Skip to content

Commit 2737172

Browse files
committed
[FEATURE] Table Add data link settings under column settings
Signed-off-by: Seyed Mahmoud SHAHROKNI <seyedmahmoud.shahrokni@amadeus.com> Signed-off-by: Seyed Mahmoud SHAHROKNI <seyedmahmoud.shahrokni@amadeus.com> Signed-off-by: Seyed Mahmoud SHAHROKNI <seyedmahmoud.shahrokni@amadeus.com>
1 parent 5cb5f0e commit 2737172

File tree

3 files changed

+177
-1
lines changed

3 files changed

+177
-1
lines changed

table/schemas/table.cue

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ spec: close({
4545
width?: number | "auto"
4646
hide?: bool
4747
cellSettings?: [...#cellSettings]
48+
dataLink?: {
49+
url: string
50+
title?: string
51+
openNewTab: bool
52+
}
4853
}
4954

5055
#valueCondition: {

table/src/components/ColumnsEditor/ColumnEditor.tsx

Lines changed: 166 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,22 @@
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';
1530
import { ReactElement, useState } from 'react';
1631
import {
1732
AlignSelector,
@@ -21,9 +36,13 @@ import {
2136
OptionsEditorGrid,
2237
OptionsEditorGroup,
2338
SortSelectorButtons,
39+
Dialog,
2440
} from '@perses-dev/components';
2541
import { FormatOptions } from '@perses-dev/core';
2642
import { 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';
2746
import { ColumnSettings } from '../../models';
2847
import { 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+
42158
export 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">

table/src/models/table-model.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,12 @@ export interface ColumnSettings {
6363
hide?: boolean;
6464
// Customize cell display based on their value for this specific column.
6565
cellSettings?: CellSettings[];
66+
67+
dataLink?: {
68+
url: string;
69+
title?: string;
70+
openNewTab: boolean;
71+
};
6672
}
6773

6874
export interface ValueCondition {

0 commit comments

Comments
 (0)