{"version":3,"file":"index-ZNcAQhUL.cjs","sources":["../src/app/components/forms/Action.jsx","../src/app/components/forms/NodeNameField.jsx","../node_modules/react-select/dist/useAsync-9eb532f6.esm.js","../node_modules/react-select/async/dist/react-select-async.esm.js","../src/app/pages/CubeBuilderPage/MetricsSelect.jsx","../src/app/pages/CubeBuilderPage/DimensionsSelect.jsx","../src/app/pages/CubeBuilderPage/CubePreviewPanel.jsx","../src/app/pages/CubeBuilderPage/index.jsx"],"sourcesContent":["export class Action {\n  static Add = new Action('add');\n  static Edit = new Action('edit');\n\n  constructor(name) {\n    this.name = name;\n  }\n}\n","import { ErrorMessage, Field } from 'formik';\nimport { FormikSelect } from '../../pages/AddEditNodePage/FormikSelect';\nimport { FullNameField } from '../../pages/AddEditNodePage/FullNameField';\nimport React, { useContext, useEffect, useState } from 'react';\nimport DJClientContext from '../../providers/djclient';\nimport { useParams } from 'react-router-dom';\n\n/*\n * This component creates the namespace selector, display name input, and\n * derived name fields in a form. It can be reused any time we need to create\n * a new node.\n */\n\nexport default function NodeNameField() {\n  const [namespaces, setNamespaces] = useState([]);\n  const djClient = useContext(DJClientContext).DataJunctionAPI;\n  let { initialNamespace } = useParams();\n\n  useEffect(() => {\n    const fetchData = async () => {\n      const namespaces = await djClient.namespaces();\n      setNamespaces(\n        namespaces.map(m => ({\n          value: m['namespace'],\n          label: m['namespace'],\n        })),\n      );\n    };\n    fetchData().catch(console.error);\n  }, [djClient, djClient.metrics]);\n\n  return (\n    <>\n      <div className=\"NamespaceInput\">\n        <ErrorMessage name=\"namespace\" component=\"span\" />\n        <label htmlFor=\"namespace\">Namespace *</label>\n        <FormikSelect\n          selectOptions={namespaces}\n          formikFieldName=\"namespace\"\n          placeholder=\"Choose Namespace\"\n          defaultValue={{\n            value: initialNamespace,\n            label: initialNamespace,\n          }}\n        />\n      </div>\n      <div className=\"DisplayNameInput NodeCreationInput\">\n        <ErrorMessage name=\"display_name\" component=\"span\" />\n        <label htmlFor=\"displayName\">Display Name *</label>\n        <Field\n          type=\"text\"\n          name=\"display_name\"\n          id=\"displayName\"\n          placeholder=\"Human readable display name\"\n        />\n      </div>\n      <div className=\"FullNameInput NodeCreationInput\">\n        <ErrorMessage name=\"name\" component=\"span\" />\n        <label htmlFor=\"FullName\">Full Name</label>\n        <FullNameField type=\"text\" name=\"name\" />\n      </div>\n    </>\n  );\n}\n","import _defineProperty from '@babel/runtime/helpers/esm/defineProperty';\nimport _objectSpread from '@babel/runtime/helpers/esm/objectSpread2';\nimport _slicedToArray from '@babel/runtime/helpers/esm/slicedToArray';\nimport _objectWithoutProperties from '@babel/runtime/helpers/esm/objectWithoutProperties';\nimport { useRef, useState, useEffect, useCallback } from 'react';\nimport { L as handleInputChange } from './index-6ea50319.esm.js';\n\nvar _excluded = [\"defaultOptions\", \"cacheOptions\", \"loadOptions\", \"options\", \"isLoading\", \"onInputChange\", \"filterOption\"];\nfunction useAsync(_ref) {\n  var _ref$defaultOptions = _ref.defaultOptions,\n    propsDefaultOptions = _ref$defaultOptions === void 0 ? false : _ref$defaultOptions,\n    _ref$cacheOptions = _ref.cacheOptions,\n    cacheOptions = _ref$cacheOptions === void 0 ? false : _ref$cacheOptions,\n    propsLoadOptions = _ref.loadOptions;\n    _ref.options;\n    var _ref$isLoading = _ref.isLoading,\n    propsIsLoading = _ref$isLoading === void 0 ? false : _ref$isLoading,\n    propsOnInputChange = _ref.onInputChange,\n    _ref$filterOption = _ref.filterOption,\n    filterOption = _ref$filterOption === void 0 ? null : _ref$filterOption,\n    restSelectProps = _objectWithoutProperties(_ref, _excluded);\n  var propsInputValue = restSelectProps.inputValue;\n  var lastRequest = useRef(undefined);\n  var mounted = useRef(false);\n  var _useState = useState(Array.isArray(propsDefaultOptions) ? propsDefaultOptions : undefined),\n    _useState2 = _slicedToArray(_useState, 2),\n    defaultOptions = _useState2[0],\n    setDefaultOptions = _useState2[1];\n  var _useState3 = useState(typeof propsInputValue !== 'undefined' ? propsInputValue : ''),\n    _useState4 = _slicedToArray(_useState3, 2),\n    stateInputValue = _useState4[0],\n    setStateInputValue = _useState4[1];\n  var _useState5 = useState(propsDefaultOptions === true),\n    _useState6 = _slicedToArray(_useState5, 2),\n    isLoading = _useState6[0],\n    setIsLoading = _useState6[1];\n  var _useState7 = useState(undefined),\n    _useState8 = _slicedToArray(_useState7, 2),\n    loadedInputValue = _useState8[0],\n    setLoadedInputValue = _useState8[1];\n  var _useState9 = useState([]),\n    _useState10 = _slicedToArray(_useState9, 2),\n    loadedOptions = _useState10[0],\n    setLoadedOptions = _useState10[1];\n  var _useState11 = useState(false),\n    _useState12 = _slicedToArray(_useState11, 2),\n    passEmptyOptions = _useState12[0],\n    setPassEmptyOptions = _useState12[1];\n  var _useState13 = useState({}),\n    _useState14 = _slicedToArray(_useState13, 2),\n    optionsCache = _useState14[0],\n    setOptionsCache = _useState14[1];\n  var _useState15 = useState(undefined),\n    _useState16 = _slicedToArray(_useState15, 2),\n    prevDefaultOptions = _useState16[0],\n    setPrevDefaultOptions = _useState16[1];\n  var _useState17 = useState(undefined),\n    _useState18 = _slicedToArray(_useState17, 2),\n    prevCacheOptions = _useState18[0],\n    setPrevCacheOptions = _useState18[1];\n  if (cacheOptions !== prevCacheOptions) {\n    setOptionsCache({});\n    setPrevCacheOptions(cacheOptions);\n  }\n  if (propsDefaultOptions !== prevDefaultOptions) {\n    setDefaultOptions(Array.isArray(propsDefaultOptions) ? propsDefaultOptions : undefined);\n    setPrevDefaultOptions(propsDefaultOptions);\n  }\n  useEffect(function () {\n    mounted.current = true;\n    return function () {\n      mounted.current = false;\n    };\n  }, []);\n  var loadOptions = useCallback(function (inputValue, callback) {\n    if (!propsLoadOptions) return callback();\n    var loader = propsLoadOptions(inputValue, callback);\n    if (loader && typeof loader.then === 'function') {\n      loader.then(callback, function () {\n        return callback();\n      });\n    }\n  }, [propsLoadOptions]);\n  useEffect(function () {\n    if (propsDefaultOptions === true) {\n      loadOptions(stateInputValue, function (options) {\n        if (!mounted.current) return;\n        setDefaultOptions(options || []);\n        setIsLoading(!!lastRequest.current);\n      });\n    }\n    // NOTE: this effect is designed to only run when the component mounts,\n    // so we don't want to include any hook dependencies\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, []);\n  var onInputChange = useCallback(function (newValue, actionMeta) {\n    var inputValue = handleInputChange(newValue, actionMeta, propsOnInputChange);\n    if (!inputValue) {\n      lastRequest.current = undefined;\n      setStateInputValue('');\n      setLoadedInputValue('');\n      setLoadedOptions([]);\n      setIsLoading(false);\n      setPassEmptyOptions(false);\n      return;\n    }\n    if (cacheOptions && optionsCache[inputValue]) {\n      setStateInputValue(inputValue);\n      setLoadedInputValue(inputValue);\n      setLoadedOptions(optionsCache[inputValue]);\n      setIsLoading(false);\n      setPassEmptyOptions(false);\n    } else {\n      var request = lastRequest.current = {};\n      setStateInputValue(inputValue);\n      setIsLoading(true);\n      setPassEmptyOptions(!loadedInputValue);\n      loadOptions(inputValue, function (options) {\n        if (!mounted) return;\n        if (request !== lastRequest.current) return;\n        lastRequest.current = undefined;\n        setIsLoading(false);\n        setLoadedInputValue(inputValue);\n        setLoadedOptions(options || []);\n        setPassEmptyOptions(false);\n        setOptionsCache(options ? _objectSpread(_objectSpread({}, optionsCache), {}, _defineProperty({}, inputValue, options)) : optionsCache);\n      });\n    }\n  }, [cacheOptions, loadOptions, loadedInputValue, optionsCache, propsOnInputChange]);\n  var options = passEmptyOptions ? [] : stateInputValue && loadedInputValue ? loadedOptions : defaultOptions || [];\n  return _objectSpread(_objectSpread({}, restSelectProps), {}, {\n    options: options,\n    isLoading: isLoading || propsIsLoading,\n    onInputChange: onInputChange,\n    filterOption: filterOption\n  });\n}\n\nexport { useAsync as u };\n","import _extends from '@babel/runtime/helpers/esm/extends';\nimport * as React from 'react';\nimport { forwardRef } from 'react';\nimport { S as Select } from '../../dist/Select-ce3716e1.esm.js';\nimport { u as useStateManager } from '../../dist/useStateManager-7e1e8489.esm.js';\nimport { u as useAsync } from '../../dist/useAsync-9eb532f6.esm.js';\nexport { u as useAsync } from '../../dist/useAsync-9eb532f6.esm.js';\nimport '@babel/runtime/helpers/objectSpread2';\nimport '@babel/runtime/helpers/classCallCheck';\nimport '@babel/runtime/helpers/createClass';\nimport '@babel/runtime/helpers/inherits';\nimport '@babel/runtime/helpers/createSuper';\nimport '@babel/runtime/helpers/toConsumableArray';\nimport '../../dist/index-6ea50319.esm.js';\nimport '@emotion/react';\nimport '@babel/runtime/helpers/slicedToArray';\nimport '@babel/runtime/helpers/objectWithoutProperties';\nimport '@babel/runtime/helpers/typeof';\nimport '@babel/runtime/helpers/taggedTemplateLiteral';\nimport '@babel/runtime/helpers/defineProperty';\nimport 'react-dom';\nimport '@floating-ui/dom';\nimport 'use-isomorphic-layout-effect';\nimport 'memoize-one';\n\nvar AsyncSelect = /*#__PURE__*/forwardRef(function (props, ref) {\n  var stateManagedProps = useAsync(props);\n  var selectProps = useStateManager(stateManagedProps);\n  return /*#__PURE__*/React.createElement(Select, _extends({\n    ref: ref\n  }, selectProps));\n});\nvar AsyncSelect$1 = AsyncSelect;\n\nexport { AsyncSelect$1 as default };\n","/**\n * A select component for picking metrics.\n * Uses async search to efficiently handle large numbers of metrics.\n * Results are grouped by namespace for easier navigation.\n */\nimport AsyncSelect from 'react-select/async';\n// `components` is exported from the main `react-select` entry, not from\n// `react-select/async`. CRA's webpack was lenient about this; Vite's\n// stricter ESM resolution rejects the named import on the subpath.\nimport { components } from 'react-select';\nimport React, { useContext, useEffect, useState, useCallback } from 'react';\nimport DJClientContext from '../../providers/djclient';\n\n// Debounce helper\nconst debounce = (fn, ms) => {\n  let timer;\n  return (...args) => {\n    clearTimeout(timer);\n    return new Promise(resolve => {\n      timer = setTimeout(() => resolve(fn(...args)), ms);\n    });\n  };\n};\n\n/**\n * Extract namespace from a fully qualified metric name.\n * e.g., \"finance.total_revenue\" -> \"finance\"\n */\nconst getNamespace = metricName => {\n  if (!metricName) return 'default';\n  const parts = metricName.split('.');\n  return parts.slice(0, -1).join('.') || 'default';\n};\n\n/**\n * Git branch icon SVG component\n */\nconst GitBranchIcon = () => (\n  <svg\n    xmlns=\"http://www.w3.org/2000/svg\"\n    width=\"10\"\n    height=\"10\"\n    viewBox=\"0 0 24 24\"\n    fill=\"none\"\n    stroke=\"currentColor\"\n    strokeWidth=\"2\"\n    strokeLinecap=\"round\"\n    strokeLinejoin=\"round\"\n  >\n    <line x1=\"6\" y1=\"3\" x2=\"6\" y2=\"15\" />\n    <circle cx=\"18\" cy=\"6\" r=\"3\" />\n    <circle cx=\"6\" cy=\"18\" r=\"3\" />\n    <path d=\"M18 9a9 9 0 0 1-9 9\" />\n  </svg>\n);\n\n/**\n * Custom Group heading component matching Explorer styling.\n */\nconst GroupHeading = props => {\n  const { data } = props;\n  const { namespace, gitInfo, count } = data;\n\n  return (\n    <div\n      style={{\n        display: 'flex',\n        alignItems: 'center',\n        padding: '8px 12px',\n        backgroundColor: '#fafafa',\n        borderBottom: '1px solid #eee',\n      }}\n    >\n      <span style={{ fontWeight: 500, color: '#333' }}>{namespace}</span>\n      {gitInfo?.branch && (\n        <span\n          title={`Branch: ${gitInfo.branch}`}\n          style={{\n            marginLeft: '8px',\n            fontSize: '11px',\n            padding: '2px 6px',\n            borderRadius: '3px',\n            backgroundColor: gitInfo.isDefaultBranch ? '#d4edda' : '#fff3cd',\n            color: gitInfo.isDefaultBranch ? '#155724' : '#856404',\n            display: 'inline-flex',\n            alignItems: 'center',\n            gap: '4px',\n          }}\n        >\n          <GitBranchIcon />\n          {gitInfo.branch}\n        </span>\n      )}\n      <span style={{ marginLeft: '8px', color: '#999', fontSize: '12px' }}>\n        ({count})\n      </span>\n    </div>\n  );\n};\n\n/**\n * Group flat metrics array into react-select grouped format.\n * Includes branch info for styled group headers.\n */\nconst groupMetricsByNamespace = metrics => {\n  const grouped = {};\n  const gitInfoByNamespace = {};\n\n  metrics.forEach(metric => {\n    const namespace = getNamespace(metric.value);\n    if (!grouped[namespace]) {\n      grouped[namespace] = [];\n      gitInfoByNamespace[namespace] = metric.gitInfo;\n    }\n    grouped[namespace].push(metric);\n  });\n\n  // Sort namespaces alphabetically and build grouped options\n  return Object.keys(grouped)\n    .sort()\n    .map(namespace => {\n      const gitInfo = gitInfoByNamespace[namespace];\n      const count = grouped[namespace].length;\n\n      return {\n        label: namespace,\n        namespace,\n        gitInfo,\n        count,\n        options: grouped[namespace],\n      };\n    });\n};\n\n/**\n * Custom option component that shows display name and full node name.\n */\nconst formatOptionLabel = (option, { context }) => {\n  if (context === 'menu') {\n    const displayName = option.label;\n    const nodeName = option.value;\n    const isDifferent = displayName !== nodeName;\n\n    return (\n      <div>\n        <div>{displayName}</div>\n        {isDifferent && (\n          <div style={{ fontSize: '12px', color: '#999', marginTop: '2px' }}>\n            {nodeName}\n          </div>\n        )}\n      </div>\n    );\n  }\n  // For selected chips: show display name with tooltip and optional branch badge\n  const displayName = option.label || option.value;\n  const gitInfo = option.gitInfo;\n  const showBranch = gitInfo?.branch && !gitInfo?.isDefaultBranch;\n\n  return (\n    <span\n      title={option.value}\n      style={{ display: 'inline-flex', alignItems: 'center', gap: '4px' }}\n    >\n      <span>{displayName}</span>\n      {showBranch && (\n        <span\n          style={{\n            fontSize: '9px',\n            padding: '1px 4px',\n            borderRadius: '2px',\n            backgroundColor: 'rgba(255, 255, 255, 0.6)',\n            color: '#a2283e',\n            border: '1px solid rgba(162, 40, 62, 0.2)',\n            fontWeight: 500,\n            letterSpacing: '0.2px',\n          }}\n        >\n          ⎇ {gitInfo.branch}\n        </span>\n      )}\n    </span>\n  );\n};\n\nexport const MetricsSelect = React.memo(function MetricsSelect({\n  cube,\n  onChange,\n}) {\n  const djClient = useContext(DJClientContext).DataJunctionAPI;\n\n  // Currently selected metrics (for controlled component)\n  const [selectedMetrics, setSelectedMetrics] = useState([]);\n\n  // Load existing cube metrics when editing\n  useEffect(() => {\n    if (cube?.current?.cubeMetrics) {\n      const cubeMetrics = cube.current.cubeMetrics.map(metric => ({\n        value: metric.name,\n        label: metric.displayName || metric.name,\n      }));\n      setSelectedMetrics(cubeMetrics);\n      onChange(cubeMetrics.map(m => m.value));\n\n      // Fetch gitInfo for existing metrics so we can display branch badges\n      const names = cubeMetrics.map(m => m.value);\n      djClient.getMetricsInfo(names).then(enriched => {\n        if (enriched.length > 0) {\n          const infoByName = Object.fromEntries(\n            enriched.map(e => [e.value, e]),\n          );\n          setSelectedMetrics(prev =>\n            prev.map(m => (infoByName[m.value] ? infoByName[m.value] : m)),\n          );\n        }\n      });\n    }\n  }, [cube, onChange, djClient]);\n\n  // Async load options - searches metrics via GraphQL, grouped by namespace\n  const loadOptions = useCallback(\n    debounce(async inputValue => {\n      if (!inputValue || inputValue.length < 2) {\n        return [];\n      }\n      try {\n        const results = await djClient.searchMetrics(inputValue, 50);\n        return groupMetricsByNamespace(results);\n      } catch (error) {\n        console.error('Error searching metrics:', error);\n        return [];\n      }\n    }, 300),\n    [djClient],\n  );\n\n  const handleChange = selected => {\n    setSelectedMetrics(selected || []);\n    onChange((selected || []).map(option => option.value));\n  };\n\n  // Custom styles to color-code metric tags (matching Query Planner exactly)\n  const metricStyles = {\n    multiValue: base => ({\n      ...base,\n      backgroundColor: '#fad7dd',\n      border: '1px solid rgba(162, 40, 62, 0.3)',\n      borderRadius: '3px',\n      margin: '2px',\n    }),\n    multiValueLabel: base => ({\n      ...base,\n      color: '#a2283e',\n      fontSize: '10px',\n      fontWeight: 500,\n      padding: '2px 4px 2px 6px',\n    }),\n    multiValueRemove: base => ({\n      ...base,\n      color: '#a2283e',\n      padding: '0 4px',\n      ':hover': {\n        backgroundColor: '#f5c4cd',\n        color: '#a2283e',\n      },\n    }),\n  };\n\n  return (\n    <AsyncSelect\n      value={selectedMetrics}\n      loadOptions={loadOptions}\n      onChange={handleChange}\n      name=\"metrics\"\n      placeholder=\"Type to search metrics...\"\n      noOptionsMessage={({ inputValue }) =>\n        inputValue.length < 2\n          ? 'Type at least 2 characters to search'\n          : 'No metrics found'\n      }\n      loadingMessage={() => 'Searching...'}\n      formatOptionLabel={formatOptionLabel}\n      components={{ GroupHeading }}\n      styles={metricStyles}\n      isMulti\n      isClearable\n      closeMenuOnSelect={false}\n      cacheOptions\n      defaultOptions={false}\n    />\n  );\n});\n","/**\n * A select component for picking dimensions.\n * Dimensions are grouped by hop distance (how many joins away from the metrics).\n */\nimport Select from 'react-select';\nimport React, { useContext, useEffect, useState } from 'react';\nimport DJClientContext from '../../providers/djclient';\nimport { labelize } from '../../../utils/form';\n\n/**\n * Calculate hop distance from path length.\n * path.length represents how many joins away the dimension is.\n */\nconst getHopDistance = path => {\n  if (!path || path.length === 0) return 0;\n  return path.length;\n};\n\n/**\n * Render role information as a label suffix when a dimension is reached\n * via a named role (e.g. \"[birth_country]\"). Stored role values can be raw\n * (e.g. \"birth_country\") or already bracketed; normalize either form to\n * \" [role]\". Returns \"\" when there is no role.\n */\nconst formatRoleSuffix = role => {\n  if (!role) return '';\n  const stripped = role.replace(/^\\[|\\]$/g, '');\n  return stripped ? ` [${stripped}]` : '';\n};\n\n/**\n * Parse a role suffix off the end of a dimension's full name.\n * \"default.user_dim.country_code[birth_country]\" → [\"default.user_dim.country_code\", \"birth_country\"]\n * \"default.user_dim.country_code\"                → [\"default.user_dim.country_code\", \"\"]\n */\nconst splitRole = fullName => {\n  if (!fullName) return [fullName, ''];\n  const match = fullName.match(/^(.+?)\\[([^\\]]+)\\]$/);\n  return match ? [match[1], match[2]] : [fullName, ''];\n};\n\n/**\n * Get human-readable label for hop distance.\n */\nconst getHopLabel = hopDistance => {\n  if (hopDistance === 0) return 'Direct Dimensions';\n  if (hopDistance === 1) return '1 Hop Away';\n  return `${hopDistance} Hops Away`;\n};\n\nexport const DimensionsSelect = React.memo(function DimensionsSelect({\n  cube,\n  metrics,\n  onChange,\n}) {\n  const djClient = useContext(DJClientContext).DataJunctionAPI;\n\n  // Dimensions grouped by hop distance, then by node+path\n  const [dimensionsByHop, setDimensionsByHop] = useState({});\n\n  // The selected dimensions, grouped by dimension node and path\n  const [selectedDimensionsByGroup, setSelectedDimensionsByGroup] = useState(\n    {},\n  );\n\n  // The existing cube node's dimensions, if editing a cube\n  const [defaultDimensions, setDefaultDimensions] = useState([]);\n\n  useEffect(() => {\n    const fetchData = async () => {\n      let cubeDimensions = undefined;\n      // `cube` may be the bare cube object or a ref-like { current: ... }.\n      // Either shape can also arrive partially populated while data is in\n      // flight, so guard before touching `.cubeDimensions` to avoid the\n      // Suspense boundary surfacing a TypeError to the user.\n      const cubeData = cube?.current ?? cube;\n      if (cubeData?.cubeDimensions) {\n        cubeDimensions = cubeData.cubeDimensions.map(cubeDim => {\n          return {\n            value: cubeDim.name,\n            label:\n              labelize(cubeDim.attribute) +\n              formatRoleSuffix(cubeDim.role) +\n              (cubeDim.properties?.includes('primary_key') ? ' (PK)' : ''),\n          };\n        });\n        setDefaultDimensions(cubeDimensions);\n        onChange(cubeDimensions.map(m => m.value));\n      }\n\n      if (metrics && metrics.length > 0) {\n        // Populate the common dimensions list based on the selected metrics\n        const commonDimensions = await djClient.commonDimensions(metrics);\n\n        // First group by node_name + path (original grouping)\n        const groupedByNodePath = commonDimensions.reduce(\n          (group, dimension) => {\n            const key = dimension.node_name + JSON.stringify(dimension.path);\n            group[key] = group[key] ?? [];\n            group[key].push(dimension);\n            return group;\n          },\n          {},\n        );\n\n        // Then organize by hop distance\n        const byHop = {};\n        Object.values(groupedByNodePath).forEach(dimensionsInGroup => {\n          const hopDistance = getHopDistance(dimensionsInGroup[0].path);\n          byHop[hopDistance] = byHop[hopDistance] ?? [];\n          byHop[hopDistance].push(dimensionsInGroup);\n        });\n\n        setDimensionsByHop(byHop);\n\n        // Set the selected cube dimensions if an existing cube is being edited.\n        // Only run when we actually have the cube's dimensions in hand — the\n        // outer guard leaves `cubeDimensions` undefined when the cube data\n        // hasn't loaded yet.\n        if (cube && cubeDimensions) {\n          const currentSelectedDimensionsByGroup = {};\n          Object.values(groupedByNodePath).forEach(dimensionsInGroup => {\n            const groupKey =\n              dimensionsInGroup[0].node_name +\n              JSON.stringify(dimensionsInGroup[0].path);\n            currentSelectedDimensionsByGroup[groupKey] = getValue(\n              cubeDimensions.filter(\n                dim =>\n                  dimensionsInGroup.filter(x => dim.value === x.name).length >\n                  0,\n              ),\n            );\n          });\n          setSelectedDimensionsByGroup(currentSelectedDimensionsByGroup);\n          onChange(Object.values(currentSelectedDimensionsByGroup).flat(2));\n        }\n      } else {\n        setDimensionsByHop({});\n      }\n    };\n    fetchData().catch(console.error);\n  }, [djClient, onChange, metrics, cube]);\n\n  // Retrieves the selected values as a list (since it is a multi-select)\n  const getValue = options => {\n    if (options) {\n      return options.map(option => option.value);\n    } else {\n      return [];\n    }\n  };\n\n  // Sort hop distances numerically\n  const sortedHops = Object.keys(dimensionsByHop)\n    .map(Number)\n    .sort((a, b) => a - b);\n\n  // Custom styles to color-code dimension tags (matching Query Planner exactly)\n  const dimensionStyles = {\n    multiValue: base => ({\n      ...base,\n      backgroundColor: '#ffefd0',\n      border: '1px solid rgba(169, 102, 33, 0.3)',\n      borderRadius: '3px',\n      margin: '2px',\n    }),\n    multiValueLabel: base => ({\n      ...base,\n      color: '#a96621',\n      fontSize: '10px',\n      fontWeight: 500,\n      padding: '2px 4px 2px 6px',\n    }),\n    multiValueRemove: base => ({\n      ...base,\n      color: '#a96621',\n      padding: '0 4px',\n      ':hover': {\n        backgroundColor: '#ffe4b3',\n        color: '#a96621',\n      },\n    }),\n  };\n\n  if (sortedHops.length === 0) {\n    return null;\n  }\n\n  return (\n    <div>\n      {sortedHops.map(hopDistance => {\n        const groupsAtHop = dimensionsByHop[hopDistance];\n        const dimensionCount = groupsAtHop.reduce(\n          (sum, g) => sum + g.length,\n          0,\n        );\n\n        return (\n          <div key={hopDistance} style={{ marginBottom: '20px' }}>\n            {/* Hop distance header */}\n            <div\n              style={{\n                display: 'flex',\n                alignItems: 'center',\n                padding: '6px 0',\n                borderBottom: '1px solid #dee2e6',\n                marginBottom: '8px',\n                marginTop: hopDistance > 0 ? '24px' : '0',\n              }}\n            >\n              <span\n                style={{\n                  fontWeight: 600,\n                  color: '#212529',\n                  fontSize: '14px',\n                }}\n              >\n                {getHopLabel(hopDistance)}\n              </span>\n              <span\n                style={{\n                  marginLeft: '10px',\n                  color: '#6c757d',\n                  fontSize: '13px',\n                }}\n              >\n                ({dimensionCount} dimension{dimensionCount !== 1 ? 's' : ''})\n              </span>\n            </div>\n\n            {/* Dimension groups within this hop - indented */}\n            <div style={{ paddingLeft: '6px' }}>\n              {groupsAtHop.map(dimensionsInGroup => {\n                const groupKey =\n                  dimensionsInGroup[0].node_name +\n                  JSON.stringify(dimensionsInGroup[0].path);\n\n                // Convert path node names to display names\n                const pathDisplayNames = dimensionsInGroup[0].path.map(\n                  nodeName => {\n                    const lastSegment = nodeName.split('.').pop();\n                    return labelize(lastSegment);\n                  },\n                );\n\n                const groupHeader = (\n                  <h5\n                    style={{\n                      fontWeight: 'normal',\n                      marginBottom: '5px',\n                      marginTop: '10px',\n                      fontSize: '13px',\n                    }}\n                    title={dimensionsInGroup[0].path.join(' → ')}\n                  >\n                    <a href={`/nodes/${dimensionsInGroup[0].node_name}`}>\n                      <b>{dimensionsInGroup[0].node_display_name}</b>\n                    </a>\n                    {pathDisplayNames.length > 0 && (\n                      <>\n                        {' '}\n                        <span style={{ color: '#6c757d' }}>via</span>{' '}\n                        {pathDisplayNames.map((displayName, idx) => (\n                          <span key={idx}>\n                            {idx > 0 && ' → '}\n                            <a\n                              href={`/nodes/${dimensionsInGroup[0].path[idx]}`}\n                            >\n                              {displayName}\n                            </a>\n                          </span>\n                        ))}\n                      </>\n                    )}\n                  </h5>\n                );\n\n                const dimensionGroupOptions = dimensionsInGroup.map(dim => {\n                  const [bareName, role] = splitRole(dim.name);\n                  return {\n                    value: dim.name,\n                    label:\n                      labelize(bareName.split('.').slice(-1)[0]) +\n                      formatRoleSuffix(role) +\n                      (dim.properties?.includes('primary_key') ? ' (PK)' : ''),\n                  };\n                });\n\n                const cubeDimensions = defaultDimensions.filter(\n                  dim =>\n                    dimensionGroupOptions.filter(x => dim.value === x.value)\n                      .length > 0,\n                );\n\n                return (\n                  <div key={groupKey}>\n                    {groupHeader}\n                    <span\n                      data-testid={\n                        'dimensions-' + dimensionsInGroup[0].node_name\n                      }\n                    >\n                      <Select\n                        className=\"\"\n                        name={'dimensions-' + groupKey}\n                        defaultValue={cubeDimensions}\n                        options={dimensionGroupOptions}\n                        styles={dimensionStyles}\n                        isMulti\n                        isClearable\n                        closeMenuOnSelect={false}\n                        onChange={selected => {\n                          const newSelected = {\n                            ...selectedDimensionsByGroup,\n                            [groupKey]: getValue(selected),\n                          };\n                          setSelectedDimensionsByGroup(newSelected);\n                          onChange(Object.values(newSelected).flat(2));\n                        }}\n                      />\n                    </span>\n                  </div>\n                );\n              })}\n            </div>\n          </div>\n        );\n      })}\n    </div>\n  );\n});\n","/**\n * Preview panel for cube builder showing selection summary and generated SQL.\n * Matches Query Planner styling exactly.\n */\nimport React, {\n  useContext,\n  useEffect,\n  useMemo,\n  useState,\n  useCallback,\n} from 'react';\nimport { Light as SyntaxHighlighter } from 'react-syntax-highlighter';\nimport sql from 'react-syntax-highlighter/dist/esm/languages/hljs/sql';\nimport atomOneLight from 'react-syntax-highlighter/dist/esm/styles/hljs/atom-one-light';\nimport DJClientContext from '../../providers/djclient';\nimport {\n  formatBytes,\n  formatScanEstimate,\n} from '../QueryPlannerPage/PreAggDetailsPanel';\n\nSyntaxHighlighter.registerLanguage('sql', sql);\n\nconst debounce = (fn, ms) => {\n  let timer;\n  return (...args) => {\n    clearTimeout(timer);\n    timer = setTimeout(() => fn(...args), ms);\n  };\n};\n\nexport const CubePreviewPanel = React.memo(function CubePreviewPanel({\n  metrics = [],\n  dimensions = [],\n}) {\n  const djClient = useContext(DJClientContext).DataJunctionAPI;\n  const [result, setResult] = useState(null);\n  const [loading, setLoading] = useState(false);\n  const [error, setError] = useState(null);\n\n  // Fetch SQL when metrics/dimensions change\n  const fetchSql = useCallback(\n    debounce(async (m, d) => {\n      if (m.length === 0 || d.length === 0) {\n        setResult(null);\n        return;\n      }\n      setLoading(true);\n      setError(null);\n      try {\n        const res = await djClient.metricsV3(m, d, '');\n        if (res.errors && res.errors.length > 0) {\n          setError(\n            res.errors\n              .map(e =>\n                typeof e === 'string' ? e : e.message || JSON.stringify(e),\n              )\n              .join(', '),\n          );\n          setResult(null);\n        } else if (res.message) {\n          setError(res.message);\n          setResult(null);\n        } else {\n          setResult(res);\n        }\n      } catch (err) {\n        setError(err.message || 'Failed to generate SQL');\n        setResult(null);\n      } finally {\n        setLoading(false);\n      }\n    }, 500),\n    [djClient],\n  );\n\n  useEffect(() => {\n    fetchSql(metrics, dimensions);\n  }, [metrics, dimensions, fetchSql]);\n\n  // Get short name from full metric/dimension name\n  const getShortName = fullName => {\n    if (!fullName) return '';\n    const parts = fullName.split('.');\n    return parts[parts.length - 1];\n  };\n\n  const scanInfo = formatScanEstimate(result?.scan_estimate);\n\n  // SyntaxHighlighter is the heaviest piece of DOM in the form — re-rendering\n  // it on every keystroke makes typing in unrelated fields feel laggy. Memo\n  // by `result?.sql` so the highlighted output is reused as long as the SQL\n  // hasn't changed.\n  const highlightedSql = useMemo(() => {\n    if (!result?.sql) return null;\n    return (\n      <SyntaxHighlighter\n        language=\"sql\"\n        style={atomOneLight}\n        customStyle={{\n          margin: 0,\n          padding: 0,\n          fontSize: '11px',\n          background: 'transparent',\n          border: 'none',\n        }}\n      >\n        {result.sql}\n      </SyntaxHighlighter>\n    );\n  }, [result?.sql]);\n\n  return (\n    <div className=\"cube-preview-panel\">\n      <div className=\"preview-section-header\">\n        <span className=\"preview-section-icon\">⌘</span>\n        <span className=\"preview-section-title\">Generated SQL</span>\n      </div>\n\n      {/* Scan Cost Banner */}\n      {scanInfo && (\n        <div className={`scan-estimate-banner scan-estimate-${scanInfo.level}`}>\n          <span className=\"scan-estimate-icon\">{scanInfo.icon}</span>\n          <div className=\"scan-estimate-content\">\n            <div className=\"scan-estimate-header\">\n              <strong>Scan Cost:</strong>{' '}\n              {scanInfo.totalBytes !== null && scanInfo.totalBytes !== undefined\n                ? (scanInfo.hasMissingData ? '≥ ' : '') +\n                  formatBytes(scanInfo.totalBytes)\n                : 'Unknown'}\n            </div>\n            <div className=\"scan-estimate-sources\">\n              {scanInfo.sources.map((source, idx) => {\n                let displayName = source.source_name;\n                if (source.schema_ && source.table) {\n                  displayName = `${source.schema_}.${source.table}`;\n                } else if (source.table) {\n                  displayName = source.table;\n                }\n                return (\n                  <div key={idx} className=\"scan-source-item\">\n                    <span\n                      className=\"scan-source-name\"\n                      title={source.source_name}\n                    >\n                      {displayName}\n                    </span>\n                    <span className=\"scan-source-size\">\n                      {source.total_bytes !== null &&\n                      source.total_bytes !== undefined\n                        ? formatBytes(source.total_bytes)\n                        : 'no size data'}\n                    </span>\n                  </div>\n                );\n              })}\n            </div>\n          </div>\n        </div>\n      )}\n\n      <div className=\"preview-sql-container\">\n        {loading && <div className=\"preview-loading\">Generating SQL...</div>}\n        {error && <div className=\"preview-error\">{error}</div>}\n        {!loading && !error && !result?.sql && (\n          <div className=\"preview-empty\">\n            Select metrics and dimensions to preview SQL\n          </div>\n        )}\n        {!loading && !error && highlightedSql}\n      </div>\n    </div>\n  );\n});\n","import React, { useCallback, useContext, useEffect, useState } from 'react';\nimport Select from 'react-select';\nimport NamespaceHeader from '../../components/NamespaceHeader';\nimport { DataJunctionAPI } from '../../services/DJService';\nimport DJClientContext from '../../providers/djclient';\nimport { useCurrentUser } from '../../providers/UserProvider';\nimport 'react-querybuilder/dist/query-builder.scss';\nimport 'styles/styles.scss';\nimport './styles.css';\nimport '../QueryPlannerPage/styles.css';\nimport { ErrorMessage, FastField, Field, Form, Formik, useField } from 'formik';\nimport { displayMessageAfterSubmit } from '../../../utils/form';\nimport { useParams, useNavigate } from 'react-router-dom';\nimport { Action } from '../../components/forms/Action';\nimport NodeNameField from '../../components/forms/NodeNameField';\nimport { MetricsSelect } from './MetricsSelect';\nimport { DimensionsSelect } from './DimensionsSelect';\nimport { CubePreviewPanel } from './CubePreviewPanel';\n\n// Description textarea using FastField so typing here doesn't trigger\n// re-renders of unrelated form sections (heavy ones like the SQL preview).\nconst DescriptionField = () => (\n  <FastField\n    as=\"textarea\"\n    id=\"Description\"\n    name=\"description\"\n    placeholder=\"Describe your cube\"\n  />\n);\n\n// Simple Tags select matching MetricsSelect styling\nconst CubeTagsSelect = ({ defaultValue }) => {\n  const djClient = useContext(DJClientContext).DataJunctionAPI;\n  const [field, , helpers] = useField('tags');\n  const [options, setOptions] = useState([]);\n  const [selected, setSelected] = useState(defaultValue || []);\n\n  useEffect(() => {\n    djClient.listTags().then(tags => {\n      setOptions(tags.map(t => ({ value: t.name, label: t.display_name })));\n    });\n  }, [djClient]);\n\n  useEffect(() => {\n    if (defaultValue) setSelected(defaultValue);\n  }, [defaultValue]);\n\n  const handleChange = sel => {\n    setSelected(sel || []);\n    helpers.setValue((sel || []).map(s => s.value));\n  };\n\n  return (\n    <Select\n      value={selected}\n      options={options}\n      onChange={handleChange}\n      isMulti\n      placeholder=\"Select tags...\"\n    />\n  );\n};\n\n// Simple Owners select matching MetricsSelect styling\nconst CubeOwnersSelect = ({ defaultValue, isEdit = false }) => {\n  const djClient = useContext(DJClientContext).DataJunctionAPI;\n  const { currentUser } = useCurrentUser();\n  const [field, , helpers] = useField('owners');\n  const [options, setOptions] = useState([]);\n  const [selected, setSelected] = useState(defaultValue || []);\n\n  useEffect(() => {\n    djClient.users().then(users => {\n      setOptions(users.map(u => ({ value: u.username, label: u.username })));\n    });\n  }, [djClient]);\n\n  // Only auto-default to current user in Add mode; in Edit mode wait for defaultValue\n  useEffect(() => {\n    if (defaultValue) {\n      setSelected(defaultValue);\n      helpers.setValue(defaultValue.map(d => d.value));\n    } else if (!isEdit && currentUser) {\n      const def = [\n        { value: currentUser.username, label: currentUser.username },\n      ];\n      setSelected(def);\n      helpers.setValue([currentUser.username]);\n    }\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [defaultValue, currentUser, isEdit]);\n\n  const handleChange = sel => {\n    setSelected(sel || []);\n    helpers.setValue((sel || []).map(s => s.value));\n  };\n\n  return (\n    <Select\n      value={selected}\n      options={options}\n      onChange={handleChange}\n      isMulti\n      placeholder=\"Select owners...\"\n    />\n  );\n};\n\nexport function CubeBuilderPage() {\n  const djClient = useContext(DJClientContext).DataJunctionAPI;\n  const navigate = useNavigate();\n\n  let { nodeType, initialNamespace, name } = useParams();\n  const action = name !== undefined ? Action.Edit : Action.Add;\n  const validator = ruleType => !!ruleType.value;\n\n  const initialValues = {\n    name: action === Action.Edit ? name : '',\n    namespace: action === Action.Add ? initialNamespace : '',\n    display_name: '',\n    description: '',\n    mode: 'published',\n    metrics: [],\n    dimensions: [],\n    filters: [],\n    tags: [],\n    owners: [],\n  };\n\n  const handleSubmit = (values, { setSubmitting, setStatus }) => {\n    if (action === Action.Add) {\n      setTimeout(() => {\n        createNode(values, setStatus);\n        setSubmitting(false);\n      }, 400);\n    } else {\n      setTimeout(() => {\n        patchNode(values, setStatus);\n        setSubmitting(false);\n      }, 400);\n    }\n    window.scrollTo({ top: 0, left: 0, behavior: 'smooth' });\n  };\n\n  const createNode = async (values, setStatus) => {\n    const { status, json } = await djClient.createCube(\n      values.name,\n      values.display_name,\n      values.description,\n      values.mode,\n      values.metrics,\n      values.dimensions,\n      values.filters || [],\n    );\n    if (status === 200 || status === 201) {\n      if (values.tags) {\n        await djClient.tagsNode(values.name, values.tags);\n      }\n      setStatus({\n        success: true,\n        savedName: json.name,\n      });\n    } else {\n      setStatus({\n        failure: `${json.message}`,\n      });\n    }\n  };\n\n  const patchNode = async (values, setStatus) => {\n    const { status, json } = await djClient.patchCube(\n      values.name,\n      values.display_name,\n      values.description,\n      values.mode,\n      values.metrics,\n      values.dimensions,\n      values.filters || [],\n      values.owners,\n    );\n    const tagsResponse = await djClient.tagsNode(\n      values.name,\n      (values.tags || []).map(tag => tag),\n    );\n    if ((status === 200 || status === 201) && tagsResponse.status === 200) {\n      setStatus({\n        success: true,\n        savedName: json.name,\n      });\n    } else {\n      setStatus({\n        failure: `${json.message}`,\n      });\n    }\n  };\n\n  const updateFieldsWithNodeData = (\n    data,\n    setFieldValue,\n    setSelectTags,\n    setSelectOwners,\n  ) => {\n    setFieldValue('display_name', data.current.displayName || '', false);\n    setFieldValue('description', data.current.description || '', false);\n    setFieldValue('mode', data.current.mode.toLowerCase() || 'draft', false);\n    setFieldValue(\n      'tags',\n      data.tags.map(tag => tag.name),\n    );\n    // Store default values as arrays for the Select components\n    setSelectTags(\n      data.tags.map(t => ({ value: t.name, label: t.displayName })),\n    );\n    if (data.owners) {\n      setSelectOwners(\n        data.owners.map(owner => ({\n          value: owner.username,\n          label: owner.username,\n        })),\n      );\n    }\n  };\n\n  // @ts-ignore\n  return (\n    <>\n      <div className=\"mid\">\n        <NamespaceHeader\n          namespace={\n            initialNamespace\n              ? initialNamespace\n              : name\n              ? name.substring(0, name.lastIndexOf('.'))\n              : ''\n          }\n        />\n        <Formik\n          initialValues={initialValues}\n          validate={validator}\n          onSubmit={handleSubmit}\n        >\n          {function Render({\n            isSubmitting,\n            status,\n            setFieldValue,\n            values,\n            props,\n          }) {\n            const [node, setNode] = useState([]);\n            const [selectTags, setSelectTags] = useState(null);\n            const [selectOwners, setSelectOwners] = useState(null);\n            const [justSaved, setJustSaved] = useState(false);\n            const [saveError, setSaveError] = useState(null);\n\n            // Get cube\n            useEffect(() => {\n              const fetchData = async () => {\n                if (name) {\n                  const cube = await djClient.getCubeForEditing(name);\n                  setNode(cube);\n                  updateFieldsWithNodeData(\n                    cube,\n                    setFieldValue,\n                    setSelectTags,\n                    setSelectOwners,\n                  );\n                }\n              };\n              fetchData().catch(console.error);\n            }, [setFieldValue]);\n\n            // Stable callbacks so the memoized child components don't re-render\n            // on every Formik state change (e.g. typing in display_name).\n            const setMetrics = useCallback(\n              v => setFieldValue('metrics', v),\n              [setFieldValue],\n            );\n            const setDimensions = useCallback(\n              v => setFieldValue('dimensions', v),\n              [setFieldValue],\n            );\n\n            // Briefly show \"Saved\" state on the button, then redirect to the cube page\n            useEffect(() => {\n              if (status?.success) {\n                setJustSaved(true);\n                setSaveError(null);\n                const savedName = status.savedName;\n                const timer = setTimeout(() => {\n                  if (savedName) {\n                    navigate(`/nodes/${savedName}`);\n                  }\n                }, 1200);\n                return () => clearTimeout(timer);\n              }\n              if (status?.failure) {\n                setSaveError(status.failure);\n                setJustSaved(false);\n              }\n            }, [status, navigate]);\n\n            return (\n              <Form className=\"cube-builder\">\n                {/* Header */}\n                <div className=\"cube-builder-header\">\n                  <h2>\n                    {action === Action.Edit ? 'Edit' : 'Create'}{' '}\n                    <span className=\"node_type__cube node_type_creation_heading\">\n                      Cube\n                    </span>\n                  </h2>\n                </div>\n\n                {/* Two-column layout */}\n                <div className=\"cube-builder-layout\">\n                  {/* Left: Main form */}\n                  <div className=\"cube-builder-main\">\n                    {/* Details Section */}\n                    <div className=\"cube-form-section\">\n                      <div className=\"cube-form-section-body\">\n                        {action === Action.Add ? (\n                          <>\n                            {/* Add mode uses NodeNameField for namespace/name */}\n                            <NodeNameField />\n\n                            {/* Row: Description | Mode */}\n                            <div className=\"cube-field-row\">\n                              <div className=\"cube-field cube-field-grow\">\n                                <ErrorMessage\n                                  name=\"description\"\n                                  component=\"span\"\n                                />\n                                <label\n                                  className=\"cube-field-label\"\n                                  htmlFor=\"Description\"\n                                >\n                                  Description\n                                </label>\n                                <DescriptionField />\n                              </div>\n                              <div className=\"cube-field cube-field-small\">\n                                <label\n                                  className=\"cube-field-label\"\n                                  htmlFor=\"Mode\"\n                                >\n                                  Mode\n                                </label>\n                                <Field as=\"select\" name=\"mode\" id=\"Mode\">\n                                  <option value=\"draft\">Draft</option>\n                                  <option value=\"published\">Published</option>\n                                </Field>\n                              </div>\n                            </div>\n\n                            {/* Row: Tags | Owners */}\n                            <div className=\"cube-field-row\">\n                              <div className=\"cube-field cube-field-half\">\n                                <label className=\"cube-field-label\">Tags</label>\n                                <CubeTagsSelect />\n                              </div>\n                              <div className=\"cube-field cube-field-half\">\n                                <label className=\"cube-field-label\">\n                                  Owners\n                                </label>\n                                <CubeOwnersSelect />\n                              </div>\n                            </div>\n                          </>\n                        ) : (\n                          <>\n                            {/* Row 1: Name (full width) */}\n                            <div className=\"cube-field\">\n                              <label className=\"cube-field-label\">Name</label>\n                              <div className=\"cube-field-static\">{name}</div>\n                            </div>\n\n                            {/* Row 2: Display Name | Mode */}\n                            <div className=\"cube-field-row\">\n                              <div className=\"cube-field cube-field-grow\">\n                                <ErrorMessage\n                                  name=\"display_name\"\n                                  component=\"span\"\n                                />\n                                <label\n                                  className=\"cube-field-label\"\n                                  htmlFor=\"displayName\"\n                                >\n                                  Display Name\n                                </label>\n                                <FastField\n                                  type=\"text\"\n                                  name=\"display_name\"\n                                  id=\"displayName\"\n                                  placeholder=\"Human readable name\"\n                                />\n                              </div>\n                              <div className=\"cube-field cube-field-small\">\n                                <label\n                                  className=\"cube-field-label\"\n                                  htmlFor=\"Mode\"\n                                >\n                                  Mode\n                                </label>\n                                <Field as=\"select\" name=\"mode\" id=\"Mode\">\n                                  <option value=\"draft\">Draft</option>\n                                  <option value=\"published\">Published</option>\n                                </Field>\n                              </div>\n                            </div>\n\n                            {/* Row 3: Description (full width) */}\n                            <div className=\"cube-field\">\n                              <ErrorMessage\n                                name=\"description\"\n                                component=\"span\"\n                              />\n                              <label\n                                className=\"cube-field-label\"\n                                htmlFor=\"Description\"\n                              >\n                                Description\n                              </label>\n                              <DescriptionField />\n                            </div>\n\n                            {/* Row 4: Tags | Owners */}\n                            <div className=\"cube-field-row\">\n                              <div className=\"cube-field cube-field-half\">\n                                <label className=\"cube-field-label\">Tags</label>\n                                <CubeTagsSelect defaultValue={selectTags} />\n                              </div>\n                              <div className=\"cube-field cube-field-half\">\n                                <label className=\"cube-field-label\">\n                                  Owners\n                                </label>\n                                <CubeOwnersSelect\n                                  defaultValue={selectOwners}\n                                  isEdit={true}\n                                />\n                              </div>\n                            </div>\n                          </>\n                        )}\n                      </div>\n                    </div>\n\n                    {/* Metrics Section */}\n                    <div className=\"cube-form-section\">\n                      <div className=\"cube-form-section-header\">\n                        <h3>Metrics</h3>\n                      </div>\n                      <div className=\"cube-form-section-body\">\n                        <div data-testid=\"select-metrics\">\n                          {action === Action.Edit ? (\n                            <MetricsSelect cube={node} onChange={setMetrics} />\n                          ) : (\n                            <MetricsSelect onChange={setMetrics} />\n                          )}\n                        </div>\n                      </div>\n                    </div>\n\n                    {/* Dimensions Section */}\n                    <div className=\"cube-form-section\">\n                      <div className=\"cube-form-section-header\">\n                        <h3>Dimensions</h3>\n                      </div>\n                      <div className=\"cube-form-section-body\">\n                        <div data-testid=\"select-dimensions\">\n                          {action === Action.Edit ? (\n                            <DimensionsSelect\n                              cube={node}\n                              metrics={values.metrics}\n                              onChange={setDimensions}\n                            />\n                          ) : (\n                            <DimensionsSelect\n                              metrics={values.metrics}\n                              onChange={setDimensions}\n                            />\n                          )}\n                        </div>\n                      </div>\n                    </div>\n                  </div>\n\n                  {/* Right: Sidebar */}\n                  <div className=\"cube-builder-sidebar\">\n                    <CubePreviewPanel\n                      metrics={values.metrics}\n                      dimensions={values.dimensions}\n                    />\n\n                    <div className=\"cube-settings\">\n                      {saveError && (\n                        <div className=\"save-error-message\">{saveError}</div>\n                      )}\n                      <button\n                        type=\"submit\"\n                        disabled={isSubmitting || justSaved}\n                        aria-label=\"CreateCube\"\n                        className={`save-cube-btn${\n                          justSaved ? ' save-cube-btn--saved' : ''\n                        }${isSubmitting ? ' save-cube-btn--loading' : ''}`}\n                      >\n                        {isSubmitting ? (\n                          <>\n                            <span className=\"save-spinner\" aria-hidden=\"true\" />\n                            Saving...\n                          </>\n                        ) : justSaved ? (\n                          '✓ Saved'\n                        ) : action === Action.Add ? (\n                          'Create Cube'\n                        ) : (\n                          'Save'\n                        )}\n                      </button>\n                    </div>\n                  </div>\n                </div>\n              </Form>\n            );\n          }}\n        </Formik>\n      </div>\n    </>\n  );\n}\n\nCubeBuilderPage.defaultProps = {\n  djClient: DataJunctionAPI,\n};\n"],"names":["_Action","name","__publicField","Action","NodeNameField","namespaces","setNamespaces","useState","djClient","useContext","DJClientContext","initialNamespace","useParams","useEffect","m","jsxs","Fragment","jsx","ErrorMessage","FormikSelect","Field","FullNameField","_excluded","useAsync","_ref","_ref$defaultOptions","propsDefaultOptions","_ref$cacheOptions","cacheOptions","propsLoadOptions","_ref$isLoading","propsIsLoading","propsOnInputChange","_ref$filterOption","filterOption","restSelectProps","_objectWithoutProperties","propsInputValue","lastRequest","useRef","mounted","_useState","_useState2","_slicedToArray","defaultOptions","setDefaultOptions","_useState3","_useState4","stateInputValue","setStateInputValue","_useState5","_useState6","isLoading","setIsLoading","_useState7","_useState8","loadedInputValue","setLoadedInputValue","_useState9","_useState10","loadedOptions","setLoadedOptions","_useState11","_useState12","passEmptyOptions","setPassEmptyOptions","_useState13","_useState14","optionsCache","setOptionsCache","_useState15","_useState16","prevDefaultOptions","setPrevDefaultOptions","_useState17","_useState18","prevCacheOptions","setPrevCacheOptions","loadOptions","useCallback","inputValue","callback","loader","options","onInputChange","newValue","actionMeta","handleInputChange","request","_objectSpread","_defineProperty","AsyncSelect","forwardRef","props","ref","stateManagedProps","selectProps","useStateManager","React","Select","_extends","AsyncSelect$1","debounce","fn","ms","timer","args","resolve","getNamespace","metricName","GitBranchIcon","GroupHeading","data","namespace","gitInfo","count","groupMetricsByNamespace","metrics","grouped","gitInfoByNamespace","metric","formatOptionLabel","option","context","displayName","nodeName","isDifferent","showBranch","MetricsSelect","cube","onChange","selectedMetrics","setSelectedMetrics","_a","cubeMetrics","names","enriched","infoByName","e","prev","results","error","handleChange","selected","metricStyles","base","getHopDistance","path","formatRoleSuffix","role","stripped","splitRole","fullName","match","getHopLabel","hopDistance","DimensionsSelect","dimensionsByHop","setDimensionsByHop","selectedDimensionsByGroup","setSelectedDimensionsByGroup","defaultDimensions","setDefaultDimensions","cubeDimensions","cubeData","cubeDim","labelize","groupedByNodePath","group","dimension","key","byHop","dimensionsInGroup","currentSelectedDimensionsByGroup","groupKey","getValue","dim","x","sortedHops","a","b","dimensionStyles","groupsAtHop","dimensionCount","sum","g","pathDisplayNames","lastSegment","groupHeader","idx","dimensionGroupOptions","bareName","newSelected","SyntaxHighlighter","sql","CubePreviewPanel","dimensions","result","setResult","loading","setLoading","setError","fetchSql","d","res","err","scanInfo","formatScanEstimate","highlightedSql","useMemo","atomOneLight","formatBytes","source","DescriptionField","FastField","CubeTagsSelect","defaultValue","field","helpers","useField","setOptions","setSelected","tags","t","sel","s","CubeOwnersSelect","isEdit","currentUser","useCurrentUser","users","u","def","CubeBuilderPage","navigate","useNavigate","nodeType","action","validator","ruleType","initialValues","handleSubmit","values","setSubmitting","setStatus","createNode","patchNode","status","json","tagsResponse","tag","updateFieldsWithNodeData","setFieldValue","setSelectTags","setSelectOwners","owner","NamespaceHeader","Formik","isSubmitting","node","setNode","selectTags","selectOwners","justSaved","setJustSaved","saveError","setSaveError","setMetrics","v","setDimensions","savedName","Form","DataJunctionAPI"],"mappings":"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","x_google_ignoreList":[2,3]}