1import { 2 SingleStatBaseOptions, 3 BigValueColorMode, 4 BigValueGraphMode, 5 BigValueJustifyMode, 6 BigValueTextMode, 7} from '@grafana/ui'; 8import { 9 ReducerID, 10 standardEditorsRegistry, 11 FieldOverrideContext, 12 getFieldDisplayName, 13 escapeStringForRegex, 14 VizOrientation, 15 PanelOptionsEditorBuilder, 16} from '@grafana/data'; 17 18// Structure copied from angular 19export interface StatPanelOptions extends SingleStatBaseOptions { 20 graphMode: BigValueGraphMode; 21 colorMode: BigValueColorMode; 22 justifyMode: BigValueJustifyMode; 23 textMode: BigValueTextMode; 24} 25 26export function addStandardDataReduceOptions<T extends SingleStatBaseOptions>( 27 builder: PanelOptionsEditorBuilder<T>, 28 includeFieldMatcher = true 29) { 30 const valueOptionsCategory = ['Value options']; 31 32 builder.addRadio({ 33 path: 'reduceOptions.values', 34 name: 'Show', 35 description: 'Calculate a single value per column or series or show each row', 36 settings: { 37 options: [ 38 { value: false, label: 'Calculate' }, 39 { value: true, label: 'All values' }, 40 ], 41 }, 42 category: valueOptionsCategory, 43 defaultValue: false, 44 }); 45 46 builder.addNumberInput({ 47 path: 'reduceOptions.limit', 48 name: 'Limit', 49 description: 'Max number of rows to display', 50 category: valueOptionsCategory, 51 settings: { 52 placeholder: '25', 53 integer: true, 54 min: 1, 55 max: 5000, 56 }, 57 showIf: (options) => options.reduceOptions.values === true, 58 }); 59 60 builder.addCustomEditor({ 61 id: 'reduceOptions.calcs', 62 path: 'reduceOptions.calcs', 63 name: 'Calculation', 64 description: 'Choose a reducer function / calculation', 65 category: valueOptionsCategory, 66 editor: standardEditorsRegistry.get('stats-picker').editor as any, 67 defaultValue: [ReducerID.lastNotNull], 68 // Hides it when all values mode is on 69 showIf: (currentConfig) => currentConfig.reduceOptions.values === false, 70 }); 71 72 if (includeFieldMatcher) { 73 builder.addSelect({ 74 path: 'reduceOptions.fields', 75 name: 'Fields', 76 description: 'Select the fields that should be included in the panel', 77 category: valueOptionsCategory, 78 settings: { 79 allowCustomValue: true, 80 options: [], 81 getOptions: async (context: FieldOverrideContext) => { 82 const options = [ 83 { value: '', label: 'Numeric Fields' }, 84 { value: '/.*/', label: 'All Fields' }, 85 ]; 86 if (context && context.data) { 87 for (const frame of context.data) { 88 for (const field of frame.fields) { 89 const name = getFieldDisplayName(field, frame, context.data); 90 const value = `/^${escapeStringForRegex(name)}$/`; 91 options.push({ value, label: name }); 92 } 93 } 94 } 95 return Promise.resolve(options); 96 }, 97 }, 98 defaultValue: '', 99 }); 100 } 101} 102 103export function addOrientationOption<T extends SingleStatBaseOptions>( 104 builder: PanelOptionsEditorBuilder<T>, 105 category?: string[] 106) { 107 builder.addRadio({ 108 path: 'orientation', 109 name: 'Orientation', 110 description: 'Layout orientation', 111 category, 112 settings: { 113 options: [ 114 { value: VizOrientation.Auto, label: 'Auto' }, 115 { value: VizOrientation.Horizontal, label: 'Horizontal' }, 116 { value: VizOrientation.Vertical, label: 'Vertical' }, 117 ], 118 }, 119 defaultValue: VizOrientation.Auto, 120 }); 121} 122