1111// See the License for the specific language governing permissions and
1212// limitations under the License.
1313
14- import { Button , ButtonGroup , Stack , StackProps , Switch , TextField } from '@mui/material' ;
14+ import {
15+ Box ,
16+ Button ,
17+ ButtonGroup ,
18+ DialogActions ,
19+ DialogContent ,
20+ DialogTitle ,
21+ FormControl ,
22+ FormLabel ,
23+ IconButton ,
24+ Stack ,
25+ StackProps ,
26+ Switch ,
27+ TextField ,
28+ Typography ,
29+ } from '@mui/material' ;
1530import { ReactElement , useState } from 'react' ;
1631import {
1732 AlignSelector ,
@@ -21,9 +36,13 @@ import {
2136 OptionsEditorGrid ,
2237 OptionsEditorGroup ,
2338 SortSelectorButtons ,
39+ Dialog ,
2440} from '@perses-dev/components' ;
2541import { FormatOptions } from '@perses-dev/core' ;
2642import { PluginKindSelect } from '@perses-dev/plugin-system' ;
43+ import ContentCopyIcon from 'mdi-material-ui/ContentCopy' ;
44+ import DeleteIcon from 'mdi-material-ui/Delete' ;
45+ import InformationIcon from 'mdi-material-ui/Information' ;
2746import { ColumnSettings } from '../../models' ;
2847import { ConditionalPanel } from '../ConditionalPanel' ;
2948
@@ -39,13 +58,120 @@ export interface ColumnEditorProps extends Omit<StackProps, OmittedMuiProps> {
3958 onChange : ( column : ColumnSettings ) => void ;
4059}
4160
61+ type LinkManagementDialogueProps = Pick < ColumnEditorProps , 'onChange' | 'column' > & {
62+ actionTitle : string ;
63+ open : boolean ;
64+ setOpen : ( value : boolean ) => void ;
65+ } ;
66+ const LinkManagementDialogue = ( props : LinkManagementDialogueProps ) : ReactElement => {
67+ const {
68+ actionTitle,
69+ open,
70+ column : { dataLink } ,
71+ column,
72+ onChange,
73+ setOpen,
74+ } = props ;
75+
76+ const [ url , setUrl ] = useState ( dataLink ?. url ) ;
77+ const [ title , setTitle ] = useState ( dataLink ?. title ) ;
78+ const [ openNewTab , setOpenNewTab ] = useState ( ! ! dataLink ?. openNewTab ) ;
79+
80+ const handleSaveDataLink = ( ) : void => {
81+ if ( ! url ) return ;
82+ onChange ( { ...column , dataLink : { url, title, openNewTab } } ) ;
83+ setOpen ( false ) ;
84+ } ;
85+
86+ return (
87+ < Dialog
88+ sx = { {
89+ '& .MuiDialog-paper' : {
90+ width : '80vw' ,
91+ } ,
92+ } }
93+ open = { open }
94+ >
95+ < DialogTitle > { actionTitle } </ DialogTitle >
96+ < DialogContent >
97+ < Stack spacing = { 2 } >
98+ < FormControl >
99+ < Box sx = { { display : 'flex' , flexDirection : 'row' } } >
100+ < FormLabel > URL</ FormLabel >
101+ </ Box >
102+ < TextField
103+ onChange = { ( e ) => {
104+ setUrl ( e . target . value ) ;
105+ } }
106+ type = "url"
107+ placeholder = "http://target.com/x/{dynamic_value}/z"
108+ value = { url }
109+ />
110+ </ FormControl >
111+
112+ < FormControl >
113+ < FormLabel > Title</ FormLabel >
114+ < TextField
115+ onChange = { ( e ) => {
116+ setTitle ( e . target . value ) ;
117+ } }
118+ placeholder = "Title"
119+ type = "text"
120+ value = { title }
121+ />
122+ </ FormControl >
123+ < FormControl >
124+ < FormLabel > Open in new tab</ FormLabel >
125+ < FormControl >
126+ < Switch
127+ onChange = { ( e ) => {
128+ setOpenNewTab ( e . target . checked ) ;
129+ } }
130+ value = { openNewTab }
131+ />
132+ </ FormControl >
133+ </ FormControl >
134+ < FormControl >
135+ < Stack direction = "row" spacing = { 1 } alignItems = "center" >
136+ < InformationIcon fontSize = "small" />
137+ < Typography variant = "body1" >
138+ You can create dynamic links by proper positioning of dynamic_value wrapped with curly brackets.
139+ </ Typography >
140+ </ Stack >
141+ </ FormControl >
142+ </ Stack >
143+ </ DialogContent >
144+ < DialogActions >
145+ < Button onClick = { handleSaveDataLink } > Save</ Button >
146+ < Button
147+ onClick = { ( ) => {
148+ setOpen ( false ) ;
149+ } }
150+ >
151+ Cancel
152+ </ Button >
153+ </ DialogActions >
154+ </ Dialog >
155+ ) ;
156+ } ;
157+
42158export function ColumnEditor ( { column, onChange, ...others } : ColumnEditorProps ) : ReactElement {
43159 const [ width , setWidth ] = useState < number > (
44160 column . width === undefined || column . width === 'auto' ? 100 : column . width
45161 ) ;
46162
163+ const [ openAddLinkDialogue , setOpenAddLinkDialogue ] = useState < boolean > ( false ) ;
164+ const linkManagementAction = column ?. dataLink ? 'Edit Link' : 'Add Link' ;
165+
47166 return (
48167 < Stack { ...others } >
168+ < LinkManagementDialogue
169+ actionTitle = { linkManagementAction }
170+ onChange = { onChange }
171+ column = { column }
172+ open = { openAddLinkDialogue }
173+ setOpen = { setOpenAddLinkDialogue }
174+ />
49175 < OptionsEditorGrid >
50176 < OptionsEditorColumn >
51177 < OptionsEditorGroup title = "Column" >
@@ -206,6 +332,45 @@ export function ColumnEditor({ column, onChange, ...others }: ColumnEditorProps)
206332 ) }
207333 </ OptionsEditorGroup >
208334 </ OptionsEditorColumn >
335+ < OptionsEditorColumn >
336+ < OptionsEditorGroup title = "Link and Actions" >
337+ < OptionsEditorControl
338+ label = "Link"
339+ control = {
340+ < Button
341+ onClick = { ( ) : void => {
342+ setOpenAddLinkDialogue ( true ) ;
343+ } }
344+ >
345+ { linkManagementAction }
346+ </ Button >
347+ }
348+ />
349+ { column ?. dataLink ?. url && (
350+ < Stack direction = "row" spacing = { 1 } alignItems = "center" alignContent = "center" >
351+ < Typography sx = { { flexGrow : 1 , minWidth : 0 } } component = "span" variant = "body1" noWrap >
352+ { column ?. dataLink ?. title || column ?. dataLink ?. url }
353+ </ Typography >
354+ < IconButton
355+ onClick = { ( ) : void => {
356+ if ( column ?. dataLink ?. url ) navigator . clipboard . writeText ( column ?. dataLink ?. url ) ;
357+ } }
358+ size = "small"
359+ >
360+ < ContentCopyIcon fontSize = "small" sx = { { verticalAlign : 'middle' } } />
361+ </ IconButton >
362+ < IconButton
363+ onClick = { ( ) : void => {
364+ onChange ( { ...column , dataLink : undefined } ) ;
365+ } }
366+ size = "small"
367+ >
368+ < DeleteIcon fontSize = "small" sx = { { verticalAlign : 'middle' } } />
369+ </ IconButton >
370+ </ Stack >
371+ ) }
372+ </ OptionsEditorGroup >
373+ </ OptionsEditorColumn >
209374 </ OptionsEditorGrid >
210375 < Stack sx = { { px : 8 } } >
211376 < OptionsEditorGroup title = "Conditional Cell Format" >
0 commit comments