Skip to content

Commit

Permalink
Merge pull request #2080 from Inist-CNRS/feats/2054
Browse files Browse the repository at this point in the history
Routine builder
  • Loading branch information
touv authored Jul 5, 2024
2 parents 8b779ae + 5541ec5 commit 28713dc
Show file tree
Hide file tree
Showing 6 changed files with 327 additions and 49 deletions.
1 change: 1 addition & 0 deletions src/app/custom/translations.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -1098,3 +1098,4 @@
"ejs_variable_list" "Data from a routine is displayed using an HTML template based on EJS syntax. You can use these variables to access data and utils:" "L’affichage des données en provenance d’une routine est réalisé à l’aide d’un template HTML utilisant la syntaxe EJS. Vous pouvez utiliser ces variables pour accéder aux données et aux utilitaires :"
"ejs_data" "Variable containing the routine data" "Variable contenant les données de la routine"
"ejs_lodash" "Variable containing the Lodash function" "Variable contenant les fonctions de Lodash"
"routine_args" "Routine fields" "Champs de la routine"
2 changes: 1 addition & 1 deletion src/app/js/fields/FieldRepresentation.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ function FieldRepresentation({ field, shortMode = false, p: polyglot }) {
}

FieldRepresentation.propTypes = {
field: PropTypes.isRequired,
field: PropTypes.object.isRequired,
shortMode: PropTypes.bool,
p: polyglotPropTypes.isRequired,
};
Expand Down
13 changes: 8 additions & 5 deletions src/app/js/fields/sourceValue/SourceValuePrecomputed.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { fromPrecomputed } from '../../admin/selectors';
import { polyglot as polyglotPropTypes } from '../../propTypes';
import { Autocomplete, Box, Button, TextField } from '@mui/material';
import { toast } from 'react-toastify';
import RoutineCatalogAutocomplete from '../wizard/RoutineCatalogAutocomplete';

const SourceValuePrecomputed = ({
precomputedData,
Expand Down Expand Up @@ -97,14 +98,15 @@ const SourceValuePrecomputed = ({
)}
onChange={handleChangePrecomputed}
/>

<Box display="flex" alignItems="center">
<TextField
fullWidth
placeholder={polyglot.t('enter_a_routine_value')}
label={polyglot.t('routine_value')}
<RoutineCatalogAutocomplete
onChange={handleChangeRoutine}
value={valueInput}
currentValue={valueInput}
label={polyglot.t('enter_a_routine_value')}
precomputed
/>

<Box style={{ marginLeft: '10px', height: '56px' }}>
<Button
variant="contained"
Expand All @@ -115,6 +117,7 @@ const SourceValuePrecomputed = ({
<ListAltIcon fontSize="medium" />
</Button>
</Box>

<RoutineCatalog
isOpen={openRoutineCatalog}
handleClose={() => setOpenRoutineCatalog(false)}
Expand Down
169 changes: 126 additions & 43 deletions src/app/js/fields/sourceValue/SourceValueRoutine.js
Original file line number Diff line number Diff line change
@@ -1,71 +1,154 @@
import React from 'react';
import compose from 'recompose/compose';
import { compose } from 'recompose';
import ListAltIcon from '@mui/icons-material/ListAlt';
import PropTypes from 'prop-types';
import RoutineCatalog from '../wizard/RoutineCatalog';
import translate from 'redux-polyglot/translate';
import { polyglot as polyglotPropTypes } from '../../propTypes';
import { Box, Button, TextField } from '@mui/material';
import { Box, Button } from '@mui/material';
import { fromFields } from '../../sharedSelectors';
import { loadField } from '../index';
import { connect } from 'react-redux';
import { getFieldForSpecificScope } from '../../../../common/scope';
import SearchAutocomplete from '../../admin/Search/SearchAutocomplete';
import RoutineCatalogAutocomplete from '../wizard/RoutineCatalogAutocomplete';

const SourceValueRoutine = ({
fields,
updateDefaultValueTransformers,
value,
p: polyglot,
}) => {
const [openRoutineCatalog, setOpenRoutineCatalog] = React.useState(false);
const [valueInput, setValueInput] = React.useState(value || '');
const handleChange = (event) => {
setValueInput(event.target.value);
const transformers = [
{
operation: 'ROUTINE',
args: [
{
name: 'value',
type: 'string',
value: event.target.value,
},
],
},
];
const [routine, setRoutine] = React.useState('');
const [routineArgs, setRoutineArgs] = React.useState([]);
const [routineFields, setRoutineFields] = React.useState([]);
const [first, setFirst] = React.useState(true);

updateDefaultValueTransformers(transformers);
const fieldsResource = React.useMemo(
() => getFieldForSpecificScope(fields, 'collection'),
[fields],
);

React.useEffect(() => {
if (typeof value === 'string') {
setRoutine(value.split('/').slice(0, 4).join('/'));
const args = value.split('/').slice(4);
setRoutineArgs(args);
setRoutineFields(
fieldsResource.filter((field) => {
return args.includes(field.name);
}),
);
}
}, [value]);

React.useEffect(() => {
if (!first) {
const finalRoutine = [routine, ...routineArgs].join('/');
const transformers = [
{
operation: 'ROUTINE',
args: [
{
name: 'value',
type: 'string',
value: finalRoutine,
},
],
},
];
updateDefaultValueTransformers(transformers);
} else {
setFirst(false);
}
}, [routine, routineArgs]);

const handleRoutineChange = (event) => {
setRoutine(event.target.value);
setRoutineFields([]);
setRoutineArgs([]);
};

const handleRoutineFieldsChange = (event, newValue) => {
setRoutineFields(newValue);
setRoutineArgs(newValue.map((field) => field.name));
};

return (
<Box mt={5} display="flex" alignItems="center">
<TextField
fullWidth
placeholder={polyglot.t('enter_a_routine_value')}
label={polyglot.t('routine_value')}
onChange={handleChange}
value={valueInput}
multiline
/>
<Box style={{ marginLeft: '10px', height: '56px' }}>
<Button
variant="contained"
color="primary"
onClick={() => setOpenRoutineCatalog(true)}
sx={{ height: '100%' }}
>
<ListAltIcon fontSize="medium" />
</Button>
<Box mt={4} sx={{ flexGrow: 1, overflow: 'hidden', px: 3 }}>
<Box
sx={{ width: '100%' }}
mt={1}
display="flex"
alignItems="center"
>
<RoutineCatalogAutocomplete
onChange={handleRoutineChange}
currentValue={routine}
label={polyglot.t('enter_a_routine_value')}
/>

<Box style={{ marginLeft: '10px', height: '56px' }}>
<Button
variant="contained"
color="primary"
onClick={() => setOpenRoutineCatalog(true)}
sx={{ height: '100%' }}
>
<ListAltIcon fontSize="medium" />
</Button>
</Box>

<RoutineCatalog
isOpen={openRoutineCatalog}
handleClose={() => setOpenRoutineCatalog(false)}
onChange={handleRoutineChange}
currentValue={value}
/>
</Box>

<Box
sx={{ width: '100%' }}
mt={1}
display="flex"
alignItems="center"
>
<SearchAutocomplete
testId="autocomplete_routine_args"
translation={polyglot.t('routine_args')}
fields={fieldsResource}
onChange={handleRoutineFieldsChange}
value={routineFields}
multiple
clearText={polyglot.t('clear')}
/>
</Box>
<RoutineCatalog
isOpen={openRoutineCatalog}
handleClose={() => setOpenRoutineCatalog(false)}
onChange={handleChange}
currentValue={value}
/>
</Box>
);
};

const mapStateToProps = (state) => {
return {
// sort by label asc
fields: fromFields
.getFields(state)
.sort((a, b) => a.label.localeCompare(b.label)),
};
};

const mapDispatchToProps = {
loadField,
};

SourceValueRoutine.propTypes = {
fields: PropTypes.arrayOf(PropTypes.object).isRequired,
p: polyglotPropTypes.isRequired,
updateDefaultValueTransformers: PropTypes.func.isRequired,
value: PropTypes.string,
};

export default compose(translate)(SourceValueRoutine);
export default compose(
translate,
connect(mapStateToProps, mapDispatchToProps),
)(SourceValueRoutine);
Loading

0 comments on commit 28713dc

Please sign in to comment.