Schema: Add schema for library panels (#62169)

This commit is contained in:
Ryan McKinley 2023-01-29 20:14:12 -08:00 committed by GitHub
parent 13159d03ba
commit 0d2a786816
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 724 additions and 303 deletions

View File

@ -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"]
],

View File

@ -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' &#124; 'id' &#124; '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 |
|----------|------|----------|-------------|

View File

@ -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)

View File

@ -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)
},
]
},
]

View File

@ -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,

View File

@ -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;

View File

@ -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;
}

View File

@ -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'>;
}

View File

@ -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
@ -490,7 +496,8 @@ type Panel struct {
// TODO docs
// TODO tighter constraint
Interval *string `json:"interval,omitempty"`
Interval *string `json:"interval,omitempty"`
LibraryPanel *LibraryPanelRef `json:"libraryPanel,omitempty"`
// Panel links.
// TODO fill this out - seems there are a couple variants?

View File

@ -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
}

View File

@ -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"`
}

View File

@ -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",

View File

@ -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))

View File

@ -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),
},
},
}

View File

@ -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",
},
},
},

View File

@ -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,
},
},
},

View File

@ -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,
},
},
},

View File

@ -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 != "" {

View File

@ -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

View File

@ -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,
},
},
},

View File

@ -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.
@ -129,13 +124,13 @@ type libraryElementConnectionWithMeta struct {
// LibraryElementConnectionDTO is the frontend DTO for element connections.
type LibraryElementConnectionDTO struct {
ID int64 `json:"id"`
Kind int64 `json:"kind"`
ElementID int64 `json:"elementId"`
ConnectionID int64 `json:"connectionId"`
ConnectionUID string `json:"connectionUid"`
Created time.Time `json:"created"`
CreatedBy LibraryElementDTOMetaUser `json:"createdBy"`
ID int64 `json:"id"`
Kind int64 `json:"kind"`
ElementID int64 `json:"elementId"`
ConnectionID int64 `json:"connectionId"`
ConnectionUID string `json:"connectionUid"`
Created time.Time `json:"created"`
CreatedBy librarypanel.LibraryElementDTOMetaUser `json:"createdBy"`
}
var (

View File

@ -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,
},
},
}

View File

@ -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,

View File

@ -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 });
}

View File

@ -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':

View File

@ -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;
}

View File

@ -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',

View File

@ -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,

View File

@ -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>

View File

@ -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;

View File

@ -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>
);
})}

View File

@ -101,8 +101,6 @@ function processElements(dashboardJson?: { __elements?: Record<string, LibraryEl
uid,
name,
version: 0,
meta: {},
id: 0,
type,
kind: LibraryElementKind.Panel,
description,