module.tsx 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. import {
  2. DataFrame,
  3. FieldColorModeId,
  4. FieldConfigProperty,
  5. FieldType,
  6. getFieldDisplayName,
  7. PanelPlugin,
  8. VizOrientation,
  9. } from '@grafana/data';
  10. import { config } from '@grafana/runtime';
  11. import { StackingMode, VisibilityMode } from '@grafana/schema';
  12. import { graphFieldOptions, commonOptionsBuilder } from '@grafana/ui';
  13. import { BarChartPanel } from './BarChartPanel';
  14. import { TickSpacingEditor } from './TickSpacingEditor';
  15. import { BarChartFieldConfig, PanelOptions, defaultBarChartFieldConfig, defaultPanelOptions } from './models.gen';
  16. import { BarChartSuggestionsSupplier } from './suggestions';
  17. import { prepareBarChartDisplayValues } from './utils';
  18. export const plugin = new PanelPlugin<PanelOptions, BarChartFieldConfig>(BarChartPanel)
  19. .useFieldConfig({
  20. standardOptions: {
  21. [FieldConfigProperty.Color]: {
  22. settings: {
  23. byValueSupport: true,
  24. preferThresholdsMode: false,
  25. },
  26. defaultValue: {
  27. mode: FieldColorModeId.PaletteClassic,
  28. },
  29. },
  30. },
  31. useCustomConfig: (builder) => {
  32. const cfg = defaultBarChartFieldConfig;
  33. builder
  34. .addSliderInput({
  35. path: 'lineWidth',
  36. name: 'Line width',
  37. defaultValue: cfg.lineWidth,
  38. settings: {
  39. min: 0,
  40. max: 10,
  41. step: 1,
  42. },
  43. })
  44. .addSliderInput({
  45. path: 'fillOpacity',
  46. name: 'Fill opacity',
  47. defaultValue: cfg.fillOpacity,
  48. settings: {
  49. min: 0,
  50. max: 100,
  51. step: 1,
  52. },
  53. })
  54. .addRadio({
  55. path: 'gradientMode',
  56. name: 'Gradient mode',
  57. defaultValue: graphFieldOptions.fillGradient[0].value,
  58. settings: {
  59. options: graphFieldOptions.fillGradient,
  60. },
  61. });
  62. commonOptionsBuilder.addAxisConfig(builder, cfg, false);
  63. commonOptionsBuilder.addHideFrom(builder);
  64. },
  65. })
  66. .setPanelOptions((builder, context) => {
  67. const disp = prepareBarChartDisplayValues(context.data, config.theme2, context.options ?? ({} as any));
  68. let xaxisPlaceholder = 'First string or time field';
  69. const viz = 'viz' in disp ? disp.viz[0] : undefined;
  70. if (viz?.fields?.length) {
  71. const first = viz.fields[0];
  72. xaxisPlaceholder += ` (${getFieldDisplayName(first, viz)})`;
  73. }
  74. builder
  75. .addFieldNamePicker({
  76. path: 'xField',
  77. name: 'X Axis',
  78. settings: {
  79. placeholderText: xaxisPlaceholder,
  80. },
  81. })
  82. .addRadio({
  83. path: 'orientation',
  84. name: 'Orientation',
  85. settings: {
  86. options: [
  87. { value: VizOrientation.Auto, label: 'Auto' },
  88. { value: VizOrientation.Horizontal, label: 'Horizontal' },
  89. { value: VizOrientation.Vertical, label: 'Vertical' },
  90. ],
  91. },
  92. defaultValue: defaultPanelOptions.orientation,
  93. })
  94. .addSliderInput({
  95. path: 'xTickLabelRotation',
  96. name: 'Rotate bar labels',
  97. defaultValue: defaultPanelOptions.xTickLabelRotation,
  98. settings: {
  99. min: -90,
  100. max: 90,
  101. step: 15,
  102. marks: { '-90': '-90°', '-45': '-45°', 0: '0°', 45: '45°', 90: '90°' },
  103. included: false,
  104. },
  105. showIf: (opts) => {
  106. return opts.orientation === VizOrientation.Auto || opts.orientation === VizOrientation.Vertical;
  107. },
  108. })
  109. .addNumberInput({
  110. path: 'xTickLabelMaxLength',
  111. name: 'Bar label max length',
  112. description: 'Bar labels will be truncated to the length provided',
  113. settings: {
  114. placeholder: 'None',
  115. min: 0,
  116. },
  117. })
  118. .addCustomEditor({
  119. id: 'xTickLabelSpacing',
  120. path: 'xTickLabelSpacing',
  121. name: 'Bar labels minimum spacing',
  122. defaultValue: defaultPanelOptions.xTickLabelSpacing,
  123. editor: TickSpacingEditor,
  124. })
  125. .addRadio({
  126. path: 'showValue',
  127. name: 'Show values',
  128. settings: {
  129. options: [
  130. { value: VisibilityMode.Auto, label: 'Auto' },
  131. { value: VisibilityMode.Always, label: 'Always' },
  132. { value: VisibilityMode.Never, label: 'Never' },
  133. ],
  134. },
  135. defaultValue: defaultPanelOptions.showValue,
  136. })
  137. .addRadio({
  138. path: 'stacking',
  139. name: 'Stacking',
  140. settings: {
  141. options: graphFieldOptions.stacking,
  142. },
  143. defaultValue: defaultPanelOptions.stacking,
  144. })
  145. .addSliderInput({
  146. path: 'groupWidth',
  147. name: 'Group width',
  148. defaultValue: defaultPanelOptions.groupWidth,
  149. settings: {
  150. min: 0,
  151. max: 1,
  152. step: 0.01,
  153. },
  154. showIf: (c, data) => {
  155. if (c.stacking && c.stacking !== StackingMode.None) {
  156. return false;
  157. }
  158. return countNumberFields(data) !== 1;
  159. },
  160. })
  161. .addSliderInput({
  162. path: 'barWidth',
  163. name: 'Bar width',
  164. defaultValue: defaultPanelOptions.barWidth,
  165. settings: {
  166. min: 0,
  167. max: 1,
  168. step: 0.01,
  169. },
  170. })
  171. .addSliderInput({
  172. path: 'barRadius',
  173. name: 'Bar radius',
  174. defaultValue: defaultPanelOptions.barRadius,
  175. settings: {
  176. min: 0,
  177. max: 0.5,
  178. step: 0.05,
  179. },
  180. });
  181. builder.addFieldNamePicker({
  182. path: 'colorByField',
  183. name: 'Color by field',
  184. description: 'Use the color value for a sibling field to color each bar value.',
  185. });
  186. commonOptionsBuilder.addTooltipOptions(builder);
  187. commonOptionsBuilder.addLegendOptions(builder);
  188. commonOptionsBuilder.addTextSizeOptions(builder, false);
  189. })
  190. .setSuggestionsSupplier(new BarChartSuggestionsSupplier());
  191. function countNumberFields(data?: DataFrame[]): number {
  192. let count = 0;
  193. if (data) {
  194. for (const frame of data) {
  195. for (const field of frame.fields) {
  196. if (field.type === FieldType.number) {
  197. count++;
  198. }
  199. }
  200. }
  201. }
  202. return count;
  203. }