diff --git a/table/schemas/table.cue b/table/schemas/table.cue index e1132d94..8d1c8061 100644 --- a/table/schemas/table.cue +++ b/table/schemas/table.cue @@ -45,6 +45,11 @@ spec: close({ width?: number | "auto" hide?: bool cellSettings?: [...#cellSettings] + dataLink?: { + url: string + title?: string + openNewTab: bool + } } #valueCondition: { diff --git a/table/src/components/ColumnsEditor/ColumnEditor.tsx b/table/src/components/ColumnsEditor/ColumnEditor.tsx index ac63b5d9..c89169dd 100644 --- a/table/src/components/ColumnsEditor/ColumnEditor.tsx +++ b/table/src/components/ColumnsEditor/ColumnEditor.tsx @@ -11,7 +11,21 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Button, ButtonGroup, Stack, StackProps, Switch, TextField } from '@mui/material'; +import { + Button, + ButtonGroup, + DialogActions, + DialogContent, + DialogTitle, + FormControl, + FormLabel, + IconButton, + Stack, + StackProps, + Switch, + TextField, + Typography, +} from '@mui/material'; import { ReactElement, useState } from 'react'; import { AlignSelector, @@ -21,9 +35,14 @@ import { OptionsEditorGrid, OptionsEditorGroup, SortSelectorButtons, + Dialog, } from '@perses-dev/components'; import { FormatOptions } from '@perses-dev/core'; import { PluginKindSelect } from '@perses-dev/plugin-system'; +import ContentCopyIcon from 'mdi-material-ui/ContentCopy'; +import DeleteIcon from 'mdi-material-ui/Delete'; +import InformationIcon from 'mdi-material-ui/Information'; +import LinkIcon from 'mdi-material-ui/Link'; import { ColumnSettings } from '../../models'; import { ConditionalPanel } from '../ConditionalPanel'; @@ -39,13 +58,136 @@ export interface ColumnEditorProps extends Omit { onChange: (column: ColumnSettings) => void; } +type LinkManagementDialogueProps = Pick & { + actionTitle: string; + open: boolean; + key?: string; + setOpen: (value: { open: boolean }) => void; +}; +const LinkManagementDialog = (props: LinkManagementDialogueProps): ReactElement => { + const { + actionTitle, + open, + key, + column: { dataLink }, + column, + onChange, + setOpen, + } = props; + + const [url, setUrl] = useState(dataLink?.url); + const [title, setTitle] = useState(dataLink?.title); + const [openNewTab, setOpenNewTab] = useState(!!dataLink?.openNewTab); + const [urlError, setUrlError] = useState<{ hasError: boolean; helperText: string } | undefined>(undefined); + + const handleSaveDataLink = (): void => { + if (!url) { + setUrlError({ hasError: true, helperText: 'Url Can not be empty' }); + return; + } + onChange({ ...column, dataLink: { url, title, openNewTab } }); + setOpen({ open: false }); + }; + + return ( + + {actionTitle} + + + + { + if (urlError) setUrlError(undefined); + setUrl(e.target.value); + }} + type="url" + placeholder="http://target.com/x/{column_name}/z" + value={url} + /> + + + + { + setTitle(e.target.value); + }} + placeholder="Title" + type="text" + value={title} + /> + + + Open in new tab + + { + setOpenNewTab(e.target.checked); + }} + checked={openNewTab} + /> + + + + + + + You can create dynamic links using column names wrapped with curly braces + + + + + + + + + + + ); +}; + export function ColumnEditor({ column, onChange, ...others }: ColumnEditorProps): ReactElement { const [width, setWidth] = useState( column.width === undefined || column.width === 'auto' ? 100 : column.width ); + const [openAddLinkDialog, setOpenAddLinkDialog] = useState<{ open: boolean; key?: string }>({ + open: false, + }); + const linkManagementAction = column?.dataLink ? 'Edit Column Link' : 'Add Column Link'; + return ( + @@ -206,6 +348,46 @@ export function ColumnEditor({ column, onChange, ...others }: ColumnEditorProps) )} + + + } + onClick={(): void => { + setOpenAddLinkDialog({ open: true, key: String(Date.now()) }); + }} + > + {linkManagementAction} + + } + /> + {column?.dataLink?.url && ( + + + {column?.dataLink?.title || column?.dataLink?.url} + + { + if (column?.dataLink?.url) navigator.clipboard.writeText(column?.dataLink?.url); + }} + size="small" + > + + + { + onChange({ ...column, dataLink: undefined }); + }} + size="small" + > + + + + )} + + diff --git a/table/src/models/table-model.ts b/table/src/models/table-model.ts index c23487d7..52bc071d 100644 --- a/table/src/models/table-model.ts +++ b/table/src/models/table-model.ts @@ -63,6 +63,12 @@ export interface ColumnSettings { hide?: boolean; // Customize cell display based on their value for this specific column. cellSettings?: CellSettings[]; + + dataLink?: { + url: string; + title?: string; + openNewTab: boolean; + }; } export interface ValueCondition {