mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Playlist: Add an api wrapper for playlist requests (#76308)
This commit is contained in:
parent
bf7fae4bd3
commit
6983af3a70
@ -76,6 +76,7 @@ describe('PlaylistEditPage', () => {
|
|||||||
fireEvent.submit(screen.getByRole('button', { name: /save/i }));
|
fireEvent.submit(screen.getByRole('button', { name: /save/i }));
|
||||||
await waitFor(() => expect(putMock).toHaveBeenCalledTimes(1));
|
await waitFor(() => expect(putMock).toHaveBeenCalledTimes(1));
|
||||||
expect(putMock).toHaveBeenCalledWith('/api/playlists/foo', {
|
expect(putMock).toHaveBeenCalledWith('/api/playlists/foo', {
|
||||||
|
uid: 'foo',
|
||||||
name: 'A Name',
|
name: 'A Name',
|
||||||
interval: '10s',
|
interval: '10s',
|
||||||
items: [{ title: 'First item', type: 'dashboard_by_uid', order: 1, value: '1' }],
|
items: [{ title: 'First item', type: 'dashboard_by_uid', order: 1, value: '1' }],
|
||||||
|
@ -8,11 +8,9 @@ import { t, Trans } from 'app/core/internationalization';
|
|||||||
import { GrafanaRouteComponentProps } from 'app/core/navigation/types';
|
import { GrafanaRouteComponentProps } from 'app/core/navigation/types';
|
||||||
|
|
||||||
import { PlaylistForm } from './PlaylistForm';
|
import { PlaylistForm } from './PlaylistForm';
|
||||||
import { playlistAPI, updatePlaylist } from './api';
|
import { getPlaylistAPI } from './api';
|
||||||
import { Playlist } from './types';
|
import { Playlist } from './types';
|
||||||
|
|
||||||
const { getPlaylist } = playlistAPI;
|
|
||||||
|
|
||||||
export interface RouteParams {
|
export interface RouteParams {
|
||||||
uid: string;
|
uid: string;
|
||||||
}
|
}
|
||||||
@ -20,10 +18,11 @@ export interface RouteParams {
|
|||||||
interface Props extends GrafanaRouteComponentProps<RouteParams> {}
|
interface Props extends GrafanaRouteComponentProps<RouteParams> {}
|
||||||
|
|
||||||
export const PlaylistEditPage = ({ match }: Props) => {
|
export const PlaylistEditPage = ({ match }: Props) => {
|
||||||
const playlist = useAsync(() => getPlaylist(match.params.uid), [match.params]);
|
const api = getPlaylistAPI();
|
||||||
|
const playlist = useAsync(() => api.getPlaylist(match.params.uid), [match.params]);
|
||||||
|
|
||||||
const onSubmit = async (playlist: Playlist) => {
|
const onSubmit = async (playlist: Playlist) => {
|
||||||
await updatePlaylist(match.params.uid, playlist);
|
await api.updatePlaylist(playlist);
|
||||||
locationService.push('/playlists');
|
locationService.push('/playlists');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -108,6 +108,7 @@ describe('PlaylistForm', () => {
|
|||||||
await userEvent.click(screen.getByRole('button', { name: /save/i }));
|
await userEvent.click(screen.getByRole('button', { name: /save/i }));
|
||||||
expect(onSubmitMock).toHaveBeenCalledTimes(1);
|
expect(onSubmitMock).toHaveBeenCalledTimes(1);
|
||||||
expect(onSubmitMock).toHaveBeenCalledWith({
|
expect(onSubmitMock).toHaveBeenCalledWith({
|
||||||
|
uid: 'foo',
|
||||||
name: 'A test playlist',
|
name: 'A test playlist',
|
||||||
interval: '10m',
|
interval: '10m',
|
||||||
items: [
|
items: [
|
||||||
|
@ -29,7 +29,7 @@ export const PlaylistForm = ({ onSubmit, playlist }: Props) => {
|
|||||||
|
|
||||||
const doSubmit = (list: Playlist) => {
|
const doSubmit = (list: Playlist) => {
|
||||||
setSaving(true);
|
setSaving(true);
|
||||||
onSubmit({ ...list, items });
|
onSubmit({ ...list, items, uid: playlist.uid });
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -60,6 +60,7 @@ describe('PlaylistNewPage', () => {
|
|||||||
await waitFor(() => expect(backendSrvMock).toHaveBeenCalledTimes(1));
|
await waitFor(() => expect(backendSrvMock).toHaveBeenCalledTimes(1));
|
||||||
expect(backendSrvMock).toHaveBeenCalledWith('/api/playlists', {
|
expect(backendSrvMock).toHaveBeenCalledWith('/api/playlists', {
|
||||||
name: 'A new name',
|
name: 'A new name',
|
||||||
|
uid: '',
|
||||||
interval: '5m',
|
interval: '5m',
|
||||||
items: [],
|
items: [],
|
||||||
});
|
});
|
||||||
|
@ -5,14 +5,14 @@ import { locationService } from '@grafana/runtime';
|
|||||||
import { Page } from 'app/core/components/Page/Page';
|
import { Page } from 'app/core/components/Page/Page';
|
||||||
|
|
||||||
import { PlaylistForm } from './PlaylistForm';
|
import { PlaylistForm } from './PlaylistForm';
|
||||||
import { createPlaylist, getDefaultPlaylist } from './api';
|
import { getPlaylistAPI, getDefaultPlaylist } from './api';
|
||||||
import { Playlist } from './types';
|
import { Playlist } from './types';
|
||||||
|
|
||||||
export const PlaylistNewPage = () => {
|
export const PlaylistNewPage = () => {
|
||||||
const [playlist] = useState<Playlist>(getDefaultPlaylist());
|
const [playlist] = useState<Playlist>(getDefaultPlaylist());
|
||||||
|
|
||||||
const onSubmit = async (playlist: Playlist) => {
|
const onSubmit = async (playlist: Playlist) => {
|
||||||
await createPlaylist(playlist);
|
await getPlaylistAPI().createPlaylist(playlist);
|
||||||
locationService.push('/playlists');
|
locationService.push('/playlists');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -11,15 +11,14 @@ import { contextSrv } from 'app/core/services/context_srv';
|
|||||||
import { EmptyQueryListBanner } from './EmptyQueryListBanner';
|
import { EmptyQueryListBanner } from './EmptyQueryListBanner';
|
||||||
import { PlaylistPageList } from './PlaylistPageList';
|
import { PlaylistPageList } from './PlaylistPageList';
|
||||||
import { StartModal } from './StartModal';
|
import { StartModal } from './StartModal';
|
||||||
import { deletePlaylist, searchPlaylists, playlistAPI } from './api';
|
import { getPlaylistAPI, searchPlaylists } from './api';
|
||||||
import { Playlist } from './types';
|
import { Playlist } from './types';
|
||||||
|
|
||||||
const { getAllPlaylist } = playlistAPI;
|
|
||||||
|
|
||||||
export const PlaylistPage = () => {
|
export const PlaylistPage = () => {
|
||||||
|
const api = getPlaylistAPI();
|
||||||
const [forcePlaylistsFetch, setForcePlaylistsFetch] = useState(0);
|
const [forcePlaylistsFetch, setForcePlaylistsFetch] = useState(0);
|
||||||
const [searchQuery, setSearchQuery] = useState('');
|
const [searchQuery, setSearchQuery] = useState('');
|
||||||
const allPlaylists = useAsync(() => getAllPlaylist(), [forcePlaylistsFetch]);
|
const allPlaylists = useAsync(() => api.getAllPlaylist(), [forcePlaylistsFetch]);
|
||||||
const playlists = useMemo(() => searchPlaylists(allPlaylists.value ?? [], searchQuery), [searchQuery, allPlaylists]);
|
const playlists = useMemo(() => searchPlaylists(allPlaylists.value ?? [], searchQuery), [searchQuery, allPlaylists]);
|
||||||
|
|
||||||
const [startPlaylist, setStartPlaylist] = useState<Playlist | undefined>();
|
const [startPlaylist, setStartPlaylist] = useState<Playlist | undefined>();
|
||||||
@ -31,7 +30,7 @@ export const PlaylistPage = () => {
|
|||||||
if (!playlistToDelete) {
|
if (!playlistToDelete) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
deletePlaylist(playlistToDelete.uid).finally(() => {
|
api.deletePlaylist(playlistToDelete.uid).finally(() => {
|
||||||
setForcePlaylistsFetch(forcePlaylistsFetch + 1);
|
setForcePlaylistsFetch(forcePlaylistsFetch + 1);
|
||||||
setPlaylistToDelete(undefined);
|
setPlaylistToDelete(undefined);
|
||||||
});
|
});
|
||||||
|
@ -11,16 +11,17 @@ import { PlaylistSrv } from './PlaylistSrv';
|
|||||||
import { Playlist, PlaylistItem } from './types';
|
import { Playlist, PlaylistItem } from './types';
|
||||||
|
|
||||||
jest.mock('./api', () => ({
|
jest.mock('./api', () => ({
|
||||||
playlistAPI: {
|
getPlaylistAPI: () => ({
|
||||||
getPlaylist: jest.fn().mockReturnValue({
|
getPlaylist: jest.fn().mockReturnValue({
|
||||||
interval: '1s',
|
interval: '1s',
|
||||||
uid: 'xyz',
|
uid: 'xyz',
|
||||||
|
name: 'The display',
|
||||||
items: [
|
items: [
|
||||||
{ type: 'dashboard_by_uid', value: 'aaa' },
|
{ type: 'dashboard_by_uid', value: 'aaa' },
|
||||||
{ type: 'dashboard_by_uid', value: 'bbb' },
|
{ type: 'dashboard_by_uid', value: 'bbb' },
|
||||||
],
|
],
|
||||||
} as Playlist),
|
} as Playlist),
|
||||||
},
|
}),
|
||||||
loadDashboards: (items: PlaylistItem[]) => {
|
loadDashboards: (items: PlaylistItem[]) => {
|
||||||
return Promise.resolve(
|
return Promise.resolve(
|
||||||
items.map((v) => ({
|
items.map((v) => ({
|
||||||
|
@ -4,9 +4,8 @@ import { pickBy } from 'lodash';
|
|||||||
import { locationUtil, urlUtil, rangeUtil } from '@grafana/data';
|
import { locationUtil, urlUtil, rangeUtil } from '@grafana/data';
|
||||||
import { locationService } from '@grafana/runtime';
|
import { locationService } from '@grafana/runtime';
|
||||||
|
|
||||||
import { playlistAPI, loadDashboards } from './api';
|
import { getPlaylistAPI, loadDashboards } from './api';
|
||||||
|
import { PlaylistAPI } from './types';
|
||||||
const { getPlaylist } = playlistAPI;
|
|
||||||
|
|
||||||
export const queryParamsToPreserve: { [key: string]: boolean } = {
|
export const queryParamsToPreserve: { [key: string]: boolean } = {
|
||||||
kiosk: true,
|
kiosk: true,
|
||||||
@ -23,11 +22,13 @@ export class PlaylistSrv {
|
|||||||
private numberOfLoops = 0;
|
private numberOfLoops = 0;
|
||||||
private declare validPlaylistUrl: string;
|
private declare validPlaylistUrl: string;
|
||||||
private locationListenerUnsub?: () => void;
|
private locationListenerUnsub?: () => void;
|
||||||
|
private api: PlaylistAPI;
|
||||||
|
|
||||||
isPlaying = false;
|
isPlaying = false;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.locationUpdated = this.locationUpdated.bind(this);
|
this.locationUpdated = this.locationUpdated.bind(this);
|
||||||
|
this.api = getPlaylistAPI();
|
||||||
}
|
}
|
||||||
|
|
||||||
next() {
|
next() {
|
||||||
@ -81,7 +82,7 @@ export class PlaylistSrv {
|
|||||||
this.locationListenerUnsub = locationService.getHistory().listen(this.locationUpdated);
|
this.locationListenerUnsub = locationService.getHistory().listen(this.locationUpdated);
|
||||||
|
|
||||||
const urls: string[] = [];
|
const urls: string[] = [];
|
||||||
let playlist = await getPlaylist(playlistUid);
|
let playlist = await this.api.getPlaylist(playlistUid);
|
||||||
if (!playlist.items?.length) {
|
if (!playlist.items?.length) {
|
||||||
// alert
|
// alert
|
||||||
return;
|
return;
|
||||||
|
@ -11,71 +11,132 @@ import { dispatch } from 'app/store/store';
|
|||||||
|
|
||||||
import { DashboardQueryResult, getGrafanaSearcher, SearchQuery } from '../search/service';
|
import { DashboardQueryResult, getGrafanaSearcher, SearchQuery } from '../search/service';
|
||||||
|
|
||||||
import { Playlist, PlaylistItem, KubernetesPlaylist, KubernetesPlaylistList, PlaylistAPI } from './types';
|
import { Playlist, PlaylistItem, PlaylistAPI } from './types';
|
||||||
|
|
||||||
export async function createPlaylist(playlist: Playlist) {
|
class LegacyAPI implements PlaylistAPI {
|
||||||
await withErrorHandling(() => getBackendSrv().post('/api/playlists', playlist));
|
async getAllPlaylist(): Promise<Playlist[]> {
|
||||||
}
|
|
||||||
|
|
||||||
export async function updatePlaylist(uid: string, playlist: Playlist) {
|
|
||||||
await withErrorHandling(() => getBackendSrv().put(`/api/playlists/${uid}`, playlist));
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function deletePlaylist(uid: string) {
|
|
||||||
await withErrorHandling(() => getBackendSrv().delete(`/api/playlists/${uid}`), 'Playlist deleted');
|
|
||||||
}
|
|
||||||
|
|
||||||
export const playlistAPI: PlaylistAPI = {
|
|
||||||
getPlaylist: config.featureToggles.kubernetesPlaylists ? k8sGetPlaylist : legacyGetPlaylist,
|
|
||||||
getAllPlaylist: config.featureToggles.kubernetesPlaylists ? k8sGetAllPlaylist : legacyGetAllPlaylist,
|
|
||||||
};
|
|
||||||
|
|
||||||
/** This returns a playlist where all ids are replaced with UIDs */
|
|
||||||
export async function k8sGetPlaylist(uid: string): Promise<Playlist> {
|
|
||||||
const k8splaylist = await getBackendSrv().get<KubernetesPlaylist>(
|
|
||||||
`/apis/playlist.x.grafana.com/v0alpha1/namespaces/org-${contextSrv.user.orgId}/playlists/${uid}`
|
|
||||||
);
|
|
||||||
const playlist = k8splaylist.spec;
|
|
||||||
if (playlist.items) {
|
|
||||||
for (const item of playlist.items) {
|
|
||||||
if (item.type === 'dashboard_by_id') {
|
|
||||||
item.type = 'dashboard_by_uid';
|
|
||||||
const uids = await getBackendSrv().get<string[]>(`/api/dashboards/ids/${item.value}`);
|
|
||||||
if (uids.length) {
|
|
||||||
item.value = uids[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return playlist;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function k8sGetAllPlaylist(): Promise<Playlist[]> {
|
|
||||||
const k8splaylists = await getBackendSrv().get<KubernetesPlaylistList>(
|
|
||||||
`/apis/playlist.x.grafana.com/v0alpha1/namespaces/org-${contextSrv.user.orgId}/playlists`
|
|
||||||
);
|
|
||||||
return k8splaylists.playlists.map((p) => p.spec);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** This returns a playlist where all ids are replaced with UIDs */
|
|
||||||
export async function legacyGetPlaylist(uid: string): Promise<Playlist> {
|
|
||||||
const playlist = await getBackendSrv().get<Playlist>(`/api/playlists/${uid}`);
|
|
||||||
if (playlist.items) {
|
|
||||||
for (const item of playlist.items) {
|
|
||||||
if (item.type === 'dashboard_by_id') {
|
|
||||||
item.type = 'dashboard_by_uid';
|
|
||||||
const uids = await getBackendSrv().get<string[]>(`/api/dashboards/ids/${item.value}`);
|
|
||||||
if (uids.length) {
|
|
||||||
item.value = uids[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return playlist;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function legacyGetAllPlaylist(): Promise<Playlist[]> {
|
|
||||||
return getBackendSrv().get<Playlist[]>('/api/playlists/');
|
return getBackendSrv().get<Playlist[]>('/api/playlists/');
|
||||||
|
}
|
||||||
|
|
||||||
|
async getPlaylist(uid: string): Promise<Playlist> {
|
||||||
|
const p = await getBackendSrv().get<Playlist>(`/api/playlists/${uid}`);
|
||||||
|
await migrateInternalIDs(p);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
async createPlaylist(playlist: Playlist): Promise<void> {
|
||||||
|
await withErrorHandling(() => getBackendSrv().post('/api/playlists', playlist));
|
||||||
|
}
|
||||||
|
|
||||||
|
async updatePlaylist(playlist: Playlist): Promise<void> {
|
||||||
|
await withErrorHandling(() => getBackendSrv().put(`/api/playlists/${playlist.uid}`, playlist));
|
||||||
|
}
|
||||||
|
|
||||||
|
async deletePlaylist(uid: string): Promise<void> {
|
||||||
|
await withErrorHandling(() => getBackendSrv().delete(`/api/playlists/${uid}`), 'Playlist deleted');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface K8sPlaylistList {
|
||||||
|
playlists: K8sPlaylist[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface K8sPlaylist {
|
||||||
|
metadata: {
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
spec: {
|
||||||
|
name: string;
|
||||||
|
interval: string;
|
||||||
|
items: PlaylistItem[];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class K8sAPI implements PlaylistAPI {
|
||||||
|
readonly url = `/apis/playlist.x.grafana.com/v0alpha1/namespaces/org-${contextSrv.user.orgId}/playlists`;
|
||||||
|
readonly legacy = new LegacyAPI(); // set to null for full CRUD
|
||||||
|
|
||||||
|
async getAllPlaylist(): Promise<Playlist[]> {
|
||||||
|
const result = await getBackendSrv().get<K8sPlaylistList>(this.url);
|
||||||
|
console.log('getAllPlaylist', result);
|
||||||
|
const v = result.playlists.map(k8sResourceAsPlaylist);
|
||||||
|
console.log('after', v);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getPlaylist(uid: string): Promise<Playlist> {
|
||||||
|
const r = await getBackendSrv().get<K8sPlaylist>(this.url + '/' + uid);
|
||||||
|
const p = k8sResourceAsPlaylist(r);
|
||||||
|
await migrateInternalIDs(p);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
async createPlaylist(playlist: Playlist): Promise<void> {
|
||||||
|
if (this.legacy) {
|
||||||
|
return this.legacy.createPlaylist(playlist);
|
||||||
|
}
|
||||||
|
await withErrorHandling(() =>
|
||||||
|
getBackendSrv().post(this.url, {
|
||||||
|
apiVersion: 'playlists.grafana.com/v0alpha1',
|
||||||
|
kind: 'Playlist',
|
||||||
|
metadata: {
|
||||||
|
name: playlist.uid,
|
||||||
|
},
|
||||||
|
spec: playlist,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async updatePlaylist(playlist: Playlist): Promise<void> {
|
||||||
|
if (this.legacy) {
|
||||||
|
return this.legacy.updatePlaylist(playlist);
|
||||||
|
}
|
||||||
|
await withErrorHandling(() =>
|
||||||
|
getBackendSrv().put(`${this.url}/${playlist.uid}`, {
|
||||||
|
apiVersion: 'playlists.grafana.com/v0alpha1',
|
||||||
|
kind: 'Playlist',
|
||||||
|
metadata: {
|
||||||
|
name: playlist.uid,
|
||||||
|
},
|
||||||
|
spec: {
|
||||||
|
...playlist,
|
||||||
|
title: playlist.name,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async deletePlaylist(uid: string): Promise<void> {
|
||||||
|
if (this.legacy) {
|
||||||
|
return this.legacy.deletePlaylist(uid);
|
||||||
|
}
|
||||||
|
await withErrorHandling(() => getBackendSrv().delete(`${this.url}/${uid}`), 'Playlist deleted');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This converts a saved k8s resource into a playlist object
|
||||||
|
// the main difference is that k8s uses metdata.name as the uid
|
||||||
|
// to avoid future confusion, the display name is now called "title"
|
||||||
|
function k8sResourceAsPlaylist(r: K8sPlaylist): Playlist {
|
||||||
|
return {
|
||||||
|
...r.spec,
|
||||||
|
uid: r.metadata.name, // replace the uid from the k8s name
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @deprecated -- this migrates playlists saved with internal ids to uid */
|
||||||
|
async function migrateInternalIDs(playlist: Playlist) {
|
||||||
|
if (playlist?.items) {
|
||||||
|
for (const item of playlist.items) {
|
||||||
|
if (item.type === 'dashboard_by_id') {
|
||||||
|
item.type = 'dashboard_by_uid';
|
||||||
|
const uids = await getBackendSrv().get<string[]>(`/api/dashboards/ids/${item.value}`);
|
||||||
|
if (uids?.length) {
|
||||||
|
item.value = uids[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function withErrorHandling(apiCall: () => Promise<void>, message = 'Playlist saved') {
|
async function withErrorHandling(apiCall: () => Promise<void>, message = 'Playlist saved') {
|
||||||
@ -158,3 +219,7 @@ export function searchPlaylists(playlists: Playlist[], query?: string): Playlist
|
|||||||
query = query.toLowerCase();
|
query = query.toLowerCase();
|
||||||
return playlists.filter((v) => v.name.toLowerCase().includes(query!));
|
return playlists.filter((v) => v.name.toLowerCase().includes(query!));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getPlaylistAPI() {
|
||||||
|
return config.featureToggles.kubernetesPlaylists ? new K8sAPI() : new LegacyAPI();
|
||||||
|
}
|
||||||
|
@ -1,37 +1,65 @@
|
|||||||
import { PlaylistItem as PlaylistItemFromSchema } from '@grafana/schema';
|
|
||||||
|
|
||||||
import { DashboardQueryResult } from '../search/service';
|
import { DashboardQueryResult } from '../search/service';
|
||||||
|
|
||||||
export type PlaylistMode = boolean | 'tv';
|
export type PlaylistMode = boolean | 'tv';
|
||||||
|
|
||||||
export interface PlayListItemDTO {
|
|
||||||
id: number;
|
|
||||||
title: string;
|
|
||||||
playlistid: string;
|
|
||||||
type: 'dashboard' | 'tag';
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PlaylistAPI {
|
export interface PlaylistAPI {
|
||||||
getPlaylist(uid: string): Promise<Playlist>;
|
|
||||||
getAllPlaylist(): Promise<Playlist[]>;
|
getAllPlaylist(): Promise<Playlist[]>;
|
||||||
}
|
getPlaylist(uid: string): Promise<Playlist>;
|
||||||
|
createPlaylist(playlist: Playlist): Promise<void>;
|
||||||
export interface KubernetesPlaylistList {
|
updatePlaylist(playlist: Playlist): Promise<void>;
|
||||||
playlists: KubernetesPlaylist[];
|
deletePlaylist(uid: string): Promise<void>;
|
||||||
}
|
|
||||||
|
|
||||||
export interface KubernetesPlaylist {
|
|
||||||
spec: Playlist;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Playlist {
|
export interface Playlist {
|
||||||
|
/**
|
||||||
|
* Unique playlist identifier. Generated on creation, either by the
|
||||||
|
* creator of the playlist of by the application.
|
||||||
|
*/
|
||||||
uid: string;
|
uid: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the playlist.
|
||||||
|
*/
|
||||||
name: string;
|
name: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interval sets the time between switching views in a playlist.
|
||||||
|
*/
|
||||||
interval: string;
|
interval: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ordered list of items that the playlist will iterate over.
|
||||||
|
*/
|
||||||
items?: PlaylistItem[];
|
items?: PlaylistItem[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PlaylistItem extends PlaylistItemFromSchema {
|
export interface PlaylistItem {
|
||||||
// Loaded in the frontend
|
/**
|
||||||
|
* Type of the item.
|
||||||
|
*/
|
||||||
|
type: // Use an explicit dashboard
|
||||||
|
| 'dashboard_by_uid'
|
||||||
|
// find all dashboards with a given tag
|
||||||
|
| 'dashboard_by_tag'
|
||||||
|
// @deprecated use a dashboard with a given internal id
|
||||||
|
| 'dashboard_by_id';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value depends on type and describes the playlist item.
|
||||||
|
*
|
||||||
|
* - dashboard_by_id: The value is an internal numerical identifier set by Grafana. This
|
||||||
|
* is not portable as the numerical identifier is non-deterministic between different instances.
|
||||||
|
* Will be replaced by dashboard_by_uid in the future. (deprecated)
|
||||||
|
* - dashboard_by_tag: The value is a tag which is set on any number of dashboards. All
|
||||||
|
* dashboards behind the tag will be added to the playlist.
|
||||||
|
* - dashboard_by_uid: The value is the dashboard UID
|
||||||
|
*/
|
||||||
|
value: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loaded at runtime by the frontend.
|
||||||
|
*
|
||||||
|
* The values are not stored in the backend database.
|
||||||
|
*/
|
||||||
dashboards?: DashboardQueryResult[];
|
dashboards?: DashboardQueryResult[];
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user