Update ODLUX
[ccsdk/features.git] / sdnr / wt / odlux / apps / configurationApp / src / components / uiElementLeafList.tsx
1 /**
2  * ============LICENSE_START========================================================================
3  * ONAP : ccsdk feature sdnr wt odlux
4  * =================================================================================================
5  * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
6  * =================================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
8  * in compliance with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software distributed under the License
13  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
14  * or implied. See the License for the specific language governing permissions and limitations under
15  * the License.
16  * ============LICENSE_END==========================================================================
17  */
18
19 import * as React from "react"
20 import { FormControl, InputLabel, Paper, Chip, FormHelperText, Dialog, DialogTitle, DialogContentText, DialogActions, Button, DialogContent } from "@mui/material";
21 import makeStyles from '@mui/styles/makeStyles';
22 import AddIcon from '@mui/icons-material/Add';
23
24 import { Theme } from '@mui/material/styles';
25 import { ViewElement } from "../models/uiModels";
26
27 import { BaseProps } from "./baseProps";
28
29 type LeafListProps = BaseProps<any []> & {
30   getEditorForViewElement:  (uiElement: ViewElement) => (null | React.ComponentType<BaseProps<any>>)  
31 };
32
33 const useStyles = makeStyles((theme: Theme) => {
34   const light = theme.palette.mode === 'light';
35   const bottomLineColor = light ? 'rgba(0, 0, 0, 0.42)' : 'rgba(255, 255, 255, 0.7)';
36
37   return ({
38     root: {
39       display: 'flex',
40       justifyContent: 'left',
41       verticalAlign: 'bottom',
42       flexWrap: 'wrap',
43       listStyle: 'none',
44       margin: 0,
45       padding: 0,
46       paddingTop: theme.spacing(0.5),
47       marginTop: theme.spacing(1),
48     },
49     chip: {
50       margin: theme.spacing(0.5),
51     },
52     underline: {
53         '&:after': {
54           borderBottom: `2px solid ${theme.palette.primary.main}`,
55           left: 0,
56           bottom: 0,
57           // Doing the other way around crash on IE 11 "''" https://github.com/cssinjs/jss/issues/242
58           content: '""',
59           position: 'absolute',
60           right: 0,
61           transform: 'scaleX(0)',
62           transition: theme.transitions.create('transform', {
63             duration: theme.transitions.duration.shorter,
64             easing: theme.transitions.easing.easeOut,
65           }),
66           pointerEvents: 'none', // Transparent to the hover style.
67         },
68         '&.Mui-focused:after': {
69           transform: 'scaleX(1)',
70         },
71         '&.Mui-error:after': {
72           borderBottomColor: theme.palette.error.main,
73           transform: 'scaleX(1)', // error is always underlined in red
74         },
75         '&:before': {
76           borderBottom: `1px solid ${bottomLineColor}`,
77           left: 0,
78           bottom: 0,
79           // Doing the other way around crash on IE 11 "''" https://github.com/cssinjs/jss/issues/242
80           content: '"\\00a0"',
81           position: 'absolute',
82           right: 0,
83           transition: theme.transitions.create('border-bottom-color', {
84             duration: theme.transitions.duration.shorter,
85           }),
86           pointerEvents: 'none', // Transparent to the hover style.
87         },
88         '&:hover:not($disabled):before': {
89           borderBottom: `2px solid ${theme.palette.text.primary}`,
90           // Reset on touch devices, it doesn't add specificity
91           '@media (hover: none)': {
92             borderBottom: `1px solid ${bottomLineColor}`,
93           },
94         },
95         '&.Mui-disabled:before': {
96           borderBottomStyle: 'dotted',
97         },
98       },
99   })
100 });
101
102 export const UiElementLeafList = (props: LeafListProps) => {
103   const { value: element, inputValue, onChange } = props;
104
105   const classes = useStyles();
106
107   const [open, setOpen] = React.useState(false);
108   const [editorValue, setEditorValue] = React.useState("");
109   const [editorValueIndex, setEditorValueIndex] = React.useState(-1);
110   
111
112   const handleClickOpen = () => {
113     setOpen(true);
114   };
115
116   const handleClose = () => {
117     setOpen(false);
118   };
119
120   const onApplyButton = () => { 
121      if (editorValue != null && editorValue != "" && editorValueIndex < 0) {
122        props.onChange([
123          ...inputValue,
124          editorValue,
125        ]);
126      } else if (editorValue != null && editorValue != "") {
127        props.onChange([
128          ...inputValue.slice(0, editorValueIndex),
129          editorValue,
130          ...inputValue.slice(editorValueIndex+1),
131        ]);
132      }
133      setOpen(false);
134   };
135
136   const onDelete = (index : number) => {
137     const newValue : any[] = [
138       ...inputValue.slice(0, index),
139       ...inputValue.slice(index+1),
140     ];
141     onChange(newValue);
142   };
143
144   const ValueEditor = props.getEditorForViewElement(props.value); 
145
146   return (
147     <>
148       <FormControl variant="standard" style={{ width: 485, marginLeft: 20, marginRight: 20 }}>
149         <InputLabel htmlFor={`list-${element.id}`} shrink={!props.readOnly || !!(inputValue && inputValue.length)} >{element.label}</InputLabel>
150         <ul className={`${classes.root} ${classes.underline}`} id={`list-${element.id}`}>
151         { !props.readOnly ? <li>
152           <Chip
153             icon={<AddIcon />}
154             label={"Add"}
155             className={classes.chip}
156             size="small"
157             color="secondary"
158             onClick={ () => { 
159               setOpen(true); 
160               setEditorValue("");
161               setEditorValueIndex(-1);
162              } 
163             }
164           />
165         </li> : null }  
166         { inputValue.map((val, ind) => (
167           <li key={ind}>
168             <Chip
169               className={classes.chip}
170               size="small"
171               variant="outlined"
172               label={String(val)}
173               onDelete={ !props.readOnly ? () => { onDelete(ind); } : undefined }  
174               onClick={ !props.readOnly ? () => { 
175                   setOpen(true); 
176                   setEditorValue(val);
177                   setEditorValueIndex(ind);
178                   } : undefined
179               }   
180             />
181             </li>
182           ))
183         }
184         </ul>
185         {/* <FormHelperText>{ "Value is mandetory"}</FormHelperText> */}
186         </FormControl>
187         <Dialog open={open} onClose={handleClose} aria-labelledby="form-dialog-title">
188           <DialogTitle id="form-dialog-title">{editorValueIndex < 0 ? "Add new value" : "Edit value" } </DialogTitle>
189           <DialogContent>
190             { ValueEditor && <ValueEditor 
191                 inputValue={ editorValue }
192                 value={{ ...element, isList: false}}
193                 disabled={false}
194                 readOnly={props.readOnly}
195                 onChange={ setEditorValue }
196             /> || null }
197           </DialogContent>
198           <DialogActions>
199             <Button color="inherit" onClick={ handleClose }> Cancel </Button>
200             <Button disabled={editorValue == null || editorValue === "" } onClick={ onApplyButton } color="secondary"> {editorValueIndex < 0 ? "Add" : "Apply"} </Button>
201           </DialogActions>
202         </Dialog>
203       </>
204   );
205 };