Skip to content

Commit

Permalink
[DOJOT-74] - add info tooltips and attribute label validation to temp…
Browse files Browse the repository at this point in the history
…late creation (#204)

* add info tooltips and attr label validation to template creation

* abstract attribute input label to a component

* adjust on the translations of attribute type tooltip

* removing unused useState
  • Loading branch information
LeonamMoura committed Aug 19, 2022
1 parent ac72719 commit 3ef796b
Show file tree
Hide file tree
Showing 13 changed files with 259 additions and 133 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React, { useState } from 'react';
import { TextField } from '@material-ui/core';
import PropTypes from 'prop-types';
import { useStyles } from './style';

const AttributeInputLabel = ({ className, value, handleUpdateLabel, placeholder, helperText }) => {
const classes = useStyles();
const reAttrLabel = /^[0-9a-zA-Z-_]+$/;

const [attrLabelError, setAttrLabelError] = useState(false);

const hanleChangeLabel = newLabel => {
handleUpdateLabel(newLabel);

if (reAttrLabel.test(newLabel)) {
setAttrLabelError(false);
} else {
setAttrLabelError(true);
}
};

return (
<TextField
className={className}
size='small'
value={value}
variant='outlined'
placeholder={placeholder}
onChange={e => hanleChangeLabel(e.target.value)}
error={attrLabelError}
helperText={attrLabelError ? helperText : null}
FormHelperTextProps={{
classes: {
error: classes.attrLabelHelperText,
},
}}
/>
);
};

AttributeInputLabel.propTypes = {
className: PropTypes.string.isRequired,
value: PropTypes.string.isRequired,
handleUpdateLabel: PropTypes.func.isRequired,
placeholder: PropTypes.string.isRequired,
helperText: PropTypes.string.isRequired,
};

export default AttributeInputLabel;
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ import {
} from '@material-ui/core';
import { Close, Delete, InfoOutlined } from '@material-ui/icons';
import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next';
import { Trans, useTranslation } from 'react-i18next';

import { TEMPLATE_ATTR_TYPES, TEMPLATE_ATTR_VALUE_TYPES } from '../../../constants';
import { useStyles } from './style';
import AttributeInputLabel from './AttributeInputLabel';

const TemplateCreation = ({
className,
Expand Down Expand Up @@ -82,140 +83,175 @@ const TemplateCreation = ({
</Box>

<Box className={classes.tableWrapper}>
<Table size='small'>
<TableHead className={classes.tableHead}>
<TableRow>
<TableCell>
<strong>{t('attrs:attrLabel.attrLabel')}</strong>
&nbsp;
<span>*</span>
</TableCell>

<TableCell>
<strong>{t('attrs:attrLabel.attrType')}</strong>
&nbsp;
<span>*</span>
</TableCell>

<TableCell>
<strong>{t('attrs:attrLabel.attrValueType')}</strong>
&nbsp;
<span>*</span>
</TableCell>

<TableCell>
<Tooltip
classes={{ tooltip: classes.tooltip }}
title={t('attrs:attrValueHint')}
placement='top-start'
>
<Box display='flex' alignItems='center'>
<strong>{t('attrs:attrLabel.attrValue')}</strong>
&nbsp;
<InfoOutlined fontSize='small' />
</Box>
</Tooltip>
</TableCell>

<TableCell />
</TableRow>
</TableHead>

<TableBody>
{attrs.map(({ id, label, type, valueType, staticValue }, index) => {
const isStaticAttr = type === TEMPLATE_ATTR_TYPES.STATIC.value;

const handleUpdateLabel = newLabel => {
handleUpdateAttr(index, 'label', newLabel);
};

const handleUpdateType = newType => {
if (isStaticAttr && newType !== type) {
handleUpdateAttr(index, 'staticValue', '');
}
handleUpdateAttr(index, 'type', newType);
};

const handleUpdateValueType = newValueType => {
handleUpdateAttr(index, 'valueType', newValueType);
};

const handleUpdateValue = newStaticValue => {
handleUpdateAttr(index, 'staticValue', newStaticValue);
};

return (
<TableRow key={id}>
<TableCell>
<TextField
className={classes.input}
size='small'
value={label}
variant='outlined'
placeholder={t('attrs:attrLabel.attrLabel')}
onChange={e => handleUpdateLabel(e.target.value)}
/>
</TableCell>

<TableCell>
<Select
className={classes.select}
value={type}
variant='outlined'
onChange={e => handleUpdateType(e.target.value)}
autoWidth
>
{Object.values(TEMPLATE_ATTR_TYPES).map(attrType => {
return (
<MenuItem key={attrType.value} value={attrType.value}>
{t(attrType.translation)}
</MenuItem>
);
})}
</Select>
</TableCell>

<TableCell>
<Select
className={classes.select}
value={valueType}
variant='outlined'
onChange={e => handleUpdateValueType(e.target.value)}
autoWidth
>
{Object.values(TEMPLATE_ATTR_VALUE_TYPES).map(attrValueType => {
return (
<MenuItem key={attrValueType.value} value={attrValueType.value}>
{t(attrValueType.translation)}
</MenuItem>
);
})}
</Select>
</TableCell>

<TableCell>
{isStaticAttr && (
<TextField
{attrs.length > 0 && (
<Table size='small'>
<TableHead className={classes.tableHead}>
<TableRow>
<TableCell>
<Tooltip
arrow
classes={{ tooltip: classes.tooltip }}
title={<Trans t={t} i18nKey='attrs:attrLabelHint' />}
placement='top-start'
>
<Box display='flex' alignItems='center'>
<strong>{t('attrs:attrLabel.attrLabel')}</strong>
&nbsp;
<span>*</span>
&nbsp;
<InfoOutlined fontSize='small' />
</Box>
</Tooltip>
</TableCell>

<TableCell>
<Tooltip
arrow
classes={{ tooltip: classes.tooltip }}
title={<Trans t={t} i18nKey='attrs:attrTypeHint' />}
placement='top-start'
>
<Box display='flex' alignItems='center'>
<strong>{t('attrs:attrLabel.attrType')}</strong>
&nbsp;
<span>*</span>
&nbsp;
<InfoOutlined fontSize='small' />
</Box>
</Tooltip>
</TableCell>

<TableCell>
<Tooltip
arrow
classes={{ tooltip: classes.tooltip }}
title={t('attrs:valueTypeHint')}
placement='top-start'
>
<Box display='flex' alignItems='center'>
<strong>{t('attrs:attrLabel.attrValueType')}</strong>
&nbsp;
<span>*</span>
&nbsp;
<InfoOutlined fontSize='small' />
</Box>
</Tooltip>
</TableCell>

<TableCell>
<Tooltip
arrow
classes={{ tooltip: classes.tooltip }}
title={t('attrs:attrValueHint')}
placement='top-start'
>
<Box display='flex' alignItems='center'>
<strong>{t('attrs:attrLabel.attrValue')}</strong>
&nbsp;
<InfoOutlined fontSize='small' />
</Box>
</Tooltip>
</TableCell>

<TableCell />
</TableRow>
</TableHead>

<TableBody>
{attrs.map(({ id, label, type, valueType, staticValue }, index) => {
const isStaticAttr = type === TEMPLATE_ATTR_TYPES.STATIC.value;

const handleUpdateLabel = newLabel => {
handleUpdateAttr(index, 'label', newLabel);
};

const handleUpdateType = newType => {
if (isStaticAttr && newType !== type) {
handleUpdateAttr(index, 'staticValue', '');
}
handleUpdateAttr(index, 'type', newType);
};

const handleUpdateValueType = newValueType => {
handleUpdateAttr(index, 'valueType', newValueType);
};

const handleUpdateValue = newStaticValue => {
handleUpdateAttr(index, 'staticValue', newStaticValue);
};

return (
<TableRow key={id}>
<TableCell className={classes.tableCell}>
<AttributeInputLabel
className={classes.input}
size='small'
variant='outlined'
value={staticValue}
placeholder={t('attrs:attrLabel.attrValue')}
onChange={e => handleUpdateValue(e.target.value)}
value={label}
placeholder={t('attrs:attrLabel.attrLabel')}
handleUpdateLabel={handleUpdateLabel}
helperText={t('attrs:attrLabelHint')}
/>
)}
</TableCell>

<TableCell align='right'>
<IconButton onClick={() => handleDeleteAttr(index)}>
<Delete />
</IconButton>
</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</TableCell>

<TableCell className={classes.tableCell}>
<Select
className={classes.select}
value={type}
variant='outlined'
onChange={e => handleUpdateType(e.target.value)}
autoWidth
>
{Object.values(TEMPLATE_ATTR_TYPES).map(attrType => {
return (
<MenuItem key={attrType.value} value={attrType.value}>
{t(attrType.translation)}
</MenuItem>
);
})}
</Select>
</TableCell>

<TableCell className={classes.tableCell}>
<Select
className={classes.select}
value={valueType}
variant='outlined'
onChange={e => handleUpdateValueType(e.target.value)}
autoWidth
>
{Object.values(TEMPLATE_ATTR_VALUE_TYPES).map(attrValueType => {
return (
<MenuItem key={attrValueType.value} value={attrValueType.value}>
{t(attrValueType.translation)}
</MenuItem>
);
})}
</Select>
</TableCell>

<TableCell className={classes.tableCell}>
{isStaticAttr && (
<TextField
className={classes.input}
size='small'
variant='outlined'
value={staticValue}
placeholder={t('attrs:attrLabel.attrValue')}
onChange={e => handleUpdateValue(e.target.value)}
/>
)}
</TableCell>

<TableCell align='right'>
<IconButton onClick={() => handleDeleteAttr(index)}>
<Delete />
</IconButton>
</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
)}

{attrs.length === 0 && (
<Box className={classes.noAttr}>
Expand Down
11 changes: 11 additions & 0 deletions MFE/common/src/components/WizardForms/TemplateCreation/style.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,15 @@ export const useStyles = makeStyles(theme => ({
tooltip: {
fontSize: '1rem',
},
attrLabelHelperText: {
backgroundColor: theme.palette.background.default,
color: `${theme.palette.error.main} !important`,
margin: 0,
},
tableCell: {
height: 'auto',
verticalAlign: 'top',
paddingTop: 10,
paddingBottom: 10,
},
}));
3 changes: 3 additions & 0 deletions MFE/container/src/i18n/translations/en.attrs.i18n.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
{
"attrValueHint": "You can only set the value for static attributes.",
"attrLabelHint": "Cannot contain special characteres or whitespaces",
"attrTypeHint": "<strong>Dynamic:</strong> <i>Data is sent from devices to dojot.</i><br /><strong>Actuator:</strong> <i>Data is sent from dojot to devices.</i><br /><strong>Static:</strong> <i>Attribute informed by user that contains some information about the device</i>",
"valueTypeHint": "Use Boolean for true/false, Integer or Float for numeric values, Text or JSON for texts and strings, Geo for geolocation",
"attrLabel": {
"attrLabel": "Attribute Name",
"attrType": "Attribute Type",
Expand Down
Loading

0 comments on commit 3ef796b

Please sign in to comment.