{"version":3,"file":"PlaylistNewPage.13696f39b95b8416ede2.js","mappings":"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","sources":["webpack://grafana/./public/app/features/playlist/PlaylistTableRows.tsx","webpack://grafana/./public/app/features/playlist/PlaylistTable.tsx","webpack://grafana/./public/app/features/playlist/usePlaylistItems.tsx","webpack://grafana/./public/app/features/playlist/PlaylistForm.tsx","webpack://grafana/./public/app/features/playlist/PlaylistNewPage.tsx"],"sourcesContent":["import { css } from '@emotion/css';\nimport pluralize from 'pluralize';\nimport React, { ReactNode } from 'react';\nimport { Draggable } from 'react-beautiful-dnd';\n\nimport { GrafanaTheme2 } from '@grafana/data';\nimport { selectors } from '@grafana/e2e-selectors';\nimport { Icon, IconButton, useStyles2, Spinner, IconName } from '@grafana/ui';\nimport { TagBadge } from 'app/core/components/TagFilter/TagBadge';\nimport { t, Trans } from 'app/core/internationalization';\n\nimport { PlaylistItem } from './types';\n\ninterface Props {\n items: PlaylistItem[];\n onDelete: (idx: number) => void;\n}\n\nexport const PlaylistTableRows = ({ items, onDelete }: Props) => {\n const styles = useStyles2(getStyles);\n if (!items?.length) {\n return (\n
\n \n Playlist is empty. Add dashboards below.\n \n
\n );\n }\n\n const renderItem = (item: PlaylistItem) => {\n let icon: IconName = item.type === 'dashboard_by_tag' ? 'apps' : 'tag-alt';\n const info: ReactNode[] = [];\n\n const first = item.dashboards?.[0];\n if (!item.dashboards) {\n info.push();\n } else if (item.type === 'dashboard_by_tag') {\n info.push();\n if (!first) {\n icon = 'exclamation-triangle';\n info.push(  No dashboards found);\n } else {\n info.push(  {pluralize('dashboard', item.dashboards.length, true)});\n }\n } else if (first) {\n info.push(\n item.dashboards.length > 1 ? (\n Multiple items found: ${item.value}\n ) : (\n {first.name ?? item.value}\n )\n );\n } else {\n icon = 'exclamation-triangle';\n info.push(  Not found: {item.value});\n }\n return (\n <>\n \n {info}\n \n );\n };\n\n return (\n <>\n {items.map((item, index) => (\n \n {(provided) => (\n \n
\n {renderItem(item)}\n
\n
\n onDelete(index)}\n data-testid={selectors.pages.PlaylistForm.itemDelete}\n tooltip={t('playlist-edit.form.table-delete', 'Delete playlist item')}\n />\n \n
\n \n )}\n
\n ))}\n \n );\n};\n\nfunction getStyles(theme: GrafanaTheme2) {\n return {\n row: css`\n padding: 6px;\n background: ${theme.colors.background.secondary};\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 3px;\n\n border: 1px solid ${theme.colors.border.medium};\n &:hover {\n border: 1px solid ${theme.colors.border.strong};\n }\n `,\n rightMargin: css`\n margin-right: 5px;\n `,\n actions: css`\n align-items: center;\n justify-content: center;\n display: flex;\n `,\n settings: css`\n label: settings;\n text-align: right;\n `,\n };\n}\n","import React from 'react';\nimport { DragDropContext, Droppable, DropResult } from 'react-beautiful-dnd';\n\nimport { FieldSet } from '@grafana/ui';\nimport { t } from 'app/core/internationalization';\n\nimport { PlaylistTableRows } from './PlaylistTableRows';\nimport { PlaylistItem } from './types';\n\ninterface Props {\n items: PlaylistItem[];\n deleteItem: (idx: number) => void;\n moveItem: (src: number, dst: number) => void;\n}\n\nexport const PlaylistTable = ({ items, deleteItem, moveItem }: Props) => {\n const onDragEnd = (d: DropResult) => {\n if (d.destination) {\n moveItem(d.source.index, d.destination?.index);\n }\n };\n\n return (\n
\n \n \n {(provided) => {\n return (\n
\n \n {provided.placeholder}\n
\n );\n }}\n
\n
\n
\n );\n};\n","import { useCallback, useState } from 'react';\nimport { useAsync } from 'react-use';\n\nimport { DashboardPickerDTO } from 'app/core/components/Select/DashboardPicker';\n\nimport { loadDashboards } from './api';\nimport { PlaylistItem } from './types';\n\nexport function usePlaylistItems(playlistItems?: PlaylistItem[]) {\n const [items, setItems] = useState(playlistItems ?? []);\n\n // Attach dashboards if any were missing\n useAsync(async () => {\n for (const item of items) {\n if (!item.dashboards) {\n setItems(await loadDashboards(items));\n return;\n }\n }\n }, [items]);\n\n const addByUID = useCallback(\n (dashboard?: DashboardPickerDTO) => {\n if (!dashboard) {\n return;\n }\n\n setItems([\n ...items,\n {\n type: 'dashboard_by_uid',\n value: dashboard.uid,\n },\n ]);\n },\n [items]\n );\n\n const addByTag = useCallback(\n (tags: string[]) => {\n const tag = tags[0];\n if (!tag || items.find((item) => item.value === tag)) {\n return;\n }\n\n const newItem: PlaylistItem = {\n type: 'dashboard_by_tag',\n value: tag,\n };\n setItems([...items, newItem]);\n },\n [items]\n );\n\n const moveItem = useCallback(\n (src: number, dst: number) => {\n if (src === dst || !items[src]) {\n return; // nothing to do\n }\n const update = Array.from(items);\n const [removed] = update.splice(src, 1);\n update.splice(dst, 0, removed);\n setItems(update);\n },\n [items]\n );\n\n const deleteItem = useCallback(\n (index: number) => {\n const copy = items.slice();\n copy.splice(index, 1);\n setItems(copy);\n },\n [items]\n );\n\n return { items, addByUID, addByTag, deleteItem, moveItem };\n}\n","import React, { useMemo, useState } from 'react';\n\nimport { selectors } from '@grafana/e2e-selectors';\nimport { config } from '@grafana/runtime';\nimport { Button, Field, FieldSet, Form, HorizontalGroup, Input, LinkButton } from '@grafana/ui';\nimport { DashboardPicker } from 'app/core/components/Select/DashboardPicker';\nimport { TagFilter } from 'app/core/components/TagFilter/TagFilter';\nimport { Trans, t } from 'app/core/internationalization';\n\nimport { getGrafanaSearcher } from '../search/service';\n\nimport { PlaylistTable } from './PlaylistTable';\nimport { Playlist } from './types';\nimport { usePlaylistItems } from './usePlaylistItems';\n\ninterface Props {\n onSubmit: (playlist: Playlist) => void;\n playlist: Playlist;\n}\n\nexport const PlaylistForm = ({ onSubmit, playlist }: Props) => {\n const [saving, setSaving] = useState(false);\n const { name, interval, items: propItems } = playlist;\n const tagOptions = useMemo(() => {\n return () => getGrafanaSearcher().tags({ kind: ['dashboard'] });\n }, []);\n\n const { items, addByUID, addByTag, deleteItem, moveItem } = usePlaylistItems(propItems);\n\n const doSubmit = (list: Playlist) => {\n setSaving(true);\n onSubmit({ ...list, items, uid: playlist.uid });\n };\n\n return (\n
\n
\n {({ register, errors }) => {\n const isDisabled = items.length === 0 || Object.keys(errors).length > 0;\n return (\n <>\n \n \n \n \n \n \n\n \n\n
\n \n \n \n\n \n \n \n
\n\n \n \n \n Cancel\n \n \n \n );\n }}\n \n
\n );\n};\n","import React, { useState } from 'react';\n\nimport { NavModelItem } from '@grafana/data';\nimport { locationService } from '@grafana/runtime';\nimport { Page } from 'app/core/components/Page/Page';\n\nimport { PlaylistForm } from './PlaylistForm';\nimport { getPlaylistAPI, getDefaultPlaylist } from './api';\nimport { Playlist } from './types';\n\nexport const PlaylistNewPage = () => {\n const [playlist] = useState(getDefaultPlaylist());\n\n const onSubmit = async (playlist: Playlist) => {\n await getPlaylistAPI().createPlaylist(playlist);\n locationService.push('/playlists');\n };\n\n const pageNav: NavModelItem = {\n text: 'New playlist',\n subTitle:\n 'A playlist rotates through a pre-selected list of dashboards. A playlist can be a great way to build situational awareness, or just show off your metrics to your team or visitors.',\n };\n\n return (\n \n \n \n \n \n );\n};\n\nexport default PlaylistNewPage;\n"],"names":["PlaylistTableRows","items","onDelete","styles","getStyles","renderItem","item","icon","info","first","TagBadge","Spinner","Icon","index","provided","IconButton","selectors","theme","PlaylistTable","deleteItem","moveItem","onDragEnd","d","FieldSet","usePlaylistItems","playlistItems","setItems","useAsync","addByUID","dashboard","addByTag","tags","tag","newItem","src","dst","update","removed","copy","PlaylistForm","onSubmit","playlist","saving","setSaving","name","interval","propItems","tagOptions","doSubmit","list","Form","register","errors","isDisabled","Field","Input","DashboardPicker","TagFilter","Button","config","PlaylistNewPage","pageNav"],"sourceRoot":""}