diff --git a/public/app/features/live/pages/AddNewRule.tsx b/public/app/features/live/pages/AddNewRule.tsx index 44304b4ea7f..78844a8ebea 100644 --- a/public/app/features/live/pages/AddNewRule.tsx +++ b/public/app/features/live/pages/AddNewRule.tsx @@ -12,7 +12,7 @@ export function AddNewRule({ onClose }: Props) { .post(`api/live/channel-rules`, { pattern: formData.pattern, settings: { - output: formData.settings.output, + output: formData.settings.frameOutputs, converter: formData.settings.converter, }, }) @@ -31,9 +31,11 @@ export function AddNewRule({ onClose }: Props) { converter: { type: 'jsonAuto', }, - output: { - type: 'managedStream', - }, + frameOutputs: [ + { + type: 'managedStream', + }, + ], }, }} onSubmit={onSubmit} diff --git a/public/app/features/live/pages/PipelineAdminPage.tsx b/public/app/features/live/pages/PipelineAdminPage.tsx index 46a1291db49..8a6120f15b7 100644 --- a/public/app/features/live/pages/PipelineAdminPage.tsx +++ b/public/app/features/live/pages/PipelineAdminPage.tsx @@ -13,9 +13,6 @@ function renderOutputTags(key: string, output?: Output): React.ReactNode { if (!output?.type) { return null; } - if (output.multiple?.outputs?.length) { - return output.multiple?.outputs.map((v, i) => renderOutputTags(`${key}-${i}`, v)); - } return ; } @@ -47,7 +44,9 @@ export default function PipelineAdminPage() { const onRowClick = (event: any) => { const pattern = event.target.getAttribute('data-pattern'); const column = event.target.getAttribute('data-column'); - if (column) { + if (column === 'pattern') { + setClickColumn('converter'); + } else { setClickColumn(column); } setSelectedRule(rules.filter((rule) => rule.pattern === pattern)[0]); @@ -99,10 +98,14 @@ export default function PipelineAdminPage() { {rule.settings?.converter?.type} - {rule.settings?.processor?.type} + {rule.settings?.frameProcessors?.map((processor) => ( + {processor.type} + ))} - {renderOutputTags('out', rule.settings?.output)} + {rule.settings?.frameOutputs?.map((output) => ( + {renderOutputTags('out', output)} + ))} onRemoveRule(rule.pattern)}> diff --git a/public/app/features/live/pages/RuleModal.tsx b/public/app/features/live/pages/RuleModal.tsx index 01cd60bfafb..605a564da1f 100644 --- a/public/app/features/live/pages/RuleModal.tsx +++ b/public/app/features/live/pages/RuleModal.tsx @@ -6,6 +6,7 @@ import { css } from '@emotion/css'; import { GrafanaTheme } from '@grafana/data'; import { RuleSettingsEditor } from './RuleSettingsEditor'; import { getPipeLineEntities } from './utils'; +import { RuleSettingsArray } from './RuleSettingsArray'; interface Props { rule: Rule; @@ -19,8 +20,8 @@ interface TabType { } const tabs: TabType[] = [ { label: 'Converter', value: 'converter' }, - { label: 'Processor', value: 'processor' }, - { label: 'Output', value: 'output' }, + { label: 'Processors', value: 'frameProcessors' }, + { label: 'Outputs', value: 'frameOutputs' }, ]; export const RuleModal: React.FC = (props) => { @@ -33,7 +34,7 @@ export const RuleModal: React.FC = (props) => { const [entitiesInfo, setEntitiesInfo] = useState(); const styles = useStyles(getStyles); - const onRuleSettingChange = (value: RuleSetting) => { + const onRuleSettingChange = (value: RuleSetting | RuleSetting[]) => { setChange(true); setRule({ ...rule, @@ -57,6 +58,7 @@ export const RuleModal: React.FC = (props) => { .put(`api/live/channel-rules`, rule) .then(() => { setChange(false); + onClose(); }) .catch((e) => console.error(e)); }; @@ -80,7 +82,7 @@ export const RuleModal: React.FC = (props) => { })} - {entitiesInfo && rule && ( + {entitiesInfo && rule && activeTab === 'converter' && ( = (props) => { entitiesInfo={entitiesInfo} /> )} + {entitiesInfo && rule && activeTab !== 'converter' && ( + + )} diff --git a/public/app/features/live/pages/RuleSettingsArray.tsx b/public/app/features/live/pages/RuleSettingsArray.tsx new file mode 100644 index 00000000000..c209e9d578d --- /dev/null +++ b/public/app/features/live/pages/RuleSettingsArray.tsx @@ -0,0 +1,50 @@ +import React, { useState } from 'react'; +import { RuleSettingsEditor } from './RuleSettingsEditor'; +import { RuleType, RuleSetting, PipeLineEntitiesInfo } from './types'; +import { Select } from '@grafana/ui'; +import { SelectableValue } from '../../../../../packages/grafana-data/src'; + +interface Props { + ruleType: RuleType; + onChange: (value: RuleSetting[]) => void; + value: RuleSetting[]; + entitiesInfo: PipeLineEntitiesInfo; +} + +export const RuleSettingsArray: React.FC = ({ onChange, value, ruleType, entitiesInfo }) => { + const [index, setIndex] = useState(0); + const arr = value ?? []; + const onRuleChange = (v: RuleSetting) => { + if (!value) { + onChange([v]); + } else { + const copy = [...value]; + copy[index] = v; + onChange(copy); + } + }; + // create array of value.length + 1 + let indexArr: Array> = []; + for (let i = 0; i <= arr.length; i++) { + indexArr.push({ + label: `${ruleType}: ${i}`, + value: i, + }); + } + + return ( + <> + + + + ); +}; diff --git a/public/app/features/live/pages/types.ts b/public/app/features/live/pages/types.ts index e035c930c10..921ad730575 100644 --- a/public/app/features/live/pages/types.ts +++ b/public/app/features/live/pages/types.ts @@ -9,9 +9,6 @@ export interface Processor extends RuleSetting { export interface Output extends RuleSetting { [t: string]: any; - multiple?: { - outputs: Output[]; - }; } export interface RuleSetting { @@ -20,8 +17,8 @@ export interface RuleSetting { } export interface RuleSettings { converter?: Converter; - processor?: Processor; - output?: Output; + frameProcessors?: Processor[]; + frameOutputs?: Output[]; } export interface Rule { @@ -38,22 +35,22 @@ export interface GrafanaCloudBackend { settings: any; } -export type RuleType = 'converter' | 'processor' | 'output'; +export type RuleType = 'converter' | 'frameProcessors' | 'frameOutputs'; export interface PipelineListOption { type: string; description: string; - example: object; + example?: object; } export interface EntitiesTypes { converters: PipelineListOption[]; - processors: PipelineListOption[]; - outputs: PipelineListOption[]; + frameProcessors: PipelineListOption[]; + frameOutputs: PipelineListOption[]; } export interface PipeLineEntitiesInfo { converter: SelectableValue[]; - processor: SelectableValue[]; - output: SelectableValue[]; + frameProcessors: SelectableValue[]; + frameOutputs: SelectableValue[]; getExample: (rule: RuleType, type: string) => object; } diff --git a/public/app/features/live/pages/utils.ts b/public/app/features/live/pages/utils.ts index 007ddbb9ea6..edb8e90ad1a 100644 --- a/public/app/features/live/pages/utils.ts +++ b/public/app/features/live/pages/utils.ts @@ -7,8 +7,8 @@ export async function getPipeLineEntities(): Promise { .then((data) => { return { converter: transformLabel(data, 'converters'), - processor: transformLabel(data, 'processors'), - output: transformLabel(data, 'outputs'), + frameProcessors: transformLabel(data, 'frameProcessors'), + frameOutputs: transformLabel(data, 'frameOutputs'), getExample: (ruleType, type) => { return data[`${ruleType}s`]?.filter((option: PipelineListOption) => option.type === type)?.[0]?.['example']; },