chore: init - create hello world panel plugin

This commit is contained in:
Galen
2026-01-07 15:27:05 -06:00
parent 29b04bd2ed
commit 3914147c86
9 changed files with 294 additions and 0 deletions
@@ -0,0 +1,58 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
//
// Generated by:
// public/app/plugins/gen.go
// Using jennies:
// TSTypesJenny
// PluginTsTypesJenny
//
// Run 'make gen-cue' from repository root to regenerate.
export const pluginVersion = "12.4.0-pre";
export interface Options {
controlsStorageKey?: string;
/**
* isFilterLabelActive?: _
* onClickFilterString?: _
* onClickFilterOutString?: _
* onClickShowField?: _
* onClickHideField?: _
* onLogOptionsChange?: _
* logRowMenuIconsBefore?: _
* logRowMenuIconsAfter?: _
* logLineMenuCustomItems?: _
* onNewLogsReceived?: _
*/
displayedFields?: Array<string>;
/**
* wrapLogMessage: bool
* prettifyLogMessage: bool
* enableLogDetails: bool
* syntaxHighlighting?: bool
* sortOrder: common.LogsSortOrder
* dedupStrategy: common.LogsDedupStrategy
* enableInfiniteScrolling?: bool
* noInteractions?: bool
* showLogAttributes?: bool
* fontSize?: "default" | "small" @cuetsy(kind="enum", memberNames="default|small")
* detailsMode?: "inline" | "sidebar" @cuetsy(kind="enum", memberNames="inline|sidebar")
* timestampResolution?: "ms" | "ns" @cuetsy(kind="enum", memberNames="ms|ns")
* TODO: figure out how to define callbacks
*/
onClickFilterLabel?: unknown;
onClickFilterOutLabel?: unknown;
setDisplayedFields?: unknown;
showControls?: boolean;
/**
* showLabels: bool
* showCommonLabels: bool
* showFieldSelector?: bool
* showTime: bool
*/
showLogContextToggle: boolean;
}
export const defaultOptions: Partial<Options> = {
displayedFields: [],
};
+10
View File
@@ -248,6 +248,16 @@ func GetComposableKinds() ([]ComposableKind, error) {
CueFile: logsCue,
})
logstableCue, err := loadCueFileWithCommon(root, filepath.Join(root, "./public/app/plugins/panel/logstable/panelcfg.cue"))
if err != nil {
return nil, err
}
kinds = append(kinds, ComposableKind{
Name: "logstable",
Filename: "panelcfg.cue",
CueFile: logstableCue,
})
newsCue, err := loadCueFileWithCommon(root, filepath.Join(root, "./public/app/plugins/panel/news/panelcfg.cue"))
if err != nil {
return nil, err
@@ -42,6 +42,8 @@ const histogramPanel = async () =>
await import(/* webpackChunkName: "histogramPanel" */ 'app/plugins/panel/histogram/module');
const livePanel = async () => await import(/* webpackChunkName: "livePanel" */ 'app/plugins/panel/live/module');
const logsPanel = async () => await import(/* webpackChunkName: "logsPanel" */ 'app/plugins/panel/logs/module');
const logsTablePanel = async () =>
await import(/* webpackChunkName: "logsPanel" */ 'app/plugins/panel/logstable/module');
const newsPanel = async () => await import(/* webpackChunkName: "newsPanel" */ 'app/plugins/panel/news/module');
const pieChartPanel = async () =>
await import(/* webpackChunkName: "pieChartPanel" */ 'app/plugins/panel/piechart/module');
@@ -108,6 +110,7 @@ const builtInPlugins: Record<string, System.Module | (() => Promise<System.Modul
'core:plugin/bargauge': barGaugePanel,
'core:plugin/barchart': barChartPanel,
'core:plugin/logs': logsPanel,
'core:plugin/logstable': logsTablePanel,
'core:plugin/traces': tracesPanel,
'core:plugin/welcome': welcomeBanner,
'core:plugin/nodeGraph': nodeGraph,
@@ -0,0 +1,4 @@
export const LogsTable = () => {
// eslint-disable-next-line @grafana/i18n/no-untranslated-strings
return <div>Hello plugin</div>;
};
@@ -0,0 +1,70 @@
import { PanelPlugin, LogsSortOrder, LogsDedupStrategy, LogsDedupDescription } from '@grafana/data';
import { LogsTable } from './LogsTable';
import { Options } from './panelcfg.gen';
export const plugin = new PanelPlugin<Options>(LogsTable).setPanelOptions((builder) => {
builder
.addBooleanSwitch({
path: 'showTime',
name: 'Time',
description: '',
defaultValue: false,
})
.addBooleanSwitch({
path: 'wrapLogMessage',
name: 'Wrap lines',
description: '',
defaultValue: false,
})
.addBooleanSwitch({
path: 'enableLogDetails',
name: 'Enable log details',
description: '',
defaultValue: true,
})
.addBooleanSwitch({
path: 'enableInfiniteScrolling',
name: 'Enable infinite scrolling',
description: 'Experimental. Request more results by scrolling to the bottom of the logs list.',
defaultValue: false,
})
.addRadio({
path: 'dedupStrategy',
name: 'Deduplication',
description: '',
settings: {
options: [
{ value: LogsDedupStrategy.none, label: 'None', description: LogsDedupDescription[LogsDedupStrategy.none] },
{
value: LogsDedupStrategy.exact,
label: 'Exact',
description: LogsDedupDescription[LogsDedupStrategy.exact],
},
{
value: LogsDedupStrategy.numbers,
label: 'Numbers',
description: LogsDedupDescription[LogsDedupStrategy.numbers],
},
{
value: LogsDedupStrategy.signature,
label: 'Signature',
description: LogsDedupDescription[LogsDedupStrategy.signature],
},
],
},
defaultValue: LogsDedupStrategy.none,
})
.addRadio({
path: 'sortOrder',
name: 'Order',
description: '',
settings: {
options: [
{ value: LogsSortOrder.Descending, label: 'Newest first' },
{ value: LogsSortOrder.Ascending, label: 'Oldest first' },
],
},
defaultValue: LogsSortOrder.Descending,
});
});
@@ -0,0 +1,68 @@
// Copyright 2026 Grafana Labs
//
// Licensed under the Apache License, Version 2.0 (the "License")
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package grafanaplugin
//import (
// "github.com/grafana/grafana/packages/grafana-schema/src/common"
//)
composableKinds: PanelCfg: {
maturity: "experimental"
lineage: {
schemas: [{
version: [0, 0]
schema: {
Options: {
// showLabels: bool
// showCommonLabels: bool
// showFieldSelector?: bool
// showTime: bool
showLogContextToggle: bool
showControls?: bool
controlsStorageKey?: string
// wrapLogMessage: bool
// prettifyLogMessage: bool
// enableLogDetails: bool
// syntaxHighlighting?: bool
// sortOrder: common.LogsSortOrder
// dedupStrategy: common.LogsDedupStrategy
// enableInfiniteScrolling?: bool
// noInteractions?: bool
// showLogAttributes?: bool
// fontSize?: "default" | "small" @cuetsy(kind="enum", memberNames="default|small")
// detailsMode?: "inline" | "sidebar" @cuetsy(kind="enum", memberNames="inline|sidebar")
// timestampResolution?: "ms" | "ns" @cuetsy(kind="enum", memberNames="ms|ns")
// TODO: figure out how to define callbacks
onClickFilterLabel?: _
onClickFilterOutLabel?: _
// isFilterLabelActive?: _
// onClickFilterString?: _
// onClickFilterOutString?: _
// onClickShowField?: _
// onClickHideField?: _
// onLogOptionsChange?: _
// logRowMenuIconsBefore?: _
// logRowMenuIconsAfter?: _
// logLineMenuCustomItems?: _
// onNewLogsReceived?: _
displayedFields?: [...string]
setDisplayedFields?: _
} @cuetsy(kind="interface")
}
}]
lenses: []
}
}
+56
View File
@@ -0,0 +1,56 @@
// Code generated - EDITING IS FUTILE. DO NOT EDIT.
//
// Generated by:
// public/app/plugins/gen.go
// Using jennies:
// TSTypesJenny
// PluginTsTypesJenny
//
// Run 'make gen-cue' from repository root to regenerate.
export interface Options {
controlsStorageKey?: string;
/**
* isFilterLabelActive?: _
* onClickFilterString?: _
* onClickFilterOutString?: _
* onClickShowField?: _
* onClickHideField?: _
* onLogOptionsChange?: _
* logRowMenuIconsBefore?: _
* logRowMenuIconsAfter?: _
* logLineMenuCustomItems?: _
* onNewLogsReceived?: _
*/
displayedFields?: Array<string>;
/**
* wrapLogMessage: bool
* prettifyLogMessage: bool
* enableLogDetails: bool
* syntaxHighlighting?: bool
* sortOrder: common.LogsSortOrder
* dedupStrategy: common.LogsDedupStrategy
* enableInfiniteScrolling?: bool
* noInteractions?: bool
* showLogAttributes?: bool
* fontSize?: "default" | "small" @cuetsy(kind="enum", memberNames="default|small")
* detailsMode?: "inline" | "sidebar" @cuetsy(kind="enum", memberNames="inline|sidebar")
* timestampResolution?: "ms" | "ns" @cuetsy(kind="enum", memberNames="ms|ns")
* TODO: figure out how to define callbacks
*/
onClickFilterLabel?: unknown;
onClickFilterOutLabel?: unknown;
setDisplayedFields?: unknown;
showControls?: boolean;
/**
* showLabels: bool
* showCommonLabels: bool
* showFieldSelector?: bool
* showTime: bool
*/
showLogContextToggle: boolean;
}
export const defaultOptions: Partial<Options> = {
displayedFields: [],
};
@@ -0,0 +1,23 @@
{
"type": "panel",
"name": "Logs Table",
"id": "logs_table",
"state": "alpha",
"info": {
"author": {
"name": "Grafana Labs",
"url": "https://grafana.com"
},
"logos": {
"small": "img/icn-logs-panel.svg",
"large": "img/icn-logs-panel.svg"
},
"links": [
{ "name": "Raise issue", "url": "https://github.com/grafana/grafana/issues/new" },
{
"name": "Documentation",
"url": "https://grafana.com/docs/grafana/latest/panels-visualizations/visualizations/@todo/"
}
]
}
}
@@ -0,0 +1,2 @@
// @todo add some stuff
export type TODO = string;