mirror of https://github.com/grafana/grafana.git
				
				
				
			Schema: Add schema for library panels (#62169)
This commit is contained in:
		
							parent
							
								
									13159d03ba
								
							
						
					
					
						commit
						0d2a786816
					
				|  | @ -3106,8 +3106,10 @@ exports[`better eslint`] = { | |||
|       [0, 0, 0, "Do not use any type assertions.", "6"], | ||||
|       [0, 0, 0, "Unexpected any. Specify a different type.", "7"], | ||||
|       [0, 0, 0, "Do not use any type assertions.", "8"], | ||||
|       [0, 0, 0, "Do not use any type assertions.", "9"], | ||||
|       [0, 0, 0, "Unexpected any. Specify a different type.", "10"] | ||||
|       [0, 0, 0, "Unexpected any. Specify a different type.", "9"], | ||||
|       [0, 0, 0, "Do not use any type assertions.", "10"], | ||||
|       [0, 0, 0, "Do not use any type assertions.", "11"], | ||||
|       [0, 0, 0, "Unexpected any. Specify a different type.", "12"] | ||||
|     ], | ||||
|     "public/app/features/dashboard/components/DashboardPrompt/DashboardPrompt.test.tsx:5381": [ | ||||
|       [0, 0, 0, "Unexpected any. Specify a different type.", "0"], | ||||
|  | @ -3988,9 +3990,6 @@ exports[`better eslint`] = { | |||
|     "public/app/features/library-panels/components/LibraryPanelsView/actions.ts:5381": [ | ||||
|       [0, 0, 0, "Unexpected any. Specify a different type.", "0"] | ||||
|     ], | ||||
|     "public/app/features/library-panels/types.ts:5381": [ | ||||
|       [0, 0, 0, "Unexpected any. Specify a different type.", "0"] | ||||
|     ], | ||||
|     "public/app/features/library-panels/utils.ts:5381": [ | ||||
|       [0, 0, 0, "Unexpected any. Specify a different type.", "0"], | ||||
|       [0, 0, 0, "Unexpected any. Specify a different type.", "1"] | ||||
|  | @ -4091,6 +4090,9 @@ exports[`better eslint`] = { | |||
|       [0, 0, 0, "Do not use any type assertions.", "4"], | ||||
|       [0, 0, 0, "Unexpected any. Specify a different type.", "5"] | ||||
|     ], | ||||
|     "public/app/features/manage-dashboards/components/ImportDashboardLibraryPanelsList.tsx:5381": [ | ||||
|       [0, 0, 0, "Do not use any type assertions.", "0"] | ||||
|     ], | ||||
|     "public/app/features/manage-dashboards/components/SnapshotListTable.test.tsx:5381": [ | ||||
|       [0, 0, 0, "Unexpected any. Specify a different type.", "0"] | ||||
|     ], | ||||
|  |  | |||
|  | @ -0,0 +1,70 @@ | |||
| --- | ||||
| keywords: | ||||
|   - grafana | ||||
|   - schema | ||||
| title: LibraryPanel kind | ||||
| --- | ||||
| > Both documentation generation and kinds schemas are in active development and subject to change without prior notice. | ||||
| 
 | ||||
| # LibraryPanel kind | ||||
| 
 | ||||
| ## Maturity: experimental | ||||
| ## Version: 0.0 | ||||
| 
 | ||||
| ## Properties | ||||
| 
 | ||||
| | Property        | Type                                            | Required | Description                                                                                                                          | | ||||
| |-----------------|-------------------------------------------------|----------|--------------------------------------------------------------------------------------------------------------------------------------| | ||||
| | `model`         | [object](#model)                                | **Yes**  | TODO: should be the same panel schema defined in dashboard<br/>Typescript: Omit<Panel, 'gridPos' | 'id' | 'libraryPanel'>; | | ||||
| | `name`          | string                                          | **Yes**  | Panel name (also saved in the model)                                                                                                 | | ||||
| | `type`          | string                                          | **Yes**  | The panel type (from inside the model)                                                                                               | | ||||
| | `uid`           | string                                          | **Yes**  | Library element UID                                                                                                                  | | ||||
| | `version`       | integer                                         | **Yes**  | panel version, incremented each time the dashboard is updated.                                                                       | | ||||
| | `description`   | string                                          | No       | Panel description                                                                                                                    | | ||||
| | `folderUid`     | string                                          | No       | Folder UID                                                                                                                           | | ||||
| | `meta`          | [LibraryElementDTOMeta](#libraryelementdtometa) | No       |                                                                                                                                      | | ||||
| | `schemaVersion` | integer                                         | No       | Dashboard version when this was saved (zero if unknown)                                                                              | | ||||
| 
 | ||||
| ## LibraryElementDTOMeta | ||||
| 
 | ||||
| ### Properties | ||||
| 
 | ||||
| | Property              | Type                                                    | Required | Description | | ||||
| |-----------------------|---------------------------------------------------------|----------|-------------| | ||||
| | `connectedDashboards` | integer                                                 | **Yes**  |             | | ||||
| | `createdBy`           | [LibraryElementDTOMetaUser](#libraryelementdtometauser) | **Yes**  |             | | ||||
| | `created`             | string                                                  | **Yes**  |             | | ||||
| | `folderName`          | string                                                  | **Yes**  |             | | ||||
| | `folderUid`           | string                                                  | **Yes**  |             | | ||||
| | `updatedBy`           | [LibraryElementDTOMetaUser](#libraryelementdtometauser) | **Yes**  |             | | ||||
| | `updated`             | string                                                  | **Yes**  |             | | ||||
| 
 | ||||
| ### LibraryElementDTOMetaUser | ||||
| 
 | ||||
| #### Properties | ||||
| 
 | ||||
| | Property    | Type    | Required | Description | | ||||
| |-------------|---------|----------|-------------| | ||||
| | `avatarUrl` | string  | **Yes**  |             | | ||||
| | `id`        | integer | **Yes**  |             | | ||||
| | `name`      | string  | **Yes**  |             | | ||||
| 
 | ||||
| ### LibraryElementDTOMetaUser | ||||
| 
 | ||||
| #### Properties | ||||
| 
 | ||||
| | Property    | Type    | Required | Description | | ||||
| |-------------|---------|----------|-------------| | ||||
| | `avatarUrl` | string  | **Yes**  |             | | ||||
| | `id`        | integer | **Yes**  |             | | ||||
| | `name`      | string  | **Yes**  |             | | ||||
| 
 | ||||
| ## model | ||||
| 
 | ||||
| TODO: should be the same panel schema defined in dashboard | ||||
| Typescript: Omit<Panel, 'gridPos' | 'id' | 'libraryPanel'>; | ||||
| 
 | ||||
| | Property | Type | Required | Description | | ||||
| |----------|------|----------|-------------| | ||||
| 
 | ||||
| 
 | ||||
|  | @ -397,6 +397,9 @@ lineage: seqs: [ | |||
| 					// TODO tighter constraint | ||||
| 					timeShift?: string @grafanamaturity(NeedsExpertReview) | ||||
| 
 | ||||
| 					// Dynamically load the panel | ||||
| 					libraryPanel?: #LibraryPanelRef | ||||
| 
 | ||||
| 					// options is specified by the PanelOptions field in panel | ||||
| 					// plugin schemas. | ||||
| 					options: {...} @grafanamaturity(NeedsExpertReview) | ||||
|  | @ -412,6 +415,11 @@ lineage: seqs: [ | |||
| 					}] @grafanamaturity(NeedsExpertReview) | ||||
| 				} @cuetsy(kind="interface") @grafana(TSVeneer="type") @grafanamaturity(NeedsExpertReview) | ||||
| 
 | ||||
| 				#LibraryPanelRef: { | ||||
| 					name: string | ||||
| 					uid:  string | ||||
| 				} @cuetsy(kind="interface") | ||||
| 
 | ||||
| 				#MatcherConfig: { | ||||
| 					id:       string | *"" @grafanamaturity(NeedsExpertReview)
 | ||||
| 					options?: _            @grafanamaturity(NeedsExpertReview) | ||||
|  |  | |||
|  | @ -0,0 +1,63 @@ | |||
| package kind | ||||
| 
 | ||||
| import "strings" | ||||
| 
 | ||||
| name:     "LibraryPanel" | ||||
| maturity: "experimental" | ||||
| 
 | ||||
| lineage: seqs: [ | ||||
| 	{ | ||||
| 		schemas: [ | ||||
| 			// 0.0 | ||||
| 			{ | ||||
| 				@grafana(TSVeneer="type") | ||||
| 
 | ||||
| 				// Folder UID | ||||
| 				folderUid?: string @grafanamaturity(ToMetadata="sys") | ||||
| 
 | ||||
| 				// Library element UID | ||||
| 				uid: string | ||||
| 
 | ||||
| 				// Panel name (also saved in the model) | ||||
| 				name: string & strings.MinRunes(1) | ||||
| 
 | ||||
| 				// Panel description | ||||
| 				description?: string | ||||
| 
 | ||||
| 				// The panel type (from inside the model) | ||||
| 				type: string & strings.MinRunes(1) | ||||
| 
 | ||||
| 				// Dashboard version when this was saved (zero if unknown) | ||||
| 				schemaVersion?: uint16 | ||||
| 
 | ||||
| 				// panel version, incremented each time the dashboard is updated. | ||||
| 				version: int64 @grafanamaturity(NeedsExpertReview) | ||||
| 
 | ||||
| 				// TODO: should be the same panel schema defined in dashboard | ||||
| 				// Typescript: Omit<Panel, 'gridPos' | 'id' | 'libraryPanel'>; | ||||
| 				model: {...} | ||||
| 
 | ||||
| 				// Object storage metadata | ||||
| 				meta?: #LibraryElementDTOMeta @grafanamaturity(ToMetadata="sys") | ||||
| 
 | ||||
| 				#LibraryElementDTOMetaUser: { | ||||
| 					id:        int64 | ||||
| 					name:      string | ||||
| 					avatarUrl: string | ||||
| 				} @cuetsy(kind="interface") @grafanamaturity(NeedsExpertReview) | ||||
| 
 | ||||
| 				#LibraryElementDTOMeta: { | ||||
| 					folderName:          string | ||||
| 					folderUid:           string @grafanamaturity(ToMetadata="sys") | ||||
| 					connectedDashboards: int64 | ||||
| 
 | ||||
| 					created: string @grafanamaturity(ToMetadata="sys") // time.Time in golang | ||||
| 					updated: string @grafanamaturity(ToMetadata="sys") // time.Time in golang | ||||
| 
 | ||||
| 					createdBy: #LibraryElementDTOMetaUser @grafanamaturity(ToMetadata="sys") | ||||
| 					updatedBy: #LibraryElementDTOMetaUser @grafanamaturity(ToMetadata="sys") | ||||
| 				} @cuetsy(kind="interface") @grafanamaturity(NeedsExpertReview) | ||||
| 			}, | ||||
| 		] | ||||
| 	}, | ||||
| ] | ||||
|  | @ -26,6 +26,7 @@ export type { | |||
|   SpecialValueMap, | ||||
|   ValueMappingResult, | ||||
|   Transformation, | ||||
|   LibraryPanelRef, | ||||
|   RowPanel, | ||||
|   GraphPanel, | ||||
|   HeatmapPanel | ||||
|  | @ -86,6 +87,23 @@ export { | |||
|   defaultFieldConfig | ||||
| } from './veneer/dashboard.types'; | ||||
| 
 | ||||
| // Raw generated types from LibraryPanel kind.
 | ||||
| export type { | ||||
|   LibraryElementDTOMetaUser, | ||||
|   LibraryElementDTOMeta | ||||
| } from './raw/librarypanel/x/librarypanel_types.gen'; | ||||
| 
 | ||||
| // The following exported declarations correspond to types in the librarypanel@0.0 kind's
 | ||||
| // schema with attribute @grafana(TSVeneer="type").
 | ||||
| //
 | ||||
| // The handwritten file for these type and default veneers is expected to be at
 | ||||
| // packages/grafana-schema/src/veneer/librarypanel.types.ts.
 | ||||
| // This re-export declaration enforces that the handwritten veneer file exists,
 | ||||
| // and exports all the symbols in the list.
 | ||||
| //
 | ||||
| // TODO generate code such that tsc enforces type compatibility between raw and veneer decls
 | ||||
| export type { LibraryPanel } from './veneer/librarypanel.types'; | ||||
| 
 | ||||
| // Raw generated types from Playlist kind.
 | ||||
| export type { | ||||
|   Playlist, | ||||
|  |  | |||
|  | @ -404,6 +404,10 @@ export interface Panel { | |||
|    * TODO tighter constraint | ||||
|    */ | ||||
|   interval?: string; | ||||
|   /** | ||||
|    * Dynamically load the panel | ||||
|    */ | ||||
|   libraryPanel?: LibraryPanelRef; | ||||
|   /** | ||||
|    * Panel links. | ||||
|    * TODO fill this out - seems there are a couple variants? | ||||
|  | @ -503,6 +507,11 @@ export const defaultFieldConfigSource: Partial<FieldConfigSource> = { | |||
|   overrides: [], | ||||
| }; | ||||
| 
 | ||||
| export interface LibraryPanelRef { | ||||
|   name: string; | ||||
|   uid: string; | ||||
| } | ||||
| 
 | ||||
| export interface MatcherConfig { | ||||
|   id: string; | ||||
|   options?: unknown; | ||||
|  |  | |||
|  | @ -0,0 +1,65 @@ | |||
| // Code generated - EDITING IS FUTILE. DO NOT EDIT.
 | ||||
| //
 | ||||
| // Generated by:
 | ||||
| //     kinds/gen.go
 | ||||
| // Using jennies:
 | ||||
| //     TSTypesJenny
 | ||||
| //     LatestMajorsOrXJenny
 | ||||
| //
 | ||||
| // Run 'make gen-cue' from repository root to regenerate.
 | ||||
| 
 | ||||
| export interface LibraryElementDTOMetaUser { | ||||
|   avatarUrl: string; | ||||
|   id: number; | ||||
|   name: string; | ||||
| } | ||||
| 
 | ||||
| export interface LibraryElementDTOMeta { | ||||
|   connectedDashboards: number; | ||||
|   created: string; | ||||
|   createdBy: LibraryElementDTOMetaUser; | ||||
|   folderName: string; | ||||
|   folderUid: string; | ||||
|   updated: string; | ||||
|   updatedBy: LibraryElementDTOMetaUser; | ||||
| } | ||||
| 
 | ||||
| export interface LibraryPanel { | ||||
|   /** | ||||
|    * Panel description | ||||
|    */ | ||||
|   description?: string; | ||||
|   /** | ||||
|    * Folder UID | ||||
|    */ | ||||
|   folderUid?: string; | ||||
|   /** | ||||
|    * Object storage metadata | ||||
|    */ | ||||
|   meta?: LibraryElementDTOMeta; | ||||
|   /** | ||||
|    * TODO: should be the same panel schema defined in dashboard | ||||
|    * Typescript: Omit<Panel, 'gridPos' | 'id' | 'libraryPanel'>; | ||||
|    */ | ||||
|   model: Record<string, unknown>; | ||||
|   /** | ||||
|    * Panel name (also saved in the model) | ||||
|    */ | ||||
|   name: string; | ||||
|   /** | ||||
|    * Dashboard version when this was saved (zero if unknown) | ||||
|    */ | ||||
|   schemaVersion?: number; | ||||
|   /** | ||||
|    * The panel type (from inside the model) | ||||
|    */ | ||||
|   type: string; | ||||
|   /** | ||||
|    * Library element UID | ||||
|    */ | ||||
|   uid: string; | ||||
|   /** | ||||
|    * panel version, incremented each time the dashboard is updated. | ||||
|    */ | ||||
|   version: number; | ||||
| } | ||||
|  | @ -0,0 +1,7 @@ | |||
| import * as raw from '../raw/librarypanel/x/librarypanel_types.gen'; | ||||
| 
 | ||||
| import { Panel } from './dashboard.types'; | ||||
| 
 | ||||
| export interface LibraryPanel extends raw.LibraryPanel { | ||||
|   model: Omit<Panel, 'gridPos' | 'id' | 'libraryPanel'>; | ||||
| } | ||||
|  | @ -458,6 +458,12 @@ type HeatmapPanel struct { | |||
| // HeatmapPanelType defines model for HeatmapPanel.Type.
 | ||||
| type HeatmapPanelType string | ||||
| 
 | ||||
| // LibraryPanelRef defines model for LibraryPanelRef.
 | ||||
| type LibraryPanelRef struct { | ||||
| 	Name string `json:"name"` | ||||
| 	Uid  string `json:"uid"` | ||||
| } | ||||
| 
 | ||||
| // LoadingState defines model for LoadingState.
 | ||||
| type LoadingState string | ||||
| 
 | ||||
|  | @ -491,6 +497,7 @@ type Panel struct { | |||
| 	// TODO docs
 | ||||
| 	// TODO tighter constraint
 | ||||
| 	Interval     *string          `json:"interval,omitempty"` | ||||
| 	LibraryPanel *LibraryPanelRef `json:"libraryPanel,omitempty"` | ||||
| 
 | ||||
| 	// Panel links.
 | ||||
| 	// TODO fill this out - seems there are a couple variants?
 | ||||
|  |  | |||
|  | @ -0,0 +1,113 @@ | |||
| // Code generated - EDITING IS FUTILE. DO NOT EDIT.
 | ||||
| //
 | ||||
| // Generated by:
 | ||||
| //     kinds/gen.go
 | ||||
| // Using jennies:
 | ||||
| //     CoreKindJenny
 | ||||
| //
 | ||||
| // Run 'make gen-cue' from repository root to regenerate.
 | ||||
| 
 | ||||
| package librarypanel | ||||
| 
 | ||||
| import ( | ||||
| 	"github.com/grafana/grafana/pkg/kindsys" | ||||
| 	"github.com/grafana/thema" | ||||
| 	"github.com/grafana/thema/vmux" | ||||
| ) | ||||
| 
 | ||||
| // rootrel is the relative path from the grafana repository root to the
 | ||||
| // directory containing the .cue files in which this kind is declared. Necessary
 | ||||
| // for runtime errors related to the declaration and/or lineage to provide
 | ||||
| // a real path to the correct .cue file.
 | ||||
| const rootrel string = "kinds/librarypanel" | ||||
| 
 | ||||
| // TODO standard generated docs
 | ||||
| type Kind struct { | ||||
| 	lin    thema.ConvergentLineage[*LibraryPanel] | ||||
| 	jcodec vmux.Codec | ||||
| 	valmux vmux.ValueMux[*LibraryPanel] | ||||
| 	decl   kindsys.Decl[kindsys.CoreProperties] | ||||
| } | ||||
| 
 | ||||
| // type guard
 | ||||
| var _ kindsys.Core = &Kind{} | ||||
| 
 | ||||
| // TODO standard generated docs
 | ||||
| func NewKind(rt *thema.Runtime, opts ...thema.BindOption) (*Kind, error) { | ||||
| 	decl, err := kindsys.LoadCoreKind(rootrel, rt.Context(), nil) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	k := &Kind{ | ||||
| 		decl: decl, | ||||
| 	} | ||||
| 
 | ||||
| 	lin, err := decl.Some().BindKindLineage(rt, opts...) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	// Get the thema.Schema that the meta says is in the current version (which
 | ||||
| 	// codegen ensures is always the latest)
 | ||||
| 	cursch := thema.SchemaP(lin, k.decl.Properties.CurrentVersion) | ||||
| 	tsch, err := thema.BindType[*LibraryPanel](cursch, &LibraryPanel{}) | ||||
| 	if err != nil { | ||||
| 		// Should be unreachable, modulo bugs in the Thema->Go code generator
 | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	k.jcodec = vmux.NewJSONCodec("librarypanel.json") | ||||
| 	k.lin = tsch.ConvergentLineage() | ||||
| 	k.valmux = vmux.NewValueMux(k.lin.TypedSchema(), k.jcodec) | ||||
| 	return k, nil | ||||
| } | ||||
| 
 | ||||
| // TODO standard generated docs
 | ||||
| func (k *Kind) Name() string { | ||||
| 	return "librarypanel" | ||||
| } | ||||
| 
 | ||||
| // TODO standard generated docs
 | ||||
| func (k *Kind) MachineName() string { | ||||
| 	return "librarypanel" | ||||
| } | ||||
| 
 | ||||
| // TODO standard generated docs
 | ||||
| func (k *Kind) Lineage() thema.Lineage { | ||||
| 	return k.lin | ||||
| } | ||||
| 
 | ||||
| // TODO standard generated docs
 | ||||
| func (k *Kind) ConvergentLineage() thema.ConvergentLineage[*LibraryPanel] { | ||||
| 	return k.lin | ||||
| } | ||||
| 
 | ||||
| // JSONValueMux is a version multiplexer that maps a []byte containing JSON data
 | ||||
| // at any schematized dashboard version to an instance of LibraryPanel.
 | ||||
| //
 | ||||
| // Validation and translation errors emitted from this func will identify the
 | ||||
| // input bytes as "dashboard.json".
 | ||||
| //
 | ||||
| // This is a thin wrapper around Thema's [vmux.ValueMux].
 | ||||
| func (k *Kind) JSONValueMux(b []byte) (*LibraryPanel, thema.TranslationLacunas, error) { | ||||
| 	return k.valmux(b) | ||||
| } | ||||
| 
 | ||||
| // TODO standard generated docs
 | ||||
| func (k *Kind) Maturity() kindsys.Maturity { | ||||
| 	return k.decl.Properties.Maturity | ||||
| } | ||||
| 
 | ||||
| // Decl returns the [kindsys.Decl] containing both CUE and Go representations of the
 | ||||
| // librarypanel declaration in .cue files.
 | ||||
| func (k *Kind) Decl() kindsys.Decl[kindsys.CoreProperties] { | ||||
| 	return k.decl | ||||
| } | ||||
| 
 | ||||
| // Props returns a [kindsys.SomeKindProps], with underlying type [kindsys.CoreProperties],
 | ||||
| // representing the static properties declared in the librarypanel kind.
 | ||||
| //
 | ||||
| // This method is identical to calling Decl().Props. It is provided to satisfy [kindsys.Interface].
 | ||||
| func (k *Kind) Props() kindsys.SomeKindProperties { | ||||
| 	return k.decl.Properties | ||||
| } | ||||
|  | @ -0,0 +1,58 @@ | |||
| // Code generated - EDITING IS FUTILE. DO NOT EDIT.
 | ||||
| //
 | ||||
| // Generated by:
 | ||||
| //     kinds/gen.go
 | ||||
| // Using jennies:
 | ||||
| //     GoTypesJenny
 | ||||
| //     LatestJenny
 | ||||
| //
 | ||||
| // Run 'make gen-cue' from repository root to regenerate.
 | ||||
| 
 | ||||
| package librarypanel | ||||
| 
 | ||||
| // LibraryElementDTOMeta defines model for LibraryElementDTOMeta.
 | ||||
| type LibraryElementDTOMeta struct { | ||||
| 	ConnectedDashboards int64                     `json:"connectedDashboards"` | ||||
| 	Created             string                    `json:"created"` | ||||
| 	CreatedBy           LibraryElementDTOMetaUser `json:"createdBy"` | ||||
| 	FolderName          string                    `json:"folderName"` | ||||
| 	FolderUid           string                    `json:"folderUid"` | ||||
| 	Updated             string                    `json:"updated"` | ||||
| 	UpdatedBy           LibraryElementDTOMetaUser `json:"updatedBy"` | ||||
| } | ||||
| 
 | ||||
| // LibraryElementDTOMetaUser defines model for LibraryElementDTOMetaUser.
 | ||||
| type LibraryElementDTOMetaUser struct { | ||||
| 	AvatarUrl string `json:"avatarUrl"` | ||||
| 	Id        int64  `json:"id"` | ||||
| 	Name      string `json:"name"` | ||||
| } | ||||
| 
 | ||||
| // LibraryPanel defines model for LibraryPanel.
 | ||||
| type LibraryPanel struct { | ||||
| 	// Panel description
 | ||||
| 	Description *string `json:"description,omitempty"` | ||||
| 
 | ||||
| 	// Folder UID
 | ||||
| 	FolderUid *string                `json:"folderUid,omitempty"` | ||||
| 	Meta      *LibraryElementDTOMeta `json:"meta,omitempty"` | ||||
| 
 | ||||
| 	// TODO: should be the same panel schema defined in dashboard
 | ||||
| 	// Typescript: Omit<Panel, 'gridPos' | 'id' | 'libraryPanel'>;
 | ||||
| 	Model map[string]interface{} `json:"model"` | ||||
| 
 | ||||
| 	// Panel name (also saved in the model)
 | ||||
| 	Name string `json:"name"` | ||||
| 
 | ||||
| 	// Dashboard version when this was saved (zero if unknown)
 | ||||
| 	SchemaVersion *int `json:"schemaVersion,omitempty"` | ||||
| 
 | ||||
| 	// The panel type (from inside the model)
 | ||||
| 	Type string `json:"type"` | ||||
| 
 | ||||
| 	// Library element UID
 | ||||
| 	Uid string `json:"uid"` | ||||
| 
 | ||||
| 	// panel version, incremented each time the dashboard is updated.
 | ||||
| 	Version int64 `json:"version"` | ||||
| } | ||||
|  | @ -807,6 +807,32 @@ | |||
|       "pluralName": "JaegerDataSourceCfgs", | ||||
|       "schemaInterface": "DataSourceCfg" | ||||
|     }, | ||||
|     "librarypanel": { | ||||
|       "category": "core", | ||||
|       "codeowners": [ | ||||
|         "grafana/grafana-as-code", | ||||
|         "grafana/grafana-bi-squad", | ||||
|         "grafana/plugins-platform-frontend", | ||||
|         "grafana/user-essentials" | ||||
|       ], | ||||
|       "currentVersion": [ | ||||
|         0, | ||||
|         0 | ||||
|       ], | ||||
|       "grafanaMaturityCount": 10, | ||||
|       "lineageIsGroup": false, | ||||
|       "links": { | ||||
|         "docs": "https://grafana.com/docs/grafana/next/developers/kinds/core/librarypanel/schema-reference", | ||||
|         "go": "https://github.com/grafana/grafana/tree/main/pkg/kinds/librarypanel", | ||||
|         "schema": "https://github.com/grafana/grafana/tree/main/kinds/librarypanel/librarypanel_kind.cue", | ||||
|         "ts": "https://github.com/grafana/grafana/tree/main/packages/grafana-schema/src/raw/librarypanel/x/librarypanel_types.gen.ts" | ||||
|       }, | ||||
|       "machineName": "librarypanel", | ||||
|       "maturity": "experimental", | ||||
|       "name": "LibraryPanel", | ||||
|       "pluralMachineName": "librarypanels", | ||||
|       "pluralName": "LibraryPanels" | ||||
|     }, | ||||
|     "livepanelcfg": { | ||||
|       "category": "composable", | ||||
|       "codeowners": [], | ||||
|  | @ -1846,6 +1872,7 @@ | |||
|           "dashboard", | ||||
|           "datasource", | ||||
|           "folder", | ||||
|           "librarypanel", | ||||
|           "playlist", | ||||
|           "preferences", | ||||
|           "publicdashboard", | ||||
|  | @ -1856,7 +1883,7 @@ | |||
|           "thumb", | ||||
|           "user" | ||||
|         ], | ||||
|         "count": 13 | ||||
|         "count": 14 | ||||
|       } | ||||
|     }, | ||||
|     "maturity": { | ||||
|  | @ -1870,6 +1897,7 @@ | |||
|           "dashboardlistpanelcfg", | ||||
|           "gaugepanelcfg", | ||||
|           "histogrampanelcfg", | ||||
|           "librarypanel", | ||||
|           "newspanelcfg", | ||||
|           "nodegraphpanelcfg", | ||||
|           "piechartpanelcfg", | ||||
|  | @ -1880,7 +1908,7 @@ | |||
|           "textpanelcfg", | ||||
|           "xychartpanelcfg" | ||||
|         ], | ||||
|         "count": 16 | ||||
|         "count": 17 | ||||
|       }, | ||||
|       "mature": { | ||||
|         "name": "mature", | ||||
|  |  | |||
|  | @ -13,6 +13,7 @@ import ( | |||
| 	"fmt" | ||||
| 
 | ||||
| 	"github.com/grafana/grafana/pkg/kinds/dashboard" | ||||
| 	"github.com/grafana/grafana/pkg/kinds/librarypanel" | ||||
| 	"github.com/grafana/grafana/pkg/kinds/playlist" | ||||
| 	"github.com/grafana/grafana/pkg/kinds/preferences" | ||||
| 	"github.com/grafana/grafana/pkg/kinds/publicdashboard" | ||||
|  | @ -35,6 +36,7 @@ import ( | |||
| type Base struct { | ||||
| 	all             []kindsys.Core | ||||
| 	dashboard       *dashboard.Kind | ||||
| 	librarypanel    *librarypanel.Kind | ||||
| 	playlist        *playlist.Kind | ||||
| 	preferences     *preferences.Kind | ||||
| 	publicdashboard *publicdashboard.Kind | ||||
|  | @ -45,6 +47,7 @@ type Base struct { | |||
| // type guards
 | ||||
| var ( | ||||
| 	_ kindsys.Core = &dashboard.Kind{} | ||||
| 	_ kindsys.Core = &librarypanel.Kind{} | ||||
| 	_ kindsys.Core = &playlist.Kind{} | ||||
| 	_ kindsys.Core = &preferences.Kind{} | ||||
| 	_ kindsys.Core = &publicdashboard.Kind{} | ||||
|  | @ -57,6 +60,11 @@ func (b *Base) Dashboard() *dashboard.Kind { | |||
| 	return b.dashboard | ||||
| } | ||||
| 
 | ||||
| // LibraryPanel returns the [kindsys.Interface] implementation for the librarypanel kind.
 | ||||
| func (b *Base) LibraryPanel() *librarypanel.Kind { | ||||
| 	return b.librarypanel | ||||
| } | ||||
| 
 | ||||
| // Playlist returns the [kindsys.Interface] implementation for the playlist kind.
 | ||||
| func (b *Base) Playlist() *playlist.Kind { | ||||
| 	return b.playlist | ||||
|  | @ -92,6 +100,12 @@ func doNewBase(rt *thema.Runtime) *Base { | |||
| 	} | ||||
| 	reg.all = append(reg.all, reg.dashboard) | ||||
| 
 | ||||
| 	reg.librarypanel, err = librarypanel.NewKind(rt) | ||||
| 	if err != nil { | ||||
| 		panic(fmt.Sprintf("error while initializing the librarypanel Kind: %s", err)) | ||||
| 	} | ||||
| 	reg.all = append(reg.all, reg.librarypanel) | ||||
| 
 | ||||
| 	reg.playlist, err = playlist.NewKind(rt) | ||||
| 	if err != nil { | ||||
| 		panic(fmt.Sprintf("error while initializing the playlist Kind: %s", err)) | ||||
|  |  | |||
|  | @ -10,6 +10,7 @@ import ( | |||
| 
 | ||||
| 	"github.com/grafana/grafana/pkg/api/dtos" | ||||
| 	"github.com/grafana/grafana/pkg/infra/db" | ||||
| 	"github.com/grafana/grafana/pkg/kinds/librarypanel" | ||||
| 	"github.com/grafana/grafana/pkg/models" | ||||
| 	"github.com/grafana/grafana/pkg/services/dashboards" | ||||
| 	"github.com/grafana/grafana/pkg/services/org" | ||||
|  | @ -166,15 +167,15 @@ func (l *LibraryElementService) createLibraryElement(c context.Context, signedIn | |||
| 			ConnectedDashboards: 0, | ||||
| 			Created:             element.Created, | ||||
| 			Updated:             element.Updated, | ||||
| 			CreatedBy: LibraryElementDTOMetaUser{ | ||||
| 				ID:        element.CreatedBy, | ||||
| 			CreatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 				Id:        element.CreatedBy, | ||||
| 				Name:      signedInUser.Login, | ||||
| 				AvatarURL: dtos.GetGravatarUrl(signedInUser.Email), | ||||
| 				AvatarUrl: dtos.GetGravatarUrl(signedInUser.Email), | ||||
| 			}, | ||||
| 			UpdatedBy: LibraryElementDTOMetaUser{ | ||||
| 				ID:        element.UpdatedBy, | ||||
| 			UpdatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 				Id:        element.UpdatedBy, | ||||
| 				Name:      signedInUser.Login, | ||||
| 				AvatarURL: dtos.GetGravatarUrl(signedInUser.Email), | ||||
| 				AvatarUrl: dtos.GetGravatarUrl(signedInUser.Email), | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
|  | @ -279,15 +280,15 @@ func getLibraryElements(c context.Context, store db.DB, cfg *setting.Cfg, signed | |||
| 				ConnectedDashboards: libraryElement.ConnectedDashboards, | ||||
| 				Created:             libraryElement.Created, | ||||
| 				Updated:             libraryElement.Updated, | ||||
| 				CreatedBy: LibraryElementDTOMetaUser{ | ||||
| 					ID:        libraryElement.CreatedBy, | ||||
| 				CreatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 					Id:        libraryElement.CreatedBy, | ||||
| 					Name:      libraryElement.CreatedByName, | ||||
| 					AvatarURL: dtos.GetGravatarUrl(libraryElement.CreatedByEmail), | ||||
| 					AvatarUrl: dtos.GetGravatarUrl(libraryElement.CreatedByEmail), | ||||
| 				}, | ||||
| 				UpdatedBy: LibraryElementDTOMetaUser{ | ||||
| 					ID:        libraryElement.UpdatedBy, | ||||
| 				UpdatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 					Id:        libraryElement.UpdatedBy, | ||||
| 					Name:      libraryElement.UpdatedByName, | ||||
| 					AvatarURL: dtos.GetGravatarUrl(libraryElement.UpdatedByEmail), | ||||
| 					AvatarUrl: dtos.GetGravatarUrl(libraryElement.UpdatedByEmail), | ||||
| 				}, | ||||
| 			}, | ||||
| 		} | ||||
|  | @ -392,15 +393,15 @@ func (l *LibraryElementService) getAllLibraryElements(c context.Context, signedI | |||
| 					ConnectedDashboards: element.ConnectedDashboards, | ||||
| 					Created:             element.Created, | ||||
| 					Updated:             element.Updated, | ||||
| 					CreatedBy: LibraryElementDTOMetaUser{ | ||||
| 						ID:        element.CreatedBy, | ||||
| 					CreatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 						Id:        element.CreatedBy, | ||||
| 						Name:      element.CreatedByName, | ||||
| 						AvatarURL: dtos.GetGravatarUrl(element.CreatedByEmail), | ||||
| 						AvatarUrl: dtos.GetGravatarUrl(element.CreatedByEmail), | ||||
| 					}, | ||||
| 					UpdatedBy: LibraryElementDTOMetaUser{ | ||||
| 						ID:        element.UpdatedBy, | ||||
| 					UpdatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 						Id:        element.UpdatedBy, | ||||
| 						Name:      element.UpdatedByName, | ||||
| 						AvatarURL: dtos.GetGravatarUrl(element.UpdatedByEmail), | ||||
| 						AvatarUrl: dtos.GetGravatarUrl(element.UpdatedByEmail), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}) | ||||
|  | @ -541,15 +542,15 @@ func (l *LibraryElementService) patchLibraryElement(c context.Context, signedInU | |||
| 				ConnectedDashboards: elementInDB.ConnectedDashboards, | ||||
| 				Created:             libraryElement.Created, | ||||
| 				Updated:             libraryElement.Updated, | ||||
| 				CreatedBy: LibraryElementDTOMetaUser{ | ||||
| 					ID:        elementInDB.CreatedBy, | ||||
| 				CreatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 					Id:        elementInDB.CreatedBy, | ||||
| 					Name:      elementInDB.CreatedByName, | ||||
| 					AvatarURL: dtos.GetGravatarUrl(elementInDB.CreatedByEmail), | ||||
| 					AvatarUrl: dtos.GetGravatarUrl(elementInDB.CreatedByEmail), | ||||
| 				}, | ||||
| 				UpdatedBy: LibraryElementDTOMetaUser{ | ||||
| 					ID:        libraryElement.UpdatedBy, | ||||
| 				UpdatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 					Id:        libraryElement.UpdatedBy, | ||||
| 					Name:      signedInUser.Login, | ||||
| 					AvatarURL: dtos.GetGravatarUrl(signedInUser.Email), | ||||
| 					AvatarUrl: dtos.GetGravatarUrl(signedInUser.Email), | ||||
| 				}, | ||||
| 			}, | ||||
| 		} | ||||
|  | @ -589,10 +590,10 @@ func (l *LibraryElementService) getConnections(c context.Context, signedInUser * | |||
| 				ConnectionID:  connection.ConnectionID, | ||||
| 				ConnectionUID: connection.ConnectionUID, | ||||
| 				Created:       connection.Created, | ||||
| 				CreatedBy: LibraryElementDTOMetaUser{ | ||||
| 					ID:        connection.CreatedBy, | ||||
| 				CreatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 					Id:        connection.CreatedBy, | ||||
| 					Name:      connection.CreatedByName, | ||||
| 					AvatarURL: dtos.GetGravatarUrl(connection.CreatedByEmail), | ||||
| 					AvatarUrl: dtos.GetGravatarUrl(connection.CreatedByEmail), | ||||
| 				}, | ||||
| 			}) | ||||
| 		} | ||||
|  | @ -638,15 +639,15 @@ func (l *LibraryElementService) getElementsForDashboardID(c context.Context, das | |||
| 					ConnectedDashboards: element.ConnectedDashboards, | ||||
| 					Created:             element.Created, | ||||
| 					Updated:             element.Updated, | ||||
| 					CreatedBy: LibraryElementDTOMetaUser{ | ||||
| 						ID:        element.CreatedBy, | ||||
| 					CreatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 						Id:        element.CreatedBy, | ||||
| 						Name:      element.CreatedByName, | ||||
| 						AvatarURL: dtos.GetGravatarUrl(element.CreatedByEmail), | ||||
| 						AvatarUrl: dtos.GetGravatarUrl(element.CreatedByEmail), | ||||
| 					}, | ||||
| 					UpdatedBy: LibraryElementDTOMetaUser{ | ||||
| 						ID:        element.UpdatedBy, | ||||
| 					UpdatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 						Id:        element.UpdatedBy, | ||||
| 						Name:      element.UpdatedByName, | ||||
| 						AvatarURL: dtos.GetGravatarUrl(element.UpdatedByEmail), | ||||
| 						AvatarUrl: dtos.GetGravatarUrl(element.UpdatedByEmail), | ||||
| 					}, | ||||
| 				}, | ||||
| 			} | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ import ( | |||
| 	"github.com/google/go-cmp/cmp" | ||||
| 	"github.com/stretchr/testify/require" | ||||
| 
 | ||||
| 	"github.com/grafana/grafana/pkg/kinds/librarypanel" | ||||
| 	"github.com/grafana/grafana/pkg/models" | ||||
| 	"github.com/grafana/grafana/pkg/util" | ||||
| ) | ||||
|  | @ -45,15 +46,15 @@ func TestCreateLibraryElement(t *testing.T) { | |||
| 						ConnectedDashboards: 0, | ||||
| 						Created:             sc.initialResult.Result.Meta.Created, | ||||
| 						Updated:             sc.initialResult.Result.Meta.Updated, | ||||
| 						CreatedBy: LibraryElementDTOMetaUser{ | ||||
| 							ID:        1, | ||||
| 						CreatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 							Id:        1, | ||||
| 							Name:      "signed_in_user", | ||||
| 							AvatarURL: "/avatar/37524e1eb8b3e32850b57db0a19af93b", | ||||
| 							AvatarUrl: "/avatar/37524e1eb8b3e32850b57db0a19af93b", | ||||
| 						}, | ||||
| 						UpdatedBy: LibraryElementDTOMetaUser{ | ||||
| 							ID:        1, | ||||
| 						UpdatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 							Id:        1, | ||||
| 							Name:      "signed_in_user", | ||||
| 							AvatarURL: "/avatar/37524e1eb8b3e32850b57db0a19af93b", | ||||
| 							AvatarUrl: "/avatar/37524e1eb8b3e32850b57db0a19af93b", | ||||
| 						}, | ||||
| 					}, | ||||
| 				}, | ||||
|  | @ -94,15 +95,15 @@ func TestCreateLibraryElement(t *testing.T) { | |||
| 						ConnectedDashboards: 0, | ||||
| 						Created:             result.Result.Meta.Created, | ||||
| 						Updated:             result.Result.Meta.Updated, | ||||
| 						CreatedBy: LibraryElementDTOMetaUser{ | ||||
| 							ID:        1, | ||||
| 						CreatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 							Id:        1, | ||||
| 							Name:      "signed_in_user", | ||||
| 							AvatarURL: "/avatar/37524e1eb8b3e32850b57db0a19af93b", | ||||
| 							AvatarUrl: "/avatar/37524e1eb8b3e32850b57db0a19af93b", | ||||
| 						}, | ||||
| 						UpdatedBy: LibraryElementDTOMetaUser{ | ||||
| 							ID:        1, | ||||
| 						UpdatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 							Id:        1, | ||||
| 							Name:      "signed_in_user", | ||||
| 							AvatarURL: "/avatar/37524e1eb8b3e32850b57db0a19af93b", | ||||
| 							AvatarUrl: "/avatar/37524e1eb8b3e32850b57db0a19af93b", | ||||
| 						}, | ||||
| 					}, | ||||
| 				}, | ||||
|  | @ -169,15 +170,15 @@ func TestCreateLibraryElement(t *testing.T) { | |||
| 						ConnectedDashboards: 0, | ||||
| 						Created:             result.Result.Meta.Created, | ||||
| 						Updated:             result.Result.Meta.Updated, | ||||
| 						CreatedBy: LibraryElementDTOMetaUser{ | ||||
| 							ID:        1, | ||||
| 						CreatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 							Id:        1, | ||||
| 							Name:      "signed_in_user", | ||||
| 							AvatarURL: "/avatar/37524e1eb8b3e32850b57db0a19af93b", | ||||
| 							AvatarUrl: "/avatar/37524e1eb8b3e32850b57db0a19af93b", | ||||
| 						}, | ||||
| 						UpdatedBy: LibraryElementDTOMetaUser{ | ||||
| 							ID:        1, | ||||
| 						UpdatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 							Id:        1, | ||||
| 							Name:      "signed_in_user", | ||||
| 							AvatarURL: "/avatar/37524e1eb8b3e32850b57db0a19af93b", | ||||
| 							AvatarUrl: "/avatar/37524e1eb8b3e32850b57db0a19af93b", | ||||
| 						}, | ||||
| 					}, | ||||
| 				}, | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ import ( | |||
| 	"github.com/google/go-cmp/cmp" | ||||
| 	"github.com/stretchr/testify/require" | ||||
| 
 | ||||
| 	"github.com/grafana/grafana/pkg/kinds/librarypanel" | ||||
| 	"github.com/grafana/grafana/pkg/models" | ||||
| 	"github.com/grafana/grafana/pkg/services/org" | ||||
| 	"github.com/grafana/grafana/pkg/services/search" | ||||
|  | @ -81,15 +82,15 @@ func TestGetAllLibraryElements(t *testing.T) { | |||
| 								ConnectedDashboards: 0, | ||||
| 								Created:             result.Result.Elements[0].Meta.Created, | ||||
| 								Updated:             result.Result.Elements[0].Meta.Updated, | ||||
| 								CreatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								CreatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 								UpdatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								UpdatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 							}, | ||||
| 						}, | ||||
|  | @ -146,15 +147,15 @@ func TestGetAllLibraryElements(t *testing.T) { | |||
| 								ConnectedDashboards: 0, | ||||
| 								Created:             result.Result.Elements[0].Meta.Created, | ||||
| 								Updated:             result.Result.Elements[0].Meta.Updated, | ||||
| 								CreatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								CreatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 								UpdatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								UpdatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 							}, | ||||
| 						}, | ||||
|  | @ -208,15 +209,15 @@ func TestGetAllLibraryElements(t *testing.T) { | |||
| 								ConnectedDashboards: 0, | ||||
| 								Created:             result.Result.Elements[0].Meta.Created, | ||||
| 								Updated:             result.Result.Elements[0].Meta.Updated, | ||||
| 								CreatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								CreatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 								UpdatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								UpdatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 							}, | ||||
| 						}, | ||||
|  | @ -243,15 +244,15 @@ func TestGetAllLibraryElements(t *testing.T) { | |||
| 								ConnectedDashboards: 0, | ||||
| 								Created:             result.Result.Elements[1].Meta.Created, | ||||
| 								Updated:             result.Result.Elements[1].Meta.Updated, | ||||
| 								CreatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								CreatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 								UpdatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								UpdatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 							}, | ||||
| 						}, | ||||
|  | @ -308,15 +309,15 @@ func TestGetAllLibraryElements(t *testing.T) { | |||
| 								ConnectedDashboards: 0, | ||||
| 								Created:             result.Result.Elements[0].Meta.Created, | ||||
| 								Updated:             result.Result.Elements[0].Meta.Updated, | ||||
| 								CreatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								CreatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 								UpdatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								UpdatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 							}, | ||||
| 						}, | ||||
|  | @ -343,15 +344,15 @@ func TestGetAllLibraryElements(t *testing.T) { | |||
| 								ConnectedDashboards: 0, | ||||
| 								Created:             result.Result.Elements[1].Meta.Created, | ||||
| 								Updated:             result.Result.Elements[1].Meta.Updated, | ||||
| 								CreatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								CreatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 								UpdatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								UpdatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 							}, | ||||
| 						}, | ||||
|  | @ -429,15 +430,15 @@ func TestGetAllLibraryElements(t *testing.T) { | |||
| 								ConnectedDashboards: 0, | ||||
| 								Created:             result.Result.Elements[0].Meta.Created, | ||||
| 								Updated:             result.Result.Elements[0].Meta.Updated, | ||||
| 								CreatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								CreatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 								UpdatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								UpdatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 							}, | ||||
| 						}, | ||||
|  | @ -464,15 +465,15 @@ func TestGetAllLibraryElements(t *testing.T) { | |||
| 								ConnectedDashboards: 0, | ||||
| 								Created:             result.Result.Elements[1].Meta.Created, | ||||
| 								Updated:             result.Result.Elements[1].Meta.Updated, | ||||
| 								CreatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								CreatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 								UpdatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								UpdatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 							}, | ||||
| 						}, | ||||
|  | @ -568,15 +569,15 @@ func TestGetAllLibraryElements(t *testing.T) { | |||
| 								ConnectedDashboards: 0, | ||||
| 								Created:             result.Result.Elements[0].Meta.Created, | ||||
| 								Updated:             result.Result.Elements[0].Meta.Updated, | ||||
| 								CreatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								CreatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 								UpdatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								UpdatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 							}, | ||||
| 						}, | ||||
|  | @ -665,15 +666,15 @@ func TestGetAllLibraryElements(t *testing.T) { | |||
| 								ConnectedDashboards: 0, | ||||
| 								Created:             result.Result.Elements[0].Meta.Created, | ||||
| 								Updated:             result.Result.Elements[0].Meta.Updated, | ||||
| 								CreatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								CreatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 								UpdatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								UpdatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 							}, | ||||
| 						}, | ||||
|  | @ -700,15 +701,15 @@ func TestGetAllLibraryElements(t *testing.T) { | |||
| 								ConnectedDashboards: 0, | ||||
| 								Created:             result.Result.Elements[1].Meta.Created, | ||||
| 								Updated:             result.Result.Elements[1].Meta.Updated, | ||||
| 								CreatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								CreatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 								UpdatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								UpdatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 							}, | ||||
| 						}, | ||||
|  | @ -765,15 +766,15 @@ func TestGetAllLibraryElements(t *testing.T) { | |||
| 								ConnectedDashboards: 0, | ||||
| 								Created:             result.Result.Elements[0].Meta.Created, | ||||
| 								Updated:             result.Result.Elements[0].Meta.Updated, | ||||
| 								CreatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								CreatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 								UpdatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								UpdatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 							}, | ||||
| 						}, | ||||
|  | @ -830,15 +831,15 @@ func TestGetAllLibraryElements(t *testing.T) { | |||
| 								ConnectedDashboards: 0, | ||||
| 								Created:             result.Result.Elements[0].Meta.Created, | ||||
| 								Updated:             result.Result.Elements[0].Meta.Updated, | ||||
| 								CreatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								CreatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 								UpdatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								UpdatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 							}, | ||||
| 						}, | ||||
|  | @ -896,15 +897,15 @@ func TestGetAllLibraryElements(t *testing.T) { | |||
| 								ConnectedDashboards: 0, | ||||
| 								Created:             result.Result.Elements[0].Meta.Created, | ||||
| 								Updated:             result.Result.Elements[0].Meta.Updated, | ||||
| 								CreatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								CreatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 								UpdatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								UpdatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 							}, | ||||
| 						}, | ||||
|  | @ -971,15 +972,15 @@ func TestGetAllLibraryElements(t *testing.T) { | |||
| 								ConnectedDashboards: 0, | ||||
| 								Created:             result.Result.Elements[0].Meta.Created, | ||||
| 								Updated:             result.Result.Elements[0].Meta.Updated, | ||||
| 								CreatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								CreatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 								UpdatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								UpdatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 							}, | ||||
| 						}, | ||||
|  | @ -1044,15 +1045,15 @@ func TestGetAllLibraryElements(t *testing.T) { | |||
| 								ConnectedDashboards: 0, | ||||
| 								Created:             result.Result.Elements[0].Meta.Created, | ||||
| 								Updated:             result.Result.Elements[0].Meta.Updated, | ||||
| 								CreatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								CreatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 								UpdatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								UpdatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 							}, | ||||
| 						}, | ||||
|  | @ -1079,15 +1080,15 @@ func TestGetAllLibraryElements(t *testing.T) { | |||
| 								ConnectedDashboards: 0, | ||||
| 								Created:             result.Result.Elements[1].Meta.Created, | ||||
| 								Updated:             result.Result.Elements[1].Meta.Updated, | ||||
| 								CreatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								CreatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 								UpdatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								UpdatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 							}, | ||||
| 						}, | ||||
|  | @ -1146,15 +1147,15 @@ func TestGetAllLibraryElements(t *testing.T) { | |||
| 								ConnectedDashboards: 0, | ||||
| 								Created:             result.Result.Elements[0].Meta.Created, | ||||
| 								Updated:             result.Result.Elements[0].Meta.Updated, | ||||
| 								CreatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								CreatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 								UpdatedBy: LibraryElementDTOMetaUser{ | ||||
| 									ID:        1, | ||||
| 								UpdatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 									Id:        1, | ||||
| 									Name:      userInDbName, | ||||
| 									AvatarURL: userInDbAvatar, | ||||
| 									AvatarUrl: userInDbAvatar, | ||||
| 								}, | ||||
| 							}, | ||||
| 						}, | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ import ( | |||
| 
 | ||||
| 	"github.com/google/go-cmp/cmp" | ||||
| 	"github.com/grafana/grafana/pkg/components/simplejson" | ||||
| 	"github.com/grafana/grafana/pkg/kinds/librarypanel" | ||||
| 	"github.com/grafana/grafana/pkg/services/dashboards" | ||||
| 	"github.com/grafana/grafana/pkg/services/org" | ||||
| 	"github.com/grafana/grafana/pkg/web" | ||||
|  | @ -54,15 +55,15 @@ func TestGetLibraryElement(t *testing.T) { | |||
| 							ConnectedDashboards: 0, | ||||
| 							Created:             res.Result.Meta.Created, | ||||
| 							Updated:             res.Result.Meta.Updated, | ||||
| 							CreatedBy: LibraryElementDTOMetaUser{ | ||||
| 								ID:        1, | ||||
| 							CreatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 								Id:        1, | ||||
| 								Name:      userInDbName, | ||||
| 								AvatarURL: userInDbAvatar, | ||||
| 								AvatarUrl: userInDbAvatar, | ||||
| 							}, | ||||
| 							UpdatedBy: LibraryElementDTOMetaUser{ | ||||
| 								ID:        1, | ||||
| 							UpdatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 								Id:        1, | ||||
| 								Name:      userInDbName, | ||||
| 								AvatarURL: userInDbAvatar, | ||||
| 								AvatarUrl: userInDbAvatar, | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
|  | @ -149,15 +150,15 @@ func TestGetLibraryElement(t *testing.T) { | |||
| 							ConnectedDashboards: 1, | ||||
| 							Created:             res.Result.Meta.Created, | ||||
| 							Updated:             res.Result.Meta.Updated, | ||||
| 							CreatedBy: LibraryElementDTOMetaUser{ | ||||
| 								ID:        1, | ||||
| 							CreatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 								Id:        1, | ||||
| 								Name:      userInDbName, | ||||
| 								AvatarURL: userInDbAvatar, | ||||
| 								AvatarUrl: userInDbAvatar, | ||||
| 							}, | ||||
| 							UpdatedBy: LibraryElementDTOMetaUser{ | ||||
| 								ID:        1, | ||||
| 							UpdatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 								Id:        1, | ||||
| 								Name:      userInDbName, | ||||
| 								AvatarURL: userInDbAvatar, | ||||
| 								AvatarUrl: userInDbAvatar, | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ package libraryelements | |||
| import ( | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"github.com/grafana/grafana/pkg/kinds/librarypanel" | ||||
| 	"github.com/grafana/grafana/pkg/util" | ||||
| 
 | ||||
| 	"github.com/google/go-cmp/cmp" | ||||
|  | @ -68,15 +69,15 @@ func TestPatchLibraryElement(t *testing.T) { | |||
| 						ConnectedDashboards: 0, | ||||
| 						Created:             sc.initialResult.Result.Meta.Created, | ||||
| 						Updated:             result.Result.Meta.Updated, | ||||
| 						CreatedBy: LibraryElementDTOMetaUser{ | ||||
| 							ID:        1, | ||||
| 						CreatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 							Id:        1, | ||||
| 							Name:      userInDbName, | ||||
| 							AvatarURL: userInDbAvatar, | ||||
| 							AvatarUrl: userInDbAvatar, | ||||
| 						}, | ||||
| 						UpdatedBy: LibraryElementDTOMetaUser{ | ||||
| 							ID:        1, | ||||
| 						UpdatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 							Id:        1, | ||||
| 							Name:      "signed_in_user", | ||||
| 							AvatarURL: "/avatar/37524e1eb8b3e32850b57db0a19af93b", | ||||
| 							AvatarUrl: "/avatar/37524e1eb8b3e32850b57db0a19af93b", | ||||
| 						}, | ||||
| 					}, | ||||
| 				}, | ||||
|  | @ -101,7 +102,7 @@ func TestPatchLibraryElement(t *testing.T) { | |||
| 			var result = validateAndUnMarshalResponse(t, resp) | ||||
| 			sc.initialResult.Result.FolderID = newFolder.ID | ||||
| 			sc.initialResult.Result.Meta.CreatedBy.Name = userInDbName | ||||
| 			sc.initialResult.Result.Meta.CreatedBy.AvatarURL = userInDbAvatar | ||||
| 			sc.initialResult.Result.Meta.CreatedBy.AvatarUrl = userInDbAvatar | ||||
| 			sc.initialResult.Result.Meta.Updated = result.Result.Meta.Updated | ||||
| 			sc.initialResult.Result.Version = 2 | ||||
| 			sc.initialResult.Result.Meta.FolderName = "NewFolder" | ||||
|  | @ -125,7 +126,7 @@ func TestPatchLibraryElement(t *testing.T) { | |||
| 			var result = validateAndUnMarshalResponse(t, resp) | ||||
| 			sc.initialResult.Result.Name = "New Name" | ||||
| 			sc.initialResult.Result.Meta.CreatedBy.Name = userInDbName | ||||
| 			sc.initialResult.Result.Meta.CreatedBy.AvatarURL = userInDbAvatar | ||||
| 			sc.initialResult.Result.Meta.CreatedBy.AvatarUrl = userInDbAvatar | ||||
| 			sc.initialResult.Result.Meta.Updated = result.Result.Meta.Updated | ||||
| 			sc.initialResult.Result.Model["title"] = "Text - Library Panel" | ||||
| 			sc.initialResult.Result.Version = 2 | ||||
|  | @ -148,7 +149,7 @@ func TestPatchLibraryElement(t *testing.T) { | |||
| 			var result = validateAndUnMarshalResponse(t, resp) | ||||
| 			sc.initialResult.Result.UID = cmd.UID | ||||
| 			sc.initialResult.Result.Meta.CreatedBy.Name = userInDbName | ||||
| 			sc.initialResult.Result.Meta.CreatedBy.AvatarURL = userInDbAvatar | ||||
| 			sc.initialResult.Result.Meta.CreatedBy.AvatarUrl = userInDbAvatar | ||||
| 			sc.initialResult.Result.Meta.Updated = result.Result.Meta.Updated | ||||
| 			sc.initialResult.Result.Model["title"] = "Text - Library Panel" | ||||
| 			sc.initialResult.Result.Version = 2 | ||||
|  | @ -225,7 +226,7 @@ func TestPatchLibraryElement(t *testing.T) { | |||
| 				"description": "New description", | ||||
| 			} | ||||
| 			sc.initialResult.Result.Meta.CreatedBy.Name = userInDbName | ||||
| 			sc.initialResult.Result.Meta.CreatedBy.AvatarURL = userInDbAvatar | ||||
| 			sc.initialResult.Result.Meta.CreatedBy.AvatarUrl = userInDbAvatar | ||||
| 			sc.initialResult.Result.Meta.Updated = result.Result.Meta.Updated | ||||
| 			sc.initialResult.Result.Version = 2 | ||||
| 			if diff := cmp.Diff(sc.initialResult.Result, result.Result, getCompareOptions()...); diff != "" { | ||||
|  | @ -252,7 +253,7 @@ func TestPatchLibraryElement(t *testing.T) { | |||
| 				"description": "New description", | ||||
| 			} | ||||
| 			sc.initialResult.Result.Meta.CreatedBy.Name = userInDbName | ||||
| 			sc.initialResult.Result.Meta.CreatedBy.AvatarURL = userInDbAvatar | ||||
| 			sc.initialResult.Result.Meta.CreatedBy.AvatarUrl = userInDbAvatar | ||||
| 			sc.initialResult.Result.Meta.Updated = result.Result.Meta.Updated | ||||
| 			sc.initialResult.Result.Version = 2 | ||||
| 			if diff := cmp.Diff(sc.initialResult.Result, result.Result, getCompareOptions()...); diff != "" { | ||||
|  | @ -279,7 +280,7 @@ func TestPatchLibraryElement(t *testing.T) { | |||
| 				"description": "A description", | ||||
| 			} | ||||
| 			sc.initialResult.Result.Meta.CreatedBy.Name = userInDbName | ||||
| 			sc.initialResult.Result.Meta.CreatedBy.AvatarURL = userInDbAvatar | ||||
| 			sc.initialResult.Result.Meta.CreatedBy.AvatarUrl = userInDbAvatar | ||||
| 			sc.initialResult.Result.Meta.Updated = result.Result.Meta.Updated | ||||
| 			sc.initialResult.Result.Version = 2 | ||||
| 			if diff := cmp.Diff(sc.initialResult.Result, result.Result, getCompareOptions()...); diff != "" { | ||||
|  | @ -295,9 +296,9 @@ func TestPatchLibraryElement(t *testing.T) { | |||
| 			sc.ctx.Req.Body = mockRequestBody(cmd) | ||||
| 			resp := sc.service.patchHandler(sc.reqContext) | ||||
| 			var result = validateAndUnMarshalResponse(t, resp) | ||||
| 			sc.initialResult.Result.Meta.UpdatedBy.ID = int64(2) | ||||
| 			sc.initialResult.Result.Meta.UpdatedBy.Id = int64(2) | ||||
| 			sc.initialResult.Result.Meta.CreatedBy.Name = userInDbName | ||||
| 			sc.initialResult.Result.Meta.CreatedBy.AvatarURL = userInDbAvatar | ||||
| 			sc.initialResult.Result.Meta.CreatedBy.AvatarUrl = userInDbAvatar | ||||
| 			sc.initialResult.Result.Meta.Updated = result.Result.Meta.Updated | ||||
| 			sc.initialResult.Result.Version = 2 | ||||
| 			if diff := cmp.Diff(sc.initialResult.Result, result.Result, getCompareOptions()...); diff != "" { | ||||
|  | @ -393,7 +394,7 @@ func TestPatchLibraryElement(t *testing.T) { | |||
| 				"description": "A description", | ||||
| 			} | ||||
| 			sc.initialResult.Result.Meta.CreatedBy.Name = userInDbName | ||||
| 			sc.initialResult.Result.Meta.CreatedBy.AvatarURL = userInDbAvatar | ||||
| 			sc.initialResult.Result.Meta.CreatedBy.AvatarUrl = userInDbAvatar | ||||
| 			sc.initialResult.Result.Meta.Updated = result.Result.Meta.Updated | ||||
| 			sc.initialResult.Result.Version = 2 | ||||
| 			if diff := cmp.Diff(sc.initialResult.Result, result.Result, getCompareOptions()...); diff != "" { | ||||
|  |  | |||
|  | @ -252,9 +252,9 @@ func TestLibraryElementPermissions(t *testing.T) { | |||
| 					resp := sc.service.createHandler(sc.reqContext) | ||||
| 					result := validateAndUnMarshalResponse(t, resp) | ||||
| 					result.Result.Meta.CreatedBy.Name = userInDbName | ||||
| 					result.Result.Meta.CreatedBy.AvatarURL = userInDbAvatar | ||||
| 					result.Result.Meta.CreatedBy.AvatarUrl = userInDbAvatar | ||||
| 					result.Result.Meta.UpdatedBy.Name = userInDbName | ||||
| 					result.Result.Meta.UpdatedBy.AvatarURL = userInDbAvatar | ||||
| 					result.Result.Meta.UpdatedBy.AvatarUrl = userInDbAvatar | ||||
| 					result.Result.Meta.FolderName = folder.Title | ||||
| 					result.Result.Meta.FolderUID = folder.UID | ||||
| 					results = append(results, result.Result) | ||||
|  | @ -275,9 +275,9 @@ func TestLibraryElementPermissions(t *testing.T) { | |||
| 				resp := sc.service.createHandler(sc.reqContext) | ||||
| 				result := validateAndUnMarshalResponse(t, resp) | ||||
| 				result.Result.Meta.CreatedBy.Name = userInDbName | ||||
| 				result.Result.Meta.CreatedBy.AvatarURL = userInDbAvatar | ||||
| 				result.Result.Meta.CreatedBy.AvatarUrl = userInDbAvatar | ||||
| 				result.Result.Meta.UpdatedBy.Name = userInDbName | ||||
| 				result.Result.Meta.UpdatedBy.AvatarURL = userInDbAvatar | ||||
| 				result.Result.Meta.UpdatedBy.AvatarUrl = userInDbAvatar | ||||
| 				result.Result.Meta.FolderName = "General" | ||||
| 				result.Result.Meta.FolderUID = "" | ||||
| 				sc.reqContext.SignedInUser.OrgRole = testCase.role | ||||
|  | @ -315,9 +315,9 @@ func TestLibraryElementPermissions(t *testing.T) { | |||
| 					resp := sc.service.createHandler(sc.reqContext) | ||||
| 					result := validateAndUnMarshalResponse(t, resp) | ||||
| 					result.Result.Meta.CreatedBy.Name = userInDbName | ||||
| 					result.Result.Meta.CreatedBy.AvatarURL = userInDbAvatar | ||||
| 					result.Result.Meta.CreatedBy.AvatarUrl = userInDbAvatar | ||||
| 					result.Result.Meta.UpdatedBy.Name = userInDbName | ||||
| 					result.Result.Meta.UpdatedBy.AvatarURL = userInDbAvatar | ||||
| 					result.Result.Meta.UpdatedBy.AvatarUrl = userInDbAvatar | ||||
| 					result.Result.Meta.FolderName = folder.Title | ||||
| 					result.Result.Meta.FolderUID = folder.UID | ||||
| 					results = append(results, result.Result) | ||||
|  | @ -367,9 +367,9 @@ func TestLibraryElementPermissions(t *testing.T) { | |||
| 				resp := sc.service.createHandler(sc.reqContext) | ||||
| 				result := validateAndUnMarshalResponse(t, resp) | ||||
| 				result.Result.Meta.CreatedBy.Name = userInDbName | ||||
| 				result.Result.Meta.CreatedBy.AvatarURL = userInDbAvatar | ||||
| 				result.Result.Meta.CreatedBy.AvatarUrl = userInDbAvatar | ||||
| 				result.Result.Meta.UpdatedBy.Name = userInDbName | ||||
| 				result.Result.Meta.UpdatedBy.AvatarURL = userInDbAvatar | ||||
| 				result.Result.Meta.UpdatedBy.AvatarUrl = userInDbAvatar | ||||
| 				result.Result.Meta.FolderName = "General" | ||||
| 				sc.reqContext.SignedInUser.OrgRole = testCase.role | ||||
| 
 | ||||
|  |  | |||
|  | @ -19,6 +19,7 @@ import ( | |||
| 	"github.com/grafana/grafana/pkg/infra/db" | ||||
| 	"github.com/grafana/grafana/pkg/infra/db/dbtest" | ||||
| 	"github.com/grafana/grafana/pkg/infra/tracing" | ||||
| 	"github.com/grafana/grafana/pkg/kinds/librarypanel" | ||||
| 	"github.com/grafana/grafana/pkg/models" | ||||
| 	acmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock" | ||||
| 	"github.com/grafana/grafana/pkg/services/alerting" | ||||
|  | @ -165,10 +166,10 @@ func TestGetLibraryPanelConnections(t *testing.T) { | |||
| 							ConnectionID:  dashInDB.ID, | ||||
| 							ConnectionUID: dashInDB.UID, | ||||
| 							Created:       res.Result[0].Created, | ||||
| 							CreatedBy: LibraryElementDTOMetaUser{ | ||||
| 								ID:        1, | ||||
| 							CreatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 								Id:        1, | ||||
| 								Name:      userInDbName, | ||||
| 								AvatarURL: userInDbAvatar, | ||||
| 								AvatarUrl: userInDbAvatar, | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
|  |  | |||
|  | @ -4,6 +4,8 @@ import ( | |||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/grafana/grafana/pkg/kinds/librarypanel" | ||||
| ) | ||||
| 
 | ||||
| type LibraryConnectionKind int | ||||
|  | @ -93,15 +95,8 @@ type LibraryElementDTOMeta struct { | |||
| 	Created time.Time `json:"created"` | ||||
| 	Updated time.Time `json:"updated"` | ||||
| 
 | ||||
| 	CreatedBy LibraryElementDTOMetaUser `json:"createdBy"` | ||||
| 	UpdatedBy LibraryElementDTOMetaUser `json:"updatedBy"` | ||||
| } | ||||
| 
 | ||||
| // LibraryElementDTOMetaUser is the meta information for user that creates/changes the library element.
 | ||||
| type LibraryElementDTOMetaUser struct { | ||||
| 	ID        int64  `json:"id"` | ||||
| 	Name      string `json:"name"` | ||||
| 	AvatarURL string `json:"avatarUrl"` | ||||
| 	CreatedBy librarypanel.LibraryElementDTOMetaUser `json:"createdBy"` | ||||
| 	UpdatedBy librarypanel.LibraryElementDTOMetaUser `json:"updatedBy"` | ||||
| } | ||||
| 
 | ||||
| // libraryElementConnection is the model for library element connections.
 | ||||
|  | @ -135,7 +130,7 @@ type LibraryElementConnectionDTO struct { | |||
| 	ConnectionID  int64                                  `json:"connectionId"` | ||||
| 	ConnectionUID string                                 `json:"connectionUid"` | ||||
| 	Created       time.Time                              `json:"created"` | ||||
| 	CreatedBy     LibraryElementDTOMetaUser `json:"createdBy"` | ||||
| 	CreatedBy     librarypanel.LibraryElementDTOMetaUser `json:"createdBy"` | ||||
| } | ||||
| 
 | ||||
| var ( | ||||
|  |  | |||
|  | @ -18,6 +18,7 @@ import ( | |||
| 	"github.com/grafana/grafana/pkg/infra/db/dbtest" | ||||
| 	"github.com/grafana/grafana/pkg/infra/slugify" | ||||
| 	"github.com/grafana/grafana/pkg/infra/tracing" | ||||
| 	"github.com/grafana/grafana/pkg/kinds/librarypanel" | ||||
| 	"github.com/grafana/grafana/pkg/models" | ||||
| 	acmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock" | ||||
| 	"github.com/grafana/grafana/pkg/services/alerting" | ||||
|  | @ -634,15 +635,15 @@ func toLibraryElement(t *testing.T, res libraryelements.LibraryElementDTO) libra | |||
| 			ConnectedDashboards: res.Meta.ConnectedDashboards, | ||||
| 			Created:             res.Meta.Created, | ||||
| 			Updated:             res.Meta.Updated, | ||||
| 			CreatedBy: libraryelements.LibraryElementDTOMetaUser{ | ||||
| 				ID:        res.Meta.CreatedBy.ID, | ||||
| 			CreatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 				Id:        res.Meta.CreatedBy.Id, | ||||
| 				Name:      res.Meta.CreatedBy.Name, | ||||
| 				AvatarURL: res.Meta.CreatedBy.AvatarURL, | ||||
| 				AvatarUrl: res.Meta.CreatedBy.AvatarUrl, | ||||
| 			}, | ||||
| 			UpdatedBy: libraryelements.LibraryElementDTOMetaUser{ | ||||
| 				ID:        res.Meta.UpdatedBy.ID, | ||||
| 			UpdatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 				Id:        res.Meta.UpdatedBy.Id, | ||||
| 				Name:      res.Meta.UpdatedBy.Name, | ||||
| 				AvatarURL: res.Meta.UpdatedBy.AvatarURL, | ||||
| 				AvatarUrl: res.Meta.UpdatedBy.AvatarUrl, | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
|  | @ -672,15 +673,15 @@ func getExpected(t *testing.T, res libraryelements.LibraryElementDTO, UID string | |||
| 			ConnectedDashboards: 0, | ||||
| 			Created:             res.Meta.Created, | ||||
| 			Updated:             res.Meta.Updated, | ||||
| 			CreatedBy: libraryelements.LibraryElementDTOMetaUser{ | ||||
| 				ID:        1, | ||||
| 			CreatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 				Id:        1, | ||||
| 				Name:      userInDbName, | ||||
| 				AvatarURL: userInDbAvatar, | ||||
| 				AvatarUrl: userInDbAvatar, | ||||
| 			}, | ||||
| 			UpdatedBy: libraryelements.LibraryElementDTOMetaUser{ | ||||
| 				ID:        1, | ||||
| 			UpdatedBy: librarypanel.LibraryElementDTOMetaUser{ | ||||
| 				Id:        1, | ||||
| 				Name:      userInDbName, | ||||
| 				AvatarURL: userInDbAvatar, | ||||
| 				AvatarUrl: userInDbAvatar, | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
|  |  | |||
|  | @ -113,7 +113,7 @@ export const AddPanelWidgetUnconnected = ({ panel, dashboard }: Props) => { | |||
|   const onAddLibraryPanel = (panelInfo: LibraryElementDTO) => { | ||||
|     const { gridPos } = panel; | ||||
| 
 | ||||
|     const newPanel: PanelModel = { | ||||
|     const newPanel = { | ||||
|       ...panelInfo.model, | ||||
|       gridPos, | ||||
|       libraryPanel: panelInfo, | ||||
|  |  | |||
|  | @ -177,7 +177,7 @@ export class DashboardExporter { | |||
|           model = libPanel.model; | ||||
|         } | ||||
| 
 | ||||
|         const { gridPos, id, ...rest } = model; | ||||
|         const { gridPos, id, ...rest } = model as any; | ||||
|         if (!libraryPanels.has(uid)) { | ||||
|           libraryPanels.set(uid, { name, uid, kind: LibraryElementKind.Panel, model: rest }); | ||||
|         } | ||||
|  |  | |||
|  | @ -23,6 +23,7 @@ import { | |||
|   restoreCustomOverrideRules, | ||||
| } from '@grafana/data'; | ||||
| import { getTemplateSrv, RefreshEvent } from '@grafana/runtime'; | ||||
| import { LibraryPanel, LibraryPanelRef } from '@grafana/schema'; | ||||
| import config from 'app/core/config'; | ||||
| import { safeStringifyValue } from 'app/core/utils/explore'; | ||||
| import { getNextRefIdChar } from 'app/core/utils/query'; | ||||
|  | @ -35,7 +36,6 @@ import { | |||
|   RenderEvent, | ||||
| } from 'app/types/events'; | ||||
| 
 | ||||
| import { LibraryElementDTO, LibraryPanelRef } from '../../library-panels/types'; | ||||
| import { PanelQueryRunner } from '../../query/state/PanelQueryRunner'; | ||||
| import { getVariablesUrlParams } from '../../variables/getAllVariableValuesForUrl'; | ||||
| import { getTimeSrv } from '../services/TimeSrv'; | ||||
|  | @ -172,7 +172,7 @@ export class PanelModel implements DataConfigSource, IPanelModel { | |||
|   links?: DataLink[]; | ||||
|   declare transparent: boolean; | ||||
| 
 | ||||
|   libraryPanel?: LibraryPanelRef | LibraryElementDTO; | ||||
|   libraryPanel?: LibraryPanelRef | LibraryPanel; | ||||
| 
 | ||||
|   autoMigrateFrom?: string; | ||||
| 
 | ||||
|  | @ -680,7 +680,7 @@ export class PanelModel implements DataConfigSource, IPanelModel { | |||
|     return this.replaceVariables(this.title, undefined, 'text'); | ||||
|   } | ||||
| 
 | ||||
|   initLibraryPanel(libPanel: LibraryElementDTO) { | ||||
|   initLibraryPanel(libPanel: LibraryPanel) { | ||||
|     for (const [key, val] of Object.entries(libPanel.model)) { | ||||
|       switch (key) { | ||||
|         case 'id': | ||||
|  |  | |||
|  | @ -62,7 +62,7 @@ interface FolderLinkProps { | |||
| function FolderLink({ libraryPanel }: FolderLinkProps): ReactElement | null { | ||||
|   const styles = useStyles2(getStyles); | ||||
| 
 | ||||
|   if (!libraryPanel.meta.folderUid && !libraryPanel.meta.folderName) { | ||||
|   if (!libraryPanel.meta?.folderUid && !libraryPanel.meta?.folderName) { | ||||
|     return null; | ||||
|   } | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,11 +4,12 @@ import userEvent from '@testing-library/user-event'; | |||
| import React from 'react'; | ||||
| 
 | ||||
| import { PanelPluginMeta, PluginType } from '@grafana/data'; | ||||
| import { Panel } from '@grafana/schema'; | ||||
| 
 | ||||
| import { backendSrv } from '../../../../core/services/backend_srv'; | ||||
| import * as panelUtils from '../../../panel/state/util'; | ||||
| import * as api from '../../state/api'; | ||||
| import { LibraryElementKind, LibraryElementsSearchResult } from '../../types'; | ||||
| import { LibraryElementsSearchResult } from '../../types'; | ||||
| 
 | ||||
| import { LibraryPanelsSearch, LibraryPanelsSearchProps } from './LibraryPanelsSearch'; | ||||
| 
 | ||||
|  | @ -182,15 +183,12 @@ describe('LibraryPanelsSearch', () => { | |||
|           { | ||||
|             elements: [ | ||||
|               { | ||||
|                 id: 1, | ||||
|                 name: 'Library Panel Name', | ||||
|                 kind: LibraryElementKind.Panel, | ||||
|                 uid: 'uid', | ||||
|                 description: 'Library Panel Description', | ||||
|                 folderUid: '', | ||||
|                 model: { type: 'timeseries', title: 'A title' }, | ||||
|                 model: { type: 'timeseries', title: 'A title' } as Panel, | ||||
|                 type: 'timeseries', | ||||
|                 orgId: 1, | ||||
|                 version: 1, | ||||
|                 meta: { | ||||
|                   folderName: 'General', | ||||
|  | @ -237,15 +235,12 @@ describe('LibraryPanelsSearch', () => { | |||
|           perPage: 40, | ||||
|           elements: [ | ||||
|             { | ||||
|               id: 1, | ||||
|               name: 'Library Panel Name', | ||||
|               kind: LibraryElementKind.Panel, | ||||
|               uid: 'uid', | ||||
|               description: 'Library Panel Description', | ||||
|               folderUid: '', | ||||
|               model: { type: 'timeseries', title: 'A title' }, | ||||
|               model: { type: 'timeseries', title: 'A title' } as Panel, | ||||
|               type: 'timeseries', | ||||
|               orgId: 1, | ||||
|               version: 1, | ||||
|               meta: { | ||||
|                 folderName: 'General', | ||||
|  | @ -281,15 +276,12 @@ describe('LibraryPanelsSearch', () => { | |||
|           perPage: 40, | ||||
|           elements: [ | ||||
|             { | ||||
|               id: 1, | ||||
|               name: 'Library Panel Name', | ||||
|               kind: LibraryElementKind.Panel, | ||||
|               uid: 'uid', | ||||
|               description: 'Library Panel Description', | ||||
|               folderUid: '', | ||||
|               model: { type: 'timeseries', title: 'A title' }, | ||||
|               model: { type: 'timeseries', title: 'A title' } as Panel, | ||||
|               type: 'timeseries', | ||||
|               orgId: 1, | ||||
|               version: 1, | ||||
|               meta: { | ||||
|                 folderName: 'General', | ||||
|  |  | |||
|  | @ -1,7 +1,8 @@ | |||
| import { LoadingState } from '@grafana/data'; | ||||
| import { Panel } from '@grafana/schema'; | ||||
| 
 | ||||
| import { reducerTester } from '../../../../../test/core/redux/reducerTester'; | ||||
| import { LibraryElementDTO, LibraryElementKind } from '../../types'; | ||||
| import { LibraryElementDTO } from '../../types'; | ||||
| 
 | ||||
| import { | ||||
|   changePage, | ||||
|  | @ -93,7 +94,6 @@ function getLibraryPanelMocks(count: number): LibraryElementDTO[] { | |||
|     mocks.push( | ||||
|       mockLibraryPanel({ | ||||
|         uid: i.toString(10), | ||||
|         id: i, | ||||
|         name: `Test Panel ${i}`, | ||||
|       }) | ||||
|     ); | ||||
|  | @ -104,11 +104,9 @@ function getLibraryPanelMocks(count: number): LibraryElementDTO[] { | |||
| 
 | ||||
| function mockLibraryPanel({ | ||||
|   uid = '1', | ||||
|   id = 1, | ||||
|   orgId = 1, | ||||
|   folderUid = '', | ||||
|   name = 'Test Panel', | ||||
|   model = { type: 'text', title: 'Test Panel' }, | ||||
|   model = { type: 'text', title: 'Test Panel' } as Panel, | ||||
|   meta = { | ||||
|     folderName: 'General', | ||||
|     folderUid: '', | ||||
|  | @ -124,11 +122,8 @@ function mockLibraryPanel({ | |||
| }: Partial<LibraryElementDTO> = {}): LibraryElementDTO { | ||||
|   return { | ||||
|     uid, | ||||
|     id, | ||||
|     orgId, | ||||
|     folderUid, | ||||
|     name, | ||||
|     kind: LibraryElementKind.Panel, | ||||
|     model, | ||||
|     version, | ||||
|     meta, | ||||
|  |  | |||
|  | @ -64,8 +64,8 @@ export const SaveLibraryPanelModal = ({ | |||
|         <p className={styles.textInfo}> | ||||
|           {'This update will affect '} | ||||
|           <strong> | ||||
|             {panel.libraryPanel.meta.connectedDashboards}{' '} | ||||
|             {panel.libraryPanel.meta.connectedDashboards === 1 ? 'dashboard' : 'dashboards'}. | ||||
|             {panel.libraryPanel.meta?.connectedDashboards}{' '} | ||||
|             {panel.libraryPanel.meta?.connectedDashboards === 1 ? 'dashboard' : 'dashboards'}. | ||||
|           </strong> | ||||
|           The following dashboards using the panel will be affected: | ||||
|         </p> | ||||
|  |  | |||
|  | @ -1,17 +1,22 @@ | |||
| import { AnyAction } from '@reduxjs/toolkit'; | ||||
| import { Dispatch } from 'react'; | ||||
| 
 | ||||
| import { LibraryPanel } from '@grafana/schema'; | ||||
| import { LibraryElementDTOMetaUser } from '@grafana/schema/src/raw/librarypanel/x/librarypanel_types.gen'; | ||||
| 
 | ||||
| import { PanelModel } from '../dashboard/state'; | ||||
| 
 | ||||
| export enum LibraryElementKind { | ||||
|   Panel = 1, | ||||
|   Variable, | ||||
| } | ||||
| 
 | ||||
| export enum LibraryElementConnectionKind { | ||||
|   Dashboard = 1, | ||||
| } | ||||
| 
 | ||||
| /** @deprecated use LibraryPanel */ | ||||
| export interface LibraryElementDTO extends LibraryPanel {} | ||||
| 
 | ||||
| export interface LibraryElementConnectionDTO { | ||||
|   id: number; | ||||
|   kind: LibraryElementConnectionKind; | ||||
|  | @ -24,48 +29,13 @@ export interface LibraryElementConnectionDTO { | |||
| 
 | ||||
| export interface LibraryElementsSearchResult { | ||||
|   totalCount: number; | ||||
|   elements: LibraryElementDTO[]; | ||||
|   elements: LibraryPanel[]; | ||||
|   perPage: number; | ||||
|   page: number; | ||||
| } | ||||
| 
 | ||||
| export interface LibraryElementDTO { | ||||
|   id: number; | ||||
|   orgId: number; | ||||
|   folderUid: string; | ||||
|   uid: string; | ||||
|   name: string; | ||||
|   kind: LibraryElementKind; | ||||
|   type: string; | ||||
|   description: string; | ||||
|   model: any; | ||||
|   version: number; | ||||
|   meta: LibraryElementDTOMeta; | ||||
| } | ||||
| 
 | ||||
| export interface LibraryElementDTOMeta { | ||||
|   folderName: string; | ||||
|   folderUid: string; | ||||
|   connectedDashboards: number; | ||||
|   created: string; | ||||
|   updated: string; | ||||
|   createdBy: LibraryElementDTOMetaUser; | ||||
|   updatedBy: LibraryElementDTOMetaUser; | ||||
| } | ||||
| 
 | ||||
| export interface LibraryElementDTOMetaUser { | ||||
|   id: number; | ||||
|   name: string; | ||||
|   avatarUrl: string; | ||||
| } | ||||
| 
 | ||||
| export interface LibraryPanelRef { | ||||
|   name: string; | ||||
|   uid: string; | ||||
| } | ||||
| 
 | ||||
| export interface PanelModelWithLibraryPanel extends PanelModel { | ||||
|   libraryPanel: LibraryElementDTO; | ||||
|   libraryPanel: LibraryPanel; | ||||
| } | ||||
| 
 | ||||
| export type DispatchResult = (dispatch: Dispatch<AnyAction>) => void; | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ import { css } from '@emotion/css'; | |||
| import React, { ReactElement } from 'react'; | ||||
| 
 | ||||
| import { GrafanaTheme2 } from '@grafana/data'; | ||||
| import { LibraryPanel } from '@grafana/schema'; | ||||
| import { Field, useStyles2 } from '@grafana/ui'; | ||||
| 
 | ||||
| import { LibraryPanelCard } from '../../library-panels/components/LibraryPanelCard/LibraryPanelCard'; | ||||
|  | @ -36,9 +37,10 @@ export function ImportDashboardLibraryPanelsList({ | |||
|               input.state === LibraryPanelInputState.New | ||||
|                 ? { ...input.model, meta: { ...input.model.meta, folderName: folderName ?? 'General' } } | ||||
|                 : { ...input.model }; | ||||
| 
 | ||||
|             return ( | ||||
|               <div className={styles.item} key={libraryPanelIndex}> | ||||
|                 <LibraryPanelCard libraryPanel={libraryPanel} onClick={() => undefined} /> | ||||
|                 <LibraryPanelCard libraryPanel={libraryPanel as LibraryPanel} onClick={() => undefined} /> | ||||
|               </div> | ||||
|             ); | ||||
|           })} | ||||
|  |  | |||
|  | @ -101,8 +101,6 @@ function processElements(dashboardJson?: { __elements?: Record<string, LibraryEl | |||
|           uid, | ||||
|           name, | ||||
|           version: 0, | ||||
|           meta: {}, | ||||
|           id: 0, | ||||
|           type, | ||||
|           kind: LibraryElementKind.Panel, | ||||
|           description, | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue