{"version":3,"file":"OperationList.cjs","sources":["../../../../src/querybuilder/shared/OperationList.tsx"],"sourcesContent":["// Core Grafana history https://github.com/grafana/grafana/blob/v11.0.0-preview/public/app/plugins/datasource/prometheus/querybuilder/shared/OperationList.tsx\nimport { css } from '@emotion/css';\nimport { DragDropContext, Droppable, type DropResult } from '@hello-pangea/dnd';\nimport { useState } from 'react';\nimport { useMountedState, usePrevious } from 'react-use';\n\nimport { type DataSourceApi, type GrafanaTheme2, type TimeRange } from '@grafana/data';\nimport { t, Trans } from '@grafana/i18n';\nimport { Button, Cascader, type CascaderOption, useStyles2, Stack } from '@grafana/ui';\n\nimport { OperationEditor } from './OperationEditor';\nimport { type QueryBuilderOperation, type QueryWithOperations, type VisualQueryModeller } from './types';\n\ninterface Props<T extends QueryWithOperations> {\n  query: T;\n  datasource: DataSourceApi;\n  onChange: (query: T) => void;\n  onRunQuery: () => void;\n  queryModeller: VisualQueryModeller;\n  explainMode?: boolean;\n  highlightedOp?: QueryBuilderOperation;\n  timeRange: TimeRange;\n}\n\nexport function OperationList<T extends QueryWithOperations>({\n  query,\n  datasource,\n  queryModeller,\n  onChange,\n  onRunQuery,\n  highlightedOp,\n  timeRange,\n}: Props<T>) {\n  const styles = useStyles2(getStyles);\n  const { operations } = query;\n\n  const opsToHighlight = useOperationsHighlight(operations);\n\n  const [cascaderOpen, setCascaderOpen] = useState(false);\n\n  const onOperationChange = (index: number, update: QueryBuilderOperation) => {\n    const updatedList = [...operations];\n    updatedList.splice(index, 1, update);\n    onChange({ ...query, operations: updatedList });\n  };\n\n  const onRemove = (index: number) => {\n    const updatedList = [...operations.slice(0, index), ...operations.slice(index + 1)];\n    onChange({ ...query, operations: updatedList });\n  };\n\n  const addOptions: CascaderOption[] = queryModeller.getCategories().map((category) => {\n    return {\n      value: category,\n      label: category,\n      items: queryModeller.getOperationsForCategory(category).map((operation) => ({\n        value: operation.id,\n        label: operation.name,\n        isLeaf: true,\n      })),\n    };\n  });\n\n  const onAddOperation = (value: string) => {\n    const operationDef = queryModeller.getOperationDef(value);\n    if (!operationDef) {\n      return;\n    }\n    onChange(operationDef.addOperationHandler(operationDef, query, queryModeller));\n    setCascaderOpen(false);\n  };\n\n  const onDragEnd = (result: DropResult) => {\n    if (!result.destination) {\n      return;\n    }\n\n    const updatedList = [...operations];\n    const element = updatedList[result.source.index];\n    updatedList.splice(result.source.index, 1);\n    updatedList.splice(result.destination.index, 0, element);\n    onChange({ ...query, operations: updatedList });\n  };\n\n  const onCascaderBlur = () => {\n    setCascaderOpen(false);\n  };\n\n  return (\n    <Stack gap={1} direction=\"column\">\n      <Stack gap={1}>\n        {operations.length > 0 && (\n          <DragDropContext onDragEnd={onDragEnd}>\n            <Droppable droppableId=\"sortable-field-mappings\" direction=\"horizontal\">\n              {(provided) => (\n                <div className={styles.operationList} ref={provided.innerRef} {...provided.droppableProps}>\n                  {operations.map((op, index) => {\n                    return (\n                      <OperationEditor\n                        key={op.id + JSON.stringify(op.params) + index}\n                        queryModeller={queryModeller}\n                        index={index}\n                        operation={op}\n                        query={query}\n                        datasource={datasource}\n                        onChange={onOperationChange}\n                        onRemove={onRemove}\n                        onRunQuery={onRunQuery}\n                        flash={opsToHighlight[index]}\n                        highlight={highlightedOp === op}\n                        timeRange={timeRange}\n                      />\n                    );\n                  })}\n                  {provided.placeholder}\n                </div>\n              )}\n            </Droppable>\n          </DragDropContext>\n        )}\n        <div className={styles.addButton}>\n          {cascaderOpen ? (\n            <Cascader\n              options={addOptions}\n              onSelect={onAddOperation}\n              onBlur={onCascaderBlur}\n              autoFocus={true}\n              alwaysOpen={true}\n              hideActiveLevelLabel={true}\n              placeholder={t('grafana-prometheus.querybuilder.operation-list.placeholder-search', 'Search')}\n            />\n          ) : (\n            <Button\n              icon={'plus'}\n              variant={'secondary'}\n              onClick={() => setCascaderOpen(true)}\n              title={t('grafana-prometheus.querybuilder.operation-list.title-add-operation', 'Add operation')}\n            >\n              <Trans i18nKey=\"grafana-prometheus.querybuilder.operation-list.operations\">Operations</Trans>\n            </Button>\n          )}\n        </div>\n      </Stack>\n    </Stack>\n  );\n}\n\n/**\n * Returns indexes of operations that should be highlighted. We check the diff of operations added but at the same time\n * we want to highlight operations only after the initial render, so we check for mounted state and calculate the diff\n * only after.\n * @param operations\n */\nfunction useOperationsHighlight(operations: QueryBuilderOperation[]) {\n  const isMounted = useMountedState();\n  const prevOperations = usePrevious(operations);\n\n  if (!isMounted()) {\n    return operations.map(() => false);\n  }\n\n  if (!prevOperations) {\n    return operations.map(() => true);\n  }\n\n  let newOps: boolean[] = [];\n\n  if (prevOperations.length - 1 === operations.length && operations.every((op) => prevOperations.includes(op))) {\n    // In case we remove one op and does not change any ops then don't highlight anything.\n    return operations.map(() => false);\n  }\n  if (prevOperations.length + 1 === operations.length && prevOperations.every((op) => operations.includes(op))) {\n    // If we add a single op just find it and highlight just that.\n    const newOp = operations.find((op) => !prevOperations.includes(op));\n    newOps = operations.map((op) => {\n      return op === newOp;\n    });\n  } else {\n    // Default diff of all ops.\n    newOps = operations.map((op, index) => {\n      return !isSameOp(op.id, prevOperations[index]?.id);\n    });\n  }\n  return newOps;\n}\n\nfunction isSameOp(op1?: string, op2?: string) {\n  return op1 === op2 || `__${op1}_by` === op2 || op1 === `__${op2}_by`;\n}\n\nconst getStyles = (theme: GrafanaTheme2) => {\n  return {\n    heading: css({\n      label: 'heading',\n      fontSize: 12,\n      fontWeight: theme.typography.fontWeightMedium,\n      marginBottom: 0,\n    }),\n    operationList: css({\n      label: 'operationList',\n      display: 'flex',\n      flexWrap: 'wrap',\n      gap: theme.spacing(2),\n    }),\n    addButton: css({\n      label: 'addButton',\n      width: 126,\n      paddingBottom: theme.spacing(1),\n    }),\n  };\n};\n"],"names":["useStyles2","useState","jsx","Stack","jsxs","DragDropContext","Droppable","OperationEditor","Cascader","t","Button","Trans","useMountedState","usePrevious","css"],"mappings":"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"}