From f5cfaad132373df4c3da03f828a69258f49ac97f Mon Sep 17 00:00:00 2001 From: Martin Krulis Date: Thu, 25 Nov 2021 17:13:40 +0100 Subject: [PATCH 01/20] Refactoring pipeline edit page and related forms. Pipeline structure removed from basic edit form (will be placed into separate component). --- .../EditPipelineEnvironmentsForm.js | 70 ++++++ .../EditPipelineEnvironmentsForm/index.js | 2 + .../EditPipelineForm/EditPipelineForm.js | 224 +++++++++--------- src/locales/cs.json | 18 +- src/locales/en.json | 18 +- src/pages/EditPipeline/EditPipeline.js | 129 +++++++--- .../resourceManager/actionTypesFactory.js | 15 +- src/redux/helpers/resourceManager/index.js | 3 +- src/redux/modules/pipelines.js | 32 ++- 9 files changed, 348 insertions(+), 163 deletions(-) create mode 100644 src/components/forms/EditPipelineEnvironmentsForm/EditPipelineEnvironmentsForm.js create mode 100644 src/components/forms/EditPipelineEnvironmentsForm/index.js diff --git a/src/components/forms/EditPipelineEnvironmentsForm/EditPipelineEnvironmentsForm.js b/src/components/forms/EditPipelineEnvironmentsForm/EditPipelineEnvironmentsForm.js new file mode 100644 index 000000000..8a5d8d350 --- /dev/null +++ b/src/components/forms/EditPipelineEnvironmentsForm/EditPipelineEnvironmentsForm.js @@ -0,0 +1,70 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { reduxForm } from 'redux-form'; +import { FormattedMessage } from 'react-intl'; + +import EditEnvironmentList from '../EditEnvironmentSimpleForm/EditEnvironmentList'; +import { SaveIcon } from '../../icons'; +import Callout from '../../widgets/Callout'; +import FormBox from '../../widgets/FormBox'; +import SubmitButton from '../SubmitButton'; + +class EditPipelineEnvironmentsForm extends Component { + render() { + const { runtimeEnvironments, dirty, submitting, handleSubmit, submitFailed, submitSucceeded, invalid } = this.props; + return ( + + } + succeeded={submitSucceeded} + dirty={dirty} + footer={ +
+ } + messages={{ + submit: , + submitting: , + success: , + }} + /> +
+ }> + {submitFailed && ( + + + + )} + + +
+ ); + } +} + +EditPipelineEnvironmentsForm.propTypes = { + runtimeEnvironments: PropTypes.array.isRequired, + handleSubmit: PropTypes.func.isRequired, + dirty: PropTypes.bool, + submitting: PropTypes.bool, + submitFailed: PropTypes.bool, + submitSucceeded: PropTypes.bool, + invalid: PropTypes.bool, +}; + +export default reduxForm({ + form: 'editPipelineEnvironments', + enableReinitialize: true, + keepDirtyOnReinitialize: false, +})(EditPipelineEnvironmentsForm); diff --git a/src/components/forms/EditPipelineEnvironmentsForm/index.js b/src/components/forms/EditPipelineEnvironmentsForm/index.js new file mode 100644 index 000000000..3b5af4e6d --- /dev/null +++ b/src/components/forms/EditPipelineEnvironmentsForm/index.js @@ -0,0 +1,2 @@ +import EditPipelineEnvironmentsForm from './EditPipelineEnvironmentsForm'; +export default EditPipelineEnvironmentsForm; diff --git a/src/components/forms/EditPipelineForm/EditPipelineForm.js b/src/components/forms/EditPipelineForm/EditPipelineForm.js index 228af7fa3..99887d1a0 100644 --- a/src/components/forms/EditPipelineForm/EditPipelineForm.js +++ b/src/components/forms/EditPipelineForm/EditPipelineForm.js @@ -1,72 +1,46 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import { connect } from 'react-redux'; -import { reduxForm, Field, touch, formValueSelector } from 'redux-form'; +import { reduxForm, Field } from 'redux-form'; import { FormattedMessage } from 'react-intl'; import { Container, Row, Col } from 'react-bootstrap'; -import { TextField, MarkdownTextAreaField, PipelineField, PipelineVariablesField } from '../Fields'; - +import { TextField, MarkdownTextAreaField, CheckboxField } from '../Fields'; +import { SaveIcon } from '../../icons'; import Callout from '../../widgets/Callout'; import FormBox from '../../widgets/FormBox'; import SubmitButton from '../SubmitButton'; -import { validatePipeline } from '../../../redux/modules/pipelines'; -import { extractVariables } from '../../../helpers/boxes'; -import { fetchSupplementaryFilesForPipeline } from '../../../redux/modules/pipelineFiles'; -import { createGetPipelineFiles } from '../../../redux/selectors/pipelineFiles'; class EditPipelineForm extends Component { - componentDidMount = () => this.props.loadAsync(); - - componentDidUpdate(prevProps) { - if (this.props.pipeline.id !== prevProps.pipeline.id) { - this.props.loadAsync(); - } - } - render() { const { - initialValues: pipeline, - anyTouched, + isSuperadmin = false, + dirty, submitting, handleSubmit, submitFailed, submitSucceeded, - variables = [], invalid, - asyncValidating, - supplementaryFiles, } = this.props; return ( - } + title={} succeeded={submitSucceeded} - dirty={anyTouched} + dirty={dirty} footer={
} messages={{ - submit: , - submitting: ( - - ), - success: , - validating: , + submit: , + submitting: , + success: , }} />
@@ -93,37 +67,110 @@ class EditPipelineForm extends Component { label={ } /> - - - } - /> - - - - +
+ + + + + } /> - } - supplementaryFiles={supplementaryFiles} - /> - - + +
+ +
+ + + + + } + /> + + + + } + /> + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> + + + + )}
); @@ -131,19 +178,15 @@ class EditPipelineForm extends Component { } EditPipelineForm.propTypes = { - initialValues: PropTypes.object.isRequired, + isSuperadmin: PropTypes.bool, values: PropTypes.object, handleSubmit: PropTypes.func.isRequired, - anyTouched: PropTypes.bool, + dirty: PropTypes.bool, submitting: PropTypes.bool, submitFailed: PropTypes.bool, submitSucceeded: PropTypes.bool, invalid: PropTypes.bool, - variables: PropTypes.array, asyncValidating: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]), - supplementaryFiles: ImmutablePropTypes.map, - loadAsync: PropTypes.func.isRequired, - pipeline: PropTypes.object, }; const validate = ({ name, description }) => { @@ -170,42 +213,9 @@ const validate = ({ name, description }) => { return errors; }; -const asyncValidate = (values, dispatch, { initialValues: { id, version } }) => - new Promise((resolve, reject) => - dispatch(validatePipeline(id, version)) - .then(res => res.value) - .then(({ versionIsUpToDate }) => { - const errors = {}; - if (versionIsUpToDate === false) { - errors.name = ( - - ); - dispatch(touch('editPipeline', 'name')); - } - - if (Object.keys(errors).length > 0) { - throw errors; - } - }) - .then(resolve()) - .catch(errors => reject(errors)) - ); - -export default connect( - (state, { pipeline }) => ({ - variables: extractVariables(formValueSelector('editPipeline')(state, 'pipeline.boxes')), - supplementaryFiles: createGetPipelineFiles(pipeline.supplementaryFilesIds)(state), - }), - (dispatch, { pipeline }) => ({ - loadAsync: () => dispatch(fetchSupplementaryFilesForPipeline(pipeline.id)), - }) -)( - reduxForm({ - form: 'editPipeline', - validate, - asyncValidate, - })(EditPipelineForm) -); +export default reduxForm({ + form: 'editPipeline', + enableReinitialize: true, + keepDirtyOnReinitialize: false, + validate, +})(EditPipelineForm); diff --git a/src/locales/cs.json b/src/locales/cs.json index a7a95b0c6..677a36228 100644 --- a/src/locales/cs.json +++ b/src/locales/cs.json @@ -480,14 +480,18 @@ "app.editPipeline.disclaimer": "Upozornění", "app.editPipeline.disclaimerWarning": "Upravení pipeline může rozbít všechny úlohy, které pipeline používají!", "app.editPipeline.title": "Změnit nastavení a obsah pipeline", - "app.editPipelineFields.pipeline": "Pipeline:", - "app.editPipelineFields.pipelineVariables": "Pipeline proměnné:", - "app.editPipelineForm.description": "Popis pro vedoucího skupiny:", + "app.editPipelineEnvironmentsForm.title": "Běhová prostředí pipeline", + "app.editPipelineForm.description": "Podrobnější popis (pro autory úloh):", + "app.editPipelineForm.global": "Globalní pipeline spojená s konkrétními běhovými prostředími", + "app.editPipelineForm.hasEntryPoint": "Obsahuje vstupní bod", + "app.editPipelineForm.hasExtraFiles": "Obsahuje extra soubory", + "app.editPipelineForm.isCompilationPipeline": "Kompilační", + "app.editPipelineForm.isExecutionPipeline": "Spouštěcí", + "app.editPipelineForm.judgeOnlyPipeline": "Pouze sudí", "app.editPipelineForm.name": "Jméno pipeline:", - "app.editPipelineForm.submit": "Uložit změny", - "app.editPipelineForm.submitting": "Ukládání...", - "app.editPipelineForm.success": "Změny byly uloženy.", - "app.editPipelineForm.title": "Změnit pipeline {name}", + "app.editPipelineForm.producesFiles": "Produkuje výstupní soubory", + "app.editPipelineForm.producesStdout": "Produkuje std. výstup", + "app.editPipelineForm.title": "Metadata pipeline", "app.editPipelineForm.validation.description": "Prosíme vyplňte popis této pipeline.", "app.editPipelineForm.validation.emptyName": "Prosíme vyplňte název této pipeline.", "app.editPipelineForm.validation.versionDiffers": "Někdo změnil nastavení této pipeline v průběhu její editace. Prosíme obnovte tuto stránku a proveďte své změny znovu.", diff --git a/src/locales/en.json b/src/locales/en.json index 4ecd821d8..0323726c4 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -480,14 +480,18 @@ "app.editPipeline.disclaimer": "Disclaimer", "app.editPipeline.disclaimerWarning": "Modifying the pipeline might break all exercises using the pipeline!", "app.editPipeline.title": "Change Pipeline Settings and Contents", - "app.editPipelineFields.pipeline": "The pipeline:", - "app.editPipelineFields.pipelineVariables": "Pipeline variables:", - "app.editPipelineForm.description": "Description for supervisors:", + "app.editPipelineEnvironmentsForm.title": "Pipeline Runtime Environments", + "app.editPipelineForm.description": "Detailed description (for exercise authors):", + "app.editPipelineForm.global": "Global pipeline associated with particular runtime environments", + "app.editPipelineForm.hasEntryPoint": "Has entry-point", + "app.editPipelineForm.hasExtraFiles": "Has extra files", + "app.editPipelineForm.isCompilationPipeline": "Compilation", + "app.editPipelineForm.isExecutionPipeline": "Execution", + "app.editPipelineForm.judgeOnlyPipeline": "Judge-Only", "app.editPipelineForm.name": "Pipeline name:", - "app.editPipelineForm.submit": "Save changes", - "app.editPipelineForm.submitting": "Saving changes...", - "app.editPipelineForm.success": "Settings were saved.", - "app.editPipelineForm.title": "Edit pipeline {name}", + "app.editPipelineForm.producesFiles": "Produces output files", + "app.editPipelineForm.producesStdout": "Produces std. out", + "app.editPipelineForm.title": "Pipeline Metadata", "app.editPipelineForm.validation.description": "Please fill the description of the pipeline.", "app.editPipelineForm.validation.emptyName": "Please fill the name of the pipeline.", "app.editPipelineForm.validation.versionDiffers": "Somebody has changed the pipeline while you have been editing it. Please reload the page and apply your changes once more.", diff --git a/src/pages/EditPipeline/EditPipeline.js b/src/pages/EditPipeline/EditPipeline.js index 11fcb9ab9..224a9990e 100644 --- a/src/pages/EditPipeline/EditPipeline.js +++ b/src/pages/EditPipeline/EditPipeline.js @@ -4,23 +4,45 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import { FormattedMessage } from 'react-intl'; import { Row, Col } from 'react-bootstrap'; import { connect } from 'react-redux'; -import { reset, formValueSelector } from 'redux-form'; +import { reset } from 'redux-form'; +import { defaultMemoize } from 'reselect'; import Page from '../../components/layout/Page'; import Box from '../../components/widgets/Box'; import Callout from '../../components/widgets/Callout'; import EditPipelineForm from '../../components/forms/EditPipelineForm'; +import EditPipelineEnvironmentsForm from '../../components/forms/EditPipelineEnvironmentsForm'; import { EditIcon } from '../../components/icons'; import PipelineFilesTableContainer from '../../containers/PipelineFilesTableContainer'; import DeletePipelineButtonContainer from '../../containers/DeletePipelineButtonContainer'; +import ResourceRenderer from '../../components/helpers/ResourceRenderer'; -import { fetchPipelineIfNeeded, editPipeline } from '../../redux/modules/pipelines'; +import { fetchPipelineIfNeeded, editPipeline, setPipelineRuntimeEnvironments } from '../../redux/modules/pipelines'; +import { fetchRuntimeEnvironments } from '../../redux/modules/runtimeEnvironments'; import { getPipeline } from '../../redux/selectors/pipelines'; -import { loggedInUserIdSelector } from '../../redux/selectors/auth'; -import { getBoxTypes } from '../../redux/selectors/boxes'; +import { runtimeEnvironmentsSelector } from '../../redux/selectors/runtimeEnvironments'; +import { isLoggedAsSuperAdmin } from '../../redux/selectors/users'; import withLinks from '../../helpers/withLinks'; -import { transformPipelineDataForApi, extractVariables } from '../../helpers/boxes'; +import { arrayToObject } from '../../helpers/common'; + +// convert pipeline data into initial structure for pipeline edit metadata form +const perpareInitialPipelineData = ({ name, description, version, parameters, author }) => ({ + name, + description, + version, + parameters, + global: author === null, +}); + +// get selected runtimes and all runtimes and prepare object for environment selection form +const perpareInitialEnvironmentsData = defaultMemoize((selectedIds, runtimeEnvironments) => + arrayToObject( + runtimeEnvironments.map(rte => rte.id), + id => id, + id => selectedIds.includes(id) + ) +); class EditPipeline extends Component { componentDidMount = () => this.props.loadAsync(); @@ -32,16 +54,52 @@ class EditPipeline extends Component { } } - static loadAsync = ({ pipelineId }, dispatch) => Promise.all([dispatch(fetchPipelineIfNeeded(pipelineId))]); + static loadAsync = ({ pipelineId }, dispatch) => + Promise.all([dispatch(fetchPipelineIfNeeded(pipelineId)), dispatch(fetchRuntimeEnvironments())]); + + // save pipeline metadata (not the structure) + savePipeline = ({ + name, + description, + version, + parameters: { + isCompilationPipeline = false, + isExecutionPipeline = false, + judgeOnlyPipeline = false, + producesStdout = false, + producesFiles = false, + hasEntryPoint = false, + hasExtraFiles = false, + }, + global, + }) => { + const dataForApi = { name, description, version }; + if (this.props.isSuperadmin) { + dataForApi.parameters = { + isCompilationPipeline, + isExecutionPipeline, + judgeOnlyPipeline, + producesStdout, + producesFiles, + hasEntryPoint, + hasExtraFiles, + }; + dataForApi.global = global; + } + return this.props.editPipeline(dataForApi); + }; + + // save associations between pipeline and runtime environments + saveEnvironments = formData => + this.props.setPipelineRuntimeEnvironments(Object.keys(formData).filter(id => formData[id])); render() { const { links: { PIPELINES_URI }, history: { replace }, pipeline, - boxTypes, - editPipeline, - variables: extractedVariables, + runtimeEnvironments, + isSuperadmin, } = this.props; return ( @@ -66,31 +124,15 @@ class EditPipeline extends Component { + ({ - ...acc, - [btoa(variable.name)]: variable.value, - }), - {} - ), - }, - }} - onSubmit={({ pipeline, ...formData }) => - editPipeline(data.version, { - pipeline: transformPipelineDataForApi(boxTypes, pipeline, extractedVariables), - ...formData, - }) - } - pipeline={data} + initialValues={perpareInitialPipelineData(data)} + onSubmit={this.savePipeline} + isSuperadmin={isSuperadmin} /> @@ -99,11 +141,26 @@ class EditPipeline extends Component {
+ + + {isSuperadmin && ( + + {environments => ( + + )} + + )} + + { return { pipeline: getPipeline(pipelineId)(state), - boxTypes: getBoxTypes(state), - userId: loggedInUserIdSelector(state), - variables: extractVariables(formValueSelector('editPipeline')(state, 'pipeline.boxes')), + runtimeEnvironments: runtimeEnvironmentsSelector(state), + isSuperadmin: isLoggedAsSuperAdmin(state), }; }, ( @@ -176,7 +233,9 @@ export default withLinks( ) => ({ reset: () => dispatch(reset('editPipeline')), loadAsync: () => EditPipeline.loadAsync({ pipelineId }, dispatch), - editPipeline: (version, data) => dispatch(editPipeline(pipelineId, { ...data, version })), + editPipeline: data => dispatch(editPipeline(pipelineId, data)), + setPipelineRuntimeEnvironments: environments => + dispatch(setPipelineRuntimeEnvironments(pipelineId, environments)), }) )(EditPipeline) ); diff --git a/src/redux/helpers/resourceManager/actionTypesFactory.js b/src/redux/helpers/resourceManager/actionTypesFactory.js index 7b95b2ab8..7298099bb 100644 --- a/src/redux/helpers/resourceManager/actionTypesFactory.js +++ b/src/redux/helpers/resourceManager/actionTypesFactory.js @@ -2,14 +2,26 @@ * @module actionTypesFactory */ +import { arrayToObject } from '../../../helpers/common'; + const defaultPrefix = resourceName => `recodex/resource/${resourceName}`; const twoPhaseActions = ['ADD', 'UPDATE', 'REMOVE', 'FETCH', 'FETCH_MANY']; const onePhaseActions = ['INVALIDATE']; +export const defaultActionPostfixes = ['', '_PENDING', '_FULFILLED', '_REJECTED']; +export const createActionsWithPostfixes = (baseName, prefix, postfixes = defaultActionPostfixes) => + arrayToObject( + postfixes, + postfix => `${baseName}${postfix}`, + postfix => `${prefix}/${baseName}${postfix}` + ); + export const getActionTypes = (prefix, actions, postfixes = ['']) => actions.reduce( (acc, action) => ({ ...acc, + ...createActionsWithPostfixes(action, prefix, postfixes), + /* ...postfixes.reduce( (acc, postfix) => ({ ...acc, @@ -17,6 +29,7 @@ export const getActionTypes = (prefix, actions, postfixes = ['']) => }), {} ), + */ }), {} ); @@ -26,7 +39,7 @@ export const getActionTypes = (prefix, actions, postfixes = ['']) => * @param {string} prefix Unique prefix for the actions */ const actionTypesFactory = (resourceName, prefix = defaultPrefix(resourceName)) => ({ - ...getActionTypes(prefix, twoPhaseActions, ['', '_PENDING', '_FULFILLED', '_REJECTED']), + ...getActionTypes(prefix, twoPhaseActions, defaultActionPostfixes), ...getActionTypes(prefix, onePhaseActions), }); diff --git a/src/redux/helpers/resourceManager/index.js b/src/redux/helpers/resourceManager/index.js index f74a9000d..b91ffc771 100644 --- a/src/redux/helpers/resourceManager/index.js +++ b/src/redux/helpers/resourceManager/index.js @@ -1,7 +1,7 @@ import { createAction } from 'redux-actions'; import { createApiAction } from '../../middleware/apiMiddleware'; -import actionTypesFactory from './actionTypesFactory'; +import actionTypesFactory, { createActionsWithPostfixes } from './actionTypesFactory'; import actionCreatorsFactory from './actionCreatorsFactory'; import reducerFactory, { initialState } from './reducerFactory'; import createRecord, { getData, getJsData, getId } from './recordFactory'; @@ -43,6 +43,7 @@ export { getId, defaultNeedsRefetching, createRecord, + createActionsWithPostfixes, }; /** diff --git a/src/redux/modules/pipelines.js b/src/redux/modules/pipelines.js index 876c150a2..59c1ece15 100644 --- a/src/redux/modules/pipelines.js +++ b/src/redux/modules/pipelines.js @@ -1,6 +1,11 @@ import { handleActions } from 'redux-actions'; import { Map, List } from 'immutable'; -import factory, { initialState, createRecord, resourceStatus } from '../helpers/resourceManager'; +import factory, { + initialState, + createRecord, + resourceStatus, + createActionsWithPostfixes, +} from '../helpers/resourceManager'; import { createApiAction } from '../middleware/apiMiddleware'; import { actionTypes as pipelineFilesActionTypes } from './pipelineFiles'; @@ -13,10 +18,8 @@ const { actions, reduceActions } = factory({ resourceName }); export const additionalActionTypes = { VALIDATE_PIPELINE: 'recodex/pipelines/VALIDATE_PIPELINE', - FORK_PIPELINE: 'recodex/pipelines/FORK_PIPELINE', - FORK_PIPELINE_PENDING: 'recodex/pipelines/FORK_PIPELINE_PENDING', - FORK_PIPELINE_REJECTED: 'recodex/pipelines/FORK_PIPELINE_REJECTED', - FORK_PIPELINE_FULFILLED: 'recodex/pipelines/FORK_PIPELINE_FULFILLED', + ...createActionsWithPostfixes('FORK_PIPELINE', 'recodex/pipelines'), + ...createActionsWithPostfixes('SET_ENVIRONMENTS', 'recodex/pipelines'), }; export const fetchPipeline = actions.fetchResource; @@ -70,6 +73,14 @@ export const validatePipeline = (id, version) => body: { version }, }); +export const setPipelineRuntimeEnvironments = (id, environments) => + createApiAction({ + type: additionalActionTypes.SET_ENVIRONMENTS, + endpoint: `/pipelines/${id}/runtime-environments`, + method: 'POST', + body: { environments }, + }); + const reducer = handleActions( Object.assign({}, reduceActions, { [pipelineFilesActionTypes.ADD_FILES_FULFILLED]: (state, { payload: files, meta: { pipelineId } }) => @@ -95,6 +106,17 @@ const reducer = handleActions( pipelineId, }), + [additionalActionTypes.SET_ENVIRONMENTS_FULFILLED]: (state, { payload }) => + state.setIn( + ['resources', payload.id], + createRecord({ + data: payload, + state: resourceStatus.FULFILLED, + didInvalidate: false, + lastUpdate: Date.now(), + }) + ), + // Pagination result needs to store entity data here whilst indices are stored in pagination module [paginationActionTypes.FETCH_PAGINATED_FULFILLED]: (state, { payload: { items }, meta: { endpoint } }) => endpoint === 'pipelines' From cf9eebf17f2c9bf8d98626e72061eeb3ec6ffa45 Mon Sep 17 00:00:00 2001 From: Martin Krulis Date: Thu, 2 Dec 2021 16:21:53 +0100 Subject: [PATCH 02/20] New interface for displaying and editing pipeline configuration. --- src/components/Pipelines/BoxForm/BoxForm.js | 471 ++++++++++------- src/components/Pipelines/BoxForm/index.js | 3 + .../Pipelines/BoxesTable/BoxesTable.js | 96 ++++ .../Pipelines/BoxesTable/BoxesTableRow.js | 308 +++++++++++ src/components/Pipelines/BoxesTable/index.js | 2 + .../Pipelines/VariableForm/VariableForm.js | 265 ++++++++++ .../Pipelines/VariableForm/index.js | 3 + .../VariablesTable/VariablesTable.js | 197 +++++++ .../Pipelines/VariablesTable/index.js | 2 + src/components/Pipelines/styles.less | 25 + .../EditSystemMessageForm.js | 46 +- .../forms/Fields/ExpandingTextField.js | 4 +- src/components/icons/index.js | 3 + src/containers/App/recodex.css | 8 + .../PipelineEditContainer.js | 479 ++++++++++++++++++ src/containers/PipelineEditContainer/index.js | 2 + .../SisSupervisorGroupsContainer.js | 15 +- src/helpers/boxes.js | 5 + src/helpers/dot.js | 5 + src/helpers/pipelines.js | 102 ++++ src/locales/cs.json | 60 ++- src/locales/en.json | 60 ++- src/locales/whitelist_cs.json | 1 + src/pages/EditPipeline/EditPipeline.js | 24 +- src/redux/modules/boxes.js | 2 +- src/redux/selectors/boxes.js | 20 +- 26 files changed, 1962 insertions(+), 246 deletions(-) create mode 100644 src/components/Pipelines/BoxForm/index.js create mode 100644 src/components/Pipelines/BoxesTable/BoxesTable.js create mode 100644 src/components/Pipelines/BoxesTable/BoxesTableRow.js create mode 100644 src/components/Pipelines/BoxesTable/index.js create mode 100644 src/components/Pipelines/VariableForm/VariableForm.js create mode 100644 src/components/Pipelines/VariableForm/index.js create mode 100644 src/components/Pipelines/VariablesTable/VariablesTable.js create mode 100644 src/components/Pipelines/VariablesTable/index.js create mode 100644 src/components/Pipelines/styles.less create mode 100644 src/containers/PipelineEditContainer/PipelineEditContainer.js create mode 100644 src/containers/PipelineEditContainer/index.js create mode 100644 src/helpers/pipelines.js diff --git a/src/components/Pipelines/BoxForm/BoxForm.js b/src/components/Pipelines/BoxForm/BoxForm.js index 3d982aa04..836439f01 100644 --- a/src/components/Pipelines/BoxForm/BoxForm.js +++ b/src/components/Pipelines/BoxForm/BoxForm.js @@ -1,135 +1,211 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { FormattedMessage } from 'react-intl'; - +import { Modal, Table, Container, Row, Col } from 'react-bootstrap'; import { connect } from 'react-redux'; import { reduxForm, Field, formValueSelector } from 'redux-form'; +import { defaultMemoize } from 'reselect'; -import { TextField, SelectField, PortsField } from '../../forms/Fields'; -import { Modal } from 'react-bootstrap'; -import Button from '../../widgets/TheButton'; -import Callout from '../../widgets/Callout'; -import DeleteButton from '../../buttons/DeleteButton'; +import { TextField, SelectField } from '../../forms/Fields'; +import Button, { TheButtonGroup } from '../../widgets/TheButton'; import SubmitButton from '../../forms/SubmitButton'; -import { CloseIcon, SaveIcon } from '../../../components/icons'; +import { CloseIcon, SaveIcon, RefreshIcon, InputIcon, OutputIcon } from '../../../components/icons'; +import { encodeId, safeSet } from '../../../helpers/common'; -import { fetchBoxTypes } from '../../../redux/modules/boxes'; -import { getBoxTypes } from '../../../redux/selectors/boxes'; -import { getVariablesTypes } from '../../../helpers/boxes'; +export const newBoxInitialData = { name: '', type: '', portsIn: {}, portsOut: {} }; -class BoxForm extends Component { - componentDidMount = () => this.loadBoxTypes(); +const prepareBoxTypeOptions = defaultMemoize(boxTypes => + Object.values(boxTypes) + .map(({ name, type }) => ({ key: type, name: `${name} (${type})` })) + .sort((a, b) => a.name.localeCompare(b.name, 'en')) +); - loadBoxTypes() { - const { fetchBoxTypes } = this.props; - fetchBoxTypes(); - } +const getSortedPorts = ports => + ports && + Object.keys(ports) + .sort() + .map(name => ({ name, ...ports[name] })); +const preparePortsOfSelectedBoxType = defaultMemoize(boxType => { + const portsIn = (boxType && getSortedPorts(boxType.portsIn)) || []; + const portsOut = (boxType && getSortedPorts(boxType.portsOut)) || []; + return { portsIn, portsOut }; +}); + +class BoxForm extends Component { render() { const { show, + editting = null, boxTypes, + variables, selectedType, - title, handleSubmit, submitSucceeded = false, - submitFailed = false, - anyTouched = false, - asyncValidating = false, invalid = false, + dirty = false, submitting = false, reset, onHide, - onDelete, } = this.props; - const currentBoxType = boxTypes.find(box => box.type === selectedType); - const getPortsArray = ports => Object.keys(ports).map(port => ({ name: port, ...ports[port] })); + const { portsIn, portsOut } = preparePortsOfSelectedBoxType(selectedType && boxTypes[selectedType]); return ( - - {title} - - {submitFailed && ( - + + +
+ {editting ? ( {content} }} /> - - )} + ) : ( + + )} +
+
- - : - - } - /> + + + {variables.map(({ name }) => ( + + ))} + + + + + + : + + } + /> + - ({ key: type, name }))]} - required - label={} - /> + + } + /> + + - {currentBoxType && ( - } - /> - )} + {((portsIn && portsIn.length > 0) || (portsOut && portsOut.length > 0)) &&
} - {currentBoxType && ( - } - /> - )} + + {portsIn && portsIn.length > 0 && ( + 0 ? 6 : 12}> +
+ + +
+ + + {portsIn.map(port => ( + + + + + + ))} + +
+ {port.name} + + {port.type} + + +
+ + )} + + {portsOut && portsOut.length > 0 && ( + 0 ? 6 : 12}> +
+ + +
+ + + {portsOut.map(port => ( + + + + + + ))} + +
+ {port.name} + + {port.type} + + +
+ + )} +
+
+ -

- { - handleSubmit(); - return Promise.resolve(); - }} - submitting={submitting} - invalid={invalid} - dirty={anyTouched} - hasFailed={submitFailed} - hasSuceeded={submitSucceeded} - asyncValidating={asyncValidating} - reset={reset} - defaultIcon={} - messages={{ - success: , - submit: , - submitting: , - }} - /> - - - -

+
+ + {(dirty || editting) && ( + { + handleSubmit(); + return Promise.resolve(); + }} + submitting={submitting} + invalid={invalid} + dirty={dirty} + hasSuceeded={submitSucceeded} + reset={reset} + defaultIcon={} + messages={{ + success: , + submit: , + submitting: , + }} + /> + )} + {dirty && ( + + )} + + +
); @@ -138,120 +214,157 @@ class BoxForm extends Component { BoxForm.propTypes = { show: PropTypes.bool, - title: PropTypes.oneOfType([PropTypes.string, PropTypes.element]).isRequired, - selectedType: PropTypes.string, - boxTypes: PropTypes.array.isRequired, + editting: PropTypes.string, + boxTypes: PropTypes.object.isRequired, + boxes: PropTypes.array.isRequired, + variables: PropTypes.array.isRequired, + variablesUtilization: PropTypes.object.isRequired, onSubmit: PropTypes.func.isRequired, + onHide: PropTypes.func.isRequired, + selectedType: PropTypes.string, handleSubmit: PropTypes.func.isRequired, reset: PropTypes.func.isRequired, submitFailed: PropTypes.bool, submitSucceeded: PropTypes.bool, - anyTouched: PropTypes.bool, - asyncValidating: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]), invalid: PropTypes.bool, - existingBoxes: PropTypes.array.isRequired, + dirty: PropTypes.bool, submitting: PropTypes.bool, - fetchBoxTypes: PropTypes.func.isRequired, - onHide: PropTypes.func.isRequired, - onDelete: PropTypes.func.isRequired, }; -const validate = ({ name, type, portsIn = {}, portsOut = {} }, { boxTypes, existingBoxes }) => { +const validate = ( + { name, type, portsIn = {}, portsOut = {} }, + { boxes, boxTypes, variables, variablesUtilization, editting, dirty } +) => { const errors = {}; + if (!dirty && !editting) { + return errors; + } - if (!name || name.length === 0) { - errors.name = ; + if (!name || name.trim() === '') { + errors.name = ; } - if (!type) { + if (name && name.trim() !== editting && boxes && boxes.find(v => v.name === name.trim())) { + errors.name = ( + + ); + } + + const boxType = type && boxTypes[type]; + if (!boxType) { errors.type = ( - + ); } else { - const boxType = boxTypes.find(box => box.type === type); - if (boxType) { - const portsInNames = Object.keys(boxType.portsIn); - const portsOutNames = Object.keys(boxType.portsOut); - const portsInErrors = {}; - - const existingVariablesTypes = getVariablesTypes( - boxTypes, - existingBoxes.filter(box => box.name !== name && box.type !== type) - ); + // Check that associated variables match the prescribed port types + const formDataPorts = { portsIn, portsOut }; + Object.keys(formDataPorts).forEach(ports => + Object.keys(boxType[ports]).forEach(portName => { + const variableName = (formDataPorts[ports][encodeId(portName)] || '').trim(); + const variable = variableName && variables.find(v => v.name === variableName); + if (variable && boxType[ports][portName].type !== variable.type) { + safeSet( + errors, + [ports, encodeId(portName)], + {content}, + }} + /> + ); + } + }) + ); - for (const portName of portsInNames) { - if (portsIn[portName] && portsIn[portName].length > 0) { - const intendedVariableName = portsIn[portName].value; - const portType = boxType.portsIn[portName].type; - const existingVariableType = existingVariablesTypes[intendedVariableName]; - if (existingVariableType && existingVariableType.type !== portType) { - portsInErrors[portName] = { - value: ( - {text}, - }} - /> - ), - }; - } + // Check that variables are not associated with too many output ports + const utilizations = {}; + Object.keys(boxType.portsOut) + .map(portName => (portsOut[encodeId(portName)] || '').trim()) + .filter(varName => varName && variablesUtilization[varName]) + .forEach(varName => { + if (!utilizations[varName]) { + utilizations[varName] = + variablesUtilization[varName].portsOut.length - // number of boxes, where the var is used in output + variablesUtilization[varName].portsOut.filter(box => box.name === editting).length; // -1 if this box is on the list } - } + ++utilizations[varName]; // increment utilization since this one variable will be present + }); - // check that the variable in a certain port has the correct port - if (Object.keys(portsInErrors).length > 0) { - errors.portsIn = portsInErrors; + Object.keys(boxType.portsOut).forEach(portName => { + const varName = portsOut[encodeId(portName)].trim(); + if (utilizations[varName] > 1) { + safeSet( + errors, + ['portsOut', encodeId(portName)], + + ); } + }); + } + + return errors; +}; - const portsOutErrors = {}; +const warn = ({ name, type, portsIn = {}, portsOut = {} }, { boxTypes, variables, editting, dirty }) => { + const warnings = {}; + if (!dirty && !editting) { + return warnings; + } - // check that one box does not have the same var as input and output - for (const portIn of portsInNames) { - for (const portOut of portsOutNames) { - if (portsIn[portIn] && portsOut[portOut] && portsIn[portIn].value === portsOut[portOut].value) { - portsOutErrors[portOut] = { - value: ( - - ), - }; - } - } - } + if (name && !name.trim().match(/^[-a-zA-Z0-9_]+$/)) { + warnings.name = ( + + ); + } - if (Object.keys(portsOutErrors).length > 0) { - errors.portsOut = portsOutErrors; - } - } + const boxType = type && boxTypes[type]; + if (boxType) { + // Check that associated variables match the prescribed port types + const formDataPorts = { portsIn, portsOut }; + Object.keys(formDataPorts).forEach(ports => + Object.keys(boxType[ports]).forEach(portName => { + const variableName = (formDataPorts[ports][encodeId(portName)] || '').trim(); + const variable = variableName && variables.find(v => v.name === variableName); + if (variableName && !variable) { + safeSet( + warnings, + [ports, encodeId(portName)], + + ); + } + }) + ); } - return errors; + return warnings; }; const mapStateToProps = state => ({ - boxTypes: getBoxTypes(state), - existingBoxes: formValueSelector('editPipeline')(state, 'pipeline.boxes'), selectedType: formValueSelector('boxForm')(state, 'type'), }); -const mapDispatchToProps = dispatch => ({ - fetchBoxTypes: () => dispatch(fetchBoxTypes()), -}); - -export default connect( - mapStateToProps, - mapDispatchToProps -)( +export default connect(mapStateToProps)( reduxForm({ form: 'boxForm', + enableReinitialize: true, + keepDirtyOnReinitialize: false, validate, + warn, })(BoxForm) ); diff --git a/src/components/Pipelines/BoxForm/index.js b/src/components/Pipelines/BoxForm/index.js new file mode 100644 index 000000000..a94bc3bf9 --- /dev/null +++ b/src/components/Pipelines/BoxForm/index.js @@ -0,0 +1,3 @@ +import BoxForm, { newBoxInitialData } from './BoxForm'; +export { newBoxInitialData }; +export default BoxForm; diff --git a/src/components/Pipelines/BoxesTable/BoxesTable.js b/src/components/Pipelines/BoxesTable/BoxesTable.js new file mode 100644 index 000000000..a4641bc84 --- /dev/null +++ b/src/components/Pipelines/BoxesTable/BoxesTable.js @@ -0,0 +1,96 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { injectIntl, FormattedMessage } from 'react-intl'; +import { Table } from 'react-bootstrap'; +import { defaultMemoize } from 'reselect'; + +import BoxesTableRow from './BoxesTableRow'; +import { arrayToObject } from '../../../helpers/common'; + +const prepareSelectionIndex = defaultMemoize( + selections => + selections && + arrayToObject( + selections, + x => x, + () => true + ) +); + +const BoxesTable = ({ + boxes, + variables = null, + secondarySelections = null, + selectedVariable = null, + removeBox = null, + intl: { locale }, + ...rowProps +}) => { + const selectionIndex = secondarySelections && prepareSelectionIndex(secondarySelections); + const variable = selectedVariable && variables && variables.find(v => v.name === selectedVariable); + return ( + 0 ? 'tbody-hover' : ''} size="sm"> + + + + + + + + + + + {boxes + .sort((a, b) => a.name.localeCompare(b.name, locale)) + .map(box => ( + + ))} + + {boxes.length === 0 && ( + + + + + + )} +
+ + + + + + + + + + + {removeBox && } +
+ + + +
+ ); +}; + +BoxesTable.propTypes = { + boxes: PropTypes.array.isRequired, + variables: PropTypes.array, + removeBox: PropTypes.func, + secondarySelections: PropTypes.array, + selectedVariable: PropTypes.string, + intl: PropTypes.shape({ locale: PropTypes.string.isRequired }).isRequired, +}; + +export default injectIntl(BoxesTable); diff --git a/src/components/Pipelines/BoxesTable/BoxesTableRow.js b/src/components/Pipelines/BoxesTable/BoxesTableRow.js new file mode 100644 index 000000000..eac0b04e5 --- /dev/null +++ b/src/components/Pipelines/BoxesTable/BoxesTableRow.js @@ -0,0 +1,308 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { FormattedMessage } from 'react-intl'; +import { OverlayTrigger, Tooltip } from 'react-bootstrap'; +import classnames from 'classnames'; + +import { AddIcon, BindIcon, UnbindIcon, InputIcon, OutputIcon, RemoveIcon, WarningIcon } from '../../icons'; +import { getVariablesTypes } from '../../../helpers/pipelines'; +import styles from '../styles.less'; + +/** + * Prepare ports obect with all data required for rendering. + * @param {Object} box of which the ports are being prepared + * @param {string} direction portsIn or portsOut + * @param {Object} boxTypes all box type descriptors + * @returns {Array} + */ +const transformPorts = (box, direction, boxTypes) => { + const ports = box[direction]; + const portsDescriptors = boxTypes && boxTypes[box.type] && boxTypes[box.type][direction]; + + return Object.keys(ports) + .sort() + .map(name => ({ + name, + direction, + ...ports[name], + prescribedType: portsDescriptors && portsDescriptors[name] && portsDescriptors[name].type, + })); +}; + +const getMissingPorts = (box, direction, boxTypes) => { + const ports = box[direction]; + const portsDescriptors = (boxTypes && boxTypes[box.type] && boxTypes[box.type][direction]) || {}; + + return Object.keys(portsDescriptors) + .filter(name => !ports[name]) + .sort() + .map(name => ({ + name, + direction, + ...portsDescriptors[name], + isMissing: true, + })); +}; + +// Fragment of table row contaning the port values +const BoxesTablePortsFragment = ({ box, port, variables, selectedVariable, assignVariable }) => { + const tipId = `${box.name}-${port.direction}-${port.name}`; + const portTypeWrong = + port.value && variables && variables[port.value] && variables[port.value] !== port.prescribedType; + return ( + <> + + {port.direction === 'portsIn' ? ( + + ) : ( + + )} + + + + {port.name} + {!port.isMissing && !port.prescribedType && ( + + + + }> + + + )} + + + + {port.type} + {!port.isMissing && port.prescribedType && port.prescribedType !== port.type && ( + + {content}, + }} + /> + + }> + + + )} + + + + {port.isMissing ? ( + + + + {content}, + }} + /> + + + ) : ( + <> + + {port.value} + {portTypeWrong && ( + + {content}, + }} + /> + + }> + + + )} + + + {assignVariable && !selectedVariable && !port.value && !portTypeWrong && ( + + + + }> + { + ev.stopPropagation(); + assignVariable(box.name, port.direction, port.name); // create new variable + }} + /> + + )} + + )} + + + + {selectedVariable && + assignVariable && + !portTypeWrong && + selectedVariable.type === port.prescribedType && + selectedVariable.name !== port.value && ( + { + ev.stopPropagation(); + assignVariable(box.name, port.direction, port.name, selectedVariable.name); + }} + /> + )} + {selectedVariable && assignVariable && selectedVariable.name === port.value && ( + { + ev.stopPropagation(); + assignVariable(box.name, port.direction, port.name, null); // remove + }} + /> + )} + + + ); +}; + +BoxesTablePortsFragment.propTypes = { + box: PropTypes.object.isRequired, + port: PropTypes.object.isRequired, + variables: PropTypes.object, + selectedVariable: PropTypes.object, + assignVariable: PropTypes.func, +}; + +const BoxesTableRow = ({ + box, + boxTypes, + variables = null, + selectedVariable = null, + primarySelection = null, + secondarySelections = null, + selectBox = null, + editBox = null, + removeBox = null, + assignVariable = null, +}) => { + const [firstPort, ...ports] = [ + ...transformPorts(box, 'portsIn', boxTypes), + ...transformPorts(box, 'portsOut', boxTypes), + ...getMissingPorts(box, 'portsIn', boxTypes), + ...getMissingPorts(box, 'portsOut', boxTypes), + ]; + + return ( + selectBox(box.name) : null} + onDoubleClick={editBox ? () => editBox(box.name) : null} + className={classnames({ + clickable: editBox || selectBox, + [styles.primarySelection]: primarySelection === box.name, + [styles.secondarySelection]: secondarySelections && secondarySelections[box.name], + })}> + + {box.name} + + + {boxTypes[box.type] ? ( + boxTypes[box.type].name + ) : ( + + )} + + }> + + {box.type} + {!boxTypes[box.type] && } + + + + + + + {removeBox && ( + + { + ev.stopPropagation(); + removeBox(box.name); + }} + /> + + )} + + {ports.map(port => ( + + + + ))} + + ); +}; + +BoxesTableRow.propTypes = { + box: PropTypes.object.isRequired, + boxTypes: PropTypes.object.isRequired, + variables: PropTypes.array, + selectedVariable: PropTypes.object, + primarySelection: PropTypes.string, + secondarySelections: PropTypes.object, + selectBox: PropTypes.func, + editBox: PropTypes.func, + removeBox: PropTypes.func, + assignVariable: PropTypes.func, +}; + +export default BoxesTableRow; diff --git a/src/components/Pipelines/BoxesTable/index.js b/src/components/Pipelines/BoxesTable/index.js new file mode 100644 index 000000000..a3cbfe6d1 --- /dev/null +++ b/src/components/Pipelines/BoxesTable/index.js @@ -0,0 +1,2 @@ +import BoxesTable from './BoxesTable'; +export default BoxesTable; diff --git a/src/components/Pipelines/VariableForm/VariableForm.js b/src/components/Pipelines/VariableForm/VariableForm.js new file mode 100644 index 000000000..b13fc26c3 --- /dev/null +++ b/src/components/Pipelines/VariableForm/VariableForm.js @@ -0,0 +1,265 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { FormattedMessage } from 'react-intl'; + +import { connect } from 'react-redux'; +import { reduxForm, Field, FieldArray, formValueSelector } from 'redux-form'; + +import { TextField, SelectField, ExpandingTextField, CheckboxField } from '../../forms/Fields'; +import { Modal } from 'react-bootstrap'; +import Button, { TheButtonGroup } from '../../widgets/TheButton'; +import Callout from '../../widgets/Callout'; +import SubmitButton from '../../forms/SubmitButton'; +import { CloseIcon, SaveIcon, RefreshIcon } from '../../../components/icons'; +import { isArrayType } from '../../../helpers/pipelines'; + +export const newVariableInitialData = { + name: '', + type: '', + value: '', + values: [], + external: false, +}; + +const variableTypeOptions = ['file', 'remote-file', 'string'] + .reduce((acc, type) => [...acc, type, type + '[]'], []) + .sort() + .map(type => ({ key: type, name: type })); + +class VariableForm extends Component { + render() { + const { + show, + editting = null, + isExternal = false, + selectedType = null, + handleSubmit, + submitSucceeded = false, + dirty = false, + invalid = false, + submitting = false, + reset, + onHide, + } = this.props; + + // const currentBoxType = boxTypes.find(box => box.type === selectedType); + // const getPortsArray = ports => Object.keys(ports).map(port => ({ name: port, ...ports[port] })); + + return ( + + +
+ {editting ? ( + {content} }} + /> + ) : ( + + )} +
+
+ + + + : + + } + /> + + } + /> + + + } + /> + + {!selectedType && !isExternal ? ( + + + + ) : isArrayType(selectedType) && !isExternal ? ( + } + /> + ) : ( + + ) : ( + + ) + } + /> + )} + + + + + {(dirty || editting) && ( + { + handleSubmit(); + return Promise.resolve(); // make sure the submit button always gets a promise + }} + submitting={submitting} + invalid={invalid} + dirty={dirty} + hasSuceeded={submitSucceeded} + reset={reset} + defaultIcon={} + messages={{ + success: , + submit: , + submitting: , + }} + /> + )} + {dirty && ( + + )} + + + +
+ ); + } +} + +VariableForm.propTypes = { + variables: PropTypes.array.isRequired, + show: PropTypes.bool, + editting: PropTypes.string, + onSubmit: PropTypes.func.isRequired, + onHide: PropTypes.func.isRequired, + isExternal: PropTypes.bool, + selectedType: PropTypes.string, + handleSubmit: PropTypes.func.isRequired, + reset: PropTypes.func.isRequired, + submitSucceeded: PropTypes.bool, + dirty: PropTypes.bool, + invalid: PropTypes.bool, + submitting: PropTypes.bool, +}; + +const validate = ({ name, type, external, value }, { variables, editting, dirty }) => { + const errors = {}; + if (!dirty && !editting) { + return errors; + } + + if (!name || name.trim() === '') { + errors.name = ( + + ); + } + + if (name && name.trim() !== editting && variables && variables.find(v => v.name === name.trim())) { + errors.name = ( + + ); + } + + if (!type) { + errors.type = ( + + ); + } + + if (external) { + if (!value || value.trim() === '') { + errors.value = ( + + ); + } + } + + return errors; +}; + +const warn = ({ name, external, value }) => { + const warnings = {}; + + if (name && !name.trim().match(/^[-a-zA-Z0-9_]+$/)) { + warnings.name = ( + + ); + } + + if (external) { + if (value && value.trim().startsWith('$')) { + warnings.value = ( + + ); + } + } + + return warnings; +}; + +const mapStateToProps = state => ({ + isExternal: formValueSelector('variableForm')(state, 'external'), + selectedType: formValueSelector('variableForm')(state, 'type'), +}); + +export default connect(mapStateToProps)( + reduxForm({ + form: 'variableForm', + enableReinitialize: true, + keepDirtyOnReinitialize: false, + validate, + warn, + })(VariableForm) +); diff --git a/src/components/Pipelines/VariableForm/index.js b/src/components/Pipelines/VariableForm/index.js new file mode 100644 index 000000000..3badeb91c --- /dev/null +++ b/src/components/Pipelines/VariableForm/index.js @@ -0,0 +1,3 @@ +import VariableForm, { newVariableInitialData } from './VariableForm'; +export { newVariableInitialData }; +export default VariableForm; diff --git a/src/components/Pipelines/VariablesTable/VariablesTable.js b/src/components/Pipelines/VariablesTable/VariablesTable.js new file mode 100644 index 000000000..abe895f70 --- /dev/null +++ b/src/components/Pipelines/VariablesTable/VariablesTable.js @@ -0,0 +1,197 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { injectIntl, FormattedMessage } from 'react-intl'; +import { Table, OverlayTrigger, Tooltip } from 'react-bootstrap'; +import { defaultMemoize } from 'reselect'; +import classnames from 'classnames'; + +import { InputIcon, OutputIcon, TransferIcon, RemoveIcon, WarningIcon } from '../../icons'; +import { isVariableValueValid } from '../../../helpers/pipelines'; +import { safeGet, arrayToObject } from '../../../helpers/common'; +import styles from '../styles.less'; + +const prepareSelectionIndex = defaultMemoize( + selections => + selections && + arrayToObject( + selections, + x => x, + () => true + ) +); + +const VariablesTable = ({ + variables, + utilization = null, + primarySelection = null, + secondarySelections = null, + selectVariable = null, + editVariable = null, + removeVariable = null, + intl: { locale }, +}) => { + const secondarySelectionsIndexed = secondarySelections && prepareSelectionIndex(secondarySelections); + + return ( + 0} size="sm"> + + + {utilization && + + + {removeVariable && + + + {variables + .sort((a, b) => a.name.localeCompare(b.name, locale)) + .map(variable => { + const portsIn = safeGet(utilization, [variable.name, 'portsIn', 'length'], 0); + const portsOut = safeGet(utilization, [variable.name, 'portsOut', 'length'], 0); + return ( + selectVariable(variable.name) : null} + onDoubleClick={editVariable ? () => editVariable(variable.name) : null} + className={classnames({ + clickable: selectVariable || editVariable, + [styles.primarySelection]: primarySelection === variable.name, + [styles.secondarySelection]: secondarySelectionsIndexed && secondarySelectionsIndexed[variable.name], + })}> + {utilization && ( + + )} + + + + + {removeVariable && ( + + )} + + ); + })} + + {variables.length === 0 && ( + + + + )} + +
} + + + + + + + } +
+ + {portsOut > 1 ? ( + + ) : portsIn && portsOut ? ( + + ) : portsIn ? ( + + ) : portsOut ? ( + + ) : ( + + )} + + }> + {portsOut > 1 ? ( + + ) : portsIn && portsOut ? ( + + ) : portsIn ? ( + + ) : portsOut ? ( + + ) : ( + + )} + + 1, + 'text-bold': secondarySelectionsIndexed && secondarySelectionsIndexed[variable.name], + })}> + {variable.name} + + {variable.type} + + {!isVariableValueValid(variable) && ( + + + + }> + + + )} + + {Array.isArray(variable.value) ? ( + variable.value.map((row, idx) => ( + + {row} + + )) + ) : ( + {variable.value} + )} + + { + ev.stopPropagation(); + removeVariable(variable.name); + }} + /> +
+ + + +
+ ); +}; + +VariablesTable.propTypes = { + variables: PropTypes.array.isRequired, + utilization: PropTypes.object, + primarySelection: PropTypes.string, + secondarySelections: PropTypes.array, + selectVariable: PropTypes.func, + editVariable: PropTypes.func, + removeVariable: PropTypes.func, + intl: PropTypes.shape({ locale: PropTypes.string.isRequired }).isRequired, +}; + +export default injectIntl(VariablesTable); diff --git a/src/components/Pipelines/VariablesTable/index.js b/src/components/Pipelines/VariablesTable/index.js new file mode 100644 index 000000000..ea1bc2ba9 --- /dev/null +++ b/src/components/Pipelines/VariablesTable/index.js @@ -0,0 +1,2 @@ +import VariablesTable from './VariablesTable'; +export default VariablesTable; diff --git a/src/components/Pipelines/styles.less b/src/components/Pipelines/styles.less new file mode 100644 index 000000000..8e43507f1 --- /dev/null +++ b/src/components/Pipelines/styles.less @@ -0,0 +1,25 @@ +.primarySelection td, .primarySelection th { + background-color: #ddf; +} + +.primarySelection:hover td, .primarySelection:hover th { + background-color: #ccf !important; +} + +.secondarySelection td, .secondarySelection th { + background-color: #ffd; +} + +.secondarySelection:hover td, .secondarySelection:hover th { + background-color: #ffa !important; +} + +.variableValue, .variableValueRow { + white-space: pre; + display: inline-block; + font-size: 80%; +} + +.variableValueRow { + display: block; +} diff --git a/src/components/forms/EditSystemMessageForm/EditSystemMessageForm.js b/src/components/forms/EditSystemMessageForm/EditSystemMessageForm.js index c9c3dd609..05dd328b9 100644 --- a/src/components/forms/EditSystemMessageForm/EditSystemMessageForm.js +++ b/src/components/forms/EditSystemMessageForm/EditSystemMessageForm.js @@ -105,31 +105,29 @@ const EditSystemMessageForm = ({ {error && dirty && {error}}
-
- - } - messages={{ - submit: , - submitting: , - success: , - validating: , - }} - /> + + } + messages={{ + submit: , + submitting: , + success: , + validating: , + }} + /> - - -
+ +
); diff --git a/src/components/forms/Fields/ExpandingTextField.js b/src/components/forms/Fields/ExpandingTextField.js index 91ed50e9a..9d95afe96 100644 --- a/src/components/forms/Fields/ExpandingTextField.js +++ b/src/components/forms/Fields/ExpandingTextField.js @@ -9,7 +9,7 @@ import TextField from './TextField'; import Icon, { AddIcon, CloseIcon } from '../../icons'; const ExpandingTextField = ({ - fields, + fields = [], meta: { active, dirty, error, warning }, label = null, noItems = null, @@ -109,7 +109,7 @@ const ExpandingTextField = ({ ); ExpandingTextField.propTypes = { - fields: PropTypes.object.isRequired, + fields: PropTypes.object, meta: PropTypes.shape({ active: PropTypes.bool, dirty: PropTypes.bool, diff --git a/src/components/icons/index.js b/src/components/icons/index.js index b4157562d..e3c489471 100644 --- a/src/components/icons/index.js +++ b/src/components/icons/index.js @@ -57,6 +57,7 @@ export const GroupIcon = ({ organizational = false, archived = false, ...props } ); export const HomeIcon = props => ; export const InfoIcon = props => ; +export const InputIcon = props => ; export const InstanceIcon = props => ; export const LimitsIcon = props => ; export const LinkIcon = props => ; @@ -67,6 +68,7 @@ export const MailIcon = props => ; export { NeedFixingIcon }; export const NoteIcon = props => ; export const ObserverIcon = props => ; +export const OutputIcon = props => ; export const PipelineIcon = props => ; export const PointsDecreasedIcon = props => ; export const PointsGraphIcon = props => ; @@ -120,6 +122,7 @@ export const TypedMessageIcon = ({ type, ...props }) => ( ); +export const UnbindIcon = props => ; export const UndoIcon = props => ; export const UnlockIcon = props => ; export const UploadIcon = props => ; diff --git a/src/containers/App/recodex.css b/src/containers/App/recodex.css index 766742500..f2f141b95 100644 --- a/src/containers/App/recodex.css +++ b/src/containers/App/recodex.css @@ -209,6 +209,10 @@ table.table-hover td.clickable:hover, table.table-hover th.clickable:hover { background-color: #eeeeee; } +table.table.tbody-hover tbody:hover td { + background-color: #eeeeee; +} + .timid { opacity: 0.2; transition: opacity 0.5s ease; @@ -299,6 +303,10 @@ code { max-width: 300px; } +.tooltip-inner code { + color: #bfb; +} + .btn.active { font-weight: bold; } diff --git a/src/containers/PipelineEditContainer/PipelineEditContainer.js b/src/containers/PipelineEditContainer/PipelineEditContainer.js new file mode 100644 index 000000000..de590e9ea --- /dev/null +++ b/src/containers/PipelineEditContainer/PipelineEditContainer.js @@ -0,0 +1,479 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import { FormattedMessage } from 'react-intl'; +import { Container, Row, Col } from 'react-bootstrap'; + +import Box from '../../components/widgets/Box'; +import BoxesTable from '../../components/Pipelines/BoxesTable'; +import VariablesTable from '../../components/Pipelines/VariablesTable'; +import VariableForm, { newVariableInitialData } from '../../components/Pipelines/VariableForm'; +import BoxForm, { newBoxInitialData } from '../../components/Pipelines/BoxForm'; +import Button, { TheButtonGroup } from '../../components/widgets/TheButton'; +import Icon, { SaveIcon } from '../../components/icons'; + +import { fetchSupplementaryFilesForPipeline } from '../../redux/modules/pipelineFiles'; + +import { + getVariablesUtilization, + isArrayType, + coerceVariableValue, + isExternalReference, + getReferenceIdentifier, + makeExternalReference, + getVariablesTypes, +} from '../../helpers/pipelines'; +import { getBoxTypes } from '../../redux/selectors/boxes'; +import { objectMap, encodeId, deepCompare, identity } from '../../helpers/common'; + +// TODO + +/* +const asyncValidate = (values, dispatch, { initialValues: { id, version } }) => + new Promise((resolve, reject) => + dispatch(validatePipeline(id, version)) + .then(res => res.value) + .then(({ versionIsUpToDate }) => { + const errors = {}; + if (versionIsUpToDate === false) { + errors.name = ( + + ); + dispatch(touch('editPipeline', 'name')); + } + + if (Object.keys(errors).length > 0) { + throw errors; + } + }) + .then(resolve()) + .catch(errors => reject(errors)) + ); +*/ + +class PipelineEditContainer extends Component { + state = { + pipelineId: null, + version: null, + boxes: null, + variables: null, + boxFormOpen: false, + boxEditName: null, + variableFormOpen: false, + variableEditName: null, + selectedBox: null, + selectedBoxVariables: null, // vars associated with selected box + selectedVariable: null, + selectedVariableBoxes: null, // boxes associated with selected var + }; + + static getDerivedStateFromProps(nextProps, prevState) { + if (prevState.pipelineId !== nextProps.pipeline.id) { + return { + pipelineId: nextProps.pipeline.id, + version: nextProps.pipeline.version, + boxes: nextProps.pipeline.pipeline.boxes, + variables: nextProps.pipeline.pipeline.variables, + boxFormOpen: false, // whether dialog is visible + boxEditName: null, // if dialog is used for editting, name of the editted box + variableFormOpen: false, // analogical to boxForm... + variableEditName: null, + selectedBox: null, + selectedBoxVariables: null, + selectedVariable: null, + selectedVariableBoxes: null, + }; + } + + if (prevState.version < nextProps.pipeline.version) { + // TODO -- deal with mergin issues + return { version: nextProps.pipeline.version }; + } + + return null; + } + + /* + * Dialog handling + */ + + openBoxForm = (boxEditName = null) => { + this.setState({ boxFormOpen: true, boxEditName }); + }; + + openVariableForm = (variableEditName = null) => { + this.setState({ variableFormOpen: true, variableEditName }); + }; + + closeForms = () => { + this.setState({ boxFormOpen: false, boxEditName: null, variableFormOpen: false, variableEditName: null }); + }; + + getBoxFormInitialData = () => { + const box = this.state.boxEditName && this.state.boxes.find(box => box.name === this.state.boxEditName); + if (box) { + const data = { name: box.name, type: box.type, portsIn: {}, portsOut: {} }; + ['portsIn', 'portsOut'].forEach(ports => + Object.keys(box[ports]).forEach(port => (data[ports][encodeId(port)] = box[ports][port].value)) + ); + return data; + } else { + return newBoxInitialData; + } + }; + + getVariableFormInitialData = () => { + const variable = + this.state.variableEditName && + this.state.variables.find(variable => variable.name === this.state.variableEditName); + + if (variable) { + const data = { ...variable, external: false, values: [] }; + coerceVariableValue(data); + + if (isExternalReference(data.value)) { + data.external = true; + data.value = getReferenceIdentifier(data.value); + } else if (isArrayType(data.type)) { + data.values = data.value; + data.value = ''; + } + + return data; + } else { + return newVariableInitialData; + } + }; + + /* + * Selection handling + */ + + selectBox = (selectedBox = null) => { + if (selectedBox === this.state.selectedBox) { + selectedBox = null; // repeated select = unselect + } + + if (selectedBox) { + this.selectVariable(); // unselect variable, so the box holds primary selection + } + + const box = selectedBox && this.state.boxes.find(b => b.name === selectedBox); + const selectedBoxVariables = + box && [...Object.values(box.portsIn), ...Object.values(box.portsOut)].map(({ value }) => value).filter(identity); + + this.setState({ + selectedBox, + selectedBoxVariables, + }); + }; + + selectVariable = (selectedVariable = null) => { + if (selectedVariable === this.state.selectedVariable) { + selectedVariable = null; // repeated select = unselect + } + + if (selectedVariable) { + this.selectBox(); // unselect box, so the variable holds primary selection + } + + const selectedVariableBoxes = + selectedVariable && + this.state.boxes + .filter( + ({ portsIn, portsOut }) => + Object.values(portsIn).find(p => p.value === selectedVariable) || + Object.values(portsOut).find(p => p.value === selectedVariable) + ) + .map(({ name }) => name); + + this.setState({ + selectedVariable, + selectedVariableBoxes, + }); + }; + + /* + * Methods that modify the pipeline + */ + + transformState = (transformBoxes, transformVariables = null) => { + const stateUpdate = {}; + + const boxes = transformBoxes && transformBoxes(this.state.boxes, this.state.variables); + if (boxes && !deepCompare(boxes, this.state.boxes)) { + stateUpdate.boxes = boxes; + } + + const variables = transformVariables && transformVariables(this.state.variables, this.state.boxes); + if (variables && !deepCompare(variables, this.state.variables)) { + stateUpdate.variables = variables; + } + + if (Object.keys(stateUpdate).length > 0) { + this.setState(stateUpdate); + } + }; + + submitBoxForm = ({ name, type, portsIn, portsOut }) => { + const oldBoxName = this.state.boxEditName; + const boxType = this.props.boxTypes[type]; + this.closeForms(); + name = name.trim(); + if (!name || !boxType) { + return; + } + + // prepare new box object + const newBox = { + name, + type, + portsIn: objectMap(boxType.portsIn, (port, name) => ({ ...port, value: portsIn[encodeId(name)].trim() })), + portsOut: objectMap(boxType.portsOut, (port, name) => ({ ...port, value: portsOut[encodeId(name)].trim() })), + }; + + // extract all assigned variables, find which of them do not exist yet, and prepare their new objects + const newVariables = [...Object.values(newBox.portsIn), ...Object.values(newBox.portsOut)] + .filter(port => port.value && !this.state.variables.find(v => v.name === port.value)) + .map(port => ({ name: port.value, type: port.type, value: isArrayType(port.type) ? [] : '' })); + + if (oldBoxName) { + // replace old box with new one + this.transformState( + boxes => boxes.map(box => (box.name === oldBoxName ? newBox : box)), + newVariables.length > 0 ? variables => [...variables, ...newVariables] : null + ); + } else { + this.transformState( + boxes => [...boxes, newBox], // append new box + newVariables.length > 0 ? variables => [...variables, ...newVariables] : null + ); + } + }; + + submitVariableForm = ({ name, type, value, values, external }) => { + const oldVarName = this.state.variableEditName; + this.closeForms(); + name = name.trim(); + if (!name || !type) { + return; + } + + const newVariable = { name, type, value: isArrayType(type) ? values : value }; + if (external) { + newVariable.value = makeExternalReference(value); + } + + if (oldVarName) { + // update in ports: if the type still matches, update the variable name; remove it otherwise + const updateVarInPorts = ports => + objectMap(ports, port => + port.value === oldVarName ? { ...port, value: port.type === type ? name : '' } : port + ); + this.transformState( + boxes => + boxes.map(({ portsIn, portsOut, ...rest }) => { + return { + portsIn: updateVarInPorts(portsIn), + portsOut: updateVarInPorts(portsOut), + ...rest, + }; + }), + variables => variables.map(variable => (variable.name === oldVarName ? newVariable : variable)) + ); + } else { + this.transformState(null, variables => [...variables, newVariable]); + } + }; + + removeBox = name => { + this.transformState(boxes => boxes.filter(box => box.name !== name)); + }; + + removeVariable = name => { + const removeVarFromPorts = ports => objectMap(ports, port => (port.value === name ? { ...port, value: '' } : port)); + + this.transformState( + boxes => + boxes.map(({ portsIn, portsOut, ...rest }) => { + return { + portsIn: removeVarFromPorts(portsIn), + portsOut: removeVarFromPorts(portsOut), + ...rest, + }; + }), + variables => variables.filter(variable => variable.name !== name) + ); + }; + + getUnusedVariableName = prefix => { + const varIndex = getVariablesTypes(this.state.variables); + let suffix = ''; + while (varIndex[prefix + suffix]) { + ++suffix; + } + return prefix + suffix; + }; + + /** + * Change association of one variable in one port. + * @param {string} boxName + * @param {string} portsKey portsIn or portsOut + * @param {string} portName + * @param {string|null} variableName to be assigned, null = remove current variable, if missing => create new variable + */ + assignVariable = (boxName, portsKey, portName, variableName) => { + if (variableName === undefined) { + variableName = this.getUnusedVariableName(portName); + } + + const box = this.state.boxes.find(b => b.name === boxName); + const port = box && box[portsKey] && box[portsKey][portName]; + if (!port) { + return; + } + + const variable = variableName && this.state.variables.find(v => v.name === variableName); + if (variableName && !variable) { + // variable needs to be created first + this.transformState(null, variables => [ + ...variables, + { name: variableName, type: port.type, value: isArrayType(port.type) ? [] : '' }, + ]); + } else if (variable && variable.type !== port.type) { + return; + } + + this.transformState(boxes => + boxes.map( + b => + b.name === boxName + ? { + ...b, // clone the box and replace corresponding port + [portsKey]: { ...b[portsKey], [portName]: { ...b[portsKey][portName], value: variableName || '' } }, + } + : b // other boxes are just passed through + ) + ); + }; + + render() { + const { boxTypes } = this.props; + const utilization = getVariablesUtilization(this.state.boxes); + return ( + } + unlimitedHeight + footer={ +
+ + + + + +
+ }> + <> + + + +

+ +

+ {this.state.boxes && ( + + )} + + + +

+ +

+ {this.state.variables && ( + + )} + +
+
+ + + + + +
+ ); + } +} + +PipelineEditContainer.propTypes = { + pipeline: PropTypes.shape({ + id: PropTypes.string.isRequired, + version: PropTypes.number.isRequired, + pipeline: PropTypes.shape({ + boxes: PropTypes.array.isRequired, + variables: PropTypes.array.isRequired, + }), + }).isRequired, + supplementaryFiles: ImmutablePropTypes.map, + boxTypes: PropTypes.object.isRequired, +}; + +export default connect( + (state, { pipeline }) => { + return { + boxTypes: getBoxTypes(state), + }; + }, + (dispatch, { pipeline }) => ({ + loadFiles: () => dispatch(fetchSupplementaryFilesForPipeline(pipeline.id)), + }) +)(PipelineEditContainer); diff --git a/src/containers/PipelineEditContainer/index.js b/src/containers/PipelineEditContainer/index.js new file mode 100644 index 000000000..62f3167fa --- /dev/null +++ b/src/containers/PipelineEditContainer/index.js @@ -0,0 +1,2 @@ +import PipelineEditContainer from './PipelineEditContainer'; +export default PipelineEditContainer; diff --git a/src/containers/SisSupervisorGroupsContainer/SisSupervisorGroupsContainer.js b/src/containers/SisSupervisorGroupsContainer/SisSupervisorGroupsContainer.js index d39daa69e..5cc3735a7 100644 --- a/src/containers/SisSupervisorGroupsContainer/SisSupervisorGroupsContainer.js +++ b/src/containers/SisSupervisorGroupsContainer/SisSupervisorGroupsContainer.js @@ -16,7 +16,15 @@ import SisBindGroupForm from '../../components/forms/SisBindGroupForm'; import Confirm from '../../components/forms/Confirm'; import CourseLabel, { getLocalizedData } from '../../components/SisIntegration/CourseLabel'; import DeleteGroupButtonContainer from '../../containers/DeleteGroupButtonContainer'; -import Icon, { AddIcon, BindIcon, EditIcon, GroupIcon, AssignmentsIcon, LoadingIcon } from '../../components/icons'; +import Icon, { + AddIcon, + BindIcon, + UnbindIcon, + EditIcon, + GroupIcon, + AssignmentsIcon, + LoadingIcon, +} from '../../components/icons'; import { fetchAllGroups, fetchGroupIfNeeded } from '../../redux/modules/groups'; import { fetchSisStatusIfNeeded } from '../../redux/modules/sisStatus'; @@ -399,10 +407,7 @@ class SisSupervisorGroupsContainer extends Component { ) ? ( ) : ( - + )} type.indexOf('[]') > 0; export const getVariablesTypes = (boxTypes, boxes) => { diff --git a/src/helpers/dot.js b/src/helpers/dot.js index b7e1a047d..17d69ee4e 100644 --- a/src/helpers/dot.js +++ b/src/helpers/dot.js @@ -1,3 +1,8 @@ +/* + * DEPRECATED - all relevant stuff moved to pipelines.js + * TODO DELETE + */ + import Viz from 'viz.js'; const { Module, render } = require('viz.js/lite.render.js'); diff --git a/src/helpers/pipelines.js b/src/helpers/pipelines.js new file mode 100644 index 000000000..c0e5b4d6e --- /dev/null +++ b/src/helpers/pipelines.js @@ -0,0 +1,102 @@ +/* + * Functions related to pipeline editting and visualization. + */ + +import { defaultMemoize } from 'reselect'; +import { arrayToObject } from './common'; + +/** + * Check whether given data type is a list of values. + * @param {string} type descriptor + * @returns {boolean} true if the type represents a list + */ +export const isArrayType = type => type.endsWith('[]'); + +/** + * Check whether given variable value is a reference to external variable (starts with $). + * @param {string|Array} value + * @returns {boolean} + */ +export const isExternalReference = value => typeof value === 'string' && value.startsWith('$'); + +/** + * Get the identifier if an external reference + * @param {*} value + * @returns {string|null} null if the value is not a reference + */ +export const getReferenceIdentifier = value => (isExternalReference(value) ? value.substr(1) : null); + +/** + * Create a value that is an external reference to a variable of given name + * @param {string} name of the variable + * @returns {string} + */ +export const makeExternalReference = name => '$' + name; + +/** + * Verify that variable value is present and matches declared type. + * @param {Object} variable + * @returns {boolean} + */ +export const isVariableValueValid = variable => + 'value' in variable && + 'type' in variable && + (Array.isArray(variable.value) === isArrayType(variable.type) || isExternalReference(variable.value)); + +/** + * Make sure the variable value is of the right type, cast it if necessary. + * @param {*} variable + */ +export const coerceVariableValue = variable => { + if (!('value' in variable)) { + variable.value = isArrayType(variable.type) ? [] : ''; + } + + if (typeof variable.value === 'object' && !Array.isArray(variable.value)) { + variable.value = Object.values(variable.value); + } + + if (!isVariableValueValid(variable)) { + if (isArrayType(variable.type)) { + variable.value = variable.value ? [variable.value] : []; + } else { + variable.value = variable.value.join(' '); + } + } +}; + +/** + * Get info about variables utilization from boxes specification (where the variables are used) + * @param {Object[]} boxes part of the pipeline specification + * @return {Object} keys are variable names, values are objects holding { portsIn, portsOut } values, + * both are arrays of boxes where the variable is present + */ +export const getVariablesUtilization = defaultMemoize(boxes => { + const utils = {}; + boxes.forEach(box => + ['portsIn', 'portsOut'].forEach(ports => + Object.values(box[ports]) + .filter(({ value }) => value) + .forEach(({ value }) => { + if (!utils[value]) { + utils[value] = { portsIn: [], portsOut: [] }; + } + utils[value][ports].push(box); + }) + ) + ); + return utils; +}); + +/** + * Transform array of variables into oject (dictionary), that translates name to type. + * @param {Object[]} variables + * @return {Object} keys are names, values are types + */ +export const getVariablesTypes = defaultMemoize(variables => + arrayToObject( + variables, + ({ name }) => name, + ({ type }) => type + ) +); diff --git a/src/locales/cs.json b/src/locales/cs.json index 677a36228..fb604d55f 100644 --- a/src/locales/cs.json +++ b/src/locales/cs.json @@ -494,7 +494,6 @@ "app.editPipelineForm.title": "Metadata pipeline", "app.editPipelineForm.validation.description": "Prosíme vyplňte popis této pipeline.", "app.editPipelineForm.validation.emptyName": "Prosíme vyplňte název této pipeline.", - "app.editPipelineForm.validation.versionDiffers": "Někdo změnil nastavení této pipeline v průběhu její editace. Prosíme obnovte tuto stránku a proveďte své změny znovu.", "app.editShadowAssignment.deleteAssignment": "Smazat stínovou úlohu", "app.editShadowAssignment.deleteAssignmentWarning": "Smazání stínové úlohy rovněž odstraní body přidělené studentům.", "app.editShadowAssignment.title": "Změnit nastavení stínové úlohy", @@ -1113,15 +1112,12 @@ "app.pipeline.title": "Podrobnosti pipeline", "app.pipeline.version": "Verze:", "app.pipeline.visualization": "Vizualizace", + "app.pipelineEditContainer.addBoxButton": "Přidat krabičku", + "app.pipelineEditContainer.addVariableButton": "Přidat proměnnou", + "app.pipelineEditContainer.boxesTitle": "Krabičky", + "app.pipelineEditContainer.title": "Struktura pipeline", + "app.pipelineEditContainer.variablesTitle": "Proměnné", "app.pipelineEditor.AddBoxForm.title": "Přidat krabičku", - "app.pipelineEditor.BoxForm.conflictingPortType": "Tato proměnná nemůže být nastavena tomuto portu - typ portu je {portType}, zatímco proměnná {variable} je už přiřazena portu, který má typ {variableType} (např., v krabičce {exampleBox}).", - "app.pipelineEditor.BoxForm.emptyName": "Název nesmí být prázdný.", - "app.pipelineEditor.BoxForm.failed": "Omlouváme se, ale nebyli jsme schopni uložit krabičku.", - "app.pipelineEditor.BoxForm.loop": "Krabička nemůže použít svůj výstup jako svůj vstup.", - "app.pipelineEditor.BoxForm.missingType": "Musíte vybrat typ.", - "app.pipelineEditor.BoxForm.portsIn": "Vstupy:", - "app.pipelineEditor.BoxForm.portsOut": "Výstupy:", - "app.pipelineEditor.BoxForm.type": "Typ:", "app.pipelineEditor.EditBoxForm.title": "Upravit krabičku \"{name}\"", "app.pipelineFilesTable.description": "Testovací soubory jsou soubory, které mohou být odkazované v konfiguraci pipeline.", "app.pipelineFilesTable.title": "Soubory pipeline", @@ -1133,9 +1129,55 @@ "app.pipelineParams.producesFiles": "Testované řešení by mělo vypsat svoje výsledky do daného souboru", "app.pipelineParams.producesStdout": "Testované řešení by mělo vypsat svoje výsledky na standardní výstup", "app.pipelineVisualEditor.addBoxButton": "Přidat krabičku", + "app.pipelines.boxForm.duplicitName": "Toto jméno již bylo přiděleno pro jinou krabičku.", + "app.pipelines.boxForm.emptyName": "Jméno krabičky nemůže zůstat prázdné.", + "app.pipelines.boxForm.inputPorts": "Vstupní porty", + "app.pipelines.boxForm.missingType": "Musí být vybrán typ krabičky.", + "app.pipelines.boxForm.outputPorts": "Výstupní porty", + "app.pipelines.boxForm.titleEditting": "Editace krabičky {editting}", + "app.pipelines.boxForm.titleNew": "Přidat novou krabičku", + "app.pipelines.boxForm.type": "Typ:", + "app.pipelines.boxForm.variableNotExistYet": "Vybraná proměnná zatím neexistuje a bude vytvořena.", + "app.pipelines.boxForm.variableUsedInMultipleOutputs": "Tato proměnná je použita ve více než jednom výstupním portu.", + "app.pipelines.boxesTable.boxType": "Typ krabičky", + "app.pipelines.boxesTable.createNewVariable": "Vytvořit novou proměnnou, která bude asociována s tímto portem.", + "app.pipelines.boxesTable.name": "Název", + "app.pipelines.boxesTable.noBoxes": "V pipeline nejsou žádné krabičky.", + "app.pipelines.boxesTable.port": "Port", + "app.pipelines.boxesTable.portMissing": "chybí!", + "app.pipelines.boxesTable.portType": "Datový typ", + "app.pipelines.boxesTable.unknownPort": "Tento port není definován v deskriptoru krabičky.", + "app.pipelines.boxesTable.unknownType": "Neznámý typ krabičky!", + "app.pipelines.boxesTable.variable": "Proměnná", + "app.pipelines.boxesTable.wrongPortType": "Typ tohoto portu je {type}, ale deskriptor krabičky předepisuje typ {descType}.", + "app.pipelines.boxesTable.wrongVariableType": "Asociovaná proměnná je typu {type}, ale port předepisuje typ {descType}.", "app.pipelines.createNew": "Vytvořit novou pipeline", "app.pipelines.listTitle": "Pipeline", "app.pipelines.title": "Seznam všech pipeline", + "app.pipelines.variableForm.duplicitName": "Toto jméno již bylo přiděleno pro jinou proměnnou.", + "app.pipelines.variableForm.emptyName": "Jméno proměnné nemůže zůstat prázdné.", + "app.pipelines.variableForm.external": "Reference na externí proměnnou ($)", + "app.pipelines.variableForm.externalIdentifierDuplicitDollar": "Znak dolaru $ je na začátek reference přidán automaticky.", + "app.pipelines.variableForm.externalValue": "Externí jméno:", + "app.pipelines.variableForm.missingExternalIdentifier": "Jméno externí proměnné musí být nastaveno.", + "app.pipelines.variableForm.missingType": "Musí být vybrán typ.", + "app.pipelines.variableForm.selectTypeFirst": "Nejprve je třeba vybrat datový typ proměnné.", + "app.pipelines.variableForm.titleEditting": "Editace proměnné {editting}", + "app.pipelines.variableForm.titleNew": "Přidat novou proměnnou", + "app.pipelines.variableForm.type": "Datový typ:", + "app.pipelines.variableForm.value": "Hodnota:", + "app.pipelines.variableForm.values": "Hodnoty:", + "app.pipelines.variableForm.warningNameChars": "Je doporučeno používat pouze bezpečné znaky uvnitř identifikátorů (písmena, čísla, pomlčku a podtržítko).", + "app.pipelines.variablesTable.inputVariable": "Vstupní proměnná", + "app.pipelines.variablesTable.interconnectingVariable": "Propojovací proměnná", + "app.pipelines.variablesTable.name": "Proměnná", + "app.pipelines.variablesTable.noVariables": "V pipeline nejsou žádné proměnné.", + "app.pipelines.variablesTable.outputVariable": "Výstupní proměnná", + "app.pipelines.variablesTable.tooManyOutputsAttached": "Proměnná je asociována s více než jedním výstupním portem!", + "app.pipelines.variablesTable.type": "Datový typ", + "app.pipelines.variablesTable.unused": "Tato proměnná není použita v žádné krabičce", + "app.pipelines.variablesTable.value": "Hodnota", + "app.pipelines.variablesTable.wrongValueType": "Hodnota proměnné má jiný typ než je deklarováno.", "app.pipelinesList.authoredPipelineIconTooltip": "Autorská pipeline, kterou je možné použít ve specializovaných konfiguracích úloh.", "app.pipelinesList.compilationIconTooltip": "Kompilační pipeline", "app.pipelinesList.empty": "Nyní v tomto seznamu nejsou žádné pipeline.", diff --git a/src/locales/en.json b/src/locales/en.json index 0323726c4..59a5dc326 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -494,7 +494,6 @@ "app.editPipelineForm.title": "Pipeline Metadata", "app.editPipelineForm.validation.description": "Please fill the description of the pipeline.", "app.editPipelineForm.validation.emptyName": "Please fill the name of the pipeline.", - "app.editPipelineForm.validation.versionDiffers": "Somebody has changed the pipeline while you have been editing it. Please reload the page and apply your changes once more.", "app.editShadowAssignment.deleteAssignment": "Delete the shadow assignment", "app.editShadowAssignment.deleteAssignmentWarning": "Deleting shadow assignment will remove all student points as well.", "app.editShadowAssignment.title": "Change Shadow Assignment Settings", @@ -1113,15 +1112,12 @@ "app.pipeline.title": "Pipeline Detail", "app.pipeline.version": "Version:", "app.pipeline.visualization": "Visualization", + "app.pipelineEditContainer.addBoxButton": "Add Box", + "app.pipelineEditContainer.addVariableButton": "Add Variable", + "app.pipelineEditContainer.boxesTitle": "Boxes", + "app.pipelineEditContainer.title": "Edit Pipeline Structure", + "app.pipelineEditContainer.variablesTitle": "Variables", "app.pipelineEditor.AddBoxForm.title": "Add a box", - "app.pipelineEditor.BoxForm.conflictingPortType": "You cannot set this variable to the port - the type of this port is {portType}, but the variable {variable} is already associated with port of type {variableType} (e.g., in box {exampleBox}).", - "app.pipelineEditor.BoxForm.emptyName": "Name cannot be empty.", - "app.pipelineEditor.BoxForm.failed": "We are sorry but we weren't able to save the box.", - "app.pipelineEditor.BoxForm.loop": "Box can't use its own output as its input.", - "app.pipelineEditor.BoxForm.missingType": "You must select some type.", - "app.pipelineEditor.BoxForm.portsIn": "Inputs:", - "app.pipelineEditor.BoxForm.portsOut": "Outputs:", - "app.pipelineEditor.BoxForm.type": "Type:", "app.pipelineEditor.EditBoxForm.title": "Edit the box \"{name}\"", "app.pipelineFilesTable.description": "Supplementary files are files which can be referenced as remote file in pipeline configuration.", "app.pipelineFilesTable.title": "Pipeline files", @@ -1133,9 +1129,55 @@ "app.pipelineParams.producesFiles": "Tested solution is expected to yield results into a specific file", "app.pipelineParams.producesStdout": "Tested solution is expected to yield results to standard output", "app.pipelineVisualEditor.addBoxButton": "Add box", + "app.pipelines.boxForm.duplicitName": "This name is already taken by another box.", + "app.pipelines.boxForm.emptyName": "Box name cannot be empty.", + "app.pipelines.boxForm.inputPorts": "Input ports", + "app.pipelines.boxForm.missingType": "You must select type of the box.", + "app.pipelines.boxForm.outputPorts": "Output ports", + "app.pipelines.boxForm.titleEditting": "Editting Box {editting}", + "app.pipelines.boxForm.titleNew": "Add New Box", + "app.pipelines.boxForm.type": "Type:", + "app.pipelines.boxForm.variableNotExistYet": "Selected variable does not exist yet and will be created.", + "app.pipelines.boxForm.variableUsedInMultipleOutputs": "This variable is being used in multiple output ports.", + "app.pipelines.boxesTable.boxType": "Box Type", + "app.pipelines.boxesTable.createNewVariable": "Create new variable and associate it with this port.", + "app.pipelines.boxesTable.name": "Name", + "app.pipelines.boxesTable.noBoxes": "There are no boxes in the pipeline.", + "app.pipelines.boxesTable.port": "Port", + "app.pipelines.boxesTable.portMissing": "missing!", + "app.pipelines.boxesTable.portType": "Data Type", + "app.pipelines.boxesTable.unknownPort": "This port is not present in the box descriptor.", + "app.pipelines.boxesTable.unknownType": "Unknown box type!", + "app.pipelines.boxesTable.variable": "Variable", + "app.pipelines.boxesTable.wrongPortType": "The type of this port is {type}, but {descType} is prescribed by the descriptor.", + "app.pipelines.boxesTable.wrongVariableType": "Associated variable is of {type}, but {descType} type is required.", "app.pipelines.createNew": "Create New Pipeline", "app.pipelines.listTitle": "Pipelines", "app.pipelines.title": "List of All Pipelines", + "app.pipelines.variableForm.duplicitName": "This name is already taken by another variable.", + "app.pipelines.variableForm.emptyName": "Variable name cannot be empty.", + "app.pipelines.variableForm.external": "External variable reference ($)", + "app.pipelines.variableForm.externalIdentifierDuplicitDollar": "The dollar sign $ is added automatically to external references.", + "app.pipelines.variableForm.externalValue": "External name:", + "app.pipelines.variableForm.missingExternalIdentifier": "Name of the external variable must be set.", + "app.pipelines.variableForm.missingType": "The type must be selected.", + "app.pipelines.variableForm.selectTypeFirst": "You need to select the data type of the variable first.", + "app.pipelines.variableForm.titleEditting": "Editting Variable {editting}", + "app.pipelines.variableForm.titleNew": "Add New Variable", + "app.pipelines.variableForm.type": "Data type:", + "app.pipelines.variableForm.value": "Value:", + "app.pipelines.variableForm.values": "Values:", + "app.pipelines.variableForm.warningNameChars": "It is recommended to use safe chars only for identifiers (letters, numbers, dash, and underscore).", + "app.pipelines.variablesTable.inputVariable": "An input variable", + "app.pipelines.variablesTable.interconnectingVariable": "An interconnecting variable", + "app.pipelines.variablesTable.name": "Variable", + "app.pipelines.variablesTable.noVariables": "There are no variables in the pipeline.", + "app.pipelines.variablesTable.outputVariable": "An output variable", + "app.pipelines.variablesTable.tooManyOutputsAttached": "Variable is attached to more than one output port!", + "app.pipelines.variablesTable.type": "Data Type", + "app.pipelines.variablesTable.unused": "This variable is not used in any box", + "app.pipelines.variablesTable.value": "Value", + "app.pipelines.variablesTable.wrongValueType": "Variable value has a different type than declared.", "app.pipelinesList.authoredPipelineIconTooltip": "Authored pipeline which can be used in custom exercise configurations.", "app.pipelinesList.compilationIconTooltip": "Compilation pipeline", "app.pipelinesList.empty": "There are no pipelines in this list.", diff --git a/src/locales/whitelist_cs.json b/src/locales/whitelist_cs.json index af5a6bab9..e85b1b356 100644 --- a/src/locales/whitelist_cs.json +++ b/src/locales/whitelist_cs.json @@ -114,6 +114,7 @@ "app.instancesTable.admin", "app.passwordStrength.ok", "app.passwordStrength.unknown", + "app.pipelines.boxesTable.port", "app.randomMessages.error", "app.randomMessages.last", "app.randomMessages.m1", diff --git a/src/pages/EditPipeline/EditPipeline.js b/src/pages/EditPipeline/EditPipeline.js index 224a9990e..f83e0260b 100644 --- a/src/pages/EditPipeline/EditPipeline.js +++ b/src/pages/EditPipeline/EditPipeline.js @@ -15,9 +15,11 @@ import EditPipelineEnvironmentsForm from '../../components/forms/EditPipelineEnv import { EditIcon } from '../../components/icons'; import PipelineFilesTableContainer from '../../containers/PipelineFilesTableContainer'; import DeletePipelineButtonContainer from '../../containers/DeletePipelineButtonContainer'; +import PipelineEditContainer from '../../containers/PipelineEditContainer'; import ResourceRenderer from '../../components/helpers/ResourceRenderer'; import { fetchPipelineIfNeeded, editPipeline, setPipelineRuntimeEnvironments } from '../../redux/modules/pipelines'; +import { fetchBoxTypes } from '../../redux/modules/boxes'; import { fetchRuntimeEnvironments } from '../../redux/modules/runtimeEnvironments'; import { getPipeline } from '../../redux/selectors/pipelines'; import { runtimeEnvironmentsSelector } from '../../redux/selectors/runtimeEnvironments'; @@ -55,7 +57,11 @@ class EditPipeline extends Component { } static loadAsync = ({ pipelineId }, dispatch) => - Promise.all([dispatch(fetchPipelineIfNeeded(pipelineId)), dispatch(fetchRuntimeEnvironments())]); + Promise.all([ + dispatch(fetchPipelineIfNeeded(pipelineId)), + dispatch(fetchRuntimeEnvironments()), + dispatch(fetchBoxTypes()), + ]); // save pipeline metadata (not the structure) savePipeline = ({ @@ -107,7 +113,7 @@ class EditPipeline extends Component { resource={pipeline} icon={} title={}> - {({ pipeline: { boxes, variables }, ...data }) => ( + {pipeline => (
@@ -130,7 +136,7 @@ class EditPipeline extends Component { @@ -144,14 +150,14 @@ class EditPipeline extends Component { - + {isSuperadmin && ( {environments => ( @@ -161,6 +167,12 @@ class EditPipeline extends Component { + + + + + +

- replace(PIPELINES_URI)} /> + replace(PIPELINES_URI)} />

diff --git a/src/redux/modules/boxes.js b/src/redux/modules/boxes.js index 337a3bcdd..9b5aa3391 100644 --- a/src/redux/modules/boxes.js +++ b/src/redux/modules/boxes.js @@ -8,7 +8,7 @@ import factory, { initialState } from '../helpers/resourceManager'; const resourceName = 'boxes'; const { actions, reduceActions } = factory({ resourceName, - idFieldName: 'name', + idFieldName: 'type', apiEndpointFactory: (name = '') => `/pipelines/boxes/${name}`, }); diff --git a/src/redux/selectors/boxes.js b/src/redux/selectors/boxes.js index 00781508b..31366c61f 100644 --- a/src/redux/selectors/boxes.js +++ b/src/redux/selectors/boxes.js @@ -1,18 +1,16 @@ import { createSelector } from 'reselect'; import { isReady } from '../helpers/resourceManager'; +import { objectMap } from '../../helpers/common'; const getResources = state => state.boxes.get('resources'); -export const getBoxTypesNames = createSelector( - getResources, - resources => Object.keys(resources.toJS()) +export const getBoxTypesNames = createSelector(getResources, resources => + resources + .toList() + .toJS() + .map(obj => obj.data.name) ); -export const getBoxTypes = createSelector( - getResources, - resources => - resources - .filter(isReady) - .toList() - .toJS() - .map(item => item.data) + +export const getBoxTypes = createSelector(getResources, resources => + objectMap(resources.filter(isReady).toJS(), obj => obj.data) ); From 77a946ce3dc0913c4965bfb8e9c89ad2a2f61c31 Mon Sep 17 00:00:00 2001 From: Martin Krulis Date: Thu, 2 Dec 2021 16:31:24 +0100 Subject: [PATCH 03/20] Fixing editting typo. --- src/components/Pipelines/BoxForm/BoxForm.js | 24 +++++++++---------- .../Pipelines/VariableForm/VariableForm.js | 18 +++++++------- .../EditAssignmentForm/EditAssignmentForm.js | 2 +- .../ScoreConfigUniversalExpression.js | 2 +- .../PipelineEditContainer.js | 6 ++--- src/helpers/pipelines.js | 2 +- src/locales/cs.json | 4 ++-- src/locales/en.json | 6 ++--- src/pages/SisIntegration/SisIntegration.js | 2 +- 9 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/components/Pipelines/BoxForm/BoxForm.js b/src/components/Pipelines/BoxForm/BoxForm.js index 836439f01..5f492eed5 100644 --- a/src/components/Pipelines/BoxForm/BoxForm.js +++ b/src/components/Pipelines/BoxForm/BoxForm.js @@ -36,7 +36,7 @@ class BoxForm extends Component { render() { const { show, - editting = null, + editing = null, boxTypes, variables, selectedType, @@ -55,11 +55,11 @@ class BoxForm extends Component {
- {editting ? ( + {editing ? ( {content} }} + defaultMessage="Editting Box {editing}" + values={{ editing, strong: content => {content} }} /> ) : ( @@ -174,7 +174,7 @@ class BoxForm extends Component {
- {(dirty || editting) && ( + {(dirty || editing) && ( { @@ -214,7 +214,7 @@ class BoxForm extends Component { BoxForm.propTypes = { show: PropTypes.bool, - editting: PropTypes.string, + editing: PropTypes.string, boxTypes: PropTypes.object.isRequired, boxes: PropTypes.array.isRequired, variables: PropTypes.array.isRequired, @@ -233,10 +233,10 @@ BoxForm.propTypes = { const validate = ( { name, type, portsIn = {}, portsOut = {} }, - { boxes, boxTypes, variables, variablesUtilization, editting, dirty } + { boxes, boxTypes, variables, variablesUtilization, editing, dirty } ) => { const errors = {}; - if (!dirty && !editting) { + if (!dirty && !editing) { return errors; } @@ -244,7 +244,7 @@ const validate = ( errors.name = ; } - if (name && name.trim() !== editting && boxes && boxes.find(v => v.name === name.trim())) { + if (name && name.trim() !== editing && boxes && boxes.find(v => v.name === name.trim())) { errors.name = ( box.name === editting).length; // -1 if this box is on the list + variablesUtilization[varName].portsOut.filter(box => box.name === editing).length; // -1 if this box is on the list } ++utilizations[varName]; // increment utilization since this one variable will be present }); @@ -315,9 +315,9 @@ const validate = ( return errors; }; -const warn = ({ name, type, portsIn = {}, portsOut = {} }, { boxTypes, variables, editting, dirty }) => { +const warn = ({ name, type, portsIn = {}, portsOut = {} }, { boxTypes, variables, editing, dirty }) => { const warnings = {}; - if (!dirty && !editting) { + if (!dirty && !editing) { return warnings; } diff --git a/src/components/Pipelines/VariableForm/VariableForm.js b/src/components/Pipelines/VariableForm/VariableForm.js index b13fc26c3..1b3365e54 100644 --- a/src/components/Pipelines/VariableForm/VariableForm.js +++ b/src/components/Pipelines/VariableForm/VariableForm.js @@ -30,7 +30,7 @@ class VariableForm extends Component { render() { const { show, - editting = null, + editing = null, isExternal = false, selectedType = null, handleSubmit, @@ -49,11 +49,11 @@ class VariableForm extends Component {
- {editting ? ( + {editing ? ( {content} }} + defaultMessage="Editting Variable {editing}" + values={{ editing, strong: content => {content} }} /> ) : ( @@ -129,7 +129,7 @@ class VariableForm extends Component { - {(dirty || editting) && ( + {(dirty || editing) && ( { @@ -169,7 +169,7 @@ class VariableForm extends Component { VariableForm.propTypes = { variables: PropTypes.array.isRequired, show: PropTypes.bool, - editting: PropTypes.string, + editing: PropTypes.string, onSubmit: PropTypes.func.isRequired, onHide: PropTypes.func.isRequired, isExternal: PropTypes.bool, @@ -182,9 +182,9 @@ VariableForm.propTypes = { submitting: PropTypes.bool, }; -const validate = ({ name, type, external, value }, { variables, editting, dirty }) => { +const validate = ({ name, type, external, value }, { variables, editing, dirty }) => { const errors = {}; - if (!dirty && !editting) { + if (!dirty && !editing) { return errors; } @@ -194,7 +194,7 @@ const validate = ({ name, type, external, value }, { variables, editting, dirty ); } - if (name && name.trim() !== editting && variables && variables.find(v => v.name === name.trim())) { + if (name && name.trim() !== editing && variables && variables.find(v => v.name === name.trim())) { errors.name = ( { /** * Create initial values for the form. It expects one object as input argument. - * If the object is assignment object, it correctly prepares editting form. + * If the object is assignment object, it correctly prepares editing form. * If the object holds `groups` property, it prepares multi-assign form. */ export const prepareInitialValues = defaultMemoize( diff --git a/src/components/scoreConfig/ScoreConfigUniversalExpression/ScoreConfigUniversalExpression.js b/src/components/scoreConfig/ScoreConfigUniversalExpression/ScoreConfigUniversalExpression.js index 189c30c25..b0cd59a37 100644 --- a/src/components/scoreConfig/ScoreConfigUniversalExpression/ScoreConfigUniversalExpression.js +++ b/src/components/scoreConfig/ScoreConfigUniversalExpression/ScoreConfigUniversalExpression.js @@ -359,7 +359,7 @@ class ScoreConfigUniversalExpression extends Component {
  • diff --git a/src/containers/PipelineEditContainer/PipelineEditContainer.js b/src/containers/PipelineEditContainer/PipelineEditContainer.js index de590e9ea..6f341ad38 100644 --- a/src/containers/PipelineEditContainer/PipelineEditContainer.js +++ b/src/containers/PipelineEditContainer/PipelineEditContainer.js @@ -79,7 +79,7 @@ class PipelineEditContainer extends Component { boxes: nextProps.pipeline.pipeline.boxes, variables: nextProps.pipeline.pipeline.variables, boxFormOpen: false, // whether dialog is visible - boxEditName: null, // if dialog is used for editting, name of the editted box + boxEditName: null, // if dialog is used for editing, name of the editted box variableFormOpen: false, // analogical to boxForm... variableEditName: null, selectedBox: null, @@ -430,7 +430,7 @@ class PipelineEditContainer extends Component { {editting}", + "app.pipelines.boxForm.titleEditting": "Editace krabičky {editing}", "app.pipelines.boxForm.titleNew": "Přidat novou krabičku", "app.pipelines.boxForm.type": "Typ:", "app.pipelines.boxForm.variableNotExistYet": "Vybraná proměnná zatím neexistuje a bude vytvořena.", @@ -1162,7 +1162,7 @@ "app.pipelines.variableForm.missingExternalIdentifier": "Jméno externí proměnné musí být nastaveno.", "app.pipelines.variableForm.missingType": "Musí být vybrán typ.", "app.pipelines.variableForm.selectTypeFirst": "Nejprve je třeba vybrat datový typ proměnné.", - "app.pipelines.variableForm.titleEditting": "Editace proměnné {editting}", + "app.pipelines.variableForm.titleEditting": "Editace proměnné {editing}", "app.pipelines.variableForm.titleNew": "Přidat novou proměnnou", "app.pipelines.variableForm.type": "Datový typ:", "app.pipelines.variableForm.value": "Hodnota:", diff --git a/src/locales/en.json b/src/locales/en.json index 59a5dc326..4ddc0563b 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -1134,7 +1134,7 @@ "app.pipelines.boxForm.inputPorts": "Input ports", "app.pipelines.boxForm.missingType": "You must select type of the box.", "app.pipelines.boxForm.outputPorts": "Output ports", - "app.pipelines.boxForm.titleEditting": "Editting Box {editting}", + "app.pipelines.boxForm.titleEditting": "Editting Box {editing}", "app.pipelines.boxForm.titleNew": "Add New Box", "app.pipelines.boxForm.type": "Type:", "app.pipelines.boxForm.variableNotExistYet": "Selected variable does not exist yet and will be created.", @@ -1162,7 +1162,7 @@ "app.pipelines.variableForm.missingExternalIdentifier": "Name of the external variable must be set.", "app.pipelines.variableForm.missingType": "The type must be selected.", "app.pipelines.variableForm.selectTypeFirst": "You need to select the data type of the variable first.", - "app.pipelines.variableForm.titleEditting": "Editting Variable {editting}", + "app.pipelines.variableForm.titleEditting": "Editting Variable {editing}", "app.pipelines.variableForm.titleNew": "Add New Variable", "app.pipelines.variableForm.type": "Data type:", "app.pipelines.variableForm.value": "Value:", @@ -1346,7 +1346,7 @@ "app.scoreConfigExpression.editTestNodeDialog.title": "Select the test result", "app.scoreConfigExpression.help.li1": "Mouse click: selects/deselects a node", "app.scoreConfigExpression.help.li2": "Mouse click + Ctrl: selects/deselects node allowing for multiple nodes to be selected", - "app.scoreConfigExpression.help.li3": "Double click: opens editting dialog for given node", + "app.scoreConfigExpression.help.li3": "Double click: opens editing dialog for given node", "app.scoreConfigExpression.help.li4": "All other operations (creating, removing, and moving nodes) are controlled by icons. Each icon has a tooltip which explains its purpose.", "app.scoreConfigExpression.help.p1": "The expression is represented by an abstract syntax tree (AST). Inner nodes are pure functions, leaves are either numeric literals or references to test results. The test results input values are in [0,1] range and the computed correctness (returned by the root node) should also be in [0,1] range.", "app.scoreConfigExpression.help.p2": "The tree is edited by basic mouse gestures and by clicking on icons:", diff --git a/src/pages/SisIntegration/SisIntegration.js b/src/pages/SisIntegration/SisIntegration.js index 2c7ec18b5..17accd684 100644 --- a/src/pages/SisIntegration/SisIntegration.js +++ b/src/pages/SisIntegration/SisIntegration.js @@ -160,7 +160,7 @@ class SisIntegration extends Component { }); }; - // editting semester parameters + // editing semester parameters openEditDialog = (openEdit, data) => { const editInitialValues = { beginning: data.beginning * 1000, From 05e04d9966553d0094088956ac43257af9e24018 Mon Sep 17 00:00:00 2001 From: Martin Krulis Date: Thu, 2 Dec 2021 18:11:08 +0100 Subject: [PATCH 04/20] Fixing several bugs. --- src/components/Pipelines/BoxForm/BoxForm.js | 2 +- .../PipelineEditContainer.js | 159 +++++++++++------- 2 files changed, 102 insertions(+), 59 deletions(-) diff --git a/src/components/Pipelines/BoxForm/BoxForm.js b/src/components/Pipelines/BoxForm/BoxForm.js index 5f492eed5..60c44d458 100644 --- a/src/components/Pipelines/BoxForm/BoxForm.js +++ b/src/components/Pipelines/BoxForm/BoxForm.js @@ -298,7 +298,7 @@ const validate = ( }); Object.keys(boxType.portsOut).forEach(portName => { - const varName = portsOut[encodeId(portName)].trim(); + const varName = (portsOut[encodeId(portName)] || '').trim(); if (utilizations[varName] > 1) { safeSet( errors, diff --git a/src/containers/PipelineEditContainer/PipelineEditContainer.js b/src/containers/PipelineEditContainer/PipelineEditContainer.js index 6f341ad38..8c43586a1 100644 --- a/src/containers/PipelineEditContainer/PipelineEditContainer.js +++ b/src/containers/PipelineEditContainer/PipelineEditContainer.js @@ -11,7 +11,7 @@ import VariablesTable from '../../components/Pipelines/VariablesTable'; import VariableForm, { newVariableInitialData } from '../../components/Pipelines/VariableForm'; import BoxForm, { newBoxInitialData } from '../../components/Pipelines/BoxForm'; import Button, { TheButtonGroup } from '../../components/widgets/TheButton'; -import Icon, { SaveIcon } from '../../components/icons'; +import Icon, { RefreshIcon, SaveIcon } from '../../components/icons'; import { fetchSupplementaryFilesForPipeline } from '../../redux/modules/pipelineFiles'; @@ -54,6 +54,33 @@ const asyncValidate = (values, dispatch, { initialValues: { id, version } }) => .catch(errors => reject(errors)) ); */ +const _getSelectedBoxVariables = (selectedBox, boxes) => { + const box = selectedBox && boxes.find(b => b.name === selectedBox); + return ( + box && [...Object.values(box.portsIn), ...Object.values(box.portsOut)].map(({ value }) => value).filter(identity) + ); +}; + +const _getSelectedVariableBoxes = (selectedVariable, boxes) => + selectedVariable && + boxes + .filter( + ({ portsIn, portsOut }) => + Object.values(portsIn).find(p => p.value === selectedVariable) || + Object.values(portsOut).find(p => p.value === selectedVariable) + ) + .map(({ name }) => name); + +const STATE_DEFAULTS = { + boxFormOpen: false, // whether dialog is visible + boxEditName: null, // if dialog is used for editing, name of the editted box + variableFormOpen: false, // analogical to boxForm... + variableEditName: null, + selectedBox: null, + selectedBoxVariables: null, // vars associated with selected box + selectedVariable: null, + selectedVariableBoxes: null, // boxes associated with selected var +}; class PipelineEditContainer extends Component { state = { @@ -61,14 +88,7 @@ class PipelineEditContainer extends Component { version: null, boxes: null, variables: null, - boxFormOpen: false, - boxEditName: null, - variableFormOpen: false, - variableEditName: null, - selectedBox: null, - selectedBoxVariables: null, // vars associated with selected box - selectedVariable: null, - selectedVariableBoxes: null, // boxes associated with selected var + ...STATE_DEFAULTS, }; static getDerivedStateFromProps(nextProps, prevState) { @@ -78,14 +98,7 @@ class PipelineEditContainer extends Component { version: nextProps.pipeline.version, boxes: nextProps.pipeline.pipeline.boxes, variables: nextProps.pipeline.pipeline.variables, - boxFormOpen: false, // whether dialog is visible - boxEditName: null, // if dialog is used for editing, name of the editted box - variableFormOpen: false, // analogical to boxForm... - variableEditName: null, - selectedBox: null, - selectedBoxVariables: null, - selectedVariable: null, - selectedVariableBoxes: null, + ...STATE_DEFAULTS, }; } @@ -97,6 +110,15 @@ class PipelineEditContainer extends Component { return null; } + reset = () => { + this.setState({ + version: this.props.pipeline.version, + boxes: this.props.pipeline.pipeline.boxes, + variables: this.props.pipeline.pipeline.variables, + ...STATE_DEFAULTS, + }); + }; + /* * Dialog handling */ @@ -162,13 +184,9 @@ class PipelineEditContainer extends Component { this.selectVariable(); // unselect variable, so the box holds primary selection } - const box = selectedBox && this.state.boxes.find(b => b.name === selectedBox); - const selectedBoxVariables = - box && [...Object.values(box.portsIn), ...Object.values(box.portsOut)].map(({ value }) => value).filter(identity); - this.setState({ selectedBox, - selectedBoxVariables, + selectedBoxVariables: _getSelectedBoxVariables(selectedBox, this.state.boxes), }); }; @@ -181,19 +199,9 @@ class PipelineEditContainer extends Component { this.selectBox(); // unselect box, so the variable holds primary selection } - const selectedVariableBoxes = - selectedVariable && - this.state.boxes - .filter( - ({ portsIn, portsOut }) => - Object.values(portsIn).find(p => p.value === selectedVariable) || - Object.values(portsOut).find(p => p.value === selectedVariable) - ) - .map(({ name }) => name); - this.setState({ selectedVariable, - selectedVariableBoxes, + selectedVariableBoxes: _getSelectedVariableBoxes(selectedVariable, this.state.boxes), }); }; @@ -201,7 +209,12 @@ class PipelineEditContainer extends Component { * Methods that modify the pipeline */ - transformState = (transformBoxes, transformVariables = null) => { + transformState = ( + transformBoxes, + transformVariables = null, + selectedBox = this.state.selectedBox, + selectedVariable = this.state.selectedVariable + ) => { const stateUpdate = {}; const boxes = transformBoxes && transformBoxes(this.state.boxes, this.state.variables); @@ -214,6 +227,21 @@ class PipelineEditContainer extends Component { stateUpdate.variables = variables; } + // update (recompute) selections if necessary + if ( + Object.keys(stateUpdate).length > 0 || + selectedBox !== this.state.selectedBox || + selectedVariable !== this.state.selectedVariable + ) { + stateUpdate.selectedBox = selectedBox; + stateUpdate.selectedBoxVariables = _getSelectedBoxVariables(selectedBox, stateUpdate.boxes || this.state.boxes); + stateUpdate.selectedVariable = selectedVariable; + stateUpdate.selectedVariableBoxes = _getSelectedVariableBoxes( + selectedVariable, + stateUpdate.boxes || this.state.boxes + ); + } + if (Object.keys(stateUpdate).length > 0) { this.setState(stateUpdate); } @@ -232,8 +260,11 @@ class PipelineEditContainer extends Component { const newBox = { name, type, - portsIn: objectMap(boxType.portsIn, (port, name) => ({ ...port, value: portsIn[encodeId(name)].trim() })), - portsOut: objectMap(boxType.portsOut, (port, name) => ({ ...port, value: portsOut[encodeId(name)].trim() })), + portsIn: objectMap(boxType.portsIn, (port, name) => ({ ...port, value: (portsIn[encodeId(name)] || '').trim() })), + portsOut: objectMap(boxType.portsOut, (port, name) => ({ + ...port, + value: (portsOut[encodeId(name)] || '').trim(), + })), }; // extract all assigned variables, find which of them do not exist yet, and prepare their new objects @@ -245,7 +276,8 @@ class PipelineEditContainer extends Component { // replace old box with new one this.transformState( boxes => boxes.map(box => (box.name === oldBoxName ? newBox : box)), - newVariables.length > 0 ? variables => [...variables, ...newVariables] : null + newVariables.length > 0 ? variables => [...variables, ...newVariables] : null, + this.state.selectedBox === oldBoxName ? newBox.name : this.state.selectedBox // update box selection ); } else { this.transformState( @@ -283,7 +315,9 @@ class PipelineEditContainer extends Component { ...rest, }; }), - variables => variables.map(variable => (variable.name === oldVarName ? newVariable : variable)) + variables => variables.map(variable => (variable.name === oldVarName ? newVariable : variable)), + this.state.selectedBox, + this.state.selectedVariable === oldVarName ? newVariable.name : this.state.selectedVariable // update selection ); } else { this.transformState(null, variables => [...variables, newVariable]); @@ -291,7 +325,11 @@ class PipelineEditContainer extends Component { }; removeBox = name => { - this.transformState(boxes => boxes.filter(box => box.name !== name)); + this.transformState( + boxes => boxes.filter(box => box.name !== name), + null, + this.state.selectedBox === name ? null : this.state.selectedBox // clear selection if box remmoved + ); }; removeVariable = name => { @@ -306,7 +344,9 @@ class PipelineEditContainer extends Component { ...rest, }; }), - variables => variables.filter(variable => variable.name !== name) + variables => variables.filter(variable => variable.name !== name), + this.state.selectedBox, + this.state.selectedVariable === name ? null : this.state.selectedVariable // clear selection if var removed ); }; @@ -338,26 +378,24 @@ class PipelineEditContainer extends Component { } const variable = variableName && this.state.variables.find(v => v.name === variableName); - if (variableName && !variable) { - // variable needs to be created first - this.transformState(null, variables => [ - ...variables, - { name: variableName, type: port.type, value: isArrayType(port.type) ? [] : '' }, - ]); - } else if (variable && variable.type !== port.type) { - return; + if (variable && variable.type !== port.type) { + return; // type check to avoid creating invalid affiliations } - this.transformState(boxes => - boxes.map( - b => - b.name === boxName - ? { - ...b, // clone the box and replace corresponding port - [portsKey]: { ...b[portsKey], [portName]: { ...b[portsKey][portName], value: variableName || '' } }, - } - : b // other boxes are just passed through - ) + this.transformState( + boxes => + boxes.map( + b => + b.name === boxName + ? { + ...b, // clone the box and replace corresponding port + [portsKey]: { ...b[portsKey], [portName]: { ...b[portsKey][portName], value: variableName || '' } }, + } + : b // other boxes are just passed through + ), + variableName && !variable // create the variable if it does not exist + ? variables => [...variables, { name: variableName, type: port.type, value: isArrayType(port.type) ? [] : '' }] + : null ); }; @@ -379,6 +417,11 @@ class PipelineEditContainer extends Component { + + + + + + + + - + @@ -537,6 +580,27 @@ class PipelineEditContainer extends Component { )} + + {this.state.errors && this.state.errors.length > 0 && ( + + + +
    + + : +
    +
      + {this.state.errors.map(error => ( +
    • {error}
    • + ))} +
    +
    + +
    + )} { + state => { return { boxTypes: getBoxTypes(state), }; }, (dispatch, { pipeline }) => ({ - loadFiles: () => dispatch(fetchSupplementaryFilesForPipeline(pipeline.id)), + // }) )(PipelineEditContainer); diff --git a/src/helpers/pipelines.js b/src/helpers/pipelines.js index 797245573..cfaa70926 100644 --- a/src/helpers/pipelines.js +++ b/src/helpers/pipelines.js @@ -1,9 +1,14 @@ /* * Functions related to pipeline editing and visualization. */ - +import React from 'react'; +import { FormattedMessage } from 'react-intl'; import { defaultMemoize } from 'reselect'; -import { arrayToObject } from './common'; +import { arrayToObject, identity } from './common'; + +export const KNOWN_DATA_TYPES = ['file', 'remote-file', 'string'] + .reduce((acc, type) => [...acc, type, type + '[]'], []) + .sort(); /** * Check whether given data type is a list of values. @@ -100,3 +105,345 @@ export const getVariablesTypes = defaultMemoize(variables => ({ type }) => type ) ); + +/* + * Validation + */ + +/** + * Make sure that names of boxes and variables are properly set (not empty). + * @param {Array} boxes + * @param {Array} variables + * @param {Array} errors output collector + */ +const validateNamesAreSet = (boxes, variables, errors) => { + const boxNames = boxes.map(({ name }) => name).filter(name => name && name.trim() !== ''); + if (boxes.length !== boxNames.length) { + errors.push( + + ); + } + if (new Set(boxNames).size !== boxNames.length) { + errors.push( + + ); + } + + const varNames = variables.map(({ name }) => name).filter(name => name && name.trim() !== ''); + if (variables.length !== varNames.length) { + errors.push( + + ); + } + if (new Set(varNames).size !== varNames.length) { + errors.push( + + ); + } +}; + +/** + * Verify that associated variable exist and match the port type. + * @param {string} boxName + * @param {string} ports + * @param {string} portName + * @param {Object} port + * @param {Object} variablesIndex + * @param {Array} errors output collector + * @returns + */ +const validatePortVariable = (boxName, ports, portName, port, variablesIndex, errors) => { + const variable = port.value; + if (!variable) { + return; // no variable associated, nothing to check + } + + if (!variablesIndex[variable]) { + // the variable does not exit + errors.push( + {content}, + }} + /> + ); + } else if (variablesIndex[variable].type !== port.type) { + // the type of the variable does not match + errors.push( + {content}, + }} + /> + ); + } +}; + +/** + * Validate ports of a given box whether its type match box type definition, + * and and associated variables exist and match their port types. + * @param {Object} box + * @param {Object} boxType + * @param {string} ports portsIn or portsOut + * @param {Object} variablesIndex build from variables array using name as key + * @param {Array} errors output collector + */ +const validateBoxPorts = (box, boxType, ports, variablesIndex, errors) => { + Object.keys(boxType[ports]).forEach(portName => { + const portDef = boxType[ports][portName]; + const port = box[ports] && box[ports][portName]; + if (!port) { + // port missing + errors.push( + {content}, + }} + /> + ); + } else { + // port type mismatch + if (port.type !== portDef.type) { + errors.push( + {content}, + }} + /> + ); + } + + validatePortVariable(box.name, ports, portName, port, variablesIndex, errors); + } + }); +}; + +/** + * Complete validation of boxes. + * - Boxes have known type, + * - structure of ports is matching that type, + * - and associated variables exist and match their port types. + * @param {Array} boxes + * @param {Array} variables + * @param {Object} boxTypes + * @param {Array} errors output collector + */ +const validateBoxes = (boxes, variables, boxTypes, errors) => { + const variablesIndex = arrayToObject(variables, ({ name }) => name); + boxes.forEach(box => { + if (!boxTypes[box.type]) { + errors.push( + {content}, + }} + /> + ); + } else { + const boxType = boxTypes[box.type]; + ['portsIn', 'portsOut'].forEach(ports => validateBoxPorts(box, boxType, ports, variablesIndex, errors)); + } + }); +}; + +/** + * Validate that variables have known types, value is matching that type, + * and no variable is attached to more than one output port. + * @param {Array} variables + * @param {Array} boxes + * @param {Array} errors output collector + */ +const validateVariables = (variables, boxes, errors) => { + const dataTypes = new Set(KNOWN_DATA_TYPES); + const utilization = getVariablesUtilization(boxes); + variables.forEach(variable => { + if (!dataTypes.has(variable.type)) { + errors.push( + {content}, + }} + /> + ); + } else if (!isVariableValueValid(variable)) { + errors.push( + {content}, + }} + /> + ); + } + + if (utilization[variable.name] && utilization[variable.name].portsOut.length > 1) { + errors.push( + {content}, + }} + /> + ); + } + }); +}; + +/** + * Build a oriented-graph representation of the pipeline (boxes are vertices, variables define edges). + * @param {Array} boxes + * @returns {Object} keys are box names, values are Set objects holding box names + */ +const buildGraph = boxes => { + const variablesToBoxes = {}; + boxes.forEach(box => + Object.values(box.portsIn) + .map(({ value }) => value) + .filter(identity) + .forEach(variable => { + if (!variablesToBoxes[variable]) { + variablesToBoxes[variable] = []; + } + variablesToBoxes[variable].push(box.name); + }) + ); + + return arrayToObject( + boxes, + ({ name }) => name, + box => + new Set( + Object.values(box.portsOut) + .map(({ value }) => value && variablesToBoxes[value]) + .filter(dests => dests && dests.length > 0) + .reduce((acc, dests) => [...acc, ...dests], []) + ) + ); +}; + +/** + * Internal function that performs DFS on the graph to detect loops. + * @param {Object} graph + * @param {string} vertex + * @param {Object} visited + * @param {Object} open + * @returns {boolean} true if a loop was detected + */ +const _visitGraphVertex = (graph, vertex, visited, open) => { + if (!vertex || !graph[vertex] || visited[vertex]) { + return false; + } + + if (open[vertex]) { + return true; + } + + open[vertex] = true; + const res = [...graph[vertex]].some(dest => _visitGraphVertex(graph, dest, visited, open)); + visited[vertex] = true; + return res; +}; + +/** + * Detect whether the graph has loop + * @param {Array} boxes + * @returns {boolean} true if the graph has an oriented loop + */ +const pipelineGraphHasLoops = boxes => { + const graph = buildGraph(boxes); + const open = {}; // vertices which have entered the processing + const visited = {}; // vertices which are done being processed + + let box = null; + let res = false; + while (!res && (box = Object.keys(graph).find(name => !visited[name]))) { + res = _visitGraphVertex(graph, box, visited, open); + } + return res; +}; + +/** + * Perform standard valiadtion of a pipeline. + * - All box names and variable names are properly filled. + * - All boxes, ports, and variables have valid types. + * - Variables assigned to ports match the port type. + * - No variable is used in two output ports. + * - There are no loops in the graph. + * @param {Array} boxes + * @param {Array} variables + * @return {Array|null} list of errors or null, if everything is ok + */ +export const validatePipeline = (boxes, variables, boxTypes) => { + const errors = []; + + validateNamesAreSet(boxes, variables, errors); + if (errors.length > 0) { + // if names are corrupted, no point in checking further... + return errors; + } + + validateBoxes(boxes, variables, boxTypes, errors); + validateVariables(variables, boxes, errors); + + if (errors.length === 0) { + // graph structure is only worth checking if everyting else is correct + if (pipelineGraphHasLoops(boxes)) { + errors.push( + + ); + } + } + + return errors.length > 0 ? errors : null; +}; diff --git a/src/locales/cs.json b/src/locales/cs.json index aad032f6e..078e66233 100644 --- a/src/locales/cs.json +++ b/src/locales/cs.json @@ -1115,6 +1115,7 @@ "app.pipelineEditContainer.addBoxButton": "Přidat krabičku", "app.pipelineEditContainer.addVariableButton": "Přidat proměnnou", "app.pipelineEditContainer.boxesTitle": "Krabičky", + "app.pipelineEditContainer.errorsCalloutTitle": "V pipeline byly nalezeny následující chyby", "app.pipelineEditContainer.title": "Struktura pipeline", "app.pipelineEditContainer.variablesTitle": "Proměnné", "app.pipelineEditor.AddBoxForm.title": "Přidat krabičku", @@ -1154,6 +1155,19 @@ "app.pipelines.createNew": "Vytvořit novou pipeline", "app.pipelines.listTitle": "Pipeline", "app.pipelines.title": "Seznam všech pipeline", + "app.pipelines.validation.invalidBoxType": "Neznámý typ {type} krabičky {name}.", + "app.pipelines.validation.invalidPortType": "Port {boxName}.{ports}.{portName} je typu {type}, ale {typeDef} je předepsán typem krabičky.", + "app.pipelines.validation.invalidVariableType": "Neznámý datový typ {type} u proměnné {name}.", + "app.pipelines.validation.loopDetected": "Pipeline obsahuje cyklus.", + "app.pipelines.validation.portMissing": "Port {boxName}.{ports}.{portName} je očekáván v krabičce daného typu, ale chybí.", + "app.pipelines.validation.portVariableDoesNotExist": "Port {boxName}.{ports}.{portName} má přiřazenou proměnnou {variable}, která neexistuje.", + "app.pipelines.validation.portVariableTypeMismatch": "Port {boxName}.{ports}.{portName} má přiřazenou proměnnou {variable}, ale její typ neodpovídá typu portu ({portType} != varType).", + "app.pipelines.validation.someBoxesHaveDuplicitNames": "Některé krabičky mají duplicitní jména.", + "app.pipelines.validation.someBoxesWithoutName": "Některé krabičky nemají vyplněné jméno.", + "app.pipelines.validation.someVariablesHaveDuplicitNames": "Některé proměnné mají duplicitní jména.", + "app.pipelines.validation.someVariablesWithoutName": "Některé proměnné nemají vyplněné jméno.", + "app.pipelines.validation.variableAttachedToMultiple": "Proměnná {name} je přiřazená více výstupním portům.", + "app.pipelines.validation.variableValueNotValid": "Hodnota proměnné {name} neodpovídá deklarovanému datovému typu {type}.", "app.pipelines.variableForm.duplicitName": "Toto jméno již bylo přiděleno pro jinou proměnnou.", "app.pipelines.variableForm.emptyName": "Jméno proměnné nemůže zůstat prázdné.", "app.pipelines.variableForm.external": "Reference na externí proměnnou ($)", @@ -1369,14 +1383,12 @@ "app.scoreConfigExpression.optimize.removeConstantsButton": "Nahrazení konstatních podvýrazů", "app.scoreConfigExpression.optimize.removeConstantsInfo": "Všechny konstantní podvýrazy (podstromy) budou vyhodnoceny a nahrazeny číselnými literály.", "app.scoreConfigExpression.optimize.title": "Optimalizovat výraz", - "generic.redo": "Znovu", "app.scoreConfigExpression.removeNode": "Odstranit tento uzel", "app.scoreConfigExpression.removeOnlyNode": "Odstranit pouze tento uzel (vnořené uzly se přesunou nahoru)", "app.scoreConfigExpression.sub.description": "Odečte hodnotu druhého vloženého uzlu od hodnoty prvního uzlu", "app.scoreConfigExpression.sum.description": "Sečte hodnoty všech vložených uzlů", "app.scoreConfigExpression.swapNodes": "Prohodit s vybraným uzlem (včetně podstromů)", "app.scoreConfigExpression.test-result.description": "Vstupní uzel obsahující hodnotu výsledku testu přiřazenou sudím (hodnota je v intervalu [0,1])", - "generic.undo": "Zpět", "app.scoreConfigExpression.value.description": "Číselný literál", "app.scoreConfigInfo.calculator": "Algoritmus", "app.scoreConfigInfo.createdAt": "Konfigurace uložena", @@ -1709,6 +1721,7 @@ "generic.noRecordsInTable": "V tabulce nejsou žádné záznamy.", "generic.operationFailed": "Operace se nezdařila. Prosíme, opakujte akci později.", "generic.reason": "Důvod", + "generic.redo": "Znovu", "generic.reevaluatedBy": "Znovu vyhodnotil(a)", "generic.refresh": "Občerstvit", "generic.remove": "Odebrat", @@ -1733,6 +1746,7 @@ "generic.submitted": "Odevzdáno", "generic.submitting": "Odevzdávání...", "generic.tags": "Nálepky", + "generic.undo": "Zpět", "generic.update": "Upravit", "generic.updated": "Upraveno", "generic.uploadedAt": "Nahráno", diff --git a/src/locales/en.json b/src/locales/en.json index 82ea26d17..8c21c4005 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -1115,6 +1115,7 @@ "app.pipelineEditContainer.addBoxButton": "Add Box", "app.pipelineEditContainer.addVariableButton": "Add Variable", "app.pipelineEditContainer.boxesTitle": "Boxes", + "app.pipelineEditContainer.errorsCalloutTitle": "The following errors were found in the pipeline", "app.pipelineEditContainer.title": "Edit Pipeline Structure", "app.pipelineEditContainer.variablesTitle": "Variables", "app.pipelineEditor.AddBoxForm.title": "Add a box", @@ -1154,6 +1155,19 @@ "app.pipelines.createNew": "Create New Pipeline", "app.pipelines.listTitle": "Pipelines", "app.pipelines.title": "List of All Pipelines", + "app.pipelines.validation.invalidBoxType": "Unknown box type {type} of box {name}.", + "app.pipelines.validation.invalidPortType": "Port {boxName}.{ports}.{portName} is of type {type}, but {typeDef} type is prescribed by the box type.", + "app.pipelines.validation.invalidVariableType": "Unknown data type {type} of variable {name}.", + "app.pipelines.validation.loopDetected": "Loop detected in the pipeline.", + "app.pipelines.validation.portMissing": "Port {boxName}.{ports}.{portName} is prescribed by the box type but missing.", + "app.pipelines.validation.portVariableDoesNotExist": "Port {boxName}.{ports}.{portName} has attached variable {variable} which does not exist.", + "app.pipelines.validation.portVariableTypeMismatch": "Port {boxName}.{ports}.{portName} has attached variable {variable}, but their types do not match ({portType} != varType).", + "app.pipelines.validation.someBoxesHaveDuplicitNames": "Some boxes have duplicit names.", + "app.pipelines.validation.someBoxesWithoutName": "At least one box does not have properly filled name.", + "app.pipelines.validation.someVariablesHaveDuplicitNames": "Some variables have duplicit names.", + "app.pipelines.validation.someVariablesWithoutName": "At least one variables does not have properly filled name.", + "app.pipelines.validation.variableAttachedToMultiple": "Variable {name} is attached to more than one output port.", + "app.pipelines.validation.variableValueNotValid": "Value of variable {name} does not match its declared data type {type}.", "app.pipelines.variableForm.duplicitName": "This name is already taken by another variable.", "app.pipelines.variableForm.emptyName": "Variable name cannot be empty.", "app.pipelines.variableForm.external": "External variable reference ($)", @@ -1369,14 +1383,12 @@ "app.scoreConfigExpression.optimize.removeConstantsButton": "Replace Constant Sub-expressions", "app.scoreConfigExpression.optimize.removeConstantsInfo": "All constant sub-expressions (sub-trees) are evaluated and replaced with numeric literal nodes.", "app.scoreConfigExpression.optimize.title": "Optimize The Expression", - "generic.redo": "Redo", "app.scoreConfigExpression.removeNode": "Remove this node", "app.scoreConfigExpression.removeOnlyNode": "Remove only this node (children are moved upwards)", "app.scoreConfigExpression.sub.description": "Subtracts the value of the second node from the value of the first node", "app.scoreConfigExpression.sum.description": "Computes a sum of all nested nodes", "app.scoreConfigExpression.swapNodes": "Swap with selected node (including sub-trees)", "app.scoreConfigExpression.test-result.description": "Input node that takes the result assigned by a judge to a particular test (as value in [0,1] range)", - "generic.undo": "Undo", "app.scoreConfigExpression.value.description": "Numeric literal", "app.scoreConfigInfo.calculator": "Algorithm", "app.scoreConfigInfo.createdAt": "Configured at", @@ -1709,6 +1721,7 @@ "generic.noRecordsInTable": "There are no records in the table.", "generic.operationFailed": "Operation failed. Please try again later.", "generic.reason": "Reason", + "generic.redo": "Redo", "generic.reevaluatedBy": "Re-evaluated by", "generic.refresh": "Refresh", "generic.remove": "Remove", @@ -1733,6 +1746,7 @@ "generic.submitted": "Submitted", "generic.submitting": "Submitting...", "generic.tags": "Tags", + "generic.undo": "Undo", "generic.update": "Update", "generic.updated": "Updated", "generic.uploadedAt": "Uploaded at", From e39d6276c343ea33ae51748543cbb73fb8f1ec4a Mon Sep 17 00:00:00 2001 From: Martin Krulis Date: Tue, 7 Dec 2021 13:08:48 +0100 Subject: [PATCH 07/20] Adding comments and hints for box types to pipeline editor. --- src/components/Pipelines/BoxForm/BoxForm.js | 44 +++- .../Pipelines/BoxesTable/BoxesTableRow.js | 22 +- src/components/Pipelines/comments.js | 193 ++++++++++++++++++ .../HighlightedText/HighlightedText.js | 1 - .../PaginationButtons/PaginationButtons.js | 1 - src/locales/cs.json | 32 +++ src/locales/en.json | 32 +++ 7 files changed, 312 insertions(+), 13 deletions(-) create mode 100644 src/components/Pipelines/comments.js diff --git a/src/components/Pipelines/BoxForm/BoxForm.js b/src/components/Pipelines/BoxForm/BoxForm.js index 60c44d458..5e510845d 100644 --- a/src/components/Pipelines/BoxForm/BoxForm.js +++ b/src/components/Pipelines/BoxForm/BoxForm.js @@ -1,6 +1,6 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import { FormattedMessage } from 'react-intl'; +import { FormattedMessage, defineMessages, injectIntl } from 'react-intl'; import { Modal, Table, Container, Row, Col } from 'react-bootstrap'; import { connect } from 'react-redux'; import { reduxForm, Field, formValueSelector } from 'redux-form'; @@ -8,12 +8,24 @@ import { defaultMemoize } from 'reselect'; import { TextField, SelectField } from '../../forms/Fields'; import Button, { TheButtonGroup } from '../../widgets/TheButton'; +import InsetPanel from '../../widgets/InsetPanel'; import SubmitButton from '../../forms/SubmitButton'; import { CloseIcon, SaveIcon, RefreshIcon, InputIcon, OutputIcon } from '../../../components/icons'; import { encodeId, safeSet } from '../../../helpers/common'; +import { getBoxTypeDescription } from '../comments'; export const newBoxInitialData = { name: '', type: '', portsIn: {}, portsOut: {} }; +const suggestedBoxName = defaultMemoize((boxType, boxes) => { + const names = new Set(boxes.map(({ name }) => name)); + const prefix = boxType || 'box'; + let suffix = 1; + while (names.has(`${prefix}${suffix}`)) { + suffix = suffix + 1; + } + return `${prefix}${suffix}`; +}); + const prepareBoxTypeOptions = defaultMemoize(boxTypes => Object.values(boxTypes) .map(({ name, type }) => ({ key: type, name: `${name} (${type})` })) @@ -32,11 +44,19 @@ const preparePortsOfSelectedBoxType = defaultMemoize(boxType => { return { portsIn, portsOut }; }); +const messages = defineMessages({ + varPlaceholder: { + id: 'app.pipelines.boxForm.portVariablePlaceholder', + defaultMessage: 'associated variable', + }, +}); + class BoxForm extends Component { render() { const { show, editing = null, + boxes, boxTypes, variables, selectedType, @@ -47,6 +67,7 @@ class BoxForm extends Component { submitting = false, reset, onHide, + intl: { formatMessage }, } = this.props; const { portsIn, portsOut } = preparePortsOfSelectedBoxType(selectedType && boxTypes[selectedType]); @@ -73,6 +94,12 @@ class BoxForm extends Component { ))} + + + {selectedType && } + {editing && } + + @@ -81,6 +108,8 @@ class BoxForm extends Component { tabIndex={1} component={TextField} maxLength={255} + list="boxNameDatalist" + placeholder={suggestedBoxName(selectedType, boxes)} label={ : @@ -101,6 +130,14 @@ class BoxForm extends Component { + {selectedType && getBoxTypeDescription(selectedType) && ( + + + {getBoxTypeDescription(selectedType)} + + + )} + {((portsIn && portsIn.length > 0) || (portsOut && portsOut.length > 0)) &&
    } @@ -123,6 +160,7 @@ class BoxForm extends Component { - {boxTypes[box.type] ? ( - boxTypes[box.type].name - ) : ( - - )} - + + + {boxTypes[box.type] ? ( + boxTypes[box.type].name + ) : ( + + )} + + {getBoxTypeDescription(box.type)} + }> {box.type} - {!boxTypes[box.type] && } + {!boxTypes[box.type] && } diff --git a/src/components/Pipelines/comments.js b/src/components/Pipelines/comments.js new file mode 100644 index 000000000..63486de3a --- /dev/null +++ b/src/components/Pipelines/comments.js @@ -0,0 +1,193 @@ +import React from 'react'; +import { FormattedMessage } from 'react-intl'; + +const BOX_TYPE_DESCRIPTIONS = { + bison: ( + + ), + 'custom-compilation': ( + + ), + 'elf-exec': ( + + ), + 'fetch-file': ( + + ), + 'fetch-files': ( + + ), + 'file-name': ( + + ), + 'file-to-array': ( + + ), + 'files-names': ( + + ), + fpc: ( + + ), + 'g++': ( + + ), + gcc: ( + + ), + 'haskell-compilation': ( + + ), + 'haskell-exec': ( + + ), + 'file-in': ( + + ), + 'files-in': ( + + ), + 'jvm-compilation': ( + + ), + 'jvm-runner': ( + + ), + 'merge-files': ( + + ), + 'merge-strings': ( + + ), + mcs: ( + + ), + 'mono-exec': ( + + ), + node: ( + + ), + 'file-out': ( + + ), + 'files-out': ( + + ), + php: ( + + ), + python3: ( + + ), + judge: ( + + ), + 'script-exec': ( + + ), + 'string-to-array': ( + + ), + 'prolog-compilation': ( + + ), + 'wrapped-exec': ( + + ), +}; + +export const getBoxTypeDescription = type => BOX_TYPE_DESCRIPTIONS[type] || null; diff --git a/src/components/widgets/HighlightedText/HighlightedText.js b/src/components/widgets/HighlightedText/HighlightedText.js index ea18ede7c..9c36050d4 100644 --- a/src/components/widgets/HighlightedText/HighlightedText.js +++ b/src/components/widgets/HighlightedText/HighlightedText.js @@ -31,7 +31,6 @@ const splitHighlightedTokens = (str, regex) => { return res; }; -// Inset panel replaces old component from bootstrap 3 const HighlightedText = React.memo(({ children, regex }) => ( <> {splitHighlightedTokens(children, regex).map((str, idx) => diff --git a/src/components/widgets/PaginationButtons/PaginationButtons.js b/src/components/widgets/PaginationButtons/PaginationButtons.js index 1f6f32772..16a81bafc 100644 --- a/src/components/widgets/PaginationButtons/PaginationButtons.js +++ b/src/components/widgets/PaginationButtons/PaginationButtons.js @@ -29,7 +29,6 @@ const prepareButtonsIndices = (activePage, items, maxButtons) => { return buttons; }; -// Inset panel replaces old component from bootstrap 3 const PaginationButtons = ({ prev = false, next = false, diff --git a/src/locales/cs.json b/src/locales/cs.json index 078e66233..6825b6171 100644 --- a/src/locales/cs.json +++ b/src/locales/cs.json @@ -1135,11 +1135,43 @@ "app.pipelines.boxForm.inputPorts": "Vstupní porty", "app.pipelines.boxForm.missingType": "Musí být vybrán typ krabičky.", "app.pipelines.boxForm.outputPorts": "Výstupní porty", + "app.pipelines.boxForm.portVariablePlaceholder": "asociovaná proměnná", "app.pipelines.boxForm.titleEditting": "Editace krabičky {editing}", "app.pipelines.boxForm.titleNew": "Přidat novou krabičku", "app.pipelines.boxForm.type": "Typ:", "app.pipelines.boxForm.variableNotExistYet": "Vybraná proměnná zatím neexistuje a bude vytvořena.", "app.pipelines.boxForm.variableUsedInMultipleOutputs": "Tato proměnná je použita ve více než jednom výstupním portu.", + "app.pipelines.boxTypeDescription.bison": "Specializovaná krabička, která spustí nástroj Bison na generování parserů.", + "app.pipelines.boxTypeDescription.custom-compilation": "Obecná kompilační krabička, která spustí libovolnou aplikaci jako kompilátor. Je možné ji použít na podobné nástroje (např. makro preprocesor nebo linker).", + "app.pipelines.boxTypeDescription.elf-exec": "Obecná krabička, která spustí ELF soubor jako testované řešení.", + "app.pipelines.boxTypeDescription.fetch-file": "Vstupní krabička, která zajistí stažení jednoho souboru pipeline do sandboxu.", + "app.pipelines.boxTypeDescription.fetch-files": "Vstupní krabička, která zajistí stažení souborů pipeline do sandboxu.", + "app.pipelines.boxTypeDescription.file-in": "Vstupní krabička, která zajistí stažení jednoho externího souboru (tj. odevzdaného souboru od uživatele, souboru z konfigurace úlohy, nebo souboru exportovaného předchozí pipeline).", + "app.pipelines.boxTypeDescription.file-name": "Konvertuje jeden soubor na řetězec obsahující interní cestu k souboru. Obzvláště užitečné, pokud je potřeba předat soubory jako argumenty příkazové řádky.", + "app.pipelines.boxTypeDescription.file-out": "Výstupní krabička reprezentující soubor, který je exportován ven z pipeline (např. zkompilovaný soubor, který je předáván následující pipeline).", + "app.pipelines.boxTypeDescription.file-to-array": "Konvertuje jeden soubor na pole souborů obsahující jediný prvek.", + "app.pipelines.boxTypeDescription.files-in": "Vstupní krabička, která zajistí stažení externích souborů (tj. odevzdaných souborů od uživatele, souborů z konfigurace úlohy, nebo souborů exportovaných z předchozí pipeline).", + "app.pipelines.boxTypeDescription.files-names": "Konvertuje pole souborů na pole řetězeců obsahující interní cesty k jednotlivým souborům. Obzvláště užitečné, pokud je potřeba předat soubory jako argumenty příkazové řádky.", + "app.pipelines.boxTypeDescription.files-out": "Výstupní krabička reprezentující soubory, které jsou exportovány ven z pipeline (např. zkompilované soubory, které jsou předávány následující pipeline).", + "app.pipelines.boxTypeDescription.fpc": "Speciální krabička pro spuštění FreePascal kompilátoru.", + "app.pipelines.boxTypeDescription.gcc": "Speciální krabička pro spuštění gcc kompilátoru.", + "app.pipelines.boxTypeDescription.gpp": "Speciální krabička pro spuštění g++ kompilátoru.", + "app.pipelines.boxTypeDescription.haskell-compilation": "Speciální krabička pro spuštění Haskell kompilátoru.", + "app.pipelines.boxTypeDescription.haskell-exec": "Speciální krabička pro spuštění testovaných řešení v Haskellu.", + "app.pipelines.boxTypeDescription.judge": "Krabička pro spuštění sudího, který určuje správnost výstupů testovaného řešení.", + "app.pipelines.boxTypeDescription.jvm-compilation": "Speciální krabička pro spuštění kompilátoru založených na JVM (tj. takových, které produkují JVM bytecode).", + "app.pipelines.boxTypeDescription.jvm-runner": "Speciální krabička pro spuštění testovaných řešení pomocí Java runtime.", + "app.pipelines.boxTypeDescription.mcs": "Speciální krabička pro spuštění mcs (Mono C#) kompilátoru. (ZASTARALÉ)", + "app.pipelines.boxTypeDescription.merge-files": "Spojí dvě pole souborů do jednoho (druhé pole je připojeno za první).", + "app.pipelines.boxTypeDescription.merge-strings": "Spojí dvě pole řetězců do jednoho (druhé pole je připojeno za první).", + "app.pipelines.boxTypeDescription.mono-exec": "Speciální krabička pro spuštění testovaných řešení v C# pomocí Mono runtime. (ZASTARALÉ)", + "app.pipelines.boxTypeDescription.node": "Speciální krabička pro spuštění testovaných řešení v JavaScriptu pomocí Nodejs runtime.", + "app.pipelines.boxTypeDescription.php": "Speciální krabička pro spuštění testovaných řešení v PHP pomocí PHP-CLI runtime.", + "app.pipelines.boxTypeDescription.prolog-compilation": "Speciální krabička pro spuštění SWI Prolog kompilátoru.", + "app.pipelines.boxTypeDescription.python3": "Speciální krabička pro spuštění testovaných řešení v Pythonu.", + "app.pipelines.boxTypeDescription.script-exec": "Obecná krabička pro spuštění testovaného řešení jako skriptu v daném prostředí (Bash, Python, PHP, ...).", + "app.pipelines.boxTypeDescription.string-to-array": "Konvertuje jeden řetězec na pole souborů obsahující jediný prvek.", + "app.pipelines.boxTypeDescription.wrapped-exec": "Obecná krabička pro spuštění testovaného řešení ve specifickém běhovém prostředí (Java, Mono, ...).", "app.pipelines.boxesTable.boxType": "Typ krabičky", "app.pipelines.boxesTable.createNewVariable": "Vytvořit novou proměnnou, která bude asociována s tímto portem.", "app.pipelines.boxesTable.name": "Název", diff --git a/src/locales/en.json b/src/locales/en.json index 8c21c4005..afb9aca24 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -1135,11 +1135,43 @@ "app.pipelines.boxForm.inputPorts": "Input ports", "app.pipelines.boxForm.missingType": "You must select type of the box.", "app.pipelines.boxForm.outputPorts": "Output ports", + "app.pipelines.boxForm.portVariablePlaceholder": "associated variable", "app.pipelines.boxForm.titleEditting": "Editting Box {editing}", "app.pipelines.boxForm.titleNew": "Add New Box", "app.pipelines.boxForm.type": "Type:", "app.pipelines.boxForm.variableNotExistYet": "Selected variable does not exist yet and will be created.", "app.pipelines.boxForm.variableUsedInMultipleOutputs": "This variable is being used in multiple output ports.", + "app.pipelines.boxTypeDescription.bison": "Specialized box that executes bison parser generator.", + "app.pipelines.boxTypeDescription.custom-compilation": "Generic compilation box that invokes any executable and treats it as a compiler. It may also be used for similar tools (e.g., macro preprocessor or liker).", + "app.pipelines.boxTypeDescription.elf-exec": "Generic box for running solutions which were compiled as ELF executables.", + "app.pipelines.boxTypeDescription.fetch-file": "Input box which ensures download of a single pipeline file into the sandbox.", + "app.pipelines.boxTypeDescription.fetch-files": "Input box which ensures download of pipeline files into the sandbox.", + "app.pipelines.boxTypeDescription.file-in": "Input box for retrieving a single external file (i.e., file from the user, exercise configuration, or exported from the previous pipeline).", + "app.pipelines.boxTypeDescription.file-name": "Converts a file into a string which holds internal path to the file. Particularly useful when files needs to be listed in command line arguments.", + "app.pipelines.boxTypeDescription.file-out": "Output box that represents a file which is being exported from the pipeline (e.g., to pass newly created executable from compilation pipeline into the next one).", + "app.pipelines.boxTypeDescription.file-to-array": "Converts a single file into a file-list type with one item.", + "app.pipelines.boxTypeDescription.files-in": "Input box for retrieving a list of external files (i.e., files from the user, exercise configuration, or exported from the previous pipeline).", + "app.pipelines.boxTypeDescription.files-names": "Converts a list of files into a list of strings where each string holds internal path to the corresponding file. Particularly useful when files needs to be listed in command line arguments.", + "app.pipelines.boxTypeDescription.files-out": "Output box that represents a list of file which are being exported from the pipeline (e.g., to pass newly created executables from compilation pipeline into the next one).", + "app.pipelines.boxTypeDescription.fpc": "Specialized box that invokes FreePascal compiler.", + "app.pipelines.boxTypeDescription.gcc": "Specialized box that invokes gcc compiler.", + "app.pipelines.boxTypeDescription.gpp": "Specialized box that invokes g++ compiler.", + "app.pipelines.boxTypeDescription.haskell-compilation": "Specialized box that invokes Haskell compiler.", + "app.pipelines.boxTypeDescription.haskell-exec": "Specialized box for executing Haskell programs.", + "app.pipelines.boxTypeDescription.judge": "Box that invokes judge that determines correctness of the result yielded by tested solution.", + "app.pipelines.boxTypeDescription.jvm-compilation": "Specialized box for invoking Java-based compilers (i.e., compilers that produce JVM bytecode).", + "app.pipelines.boxTypeDescription.jvm-runner": "Specialized box for running solutions which were compiled into JVM bytecode.", + "app.pipelines.boxTypeDescription.mcs": "Specialized box that invokes mcs (Mono C#) compiler. (DEPRECATED)", + "app.pipelines.boxTypeDescription.merge-files": "Helper box that concatenates two file lists into one.", + "app.pipelines.boxTypeDescription.merge-strings": "Helper box that concatenates two string lists into one.", + "app.pipelines.boxTypeDescription.mono-exec": "Specialized box that executes C# solution compiled for Mono runtime. (DEPRECATED)", + "app.pipelines.boxTypeDescription.node": "Specialized box that executes JavaScript solutions in Nodejs runtime.", + "app.pipelines.boxTypeDescription.php": "Specialized box that executes PHP solutions using PHP-CLI runtime.", + "app.pipelines.boxTypeDescription.prolog-compilation": "Specialized box that invokes SWI prolog compiler.", + "app.pipelines.boxTypeDescription.python3": "Specialized box that executes Python solutions.", + "app.pipelines.boxTypeDescription.script-exec": "Generic box for running solutions in a scripting environment (Bash, Python, PHP, ...).", + "app.pipelines.boxTypeDescription.string-to-array": "Converts a single string into a string-list type with one item.", + "app.pipelines.boxTypeDescription.wrapped-exec": "Generic box for running solutions in a particular execution environment (Java, Mono, ...).", "app.pipelines.boxesTable.boxType": "Box Type", "app.pipelines.boxesTable.createNewVariable": "Create new variable and associate it with this port.", "app.pipelines.boxesTable.name": "Name", From 1ea59b413e1a077280d700153c2ea8983552acb2 Mon Sep 17 00:00:00 2001 From: Martin Krulis Date: Fri, 17 Dec 2021 01:50:27 +0100 Subject: [PATCH 08/20] Implementing new visualization of the pipeline for the edit container. --- src/components/Pipelines/BoxForm/BoxForm.js | 2 +- .../Pipelines/PipelineGraph/PipelineGraph.js | 319 +++ .../Pipelines/PipelineGraph/index.js | 2 + src/components/Pipelines/styles.less | 12 +- .../PipelineEditContainer.js | 146 +- src/helpers/pipelines.js | 11 +- src/locales/cs.json | 3 + src/locales/en.json | 3 + yarn.lock | 2171 +++++++++-------- 9 files changed, 1558 insertions(+), 1111 deletions(-) create mode 100644 src/components/Pipelines/PipelineGraph/PipelineGraph.js create mode 100644 src/components/Pipelines/PipelineGraph/index.js diff --git a/src/components/Pipelines/BoxForm/BoxForm.js b/src/components/Pipelines/BoxForm/BoxForm.js index 5e510845d..c9b70c1ca 100644 --- a/src/components/Pipelines/BoxForm/BoxForm.js +++ b/src/components/Pipelines/BoxForm/BoxForm.js @@ -332,7 +332,7 @@ const validate = ( if (!utilizations[varName]) { utilizations[varName] = variablesUtilization[varName].portsOut.length - // number of boxes, where the var is used in output - variablesUtilization[varName].portsOut.filter(box => box.name === editing).length; // -1 if this box is on the list + variablesUtilization[varName].portsOut.filter(({ box }) => box.name === editing).length; // -1 if this box is on the list } ++utilizations[varName]; // increment utilization since this one variable will be present }); diff --git a/src/components/Pipelines/PipelineGraph/PipelineGraph.js b/src/components/Pipelines/PipelineGraph/PipelineGraph.js new file mode 100644 index 000000000..20d9a0a43 --- /dev/null +++ b/src/components/Pipelines/PipelineGraph/PipelineGraph.js @@ -0,0 +1,319 @@ +import React, { useState, useEffect } from 'react'; +import PropTypes from 'prop-types'; +import { canUseDOM } from 'exenv'; +import Viz from 'viz.js'; + +import InsetPanel from '../../widgets/InsetPanel'; +import { LoadingIcon } from '../../icons'; +import { isExternalReference } from '../../../helpers/pipelines'; +import styles from '../styles.less'; + +const { Module, render } = require('viz.js/lite.render.js'); + +// string sanitizations +const normalizeDotId = id => (id || '').replace(/[^-a-zA-Z0-9_]/, ''); +const normalizeDotRecordString = str => (str || '').replace(/[|{}"']/, ''); +const normalizeDotString = str => (str || '').replace('"', '"'); + +/** + * Special sanitization for variable value (also ensures max. lengh by ellipsis). + * @param {string} str + * @returns {string} + */ +const normalizeVariableValue = str => { + str = normalizeDotString(str); + if (str.length > 25) { + str = str.substring(0, 24) + '…'; + } + return str; +}; + +/** + * Ellipsis for arrays, if it has more than 4 items, it is truncated and ... becomes the last item. + * @param {Array} arr + * @returns {Array} + */ +const arrayEllipsis = arr => (arr.length > 4 ? [arr[0], arr[1], arr[2], '…'] : arr); + +/** + * Ensure given identifier is unique. + * @param {string} id original identifier (used as prefix) + * @param {Object} index id must not collide with any of the keys + * @param {Object|null} index2 id must not collide with any of the keys (if the second index is provided) + * @returns {string} + */ +const makeUnique = (id, index, index2 = null) => { + let suffix = ''; + let counter = 0; + while (`${id}${suffix}` in index) { + suffix = `_${++counter}`; + } + if (index2) { + while (`${id}${suffix}` in index2) { + suffix = `_${++counter}`; + } + } + return `${id}${suffix}`; +}; + +/** + * Render list of ports in dot-formatted label. + * @param {Object} ports + * @returns {string} + */ +const renderPorts = ports => + Object.keys(ports) + .map(port => `<${port}> ${port}`) + .join(' | '); + +/** + * Special labels for technical boxes (merges, casts, ...) that can save space. + * We do not need to show full box with name and type. + */ +const technicalBoxLabels = { + 'merge-files': '{ { [files1] | [files2] } | [files1, files2] }', + 'merge-strings': '{ { [strs1] | [strs2] } | [strs1, strs2] }', + 'file-to-array': '{ file | [file] }', + 'string-to-array': '{ str | [str] }', + 'file-name': '{ file | str }', + 'file-names': '{ [files] | [strs] }', +}; + +/** + * Formatting function that converts a box into dot string representation of record node. + * @param {Object} box + * @param {string|null} primarySelection name of the selected box (null if no box is selected) + * @returns {string} in dot format + */ +const renderBox = (box, primarySelection) => { + const portsIn = box.portsIn && Object.keys(box.portsIn).length > 0 ? `{ ${renderPorts(box.portsIn)} } |` : ''; + const portsOut = box.portsOut && Object.keys(box.portsOut).length > 0 ? `| { ${renderPorts(box.portsOut)} }` : ''; + const fillColor = primarySelection === box.name ? '#ccccff' : technicalBoxLabels[box.type] ? '#eeeeee' : '#eeffee'; + const label = + technicalBoxLabels[box.type] || + `{ ${portsIn} \\n${normalizeDotRecordString(box.name)} (${box.type})\\n  ${portsOut} }`; + return `<${box.id}> [label="${label}", tooltip="${normalizeDotString( + box.name + )}", fillcolor="${fillColor}", class="clickable"];`; +}; + +/** + * Formatting function that renders a variable into dot string representation of a node. + * @param {Object} variable + * @param {string|null} primarySelection name of the selected variable (null if no variable is selected) + * @returns {string} + */ +const renderVariableValue = (variable, primarySelection) => { + const name = normalizeDotString(variable.name); + const fillColor = primarySelection === variable.name ? '#ccccff' : null; + const attributes = ['shape=oval', 'fontsize=8', `tooltip="${name}"`, 'class="clickable"']; + + if (isExternalReference(variable.value)) { + // special case for external references so they are not missed + attributes.push( + `label="${normalizeVariableValue(variable.value)}"`, + `fillcolor="${fillColor || '#ffeee0'}"`, + 'shape=oval' + ); + } else { + const label = Array.isArray(variable.value) + ? arrayEllipsis(variable.value).map(normalizeVariableValue).join('\\l') // \l newline, but text aligned to left + : normalizeVariableValue(variable.value); + attributes.push(`label="${label}\\l"`, `fillcolor="${fillColor || '#ffffff'}"`, 'shape=note'); + } + return `<${variable.id}> [${attributes.join(',')}]`; +}; + +// Formatting functions for connectors +const renderEdge = ({ from, to, label }) => { + const res = [from, '->', to]; + if (label) { + res.push('[label="', normalizeDotString(label), '", fontsize="8"]'); + } + return res.join(' ') + ';'; +}; + +/** + * Main rendering function. Gets the configuration of the pipeline and generates a serialized dot representation. + * @param {Array} boxes + * @param {Array} variables + * @param {Object} utilization + * @param {string|null} selectedBox + * @param {string|null} selectedVariable + * @returns {Object} containg dot (string), + */ +const prepareGraphForRendering = (boxes, variables, utilization, selectedBox, selectedVariable) => { + // preprocess and index boxes (ids must be safe and unique) + const boxIndex = {}; + const boxIds = {}; + const renderedBoxes = boxes.map(box => { + const id = makeUnique(normalizeDotId(box.name || box.type || 'box'), boxIndex); + boxIndex[box.name] = id; + boxIds[id] = box.name; + return { ...box, id }; + }); + + // preprocess and index variables (like boxes, but only nonempty are shown) + const variableIndex = {}; + const variableIds = {}; + const prepVariables = variables + .filter(({ value }) => value && (!Array.isArray(value) || value.length > 0)) + .map(variable => { + const id = makeUnique(normalizeDotId(variable.name || variable.type || 'var'), variableIndex, boxIndex); + variableIndex[variable.name] = id; + variableIds[id] = variable.name; + return { ...variable, id }; + }); + + // compute connections between nodes in the dot graph based on how variables connect the boxes + const connections = []; + Object.keys(utilization).forEach(variable => { + const { portsIn, portsOut } = utilization[variable]; + if (variableIndex[variable]) { + // variable has explicit value, we need to connect outs -> var and var -> ins + portsOut.forEach(portOut => { + connections.push({ + from: `<${boxIndex[portOut.box.name]}>:<${portOut.port}>:s`, // :s = attached to south + to: `<${variableIndex[variable]}>:n`, // :n = attached to north + label: variable, + }); + }); + portsIn.forEach(portIn => { + connections.push({ + from: `<${variableIndex[variable]}>:s`, // :s = attached to south + to: `<${boxIndex[portIn.box.name]}>:<${portIn.port}>:n`, // :n = attached to north + }); + }); + } else { + // no variable box present (only a simple connection) + portsOut.forEach(portOut => { + portsIn.forEach(portIn => { + // cartesian product (although, there should be at most one port out) + connections.push({ + from: `<${boxIndex[portOut.box.name]}>:<${portOut.port}>:s`, // :s = attached to south + to: `<${boxIndex[portIn.box.name]}>:<${portIn.port}>:n`, // :n = attached to north + label: variable, + }); + }); + }); + } + }); + + // lets the assembly begin... + const dot = [ + 'digraph structs {', + 'graph [truecolor=true, bgcolor="#ffffff00"];', + 'node [shape=record, style="rounded,filled,solid", fontsize="12"];', + ...renderedBoxes.map(box => renderBox(box, selectedBox)), + ...prepVariables.map(variable => renderVariableValue(variable, selectedVariable)), + ...connections.map(renderEdge), + '}', + ].join('\n'); + return { dot, boxIds, variableIds }; +}; + +/** + * Renders serialized dot graph into svg. + * @param {string} dot + * @returns {Promise} + */ +const startRenderingToSvg = dot => { + const viz = new Viz({ Module, render }); + return viz.renderString(dot); +}; + +/** + * Event handling helper that identifies either a box or variable from a click event. + * @param {Event} ev + * @param {Object} boxIds dot id -> box name dictionary + * @param {Object} variableIds dot id -> variable name dictionary + * @returns {Object} with two keys `box` and `variable` holding either string with name or null + */ +const preprocessClickEvent = (ev, boxIds, variableIds) => { + let id = ev.target; + id = id && id.closest('g.node.clickable'); // neares group parent representing box or variable + id = id && id.querySelector('title'); // group title holds the dot id + id = id && id.textContent; + + const box = (id && boxIds && boxIds[id]) || null; + const variable = (id && variableIds && variableIds[id]) || null; + return { box, variable }; +}; + +const PipelineGraph = ({ + boxes, + boxTypes, + variables, + utilization, + selectedBox = null, + selectedVariable = null, + selectBox = null, + editBox = null, + selectVariable = null, + editVariable = null, +}) => { + if (canUseDOM) { + const [svg, setSvg] = useState(null); + const [boxIds, setBoxIds] = useState(null); + const [variableIds, setVariableIds] = useState(null); + + useEffect(() => { + setSvg(null); + const { dot, boxIds, variableIds } = prepareGraphForRendering( + boxes, + variables, + utilization, + selectedBox, + selectedVariable + ); + setBoxIds(boxIds); + setVariableIds(variableIds); + startRenderingToSvg(dot).then(result => setSvg(result)); + }, [boxes, boxTypes, variables, utilization, selectedBox, selectedVariable]); + + return ( + + {canUseDOM && svg ? ( +
    { + ev.preventDefault(); + const { box, variable } = preprocessClickEvent(ev, boxIds, variableIds); + box && selectBox && selectBox(box); + variable && selectVariable && selectVariable(variable); + }} + onClick={ev => { + const { box, variable } = preprocessClickEvent(ev, boxIds, variableIds); + box && editBox && editBox(box); + variable && editVariable && editVariable(variable); + }} + /> + ) : ( +
    + +
    + )} + + ); + } else { + ; + } +}; + +PipelineGraph.propTypes = { + boxes: PropTypes.array.isRequired, + boxTypes: PropTypes.object.isRequired, + variables: PropTypes.array.isRequired, + utilization: PropTypes.object.isRequired, + selectedBox: PropTypes.string, + selectedVariable: PropTypes.string, + selectBox: PropTypes.func, + editBox: PropTypes.func, + selectVariable: PropTypes.func, + editVariable: PropTypes.func, +}; + +export default PipelineGraph; diff --git a/src/components/Pipelines/PipelineGraph/index.js b/src/components/Pipelines/PipelineGraph/index.js new file mode 100644 index 000000000..e33017883 --- /dev/null +++ b/src/components/Pipelines/PipelineGraph/index.js @@ -0,0 +1,2 @@ +import PipelineGraph from './PipelineGraph'; +export default PipelineGraph; diff --git a/src/components/Pipelines/styles.less b/src/components/Pipelines/styles.less index 7ce04d0b1..9f51a62fc 100644 --- a/src/components/Pipelines/styles.less +++ b/src/components/Pipelines/styles.less @@ -36,4 +36,14 @@ margin-right: 0.75rem; margin-bottom: 0.75rem; display: inline-block; -} \ No newline at end of file +} + +.pipelineGraph { + padding: 20px 0; + width: 100%; + text-align: center; + + svg { + max-width: 100%; + } +} diff --git a/src/containers/PipelineEditContainer/PipelineEditContainer.js b/src/containers/PipelineEditContainer/PipelineEditContainer.js index b2a043b51..437ce676d 100644 --- a/src/containers/PipelineEditContainer/PipelineEditContainer.js +++ b/src/containers/PipelineEditContainer/PipelineEditContainer.js @@ -3,9 +3,10 @@ import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import ImmutablePropTypes from 'react-immutable-proptypes'; import { FormattedMessage } from 'react-intl'; -import { Container, Row, Col } from 'react-bootstrap'; +import { Container, Row, Col, OverlayTrigger, Tooltip } from 'react-bootstrap'; import Box from '../../components/widgets/Box'; +import PipelineGraph from '../../components/Pipelines/PipelineGraph'; import BoxesTable from '../../components/Pipelines/BoxesTable'; import VariablesTable from '../../components/Pipelines/VariablesTable'; import VariableForm, { newVariableInitialData } from '../../components/Pipelines/VariableForm'; @@ -100,6 +101,8 @@ class PipelineEditContainer extends Component { history: [], future: [], ...STATE_DEFAULTS, + showTable: true, + showGraph: false, }; static getDerivedStateFromProps(nextProps, prevState) { @@ -496,6 +499,10 @@ class PipelineEditContainer extends Component { ); }; + showAsTable = () => this.setState({ showTable: true, showGraph: false }); + showAsGraph = () => this.setState({ showTable: false, showGraph: true }); + showTableAndGraph = () => this.setState({ showTable: true, showGraph: true }); + render() { const { boxTypes } = this.props; const utilization = getVariablesUtilization(this.state.boxes); @@ -504,6 +511,64 @@ class PipelineEditContainer extends Component { title={} unlimitedHeight type={this.state.errors && this.state.errors.length > 0 ? 'danger' : 'light'} + customIcons={ + <> + + + + }> + + + + + + }> + + + + + + }> + + + + } footer={
    @@ -542,44 +607,65 @@ class PipelineEditContainer extends Component { }> <> - - -

    - -

    - {this.state.boxes && ( - + +

    + +

    + {this.state.boxes && ( + + )} + + + +

    + +

    + {this.state.variables && ( + + )} + +
    + )} + + {this.state.showGraph && ( + + + - )} - - - -

    - -

    - {this.state.variables && ( - - )} - -
    + + + )} {this.state.errors && this.state.errors.length > 0 && ( diff --git a/src/helpers/pipelines.js b/src/helpers/pipelines.js index cfaa70926..3eee8d642 100644 --- a/src/helpers/pipelines.js +++ b/src/helpers/pipelines.js @@ -74,19 +74,20 @@ export const coerceVariableValue = variable => { * Get info about variables utilization from boxes specification (where the variables are used) * @param {Object[]} boxes part of the pipeline specification * @return {Object} keys are variable names, values are objects holding { portsIn, portsOut } values, - * both are arrays of boxes where the variable is present + * both are arrays of objects { box, port } where the variable is present */ export const getVariablesUtilization = defaultMemoize(boxes => { const utils = {}; boxes.forEach(box => ['portsIn', 'portsOut'].forEach(ports => - Object.values(box[ports]) - .filter(({ value }) => value) - .forEach(({ value }) => { + Object.keys(box[ports]) + .filter(port => box[ports][port]) + .forEach(port => { + const { value } = box[ports][port]; if (!utils[value]) { utils[value] = { portsIn: [], portsOut: [] }; } - utils[value][ports].push(box); + utils[value][ports].push({ box, port }); }) ) ); diff --git a/src/locales/cs.json b/src/locales/cs.json index 6825b6171..adbc55842 100644 --- a/src/locales/cs.json +++ b/src/locales/cs.json @@ -1116,6 +1116,9 @@ "app.pipelineEditContainer.addVariableButton": "Přidat proměnnou", "app.pipelineEditContainer.boxesTitle": "Krabičky", "app.pipelineEditContainer.errorsCalloutTitle": "V pipeline byly nalezeny následující chyby", + "app.pipelineEditContainer.showAsBothIcon": "Zobrazit zároveň tabulku i diagram", + "app.pipelineEditContainer.showAsGraphIcon": "Zobrazit jako diagram", + "app.pipelineEditContainer.showAsTableIcon": "Zobrazit jako tabulku", "app.pipelineEditContainer.title": "Struktura pipeline", "app.pipelineEditContainer.variablesTitle": "Proměnné", "app.pipelineEditor.AddBoxForm.title": "Přidat krabičku", diff --git a/src/locales/en.json b/src/locales/en.json index afb9aca24..dc1fc7dc3 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -1116,6 +1116,9 @@ "app.pipelineEditContainer.addVariableButton": "Add Variable", "app.pipelineEditContainer.boxesTitle": "Boxes", "app.pipelineEditContainer.errorsCalloutTitle": "The following errors were found in the pipeline", + "app.pipelineEditContainer.showAsBothIcon": "Show both data table and diagram", + "app.pipelineEditContainer.showAsGraphIcon": "Show as visual diagram", + "app.pipelineEditContainer.showAsTableIcon": "Show as table", "app.pipelineEditContainer.title": "Edit Pipeline Structure", "app.pipelineEditContainer.variablesTitle": "Variables", "app.pipelineEditor.AddBoxForm.title": "Add a box", diff --git a/yarn.lock b/yarn.lock index 16ac8193c..75c2951e5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3,9 +3,9 @@ "@babel/cli@^7.14.5": - version "7.15.7" - resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.15.7.tgz#62658abedb786d09c1f70229224b11a65440d7a1" - integrity sha512-YW5wOprO2LzMjoWZ5ZG6jfbY9JnkDxuHDwvnrThnuYtByorova/I0HNXJedrUfwuXFQfYOjcqDA4PU3qlZGZjg== + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.16.0.tgz#a729b7a48eb80b49f48a339529fc4129fd7bcef3" + integrity sha512-WLrM42vKX/4atIoQB+eb0ovUof53UUvecb4qGjU2PDDWRiZr50ZpiV8NpcLo7iSxeGYrRG0Mqembsa+UrTAV6Q== dependencies: commander "^4.0.1" convert-source-map "^1.1.0" @@ -25,32 +25,32 @@ dependencies: "@babel/highlight" "^7.10.4" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.14.5", "@babel/code-frame@^7.15.8": - version "7.15.8" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.15.8.tgz#45990c47adadb00c03677baa89221f7cc23d2503" - integrity sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.0.tgz#0dfc80309beec8411e65e706461c408b0bb9b431" + integrity sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA== dependencies: - "@babel/highlight" "^7.14.5" + "@babel/highlight" "^7.16.0" -"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.15.0": - version "7.15.0" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.15.0.tgz#2dbaf8b85334796cafbb0f5793a90a2fc010b176" - integrity sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA== +"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.16.0", "@babel/compat-data@^7.16.4": + version "7.16.4" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.16.4.tgz#081d6bbc336ec5c2435c6346b2ae1fb98b5ac68e" + integrity sha512-1o/jo7D+kC9ZjHX5v+EHrdjl3PhxMrLSOTGsOdHJ+KL8HCaEK6ehrVL2RS6oHDZp+L7xLirLrPmQtEng769J/Q== "@babel/core@^7.0.0", "@babel/core@^7.10.4", "@babel/core@^7.14.6": - version "7.15.8" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.15.8.tgz#195b9f2bffe995d2c6c159e72fe525b4114e8c10" - integrity sha512-3UG9dsxvYBMYwRv+gS41WKHno4K60/9GPy1CJaH6xy3Elq8CTtvtjT5R5jmNhXfCYLX2mTw+7/aq5ak/gOE0og== - dependencies: - "@babel/code-frame" "^7.15.8" - "@babel/generator" "^7.15.8" - "@babel/helper-compilation-targets" "^7.15.4" - "@babel/helper-module-transforms" "^7.15.8" - "@babel/helpers" "^7.15.4" - "@babel/parser" "^7.15.8" - "@babel/template" "^7.15.4" - "@babel/traverse" "^7.15.4" - "@babel/types" "^7.15.6" + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.16.0.tgz#c4ff44046f5fe310525cc9eb4ef5147f0c5374d4" + integrity sha512-mYZEvshBRHGsIAiyH5PzCFTCfbWfoYbO/jcSdXQSUQu1/pW0xDZAUP7KEc32heqWTAfAHhV9j1vH8Sav7l+JNQ== + dependencies: + "@babel/code-frame" "^7.16.0" + "@babel/generator" "^7.16.0" + "@babel/helper-compilation-targets" "^7.16.0" + "@babel/helper-module-transforms" "^7.16.0" + "@babel/helpers" "^7.16.0" + "@babel/parser" "^7.16.0" + "@babel/template" "^7.16.0" + "@babel/traverse" "^7.16.0" + "@babel/types" "^7.16.0" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.2" @@ -58,72 +58,72 @@ semver "^6.3.0" source-map "^0.5.0" -"@babel/generator@^7.15.4", "@babel/generator@^7.15.8": - version "7.15.8" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.15.8.tgz#fa56be6b596952ceb231048cf84ee499a19c0cd1" - integrity sha512-ECmAKstXbp1cvpTTZciZCgfOt6iN64lR0d+euv3UZisU5awfRawOvg07Utn/qBGuH4bRIEZKrA/4LzZyXhZr8g== +"@babel/generator@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.16.0.tgz#d40f3d1d5075e62d3500bccb67f3daa8a95265b2" + integrity sha512-RR8hUCfRQn9j9RPKEVXo9LiwoxLPYn6hNZlvUOR8tSnaxlD0p0+la00ZP9/SnRt6HchKr+X0fO2r8vrETiJGew== dependencies: - "@babel/types" "^7.15.6" + "@babel/types" "^7.16.0" jsesc "^2.5.1" source-map "^0.5.0" -"@babel/helper-annotate-as-pure@^7.14.5", "@babel/helper-annotate-as-pure@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.15.4.tgz#3d0e43b00c5e49fdb6c57e421601a7a658d5f835" - integrity sha512-QwrtdNvUNsPCj2lfNQacsGSQvGX8ee1ttrBrcozUP2Sv/jylewBP/8QFe6ZkBsC8T/GYWonNAWJV4aRR9AL2DA== +"@babel/helper-annotate-as-pure@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.0.tgz#9a1f0ebcda53d9a2d00108c4ceace6a5d5f1f08d" + integrity sha512-ItmYF9vR4zA8cByDocY05o0LGUkp1zhbTQOH1NFyl5xXEqlTJQCEJjieriw+aFpxo16swMxUnUiKS7a/r4vtHg== dependencies: - "@babel/types" "^7.15.4" + "@babel/types" "^7.16.0" -"@babel/helper-builder-binary-assignment-operator-visitor@^7.14.5": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.15.4.tgz#21ad815f609b84ee0e3058676c33cf6d1670525f" - integrity sha512-P8o7JP2Mzi0SdC6eWr1zF+AEYvrsZa7GSY1lTayjF5XJhVH0kjLYUZPvTMflP7tBgZoe9gIhTa60QwFpqh/E0Q== +"@babel/helper-builder-binary-assignment-operator-visitor@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.0.tgz#f1a686b92da794020c26582eb852e9accd0d7882" + integrity sha512-9KuleLT0e77wFUku6TUkqZzCEymBdtuQQ27MhEKzf9UOOJu3cYj98kyaDAzxpC7lV6DGiZFuC8XqDsq8/Kl6aQ== dependencies: - "@babel/helper-explode-assignable-expression" "^7.15.4" - "@babel/types" "^7.15.4" + "@babel/helper-explode-assignable-expression" "^7.16.0" + "@babel/types" "^7.16.0" -"@babel/helper-builder-react-jsx@^7.14.5": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.15.4.tgz#44e3ed960f2cd00c4d6aab863fc3f3edafad0a0b" - integrity sha512-bT7jt6ozDCBuUUtmqxZJ6nImqJ2zdXjGehvyBSeeGO+eE4vBwsxTFM7aDp6UgUkxaQNaaYXcEJcDIdZOy2u8nA== +"@babel/helper-builder-react-jsx@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.16.0.tgz#cbff6790e8dfc29b9f986f712a1d69f1428a35b5" + integrity sha512-m04yTRoynupLijXcfkxjx5VfQeNRR67lncuW6osD6P/3o2sChz8zcwJGzso55oeTkEJlMu2atFJAdmB56i8F5Q== dependencies: - "@babel/helper-annotate-as-pure" "^7.15.4" - "@babel/types" "^7.15.4" + "@babel/helper-annotate-as-pure" "^7.16.0" + "@babel/types" "^7.16.0" -"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.4.tgz#cf6d94f30fbefc139123e27dd6b02f65aeedb7b9" - integrity sha512-rMWPCirulnPSe4d+gwdWXLfAXTTBj8M3guAf5xFQJ0nvFY7tfNAFnWdqaHegHlgDZOCT4qvhF3BYlSJag8yhqQ== +"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.16.0", "@babel/helper-compilation-targets@^7.16.3": + version "7.16.3" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.3.tgz#5b480cd13f68363df6ec4dc8ac8e2da11363cbf0" + integrity sha512-vKsoSQAyBmxS35JUOOt+07cLc6Nk/2ljLIHwmq2/NM6hdioUaqEXq/S+nXvbvXbZkNDlWOymPanJGOc4CBjSJA== dependencies: - "@babel/compat-data" "^7.15.0" + "@babel/compat-data" "^7.16.0" "@babel/helper-validator-option" "^7.14.5" - browserslist "^4.16.6" + browserslist "^4.17.5" semver "^6.3.0" -"@babel/helper-create-class-features-plugin@^7.14.5", "@babel/helper-create-class-features-plugin@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.15.4.tgz#7f977c17bd12a5fba363cb19bea090394bf37d2e" - integrity sha512-7ZmzFi+DwJx6A7mHRwbuucEYpyBwmh2Ca0RvI6z2+WLZYCqV0JOaLb+u0zbtmDicebgKBZgqbYfLaKNqSgv5Pw== +"@babel/helper-create-class-features-plugin@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.16.0.tgz#090d4d166b342a03a9fec37ef4fd5aeb9c7c6a4b" + integrity sha512-XLwWvqEaq19zFlF5PTgOod4bUA+XbkR4WLQBct1bkzmxJGB0ZEJaoKF4c8cgH9oBtCDuYJ8BP5NB9uFiEgO5QA== dependencies: - "@babel/helper-annotate-as-pure" "^7.15.4" - "@babel/helper-function-name" "^7.15.4" - "@babel/helper-member-expression-to-functions" "^7.15.4" - "@babel/helper-optimise-call-expression" "^7.15.4" - "@babel/helper-replace-supers" "^7.15.4" - "@babel/helper-split-export-declaration" "^7.15.4" + "@babel/helper-annotate-as-pure" "^7.16.0" + "@babel/helper-function-name" "^7.16.0" + "@babel/helper-member-expression-to-functions" "^7.16.0" + "@babel/helper-optimise-call-expression" "^7.16.0" + "@babel/helper-replace-supers" "^7.16.0" + "@babel/helper-split-export-declaration" "^7.16.0" -"@babel/helper-create-regexp-features-plugin@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.14.5.tgz#c7d5ac5e9cf621c26057722fb7a8a4c5889358c4" - integrity sha512-TLawwqpOErY2HhWbGJ2nZT5wSkR192QpN+nBg1THfBfftrlvOh+WbhrxXCH4q4xJ9Gl16BGPR/48JA+Ryiho/A== +"@babel/helper-create-regexp-features-plugin@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.16.0.tgz#06b2348ce37fccc4f5e18dcd8d75053f2a7c44ff" + integrity sha512-3DyG0zAFAZKcOp7aVr33ddwkxJ0Z0Jr5V99y3I690eYLpukJsJvAbzTy1ewoCqsML8SbIrjH14Jc/nSQ4TvNPA== dependencies: - "@babel/helper-annotate-as-pure" "^7.14.5" + "@babel/helper-annotate-as-pure" "^7.16.0" regexpu-core "^4.7.1" -"@babel/helper-define-polyfill-provider@^0.2.2": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.3.tgz#0525edec5094653a282688d34d846e4c75e9c0b6" - integrity sha512-RH3QDAfRMzj7+0Nqu5oqgO5q9mFtQEVvCRsi8qCEfzLR9p2BHfn5FzhSB2oj1fF7I2+DcTORkYaQ6aTR9Cofew== +"@babel/helper-define-polyfill-provider@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.0.tgz#c5b10cf4b324ff840140bb07e05b8564af2ae971" + integrity sha512-7hfT8lUljl/tM3h+izTX/pO3W3frz2ok6Pk+gzys8iJqDfZrZy2pXjRTZAvG2YmfHun1X4q8/UZRLatMfqc5Tg== dependencies: "@babel/helper-compilation-targets" "^7.13.0" "@babel/helper-module-imports" "^7.12.13" @@ -134,117 +134,117 @@ resolve "^1.14.2" semver "^6.1.2" -"@babel/helper-explode-assignable-expression@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.15.4.tgz#f9aec9d219f271eaf92b9f561598ca6b2682600c" - integrity sha512-J14f/vq8+hdC2KoWLIQSsGrC9EFBKE4NFts8pfMpymfApds+fPqR30AOUWc4tyr56h9l/GA1Sxv2q3dLZWbQ/g== +"@babel/helper-explode-assignable-expression@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.0.tgz#753017337a15f46f9c09f674cff10cee9b9d7778" + integrity sha512-Hk2SLxC9ZbcOhLpg/yMznzJ11W++lg5GMbxt1ev6TXUiJB0N42KPC+7w8a+eWGuqDnUYuwStJoZHM7RgmIOaGQ== dependencies: - "@babel/types" "^7.15.4" + "@babel/types" "^7.16.0" -"@babel/helper-function-name@^7.14.5", "@babel/helper-function-name@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.15.4.tgz#845744dafc4381a4a5fb6afa6c3d36f98a787ebc" - integrity sha512-Z91cOMM4DseLIGOnog+Z8OI6YseR9bua+HpvLAQ2XayUGU+neTtX+97caALaLdyu53I/fjhbeCnWnRH1O3jFOw== +"@babel/helper-function-name@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.16.0.tgz#b7dd0797d00bbfee4f07e9c4ea5b0e30c8bb1481" + integrity sha512-BZh4mEk1xi2h4HFjWUXRQX5AEx4rvaZxHgax9gcjdLWdkjsY7MKt5p0otjsg5noXw+pB+clMCjw+aEVYADMjog== dependencies: - "@babel/helper-get-function-arity" "^7.15.4" - "@babel/template" "^7.15.4" - "@babel/types" "^7.15.4" + "@babel/helper-get-function-arity" "^7.16.0" + "@babel/template" "^7.16.0" + "@babel/types" "^7.16.0" -"@babel/helper-get-function-arity@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.15.4.tgz#098818934a137fce78b536a3e015864be1e2879b" - integrity sha512-1/AlxSF92CmGZzHnC515hm4SirTxtpDnLEJ0UyEMgTMZN+6bxXKg04dKhiRx5Enel+SUA1G1t5Ed/yQia0efrA== +"@babel/helper-get-function-arity@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.0.tgz#0088c7486b29a9cb5d948b1a1de46db66e089cfa" + integrity sha512-ASCquNcywC1NkYh/z7Cgp3w31YW8aojjYIlNg4VeJiHkqyP4AzIvr4qx7pYDb4/s8YcsZWqqOSxgkvjUz1kpDQ== dependencies: - "@babel/types" "^7.15.4" + "@babel/types" "^7.16.0" -"@babel/helper-hoist-variables@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.15.4.tgz#09993a3259c0e918f99d104261dfdfc033f178df" - integrity sha512-VTy085egb3jUGVK9ycIxQiPbquesq0HUQ+tPO0uv5mPEBZipk+5FkRKiWq5apuyTE9FUrjENB0rCf8y+n+UuhA== +"@babel/helper-hoist-variables@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.0.tgz#4c9023c2f1def7e28ff46fc1dbcd36a39beaa81a" + integrity sha512-1AZlpazjUR0EQZQv3sgRNfM9mEVWPK3M6vlalczA+EECcPz3XPh6VplbErL5UoMpChhSck5wAJHthlj1bYpcmg== dependencies: - "@babel/types" "^7.15.4" + "@babel/types" "^7.16.0" -"@babel/helper-member-expression-to-functions@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.4.tgz#bfd34dc9bba9824a4658b0317ec2fd571a51e6ef" - integrity sha512-cokOMkxC/BTyNP1AlY25HuBWM32iCEsLPI4BHDpJCHHm1FU2E7dKWWIXJgQgSFiu4lp8q3bL1BIKwqkSUviqtA== +"@babel/helper-member-expression-to-functions@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.0.tgz#29287040efd197c77636ef75188e81da8bccd5a4" + integrity sha512-bsjlBFPuWT6IWhl28EdrQ+gTvSvj5tqVP5Xeftp07SEuz5pLnsXZuDkDD3Rfcxy0IsHmbZ+7B2/9SHzxO0T+sQ== dependencies: - "@babel/types" "^7.15.4" + "@babel/types" "^7.16.0" -"@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.14.5", "@babel/helper-module-imports@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.15.4.tgz#e18007d230632dea19b47853b984476e7b4e103f" - integrity sha512-jeAHZbzUwdW/xHgHQ3QmWR4Jg6j15q4w/gCfwZvtqOxoo5DKtLHk8Bsf4c5RZRC7NmLEs+ohkdq8jFefuvIxAA== +"@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz#90538e60b672ecf1b448f5f4f5433d37e79a3ec3" + integrity sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg== dependencies: - "@babel/types" "^7.15.4" + "@babel/types" "^7.16.0" -"@babel/helper-module-transforms@^7.14.5", "@babel/helper-module-transforms@^7.15.4", "@babel/helper-module-transforms@^7.15.8": - version "7.15.8" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.15.8.tgz#d8c0e75a87a52e374a8f25f855174786a09498b2" - integrity sha512-DfAfA6PfpG8t4S6npwzLvTUpp0sS7JrcuaMiy1Y5645laRJIp/LiLGIBbQKaXSInK8tiGNI7FL7L8UvB8gdUZg== +"@babel/helper-module-transforms@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.16.0.tgz#1c82a8dd4cb34577502ebd2909699b194c3e9bb5" + integrity sha512-My4cr9ATcaBbmaEa8M0dZNA74cfI6gitvUAskgDtAFmAqyFKDSHQo5YstxPbN+lzHl2D9l/YOEFqb2mtUh4gfA== dependencies: - "@babel/helper-module-imports" "^7.15.4" - "@babel/helper-replace-supers" "^7.15.4" - "@babel/helper-simple-access" "^7.15.4" - "@babel/helper-split-export-declaration" "^7.15.4" + "@babel/helper-module-imports" "^7.16.0" + "@babel/helper-replace-supers" "^7.16.0" + "@babel/helper-simple-access" "^7.16.0" + "@babel/helper-split-export-declaration" "^7.16.0" "@babel/helper-validator-identifier" "^7.15.7" - "@babel/template" "^7.15.4" - "@babel/traverse" "^7.15.4" - "@babel/types" "^7.15.6" + "@babel/template" "^7.16.0" + "@babel/traverse" "^7.16.0" + "@babel/types" "^7.16.0" -"@babel/helper-optimise-call-expression@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.15.4.tgz#f310a5121a3b9cc52d9ab19122bd729822dee171" - integrity sha512-E/z9rfbAOt1vDW1DR7k4SzhzotVV5+qMciWV6LaG1g4jeFrkDlJedjtV4h0i4Q/ITnUu+Pk08M7fczsB9GXBDw== +"@babel/helper-optimise-call-expression@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.0.tgz#cecdb145d70c54096b1564f8e9f10cd7d193b338" + integrity sha512-SuI467Gi2V8fkofm2JPnZzB/SUuXoJA5zXe/xzyPP2M04686RzFKFHPK6HDVN6JvWBIEW8tt9hPR7fXdn2Lgpw== dependencies: - "@babel/types" "^7.15.4" + "@babel/types" "^7.16.0" "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz#5ac822ce97eec46741ab70a517971e443a70c5a9" integrity sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ== -"@babel/helper-remap-async-to-generator@^7.14.5", "@babel/helper-remap-async-to-generator@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.15.4.tgz#2637c0731e4c90fbf58ac58b50b2b5a192fc970f" - integrity sha512-v53MxgvMK/HCwckJ1bZrq6dNKlmwlyRNYM6ypaRTdXWGOE2c1/SCa6dL/HimhPulGhZKw9W0QhREM583F/t0vQ== +"@babel/helper-remap-async-to-generator@^7.16.0", "@babel/helper-remap-async-to-generator@^7.16.4": + version "7.16.4" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.4.tgz#5d7902f61349ff6b963e07f06a389ce139fbfe6e" + integrity sha512-vGERmmhR+s7eH5Y/cp8PCVzj4XEjerq8jooMfxFdA5xVtAk9Sh4AQsrWgiErUEBjtGrBtOFKDUcWQFW4/dFwMA== dependencies: - "@babel/helper-annotate-as-pure" "^7.15.4" - "@babel/helper-wrap-function" "^7.15.4" - "@babel/types" "^7.15.4" + "@babel/helper-annotate-as-pure" "^7.16.0" + "@babel/helper-wrap-function" "^7.16.0" + "@babel/types" "^7.16.0" -"@babel/helper-replace-supers@^7.14.5", "@babel/helper-replace-supers@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.15.4.tgz#52a8ab26ba918c7f6dee28628b07071ac7b7347a" - integrity sha512-/ztT6khaXF37MS47fufrKvIsiQkx1LBRvSJNzRqmbyeZnTwU9qBxXYLaaT/6KaxfKhjs2Wy8kG8ZdsFUuWBjzw== +"@babel/helper-replace-supers@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.16.0.tgz#73055e8d3cf9bcba8ddb55cad93fedc860f68f17" + integrity sha512-TQxuQfSCdoha7cpRNJvfaYxxxzmbxXw/+6cS7V02eeDYyhxderSoMVALvwupA54/pZcOTtVeJ0xccp1nGWladA== dependencies: - "@babel/helper-member-expression-to-functions" "^7.15.4" - "@babel/helper-optimise-call-expression" "^7.15.4" - "@babel/traverse" "^7.15.4" - "@babel/types" "^7.15.4" + "@babel/helper-member-expression-to-functions" "^7.16.0" + "@babel/helper-optimise-call-expression" "^7.16.0" + "@babel/traverse" "^7.16.0" + "@babel/types" "^7.16.0" -"@babel/helper-simple-access@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.15.4.tgz#ac368905abf1de8e9781434b635d8f8674bcc13b" - integrity sha512-UzazrDoIVOZZcTeHHEPYrr1MvTR/K+wgLg6MY6e1CJyaRhbibftF6fR2KU2sFRtI/nERUZR9fBd6aKgBlIBaPg== +"@babel/helper-simple-access@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.16.0.tgz#21d6a27620e383e37534cf6c10bba019a6f90517" + integrity sha512-o1rjBT/gppAqKsYfUdfHq5Rk03lMQrkPHG1OWzHWpLgVXRH4HnMM9Et9CVdIqwkCQlobnGHEJMsgWP/jE1zUiw== dependencies: - "@babel/types" "^7.15.4" + "@babel/types" "^7.16.0" -"@babel/helper-skip-transparent-expression-wrappers@^7.14.5", "@babel/helper-skip-transparent-expression-wrappers@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.15.4.tgz#707dbdba1f4ad0fa34f9114fc8197aec7d5da2eb" - integrity sha512-BMRLsdh+D1/aap19TycS4eD1qELGrCBJwzaY9IE8LrpJtJb+H7rQkPIdsfgnMtLBA6DJls7X9z93Z4U8h7xw0A== +"@babel/helper-skip-transparent-expression-wrappers@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz#0ee3388070147c3ae051e487eca3ebb0e2e8bb09" + integrity sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw== dependencies: - "@babel/types" "^7.15.4" + "@babel/types" "^7.16.0" -"@babel/helper-split-export-declaration@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.15.4.tgz#aecab92dcdbef6a10aa3b62ab204b085f776e257" - integrity sha512-HsFqhLDZ08DxCpBdEVtKmywj6PQbwnF6HHybur0MAnkAKnlS6uHkwnmRIkElB2Owpfb4xL4NwDmDLFubueDXsw== +"@babel/helper-split-export-declaration@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.0.tgz#29672f43663e936df370aaeb22beddb3baec7438" + integrity sha512-0YMMRpuDFNGTHNRiiqJX19GjNXA4H0E8jZ2ibccfSxaCogbm3am5WN/2nQNj0YnQwGWM1J06GOcQ2qnh3+0paw== dependencies: - "@babel/types" "^7.15.4" + "@babel/types" "^7.16.0" -"@babel/helper-validator-identifier@^7.14.5", "@babel/helper-validator-identifier@^7.14.9", "@babel/helper-validator-identifier@^7.15.7": +"@babel/helper-validator-identifier@^7.15.7": version "7.15.7" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389" integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w== @@ -254,186 +254,193 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz#6e72a1fff18d5dfcb878e1e62f1a021c4b72d5a3" integrity sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow== -"@babel/helper-wrap-function@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.15.4.tgz#6f754b2446cfaf3d612523e6ab8d79c27c3a3de7" - integrity sha512-Y2o+H/hRV5W8QhIfTpRIBwl57y8PrZt6JM3V8FOo5qarjshHItyH5lXlpMfBfmBefOqSCpKZs/6Dxqp0E/U+uw== +"@babel/helper-wrap-function@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.16.0.tgz#b3cf318afce774dfe75b86767cd6d68f3482e57c" + integrity sha512-VVMGzYY3vkWgCJML+qVLvGIam902mJW0FvT7Avj1zEe0Gn7D93aWdLblYARTxEw+6DhZmtzhBM2zv0ekE5zg1g== dependencies: - "@babel/helper-function-name" "^7.15.4" - "@babel/template" "^7.15.4" - "@babel/traverse" "^7.15.4" - "@babel/types" "^7.15.4" + "@babel/helper-function-name" "^7.16.0" + "@babel/template" "^7.16.0" + "@babel/traverse" "^7.16.0" + "@babel/types" "^7.16.0" -"@babel/helpers@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.15.4.tgz#5f40f02050a3027121a3cf48d497c05c555eaf43" - integrity sha512-V45u6dqEJ3w2rlryYYXf6i9rQ5YMNu4FLS6ngs8ikblhu2VdR1AqAd6aJjBzmf2Qzh6KOLqKHxEN9+TFbAkAVQ== +"@babel/helpers@^7.16.0": + version "7.16.3" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.16.3.tgz#27fc64f40b996e7074dc73128c3e5c3e7f55c43c" + integrity sha512-Xn8IhDlBPhvYTvgewPKawhADichOsbkZuzN7qz2BusOM0brChsyXMDJvldWaYMMUNiCQdQzNEioXTp3sC8Nt8w== dependencies: - "@babel/template" "^7.15.4" - "@babel/traverse" "^7.15.4" - "@babel/types" "^7.15.4" + "@babel/template" "^7.16.0" + "@babel/traverse" "^7.16.3" + "@babel/types" "^7.16.0" -"@babel/highlight@^7.10.4", "@babel/highlight@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9" - integrity sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg== +"@babel/highlight@^7.10.4", "@babel/highlight@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.0.tgz#6ceb32b2ca4b8f5f361fb7fd821e3fddf4a1725a" + integrity sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g== dependencies: - "@babel/helper-validator-identifier" "^7.14.5" + "@babel/helper-validator-identifier" "^7.15.7" chalk "^2.0.0" js-tokens "^4.0.0" "@babel/node@^7.14.7": - version "7.15.8" - resolved "https://registry.yarnpkg.com/@babel/node/-/node-7.15.8.tgz#5d6b815d0232ae4893727971f53deabfe06c4ca7" - integrity sha512-JbgTCrnx6IUECznEbQ7e2rbVYtrXKixSbEG2bxxbMkV648WdUf3tdc+ZUW2++dvnnAswcpwc76cRwf0xEQqsrw== + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/node/-/node-7.16.0.tgz#855e783ba4cbca88dbdebf4b01c2d95844c4afdf" + integrity sha512-eFUU2RHkgMW0X1lHVVOWJYlaDTwCX2LduQQLfehAfID5VhAjNnBhGZ/r0zk3FSQfFn6enJ2aXyRCiZ829bYVeA== dependencies: - "@babel/register" "^7.15.3" + "@babel/register" "^7.16.0" commander "^4.0.1" - core-js "^3.16.0" + core-js "^3.19.0" node-environment-flags "^1.0.5" regenerator-runtime "^0.13.4" v8flags "^3.1.1" -"@babel/parser@^7.1.0", "@babel/parser@^7.15.0", "@babel/parser@^7.15.4", "@babel/parser@^7.15.8", "@babel/parser@^7.7.0": - version "7.15.8" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.8.tgz#7bacdcbe71bdc3ff936d510c15dcea7cf0b99016" - integrity sha512-BRYa3wcQnjS/nqI8Ac94pYYpJfojHVvVXJ97+IDCImX4Jc8W8Xv1+47enbruk+q1etOpsQNwnfFcNGw+gtPGxA== +"@babel/parser@^7.1.0", "@babel/parser@^7.15.0", "@babel/parser@^7.16.0", "@babel/parser@^7.16.3", "@babel/parser@^7.7.0": + version "7.16.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.4.tgz#d5f92f57cf2c74ffe9b37981c0e72fee7311372e" + integrity sha512-6V0qdPUaiVHH3RtZeLIsc+6pDhbYzHR8ogA8w+f+Wc77DuXto19g2QUwveINoS34Uw+W8/hQDGJCx+i4n7xcng== + +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.16.2": + version "7.16.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.2.tgz#2977fca9b212db153c195674e57cfab807733183" + integrity sha512-h37CvpLSf8gb2lIJ2CgC3t+EjFbi0t8qS7LCS1xcJIlEXE4czlofwaW7W1HA8zpgOCzI9C1nmoqNR1zWkk0pQg== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.15.4.tgz#dbdeabb1e80f622d9f0b583efb2999605e0a567e" - integrity sha512-eBnpsl9tlhPhpI10kU06JHnrYXwg3+V6CaP2idsCXNef0aeslpqyITXQ74Vfk5uHgY7IG7XP0yIH8b42KSzHog== +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.0.tgz#358972eaab006f5eb0826183b0c93cbcaf13e1e2" + integrity sha512-4tcFwwicpWTrpl9qjf7UsoosaArgImF85AxqCRZlgc3IQDvkUHjJpruXAL58Wmj+T6fypWTC/BakfEkwIL/pwA== dependencies: "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.15.4" - "@babel/plugin-proposal-optional-chaining" "^7.14.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" + "@babel/plugin-proposal-optional-chaining" "^7.16.0" -"@babel/plugin-proposal-async-generator-functions@^7.15.8": - version "7.15.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.15.8.tgz#a3100f785fab4357987c4223ab1b02b599048403" - integrity sha512-2Z5F2R2ibINTc63mY7FLqGfEbmofrHU9FitJW1Q7aPaKFhiPvSq6QEt/BoWN5oME3GVyjcRuNNSRbb9LC0CSWA== +"@babel/plugin-proposal-async-generator-functions@^7.16.4": + version "7.16.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.4.tgz#e606eb6015fec6fa5978c940f315eae4e300b081" + integrity sha512-/CUekqaAaZCQHleSK/9HajvcD/zdnJiKRiuUFq8ITE+0HsPzquf53cpFiqAwl/UfmJbR6n5uGPQSPdrmKOvHHg== dependencies: "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-remap-async-to-generator" "^7.15.4" + "@babel/helper-remap-async-to-generator" "^7.16.4" "@babel/plugin-syntax-async-generators" "^7.8.4" -"@babel/plugin-proposal-class-properties@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.14.5.tgz#40d1ee140c5b1e31a350f4f5eed945096559b42e" - integrity sha512-q/PLpv5Ko4dVc1LYMpCY7RVAAO4uk55qPwrIuJ5QJ8c6cVuAmhu7I/49JOppXL6gXf7ZHzpRVEUZdYoPLM04Gg== +"@babel/plugin-proposal-class-properties@^7.14.5", "@babel/plugin-proposal-class-properties@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.0.tgz#c029618267ddebc7280fa286e0f8ca2a278a2d1a" + integrity sha512-mCF3HcuZSY9Fcx56Lbn+CGdT44ioBMMvjNVldpKtj8tpniETdLjnxdHI1+sDWXIM1nNt+EanJOZ3IG9lzVjs7A== dependencies: - "@babel/helper-create-class-features-plugin" "^7.14.5" + "@babel/helper-create-class-features-plugin" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-proposal-class-static-block@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.15.4.tgz#3e7ca6128453c089e8b477a99f970c63fc1cb8d7" - integrity sha512-M682XWrrLNk3chXCjoPUQWOyYsB93B9z3mRyjtqqYJWDf2mfCdIYgDrA11cgNVhAQieaq6F2fn2f3wI0U4aTjA== +"@babel/plugin-proposal-class-static-block@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.0.tgz#5296942c564d8144c83eea347d0aa8a0b89170e7" + integrity sha512-mAy3sdcY9sKAkf3lQbDiv3olOfiLqI51c9DR9b19uMoR2Z6r5pmGl7dfNFqEvqOyqbf1ta4lknK4gc5PJn3mfA== dependencies: - "@babel/helper-create-class-features-plugin" "^7.15.4" + "@babel/helper-create-class-features-plugin" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-class-static-block" "^7.14.5" -"@babel/plugin-proposal-dynamic-import@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.14.5.tgz#0c6617df461c0c1f8fff3b47cd59772360101d2c" - integrity sha512-ExjiNYc3HDN5PXJx+bwC50GIx/KKanX2HiggnIUAYedbARdImiCU4RhhHfdf0Kd7JNXGpsBBBCOm+bBVy3Gb0g== +"@babel/plugin-proposal-dynamic-import@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.0.tgz#783eca61d50526202f9b296095453977e88659f1" + integrity sha512-QGSA6ExWk95jFQgwz5GQ2Dr95cf7eI7TKutIXXTb7B1gCLTCz5hTjFTQGfLFBBiC5WSNi7udNwWsqbbMh1c4yQ== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-dynamic-import" "^7.8.3" -"@babel/plugin-proposal-export-namespace-from@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.14.5.tgz#dbad244310ce6ccd083072167d8cea83a52faf76" - integrity sha512-g5POA32bXPMmSBu5Dx/iZGLGnKmKPc5AiY7qfZgurzrCYgIztDlHFbznSNCoQuv57YQLnQfaDi7dxCtLDIdXdA== +"@babel/plugin-proposal-export-namespace-from@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.0.tgz#9c01dee40b9d6b847b656aaf4a3976a71740f222" + integrity sha512-CjI4nxM/D+5wCnhD11MHB1AwRSAYeDT+h8gCdcVJZ/OK7+wRzFsf7PFPWVpVpNRkHMmMkQWAHpTq+15IXQ1diA== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" -"@babel/plugin-proposal-json-strings@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.14.5.tgz#38de60db362e83a3d8c944ac858ddf9f0c2239eb" - integrity sha512-NSq2fczJYKVRIsUJyNxrVUMhB27zb7N7pOFGQOhBKJrChbGcgEAqyZrmZswkPk18VMurEeJAaICbfm57vUeTbQ== +"@babel/plugin-proposal-json-strings@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.0.tgz#cae35a95ed1d2a7fa29c4dc41540b84a72e9ab25" + integrity sha512-kouIPuiv8mSi5JkEhzApg5Gn6hFyKPnlkO0a9YSzqRurH8wYzSlf6RJdzluAsbqecdW5pBvDJDfyDIUR/vLxvg== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-json-strings" "^7.8.3" -"@babel/plugin-proposal-logical-assignment-operators@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.14.5.tgz#6e6229c2a99b02ab2915f82571e0cc646a40c738" - integrity sha512-YGn2AvZAo9TwyhlLvCCWxD90Xq8xJ4aSgaX3G5D/8DW94L8aaT+dS5cSP+Z06+rCJERGSr9GxMBZ601xoc2taw== +"@babel/plugin-proposal-logical-assignment-operators@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.0.tgz#a711b8ceb3ffddd3ef88d3a49e86dbd3cc7db3fd" + integrity sha512-pbW0fE30sVTYXXm9lpVQQ/Vc+iTeQKiXlaNRZPPN2A2VdlWyAtsUrsQ3xydSlDW00TFMK7a8m3cDTkBF5WnV3Q== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.14.5.tgz#ee38589ce00e2cc59b299ec3ea406fcd3a0fdaf6" - integrity sha512-gun/SOnMqjSb98Nkaq2rTKMwervfdAoz6NphdY0vTfuzMfryj+tDGb2n6UkDKwez+Y8PZDhE3D143v6Gepp4Hg== +"@babel/plugin-proposal-nullish-coalescing-operator@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.0.tgz#44e1cce08fe2427482cf446a91bb451528ed0596" + integrity sha512-3bnHA8CAFm7cG93v8loghDYyQ8r97Qydf63BeYiGgYbjKKB/XP53W15wfRC7dvKfoiJ34f6Rbyyx2btExc8XsQ== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" -"@babel/plugin-proposal-numeric-separator@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.14.5.tgz#83631bf33d9a51df184c2102a069ac0c58c05f18" - integrity sha512-yiclALKe0vyZRZE0pS6RXgjUOt87GWv6FYa5zqj15PvhOGFO69R5DusPlgK/1K5dVnCtegTiWu9UaBSrLLJJBg== +"@babel/plugin-proposal-numeric-separator@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.0.tgz#5d418e4fbbf8b9b7d03125d3a52730433a373734" + integrity sha512-FAhE2I6mjispy+vwwd6xWPyEx3NYFS13pikDBWUAFGZvq6POGs5eNchw8+1CYoEgBl9n11I3NkzD7ghn25PQ9Q== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-numeric-separator" "^7.10.4" -"@babel/plugin-proposal-object-rest-spread@^7.15.6": - version "7.15.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.15.6.tgz#ef68050c8703d07b25af402cb96cf7f34a68ed11" - integrity sha512-qtOHo7A1Vt+O23qEAX+GdBpqaIuD3i9VRrWgCJeq7WO6H2d14EK3q11urj5Te2MAeK97nMiIdRpwd/ST4JFbNg== +"@babel/plugin-proposal-object-rest-spread@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.16.0.tgz#5fb32f6d924d6e6712810362a60e12a2609872e6" + integrity sha512-LU/+jp89efe5HuWJLmMmFG0+xbz+I2rSI7iLc1AlaeSMDMOGzWlc5yJrMN1d04osXN4sSfpo4O+azkBNBes0jg== dependencies: - "@babel/compat-data" "^7.15.0" - "@babel/helper-compilation-targets" "^7.15.4" + "@babel/compat-data" "^7.16.0" + "@babel/helper-compilation-targets" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.15.4" + "@babel/plugin-transform-parameters" "^7.16.0" -"@babel/plugin-proposal-optional-catch-binding@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.14.5.tgz#939dd6eddeff3a67fdf7b3f044b5347262598c3c" - integrity sha512-3Oyiixm0ur7bzO5ybNcZFlmVsygSIQgdOa7cTfOYCMY+wEPAYhZAJxi3mixKFCTCKUhQXuCTtQ1MzrpL3WT8ZQ== +"@babel/plugin-proposal-optional-catch-binding@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.0.tgz#5910085811ab4c28b00d6ebffa4ab0274d1e5f16" + integrity sha512-kicDo0A/5J0nrsCPbn89mTG3Bm4XgYi0CZtvex9Oyw7gGZE3HXGD0zpQNH+mo+tEfbo8wbmMvJftOwpmPy7aVw== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" -"@babel/plugin-proposal-optional-chaining@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.14.5.tgz#fa83651e60a360e3f13797eef00b8d519695b603" - integrity sha512-ycz+VOzo2UbWNI1rQXxIuMOzrDdHGrI23fRiz/Si2R4kv2XZQ1BK8ccdHwehMKBlcH/joGW/tzrUmo67gbJHlQ== +"@babel/plugin-proposal-optional-chaining@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.0.tgz#56dbc3970825683608e9efb55ea82c2a2d6c8dc0" + integrity sha512-Y4rFpkZODfHrVo70Uaj6cC1JJOt3Pp0MdWSwIKtb8z1/lsjl9AmnB7ErRFV+QNGIfcY1Eruc2UMx5KaRnXjMyg== dependencies: "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.14.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" "@babel/plugin-syntax-optional-chaining" "^7.8.3" -"@babel/plugin-proposal-private-methods@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.14.5.tgz#37446495996b2945f30f5be5b60d5e2aa4f5792d" - integrity sha512-838DkdUA1u+QTCplatfq4B7+1lnDa/+QMI89x5WZHBcnNv+47N8QEj2k9I2MUU9xIv8XJ4XvPCviM/Dj7Uwt9g== +"@babel/plugin-proposal-private-methods@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.0.tgz#b4dafb9c717e4301c5776b30d080d6383c89aff6" + integrity sha512-IvHmcTHDFztQGnn6aWq4t12QaBXTKr1whF/dgp9kz84X6GUcwq9utj7z2wFCUfeOup/QKnOlt2k0zxkGFx9ubg== dependencies: - "@babel/helper-create-class-features-plugin" "^7.14.5" + "@babel/helper-create-class-features-plugin" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-proposal-private-property-in-object@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.15.4.tgz#55c5e3b4d0261fd44fe637e3f624cfb0f484e3e5" - integrity sha512-X0UTixkLf0PCCffxgu5/1RQyGGbgZuKoI+vXP4iSbJSYwPb7hu06omsFGBvQ9lJEvwgrxHdS8B5nbfcd8GyUNA== +"@babel/plugin-proposal-private-property-in-object@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.0.tgz#69e935b2c5c79d2488112d886f0c4e2790fee76f" + integrity sha512-3jQUr/HBbMVZmi72LpjQwlZ55i1queL8KcDTQEkAHihttJnAPrcvG9ZNXIfsd2ugpizZo595egYV6xy+pv4Ofw== dependencies: - "@babel/helper-annotate-as-pure" "^7.15.4" - "@babel/helper-create-class-features-plugin" "^7.15.4" + "@babel/helper-annotate-as-pure" "^7.16.0" + "@babel/helper-create-class-features-plugin" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" -"@babel/plugin-proposal-unicode-property-regex@^7.14.5", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.14.5.tgz#0f95ee0e757a5d647f378daa0eca7e93faa8bbe8" - integrity sha512-6axIeOU5LnY471KenAB9vI8I5j7NQ2d652hIYwVyRfgaZT5UpiqFKCuVXCDMSrU+3VFafnu2c5m3lrWIlr6A5Q== +"@babel/plugin-proposal-unicode-property-regex@^7.16.0", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.0.tgz#890482dfc5ea378e42e19a71e709728cabf18612" + integrity sha512-ti7IdM54NXv29cA4+bNNKEMS4jLMCbJgl+Drv+FgYy0erJLAxNAIXcNjNjrRZEcWq0xJHsNVwQezskMFpF8N9g== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.14.5" + "@babel/helper-create-regexp-features-plugin" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-async-generators@^7.8.4": @@ -478,10 +485,10 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-jsx@7", "@babel/plugin-syntax-jsx@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.14.5.tgz#000e2e25d8673cce49300517a3eda44c263e4201" - integrity sha512-ohuFIsOMXJnbOMRfX7/w7LocdR6R7whhuRD4ax8IipLcLPlZGJKkBxgHp++U4N/vKyU16/YDQr2f5seajD3jIw== +"@babel/plugin-syntax-jsx@7", "@babel/plugin-syntax-jsx@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.0.tgz#f9624394317365a9a88c82358d3f8471154698f1" + integrity sha512-8zv2+xiPHwly31RK4RmnEYY5zziuF3O7W2kIDW+07ewWDh6Oi0dRq8kwvulRkFgt6DB97RlKs5c1y068iPlCUg== dependencies: "@babel/helper-plugin-utils" "^7.14.5" @@ -541,332 +548,333 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-arrow-functions@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.14.5.tgz#f7187d9588a768dd080bf4c9ffe117ea62f7862a" - integrity sha512-KOnO0l4+tD5IfOdi4x8C1XmEIRWUjNRV8wc6K2vz/3e8yAOoZZvsRXRRIF/yo/MAOFb4QjtAw9xSxMXbSMRy8A== +"@babel/plugin-transform-arrow-functions@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.0.tgz#951706f8b449c834ed07bd474c0924c944b95a8e" + integrity sha512-vIFb5250Rbh7roWARvCLvIJ/PtAU5Lhv7BtZ1u24COwpI9Ypjsh+bZcKk6rlIyalK+r0jOc1XQ8I4ovNxNrWrA== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-async-to-generator@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.14.5.tgz#72c789084d8f2094acb945633943ef8443d39e67" - integrity sha512-szkbzQ0mNk0rpu76fzDdqSyPu0MuvpXgC+6rz5rpMb5OIRxdmHfQxrktL8CYolL2d8luMCZTR0DpIMIdL27IjA== +"@babel/plugin-transform-async-to-generator@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.0.tgz#df12637f9630ddfa0ef9d7a11bc414d629d38604" + integrity sha512-PbIr7G9kR8tdH6g8Wouir5uVjklETk91GMVSUq+VaOgiinbCkBP6Q7NN/suM/QutZkMJMvcyAriogcYAdhg8Gw== dependencies: - "@babel/helper-module-imports" "^7.14.5" + "@babel/helper-module-imports" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-remap-async-to-generator" "^7.14.5" + "@babel/helper-remap-async-to-generator" "^7.16.0" -"@babel/plugin-transform-block-scoped-functions@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.14.5.tgz#e48641d999d4bc157a67ef336aeb54bc44fd3ad4" - integrity sha512-dtqWqdWZ5NqBX3KzsVCWfQI3A53Ft5pWFCT2eCVUftWZgjc5DpDponbIF1+c+7cSGk2wN0YK7HGL/ezfRbpKBQ== +"@babel/plugin-transform-block-scoped-functions@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.0.tgz#c618763233ad02847805abcac4c345ce9de7145d" + integrity sha512-V14As3haUOP4ZWrLJ3VVx5rCnrYhMSHN/jX7z6FAt5hjRkLsb0snPCmJwSOML5oxkKO4FNoNv7V5hw/y2bjuvg== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-block-scoping@^7.15.3": - version "7.15.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.15.3.tgz#94c81a6e2fc230bcce6ef537ac96a1e4d2b3afaf" - integrity sha512-nBAzfZwZb4DkaGtOes1Up1nOAp9TDRRFw4XBzBBSG9QK7KVFmYzgj9o9sbPv7TX5ofL4Auq4wZnxCoPnI/lz2Q== +"@babel/plugin-transform-block-scoping@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.0.tgz#bcf433fb482fe8c3d3b4e8a66b1c4a8e77d37c16" + integrity sha512-27n3l67/R3UrXfizlvHGuTwsRIFyce3D/6a37GRxn28iyTPvNXaW4XvznexRh1zUNLPjbLL22Id0XQElV94ruw== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-classes@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.15.4.tgz#50aee17aaf7f332ae44e3bce4c2e10534d5d3bf1" - integrity sha512-Yjvhex8GzBmmPQUvpXRPWQ9WnxXgAFuZSrqOK/eJlOGIXwvv8H3UEdUigl1gb/bnjTrln+e8bkZUYCBt/xYlBg== +"@babel/plugin-transform-classes@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.0.tgz#54cf5ff0b2242c6573d753cd4bfc7077a8b282f5" + integrity sha512-HUxMvy6GtAdd+GKBNYDWCIA776byUQH8zjnfjxwT1P1ARv/wFu8eBDpmXQcLS/IwRtrxIReGiplOwMeyO7nsDQ== dependencies: - "@babel/helper-annotate-as-pure" "^7.15.4" - "@babel/helper-function-name" "^7.15.4" - "@babel/helper-optimise-call-expression" "^7.15.4" + "@babel/helper-annotate-as-pure" "^7.16.0" + "@babel/helper-function-name" "^7.16.0" + "@babel/helper-optimise-call-expression" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-replace-supers" "^7.15.4" - "@babel/helper-split-export-declaration" "^7.15.4" + "@babel/helper-replace-supers" "^7.16.0" + "@babel/helper-split-export-declaration" "^7.16.0" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.14.5.tgz#1b9d78987420d11223d41195461cc43b974b204f" - integrity sha512-pWM+E4283UxaVzLb8UBXv4EIxMovU4zxT1OPnpHJcmnvyY9QbPPTKZfEj31EUvG3/EQRbYAGaYEUZ4yWOBC2xg== +"@babel/plugin-transform-computed-properties@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.0.tgz#e0c385507d21e1b0b076d66bed6d5231b85110b7" + integrity sha512-63l1dRXday6S8V3WFY5mXJwcRAnPYxvFfTlt67bwV1rTyVTM5zrp0DBBb13Kl7+ehkCVwIZPumPpFP/4u70+Tw== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-destructuring@^7.14.7": - version "7.14.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.14.7.tgz#0ad58ed37e23e22084d109f185260835e5557576" - integrity sha512-0mDE99nK+kVh3xlc5vKwB6wnP9ecuSj+zQCa/n0voENtP/zymdT4HH6QEb65wjjcbqr1Jb/7z9Qp7TF5FtwYGw== +"@babel/plugin-transform-destructuring@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.16.0.tgz#ad3d7e74584ad5ea4eadb1e6642146c590dee33c" + integrity sha512-Q7tBUwjxLTsHEoqktemHBMtb3NYwyJPTJdM+wDwb0g8PZ3kQUIzNvwD5lPaqW/p54TXBc/MXZu9Jr7tbUEUM8Q== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-dotall-regex@^7.14.5", "@babel/plugin-transform-dotall-regex@^7.4.4": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.14.5.tgz#2f6bf76e46bdf8043b4e7e16cf24532629ba0c7a" - integrity sha512-loGlnBdj02MDsFaHhAIJzh7euK89lBrGIdM9EAtHFo6xKygCUGuuWe07o1oZVk287amtW1n0808sQM99aZt3gw== +"@babel/plugin-transform-dotall-regex@^7.16.0", "@babel/plugin-transform-dotall-regex@^7.4.4": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.0.tgz#50bab00c1084b6162d0a58a818031cf57798e06f" + integrity sha512-FXlDZfQeLILfJlC6I1qyEwcHK5UpRCFkaoVyA1nk9A1L1Yu583YO4un2KsLBsu3IJb4CUbctZks8tD9xPQubLw== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.14.5" + "@babel/helper-create-regexp-features-plugin" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-duplicate-keys@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.14.5.tgz#365a4844881bdf1501e3a9f0270e7f0f91177954" - integrity sha512-iJjbI53huKbPDAsJ8EmVmvCKeeq21bAze4fu9GBQtSLqfvzj2oRuHVx4ZkDwEhg1htQ+5OBZh/Ab0XDf5iBZ7A== +"@babel/plugin-transform-duplicate-keys@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.0.tgz#8bc2e21813e3e89e5e5bf3b60aa5fc458575a176" + integrity sha512-LIe2kcHKAZOJDNxujvmp6z3mfN6V9lJxubU4fJIGoQCkKe3Ec2OcbdlYP+vW++4MpxwG0d1wSDOJtQW5kLnkZQ== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-exponentiation-operator@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.14.5.tgz#5154b8dd6a3dfe6d90923d61724bd3deeb90b493" - integrity sha512-jFazJhMBc9D27o9jDnIE5ZErI0R0m7PbKXVq77FFvqFbzvTMuv8jaAwLZ5PviOLSFttqKIW0/wxNSDbjLk0tYA== +"@babel/plugin-transform-exponentiation-operator@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.0.tgz#a180cd2881e3533cef9d3901e48dad0fbeff4be4" + integrity sha512-OwYEvzFI38hXklsrbNivzpO3fh87skzx8Pnqi4LoSYeav0xHlueSoCJrSgTPfnbyzopo5b3YVAJkFIcUpK2wsw== dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.14.5" + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-for-of@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.15.4.tgz#25c62cce2718cfb29715f416e75d5263fb36a8c2" - integrity sha512-DRTY9fA751AFBDh2oxydvVm4SYevs5ILTWLs6xKXps4Re/KG5nfUkr+TdHCrRWB8C69TlzVgA9b3RmGWmgN9LA== +"@babel/plugin-transform-for-of@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.0.tgz#f7abaced155260e2461359bbc7c7248aca5e6bd2" + integrity sha512-5QKUw2kO+GVmKr2wMYSATCTTnHyscl6sxFRAY+rvN7h7WB0lcG0o4NoV6ZQU32OZGVsYUsfLGgPQpDFdkfjlJQ== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-function-name@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.14.5.tgz#e81c65ecb900746d7f31802f6bed1f52d915d6f2" - integrity sha512-vbO6kv0fIzZ1GpmGQuvbwwm+O4Cbm2NrPzwlup9+/3fdkuzo1YqOZcXw26+YUJB84Ja7j9yURWposEHLYwxUfQ== +"@babel/plugin-transform-function-name@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.0.tgz#02e3699c284c6262236599f751065c5d5f1f400e" + integrity sha512-lBzMle9jcOXtSOXUpc7tvvTpENu/NuekNJVova5lCCWCV9/U1ho2HH2y0p6mBg8fPm/syEAbfaaemYGOHCY3mg== dependencies: - "@babel/helper-function-name" "^7.14.5" + "@babel/helper-function-name" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-literals@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.14.5.tgz#41d06c7ff5d4d09e3cf4587bd3ecf3930c730f78" - integrity sha512-ql33+epql2F49bi8aHXxvLURHkxJbSmMKl9J5yHqg4PLtdE6Uc48CH1GS6TQvZ86eoB/ApZXwm7jlA+B3kra7A== +"@babel/plugin-transform-literals@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.0.tgz#79711e670ffceb31bd298229d50f3621f7980cac" + integrity sha512-gQDlsSF1iv9RU04clgXqRjrPyyoJMTclFt3K1cjLmTKikc0s/6vE3hlDeEVC71wLTRu72Fq7650kABrdTc2wMQ== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-member-expression-literals@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.14.5.tgz#b39cd5212a2bf235a617d320ec2b48bcc091b8a7" - integrity sha512-WkNXxH1VXVTKarWFqmso83xl+2V3Eo28YY5utIkbsmXoItO8Q3aZxN4BTS2k0hz9dGUloHK26mJMyQEYfkn/+Q== +"@babel/plugin-transform-member-expression-literals@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.0.tgz#5251b4cce01eaf8314403d21aedb269d79f5e64b" + integrity sha512-WRpw5HL4Jhnxw8QARzRvwojp9MIE7Tdk3ez6vRyUk1MwgjJN0aNpRoXainLR5SgxmoXx/vsXGZ6OthP6t/RbUg== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-modules-amd@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.14.5.tgz#4fd9ce7e3411cb8b83848480b7041d83004858f7" - integrity sha512-3lpOU8Vxmp3roC4vzFpSdEpGUWSMsHFreTWOMMLzel2gNGfHE5UWIh/LN6ghHs2xurUp4jRFYMUIZhuFbody1g== +"@babel/plugin-transform-modules-amd@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.0.tgz#09abd41e18dcf4fd479c598c1cef7bd39eb1337e" + integrity sha512-rWFhWbCJ9Wdmzln1NmSCqn7P0RAD+ogXG/bd9Kg5c7PKWkJtkiXmYsMBeXjDlzHpVTJ4I/hnjs45zX4dEv81xw== dependencies: - "@babel/helper-module-transforms" "^7.14.5" + "@babel/helper-module-transforms" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-commonjs@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.15.4.tgz#8201101240eabb5a76c08ef61b2954f767b6b4c1" - integrity sha512-qg4DPhwG8hKp4BbVDvX1s8cohM8a6Bvptu4l6Iingq5rW+yRUAhe/YRup/YcW2zCOlrysEWVhftIcKzrEZv3sA== +"@babel/plugin-transform-modules-commonjs@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.0.tgz#add58e638c8ddc4875bd9a9ecb5c594613f6c922" + integrity sha512-Dzi+NWqyEotgzk/sb7kgQPJQf7AJkQBWsVp1N6JWc1lBVo0vkElUnGdr1PzUBmfsCCN5OOFya3RtpeHk15oLKQ== dependencies: - "@babel/helper-module-transforms" "^7.15.4" + "@babel/helper-module-transforms" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-simple-access" "^7.15.4" + "@babel/helper-simple-access" "^7.16.0" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-systemjs@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.15.4.tgz#b42890c7349a78c827719f1d2d0cd38c7d268132" - integrity sha512-fJUnlQrl/mezMneR72CKCgtOoahqGJNVKpompKwzv3BrEXdlPspTcyxrZ1XmDTIr9PpULrgEQo3qNKp6dW7ssw== +"@babel/plugin-transform-modules-systemjs@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.0.tgz#a92cf240afeb605f4ca16670453024425e421ea4" + integrity sha512-yuGBaHS3lF1m/5R+6fjIke64ii5luRUg97N2wr+z1sF0V+sNSXPxXDdEEL/iYLszsN5VKxVB1IPfEqhzVpiqvg== dependencies: - "@babel/helper-hoist-variables" "^7.15.4" - "@babel/helper-module-transforms" "^7.15.4" + "@babel/helper-hoist-variables" "^7.16.0" + "@babel/helper-module-transforms" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-validator-identifier" "^7.14.9" + "@babel/helper-validator-identifier" "^7.15.7" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-umd@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.14.5.tgz#fb662dfee697cce274a7cda525190a79096aa6e0" - integrity sha512-RfPGoagSngC06LsGUYyM9QWSXZ8MysEjDJTAea1lqRjNECE3y0qIJF/qbvJxc4oA4s99HumIMdXOrd+TdKaAAA== +"@babel/plugin-transform-modules-umd@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.0.tgz#195f26c2ad6d6a391b70880effce18ce625e06a7" + integrity sha512-nx4f6no57himWiHhxDM5pjwhae5vLpTK2zCnDH8+wNLJy0TVER/LJRHl2bkt6w9Aad2sPD5iNNoUpY3X9sTGDg== dependencies: - "@babel/helper-module-transforms" "^7.14.5" + "@babel/helper-module-transforms" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-named-capturing-groups-regex@^7.14.9": - version "7.14.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.9.tgz#c68f5c5d12d2ebaba3762e57c2c4f6347a46e7b2" - integrity sha512-l666wCVYO75mlAtGFfyFwnWmIXQm3kSH0C3IRnJqWcZbWkoihyAdDhFm2ZWaxWTqvBvhVFfJjMRQ0ez4oN1yYA== +"@babel/plugin-transform-named-capturing-groups-regex@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.0.tgz#d3db61cc5d5b97986559967cd5ea83e5c32096ca" + integrity sha512-LogN88uO+7EhxWc8WZuQ8vxdSyVGxhkh8WTC3tzlT8LccMuQdA81e9SGV6zY7kY2LjDhhDOFdQVxdGwPyBCnvg== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.14.5" + "@babel/helper-create-regexp-features-plugin" "^7.16.0" -"@babel/plugin-transform-new-target@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.14.5.tgz#31bdae8b925dc84076ebfcd2a9940143aed7dbf8" - integrity sha512-Nx054zovz6IIRWEB49RDRuXGI4Gy0GMgqG0cII9L3MxqgXz/+rgII+RU58qpo4g7tNEx1jG7rRVH4ihZoP4esQ== +"@babel/plugin-transform-new-target@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.0.tgz#af823ab576f752215a49937779a41ca65825ab35" + integrity sha512-fhjrDEYv2DBsGN/P6rlqakwRwIp7rBGLPbrKxwh7oVt5NNkIhZVOY2GRV+ULLsQri1bDqwDWnU3vhlmx5B2aCw== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-object-super@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.14.5.tgz#d0b5faeac9e98597a161a9cf78c527ed934cdc45" - integrity sha512-MKfOBWzK0pZIrav9z/hkRqIk/2bTv9qvxHzPQc12RcVkMOzpIKnFCNYJip00ssKWYkd8Sf5g0Wr7pqJ+cmtuFg== +"@babel/plugin-transform-object-super@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.0.tgz#fb20d5806dc6491a06296ac14ea8e8d6fedda72b" + integrity sha512-fds+puedQHn4cPLshoHcR1DTMN0q1V9ou0mUjm8whx9pGcNvDrVVrgw+KJzzCaiTdaYhldtrUps8DWVMgrSEyg== dependencies: "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-replace-supers" "^7.14.5" + "@babel/helper-replace-supers" "^7.16.0" -"@babel/plugin-transform-parameters@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.15.4.tgz#5f2285cc3160bf48c8502432716b48504d29ed62" - integrity sha512-9WB/GUTO6lvJU3XQsSr6J/WKvBC2hcs4Pew8YxZagi6GkTdniyqp8On5kqdK8MN0LMeu0mGbhPN+O049NV/9FQ== +"@babel/plugin-transform-parameters@^7.16.0", "@babel/plugin-transform-parameters@^7.16.3": + version "7.16.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.3.tgz#fa9e4c874ee5223f891ee6fa8d737f4766d31d15" + integrity sha512-3MaDpJrOXT1MZ/WCmkOFo7EtmVVC8H4EUZVrHvFOsmwkk4lOjQj8rzv8JKUZV4YoQKeoIgk07GO+acPU9IMu/w== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-property-literals@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.14.5.tgz#0ddbaa1f83db3606f1cdf4846fa1dfb473458b34" - integrity sha512-r1uilDthkgXW8Z1vJz2dKYLV1tuw2xsbrp3MrZmD99Wh9vsfKoob+JTgri5VUb/JqyKRXotlOtwgu4stIYCmnw== +"@babel/plugin-transform-property-literals@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.0.tgz#a95c552189a96a00059f6776dc4e00e3690c78d1" + integrity sha512-XLldD4V8+pOqX2hwfWhgwXzGdnDOThxaNTgqagOcpBgIxbUvpgU2FMvo5E1RyHbk756WYgdbS0T8y0Cj9FKkWQ== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-react-display-name@^7.14.5": - version "7.15.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.15.1.tgz#6aaac6099f1fcf6589d35ae6be1b6e10c8c602b9" - integrity sha512-yQZ/i/pUCJAHI/LbtZr413S3VT26qNrEm0M5RRxQJA947/YNYwbZbBaXGDrq6CG5QsZycI1VIP6d7pQaBfP+8Q== +"@babel/plugin-transform-react-display-name@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.16.0.tgz#9a0ad8aa8e8790883a7bd2736f66229a58125676" + integrity sha512-FJFdJAqaCpndL+pIf0aeD/qlQwT7QXOvR6Cc8JPvNhKJBi2zc/DPc4g05Y3fbD/0iWAMQFGij4+Xw+4L/BMpTg== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-transform-react-inline-elements@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-inline-elements/-/plugin-transform-react-inline-elements-7.14.5.tgz#5e2c8ad96612f1a86484b291df5216cc6a6cffb6" - integrity sha512-RsdXYEbicGlg9WBvanlndPqCxrG9hV86lPjObbsTzA5hkrfScoECP5NWEJFUrtE/NVFu81OcPu6pQVVQtOX20Q== + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-inline-elements/-/plugin-transform-react-inline-elements-7.16.0.tgz#e0975bba7b3fc332599c2f15d98f633ce978a198" + integrity sha512-b/MO7Rr1ew/D0UdTfcl8QTSygAzuEvVSwIzu7dqeVUuU6wWvuQGueEv3NXvdUl29mlnoXaAAcJy50fgLqXg+Lg== dependencies: - "@babel/helper-builder-react-jsx" "^7.14.5" + "@babel/helper-builder-react-jsx" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-react-jsx-development@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.14.5.tgz#1a6c73e2f7ed2c42eebc3d2ad60b0c7494fcb9af" - integrity sha512-rdwG/9jC6QybWxVe2UVOa7q6cnTpw8JRRHOxntG/h6g/guAOe6AhtQHJuJh5FwmnXIT1bdm5vC2/5huV8ZOorQ== +"@babel/plugin-transform-react-jsx-development@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.16.0.tgz#1cb52874678d23ab11d0d16488d54730807303ef" + integrity sha512-qq65iSqBRq0Hr3wq57YG2AmW0H6wgTnIzpffTphrUWUgLCOK+zf1f7G0vuOiXrp7dU1qq+fQBoqZ3wCDAkhFzw== dependencies: - "@babel/plugin-transform-react-jsx" "^7.14.5" + "@babel/plugin-transform-react-jsx" "^7.16.0" -"@babel/plugin-transform-react-jsx@^7.14.5": - version "7.14.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.14.9.tgz#3314b2163033abac5200a869c4de242cd50a914c" - integrity sha512-30PeETvS+AeD1f58i1OVyoDlVYQhap/K20ZrMjLmmzmC2AYR/G43D4sdJAaDAqCD3MYpSWbmrz3kES158QSLjw== +"@babel/plugin-transform-react-jsx@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.16.0.tgz#55b797d4960c3de04e07ad1c0476e2bc6a4889f1" + integrity sha512-rqDgIbukZ44pqq7NIRPGPGNklshPkvlmvqjdx3OZcGPk4zGIenYkxDTvl3LsSL8gqcc3ZzGmXPE6hR/u/voNOw== dependencies: - "@babel/helper-annotate-as-pure" "^7.14.5" - "@babel/helper-module-imports" "^7.14.5" + "@babel/helper-annotate-as-pure" "^7.16.0" + "@babel/helper-module-imports" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" - "@babel/plugin-syntax-jsx" "^7.14.5" - "@babel/types" "^7.14.9" + "@babel/plugin-syntax-jsx" "^7.16.0" + "@babel/types" "^7.16.0" -"@babel/plugin-transform-react-pure-annotations@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.14.5.tgz#18de612b84021e3a9802cbc212c9d9f46d0d11fc" - integrity sha512-3X4HpBJimNxW4rhUy/SONPyNQHp5YRr0HhJdT2OH1BRp0of7u3Dkirc7x9FRJMKMqTBI079VZ1hzv7Ouuz///g== +"@babel/plugin-transform-react-pure-annotations@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.16.0.tgz#23db6ddf558d8abde41b8ad9d59f48ad5532ccab" + integrity sha512-NC/Bj2MG+t8Ef5Pdpo34Ay74X4Rt804h5y81PwOpfPtmAK3i6CizmQqwyBQzIepz1Yt8wNr2Z2L7Lu3qBMfZMA== dependencies: - "@babel/helper-annotate-as-pure" "^7.14.5" + "@babel/helper-annotate-as-pure" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-regenerator@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.14.5.tgz#9676fd5707ed28f522727c5b3c0aa8544440b04f" - integrity sha512-NVIY1W3ITDP5xQl50NgTKlZ0GrotKtLna08/uGY6ErQt6VEQZXla86x/CTddm5gZdcr+5GSsvMeTmWA5Ii6pkg== +"@babel/plugin-transform-regenerator@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.0.tgz#eaee422c84b0232d03aea7db99c97deeaf6125a4" + integrity sha512-JAvGxgKuwS2PihiSFaDrp94XOzzTUeDeOQlcKzVAyaPap7BnZXK/lvMDiubkPTdotPKOIZq9xWXWnggUMYiExg== dependencies: regenerator-transform "^0.14.2" -"@babel/plugin-transform-reserved-words@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.14.5.tgz#c44589b661cfdbef8d4300dcc7469dffa92f8304" - integrity sha512-cv4F2rv1nD4qdexOGsRQXJrOcyb5CrgjUH9PKrrtyhSDBNWGxd0UIitjyJiWagS+EbUGjG++22mGH1Pub8D6Vg== +"@babel/plugin-transform-reserved-words@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.0.tgz#fff4b9dcb19e12619394bda172d14f2d04c0379c" + integrity sha512-Dgs8NNCehHSvXdhEhln8u/TtJxfVwGYCgP2OOr5Z3Ar+B+zXicEOKNTyc+eca2cuEOMtjW6m9P9ijOt8QdqWkg== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-transform-runtime@^7.14.5": - version "7.15.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.15.8.tgz#9d15b1e94e1c7f6344f65a8d573597d93c6cd886" - integrity sha512-+6zsde91jMzzvkzuEA3k63zCw+tm/GvuuabkpisgbDMTPQsIMHllE3XczJFFtEHLjjhKQFZmGQVRdELetlWpVw== + version "7.16.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.16.4.tgz#f9ba3c7034d429c581e1bd41b4952f3db3c2c7e8" + integrity sha512-pru6+yHANMTukMtEZGC4fs7XPwg35v8sj5CIEmE+gEkFljFiVJxEWxx/7ZDkTK+iZRYo1bFXBtfIN95+K3cJ5A== dependencies: - "@babel/helper-module-imports" "^7.15.4" + "@babel/helper-module-imports" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" - babel-plugin-polyfill-corejs2 "^0.2.2" - babel-plugin-polyfill-corejs3 "^0.2.5" - babel-plugin-polyfill-regenerator "^0.2.2" + babel-plugin-polyfill-corejs2 "^0.3.0" + babel-plugin-polyfill-corejs3 "^0.4.0" + babel-plugin-polyfill-regenerator "^0.3.0" semver "^6.3.0" -"@babel/plugin-transform-shorthand-properties@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.14.5.tgz#97f13855f1409338d8cadcbaca670ad79e091a58" - integrity sha512-xLucks6T1VmGsTB+GWK5Pl9Jl5+nRXD1uoFdA5TSO6xtiNjtXTjKkmPdFXVLGlK5A2/or/wQMKfmQ2Y0XJfn5g== +"@babel/plugin-transform-shorthand-properties@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.0.tgz#090372e3141f7cc324ed70b3daf5379df2fa384d" + integrity sha512-iVb1mTcD8fuhSv3k99+5tlXu5N0v8/DPm2mO3WACLG6al1CGZH7v09HJyUb1TtYl/Z+KrM6pHSIJdZxP5A+xow== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-spread@^7.15.8": - version "7.15.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.15.8.tgz#79d5aa27f68d700449b2da07691dfa32d2f6d468" - integrity sha512-/daZ8s2tNaRekl9YJa9X4bzjpeRZLt122cpgFnQPLGUe61PH8zMEBmYqKkW5xF5JUEh5buEGXJoQpqBmIbpmEQ== +"@babel/plugin-transform-spread@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.0.tgz#d21ca099bbd53ab307a8621e019a7bd0f40cdcfb" + integrity sha512-Ao4MSYRaLAQczZVp9/7E7QHsCuK92yHRrmVNRe/SlEJjhzivq0BSn8mEraimL8wizHZ3fuaHxKH0iwzI13GyGg== dependencies: "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.15.4" + "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" -"@babel/plugin-transform-sticky-regex@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.14.5.tgz#5b617542675e8b7761294381f3c28c633f40aeb9" - integrity sha512-Z7F7GyvEMzIIbwnziAZmnSNpdijdr4dWt+FJNBnBLz5mwDFkqIXU9wmBcWWad3QeJF5hMTkRe4dAq2sUZiG+8A== +"@babel/plugin-transform-sticky-regex@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.0.tgz#c35ea31a02d86be485f6aa510184b677a91738fd" + integrity sha512-/ntT2NljR9foobKk4E/YyOSwcGUXtYWv5tinMK/3RkypyNBNdhHUaq6Orw5DWq9ZcNlS03BIlEALFeQgeVAo4Q== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-template-literals@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.14.5.tgz#a5f2bc233937d8453885dc736bdd8d9ffabf3d93" - integrity sha512-22btZeURqiepOfuy/VkFr+zStqlujWaarpMErvay7goJS6BWwdd6BY9zQyDLDa4x2S3VugxFb162IZ4m/S/+Gg== +"@babel/plugin-transform-template-literals@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.0.tgz#a8eced3a8e7b8e2d40ec4ec4548a45912630d302" + integrity sha512-Rd4Ic89hA/f7xUSJQk5PnC+4so50vBoBfxjdQAdvngwidM8jYIBVxBZ/sARxD4e0yMXRbJVDrYf7dyRtIIKT6Q== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-typeof-symbol@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.14.5.tgz#39af2739e989a2bd291bf6b53f16981423d457d4" - integrity sha512-lXzLD30ffCWseTbMQzrvDWqljvZlHkXU+CnseMhkMNqU1sASnCsz3tSzAaH3vCUXb9PHeUb90ZT1BdFTm1xxJw== +"@babel/plugin-transform-typeof-symbol@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.0.tgz#8b19a244c6f8c9d668dca6a6f754ad6ead1128f2" + integrity sha512-++V2L8Bdf4vcaHi2raILnptTBjGEFxn5315YU+e8+EqXIucA+q349qWngCLpUYqqv233suJ6NOienIVUpS9cqg== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-unicode-escapes@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.14.5.tgz#9d4bd2a681e3c5d7acf4f57fa9e51175d91d0c6b" - integrity sha512-crTo4jATEOjxj7bt9lbYXcBAM3LZaUrbP2uUdxb6WIorLmjNKSpHfIybgY4B8SRpbf8tEVIWH3Vtm7ayCrKocA== +"@babel/plugin-transform-unicode-escapes@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.0.tgz#1a354064b4c45663a32334f46fa0cf6100b5b1f3" + integrity sha512-VFi4dhgJM7Bpk8lRc5CMaRGlKZ29W9C3geZjt9beuzSUrlJxsNwX7ReLwaL6WEvsOf2EQkyIJEPtF8EXjB/g2A== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-unicode-regex@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.14.5.tgz#4cd09b6c8425dd81255c7ceb3fb1836e7414382e" - integrity sha512-UygduJpC5kHeCiRw/xDVzC+wj8VaYSoKl5JNVmbP7MadpNinAm3SvZCxZ42H37KZBKztz46YC73i9yV34d0Tzw== +"@babel/plugin-transform-unicode-regex@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.0.tgz#293b80950177c8c85aede87cef280259fb995402" + integrity sha512-jHLK4LxhHjvCeZDWyA9c+P9XH1sOxRd1RO9xMtDVRAOND/PczPqizEtVdx4TQF/wyPaewqpT+tgQFYMnN/P94A== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.14.5" + "@babel/helper-create-regexp-features-plugin" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" "@babel/preset-env@^7.14.7": - version "7.15.8" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.15.8.tgz#f527ce5bcb121cd199f6b502bf23e420b3ff8dba" - integrity sha512-rCC0wH8husJgY4FPbHsiYyiLxSY8oMDJH7Rl6RQMknbN9oDDHhM9RDFvnGM2MgkbUJzSQB4gtuwygY5mCqGSsA== + version "7.16.4" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.16.4.tgz#4f6ec33b2a3fe72d6bfdcdf3859500232563a2e3" + integrity sha512-v0QtNd81v/xKj4gNKeuAerQ/azeNn/G1B1qMLeXOcV8+4TWlD2j3NV1u8q29SDFBXx/NBq5kyEAO+0mpRgacjA== dependencies: - "@babel/compat-data" "^7.15.0" - "@babel/helper-compilation-targets" "^7.15.4" + "@babel/compat-data" "^7.16.4" + "@babel/helper-compilation-targets" "^7.16.3" "@babel/helper-plugin-utils" "^7.14.5" "@babel/helper-validator-option" "^7.14.5" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.15.4" - "@babel/plugin-proposal-async-generator-functions" "^7.15.8" - "@babel/plugin-proposal-class-properties" "^7.14.5" - "@babel/plugin-proposal-class-static-block" "^7.15.4" - "@babel/plugin-proposal-dynamic-import" "^7.14.5" - "@babel/plugin-proposal-export-namespace-from" "^7.14.5" - "@babel/plugin-proposal-json-strings" "^7.14.5" - "@babel/plugin-proposal-logical-assignment-operators" "^7.14.5" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.14.5" - "@babel/plugin-proposal-numeric-separator" "^7.14.5" - "@babel/plugin-proposal-object-rest-spread" "^7.15.6" - "@babel/plugin-proposal-optional-catch-binding" "^7.14.5" - "@babel/plugin-proposal-optional-chaining" "^7.14.5" - "@babel/plugin-proposal-private-methods" "^7.14.5" - "@babel/plugin-proposal-private-property-in-object" "^7.15.4" - "@babel/plugin-proposal-unicode-property-regex" "^7.14.5" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.16.2" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.16.0" + "@babel/plugin-proposal-async-generator-functions" "^7.16.4" + "@babel/plugin-proposal-class-properties" "^7.16.0" + "@babel/plugin-proposal-class-static-block" "^7.16.0" + "@babel/plugin-proposal-dynamic-import" "^7.16.0" + "@babel/plugin-proposal-export-namespace-from" "^7.16.0" + "@babel/plugin-proposal-json-strings" "^7.16.0" + "@babel/plugin-proposal-logical-assignment-operators" "^7.16.0" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.16.0" + "@babel/plugin-proposal-numeric-separator" "^7.16.0" + "@babel/plugin-proposal-object-rest-spread" "^7.16.0" + "@babel/plugin-proposal-optional-catch-binding" "^7.16.0" + "@babel/plugin-proposal-optional-chaining" "^7.16.0" + "@babel/plugin-proposal-private-methods" "^7.16.0" + "@babel/plugin-proposal-private-property-in-object" "^7.16.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.16.0" "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-syntax-class-properties" "^7.12.13" "@babel/plugin-syntax-class-static-block" "^7.14.5" @@ -881,50 +889,50 @@ "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" "@babel/plugin-syntax-top-level-await" "^7.14.5" - "@babel/plugin-transform-arrow-functions" "^7.14.5" - "@babel/plugin-transform-async-to-generator" "^7.14.5" - "@babel/plugin-transform-block-scoped-functions" "^7.14.5" - "@babel/plugin-transform-block-scoping" "^7.15.3" - "@babel/plugin-transform-classes" "^7.15.4" - "@babel/plugin-transform-computed-properties" "^7.14.5" - "@babel/plugin-transform-destructuring" "^7.14.7" - "@babel/plugin-transform-dotall-regex" "^7.14.5" - "@babel/plugin-transform-duplicate-keys" "^7.14.5" - "@babel/plugin-transform-exponentiation-operator" "^7.14.5" - "@babel/plugin-transform-for-of" "^7.15.4" - "@babel/plugin-transform-function-name" "^7.14.5" - "@babel/plugin-transform-literals" "^7.14.5" - "@babel/plugin-transform-member-expression-literals" "^7.14.5" - "@babel/plugin-transform-modules-amd" "^7.14.5" - "@babel/plugin-transform-modules-commonjs" "^7.15.4" - "@babel/plugin-transform-modules-systemjs" "^7.15.4" - "@babel/plugin-transform-modules-umd" "^7.14.5" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.14.9" - "@babel/plugin-transform-new-target" "^7.14.5" - "@babel/plugin-transform-object-super" "^7.14.5" - "@babel/plugin-transform-parameters" "^7.15.4" - "@babel/plugin-transform-property-literals" "^7.14.5" - "@babel/plugin-transform-regenerator" "^7.14.5" - "@babel/plugin-transform-reserved-words" "^7.14.5" - "@babel/plugin-transform-shorthand-properties" "^7.14.5" - "@babel/plugin-transform-spread" "^7.15.8" - "@babel/plugin-transform-sticky-regex" "^7.14.5" - "@babel/plugin-transform-template-literals" "^7.14.5" - "@babel/plugin-transform-typeof-symbol" "^7.14.5" - "@babel/plugin-transform-unicode-escapes" "^7.14.5" - "@babel/plugin-transform-unicode-regex" "^7.14.5" - "@babel/preset-modules" "^0.1.4" - "@babel/types" "^7.15.6" - babel-plugin-polyfill-corejs2 "^0.2.2" - babel-plugin-polyfill-corejs3 "^0.2.5" - babel-plugin-polyfill-regenerator "^0.2.2" - core-js-compat "^3.16.0" + "@babel/plugin-transform-arrow-functions" "^7.16.0" + "@babel/plugin-transform-async-to-generator" "^7.16.0" + "@babel/plugin-transform-block-scoped-functions" "^7.16.0" + "@babel/plugin-transform-block-scoping" "^7.16.0" + "@babel/plugin-transform-classes" "^7.16.0" + "@babel/plugin-transform-computed-properties" "^7.16.0" + "@babel/plugin-transform-destructuring" "^7.16.0" + "@babel/plugin-transform-dotall-regex" "^7.16.0" + "@babel/plugin-transform-duplicate-keys" "^7.16.0" + "@babel/plugin-transform-exponentiation-operator" "^7.16.0" + "@babel/plugin-transform-for-of" "^7.16.0" + "@babel/plugin-transform-function-name" "^7.16.0" + "@babel/plugin-transform-literals" "^7.16.0" + "@babel/plugin-transform-member-expression-literals" "^7.16.0" + "@babel/plugin-transform-modules-amd" "^7.16.0" + "@babel/plugin-transform-modules-commonjs" "^7.16.0" + "@babel/plugin-transform-modules-systemjs" "^7.16.0" + "@babel/plugin-transform-modules-umd" "^7.16.0" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.16.0" + "@babel/plugin-transform-new-target" "^7.16.0" + "@babel/plugin-transform-object-super" "^7.16.0" + "@babel/plugin-transform-parameters" "^7.16.3" + "@babel/plugin-transform-property-literals" "^7.16.0" + "@babel/plugin-transform-regenerator" "^7.16.0" + "@babel/plugin-transform-reserved-words" "^7.16.0" + "@babel/plugin-transform-shorthand-properties" "^7.16.0" + "@babel/plugin-transform-spread" "^7.16.0" + "@babel/plugin-transform-sticky-regex" "^7.16.0" + "@babel/plugin-transform-template-literals" "^7.16.0" + "@babel/plugin-transform-typeof-symbol" "^7.16.0" + "@babel/plugin-transform-unicode-escapes" "^7.16.0" + "@babel/plugin-transform-unicode-regex" "^7.16.0" + "@babel/preset-modules" "^0.1.5" + "@babel/types" "^7.16.0" + babel-plugin-polyfill-corejs2 "^0.3.0" + babel-plugin-polyfill-corejs3 "^0.4.0" + babel-plugin-polyfill-regenerator "^0.3.0" + core-js-compat "^3.19.1" semver "^6.3.0" -"@babel/preset-modules@^0.1.4": - version "0.1.4" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.4.tgz#362f2b68c662842970fdb5e254ffc8fc1c2e415e" - integrity sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg== +"@babel/preset-modules@^0.1.5": + version "0.1.5" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.5.tgz#ef939d6e7f268827e1841638dc6ff95515e115d9" + integrity sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" @@ -933,21 +941,21 @@ esutils "^2.0.2" "@babel/preset-react@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.14.5.tgz#0fbb769513f899c2c56f3a882fa79673c2d4ab3c" - integrity sha512-XFxBkjyObLvBaAvkx1Ie95Iaq4S/GUEIrejyrntQ/VCMKUYvKLoyKxOBzJ2kjA3b6rC9/KL6KXfDC2GqvLiNqQ== + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.16.0.tgz#f71d3e8dff5218478011df037fad52660ee6d82a" + integrity sha512-d31IFW2bLRB28uL1WoElyro8RH5l6531XfxMtCeCmp6RVAF1uTfxxUA0LH1tXl+psZdwfmIbwoG4U5VwgbhtLw== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/helper-validator-option" "^7.14.5" - "@babel/plugin-transform-react-display-name" "^7.14.5" - "@babel/plugin-transform-react-jsx" "^7.14.5" - "@babel/plugin-transform-react-jsx-development" "^7.14.5" - "@babel/plugin-transform-react-pure-annotations" "^7.14.5" + "@babel/plugin-transform-react-display-name" "^7.16.0" + "@babel/plugin-transform-react-jsx" "^7.16.0" + "@babel/plugin-transform-react-jsx-development" "^7.16.0" + "@babel/plugin-transform-react-pure-annotations" "^7.16.0" -"@babel/register@^7.14.5", "@babel/register@^7.15.3": - version "7.15.3" - resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.15.3.tgz#6b40a549e06ec06c885b2ec42c3dd711f55fe752" - integrity sha512-mj4IY1ZJkorClxKTImccn4T81+UKTo4Ux0+OFSV9hME1ooqS9UV+pJ6BjD0qXPK4T3XW/KNa79XByjeEMZz+fw== +"@babel/register@^7.14.5", "@babel/register@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.16.0.tgz#f5d2aa14df37cf7146b9759f7c53818360f24ec6" + integrity sha512-lzl4yfs0zVXnooeLE0AAfYaT7F3SPA8yB2Bj4W1BiZwLbMS3MZH35ZvCWSRHvneUugwuM+Wsnrj7h0F7UmU3NQ== dependencies: clone-deep "^4.0.1" find-cache-dir "^2.0.0" @@ -955,49 +963,49 @@ pirates "^4.0.0" source-map-support "^0.5.16" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.13.8", "@babel/runtime@^7.14.0", "@babel/runtime@^7.14.6", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.4.tgz#fd17d16bfdf878e6dd02d19753a39fa8a8d9c84a" - integrity sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw== +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.13.8", "@babel/runtime@^7.14.0", "@babel/runtime@^7.14.6", "@babel/runtime@^7.15.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": + version "7.16.3" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.3.tgz#b86f0db02a04187a3c17caa77de69840165d42d5" + integrity sha512-WBwekcqacdY2e9AF/Q7WLFUWmdJGJTkbjqTjoMDgXkVZ3ZRUvOPsLb5KdwISoQVsbP+DQzVZW4Zhci0DvpbNTQ== dependencies: regenerator-runtime "^0.13.4" -"@babel/template@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.15.4.tgz#51898d35dcf3faa670c4ee6afcfd517ee139f194" - integrity sha512-UgBAfEa1oGuYgDIPM2G+aHa4Nlo9Lh6mGD2bDBGMTbYnc38vulXPuC1MGjYILIEmlwl6Rd+BPR9ee3gm20CBtg== - dependencies: - "@babel/code-frame" "^7.14.5" - "@babel/parser" "^7.15.4" - "@babel/types" "^7.15.4" - -"@babel/traverse@7", "@babel/traverse@^7.13.0", "@babel/traverse@^7.15.4", "@babel/traverse@^7.7.0": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.15.4.tgz#ff8510367a144bfbff552d9e18e28f3e2889c22d" - integrity sha512-W6lQD8l4rUbQR/vYgSuCAE75ADyyQvOpFVsvPPdkhf6lATXAsQIG9YdtOcu8BB1dZ0LKu+Zo3c1wEcbKeuhdlA== - dependencies: - "@babel/code-frame" "^7.14.5" - "@babel/generator" "^7.15.4" - "@babel/helper-function-name" "^7.15.4" - "@babel/helper-hoist-variables" "^7.15.4" - "@babel/helper-split-export-declaration" "^7.15.4" - "@babel/parser" "^7.15.4" - "@babel/types" "^7.15.4" +"@babel/template@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.0.tgz#d16a35ebf4cd74e202083356fab21dd89363ddd6" + integrity sha512-MnZdpFD/ZdYhXwiunMqqgyZyucaYsbL0IrjoGjaVhGilz+x8YB++kRfygSOIj1yOtWKPlx7NBp+9I1RQSgsd5A== + dependencies: + "@babel/code-frame" "^7.16.0" + "@babel/parser" "^7.16.0" + "@babel/types" "^7.16.0" + +"@babel/traverse@7", "@babel/traverse@^7.13.0", "@babel/traverse@^7.16.0", "@babel/traverse@^7.16.3", "@babel/traverse@^7.7.0": + version "7.16.3" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.16.3.tgz#f63e8a938cc1b780f66d9ed3c54f532ca2d14787" + integrity sha512-eolumr1vVMjqevCpwVO99yN/LoGL0EyHiLO5I043aYQvwOJ9eR5UsZSClHVCzfhBduMAsSzgA/6AyqPjNayJag== + dependencies: + "@babel/code-frame" "^7.16.0" + "@babel/generator" "^7.16.0" + "@babel/helper-function-name" "^7.16.0" + "@babel/helper-hoist-variables" "^7.16.0" + "@babel/helper-split-export-declaration" "^7.16.0" + "@babel/parser" "^7.16.3" + "@babel/types" "^7.16.0" debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.12.11", "@babel/types@^7.14.9", "@babel/types@^7.15.4", "@babel/types@^7.15.6", "@babel/types@^7.3.0", "@babel/types@^7.4.4", "@babel/types@^7.7.0": - version "7.15.6" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.15.6.tgz#99abdc48218b2881c058dd0a7ab05b99c9be758f" - integrity sha512-BPU+7QhqNjmWyDO0/vitH/CuhpV8ZmK1wpKva8nuyNF5MJfuRNWMc+hc14+u9xT93kvykMdncrJT19h74uB1Ig== +"@babel/types@^7.0.0", "@babel/types@^7.12.11", "@babel/types@^7.16.0", "@babel/types@^7.3.0", "@babel/types@^7.4.4", "@babel/types@^7.7.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.16.0.tgz#db3b313804f96aadd0b776c4823e127ad67289ba" + integrity sha512-PJgg/k3SdLsGb3hhisFvtLOw5ts113klrpLuIPtCJIU+BB24fqq6lf8RWqKJEjzqXR9AEH1rIb5XTqwBHB+kQg== dependencies: - "@babel/helper-validator-identifier" "^7.14.9" + "@babel/helper-validator-identifier" "^7.15.7" to-fast-properties "^2.0.0" "@discoveryjs/json-ext@^0.5.0": - version "0.5.5" - resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.5.tgz#9283c9ce5b289a3c4f61c12757469e59377f81f3" - integrity sha512-6nFkfkmSeV/rqSaS4oWHgmpnYw194f6hmWF5is6b0J1naJZoiD0NTc9AiUwPHvWsowkjuHErCZT1wa0jg+BLIA== + version "0.5.6" + resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz#d5e0706cf8c6acd8c6032f8d54070af261bbbb2f" + integrity sha512-ws57AidsDvREKrZKYffXddNkyaF14iHNHm8VQnZH6t99E8gczjNN0GpvcGny0imC80yQ0tHz1xVUKk/KFQSUyA== "@eslint/eslintrc@^0.4.3": version "0.4.3" @@ -1015,12 +1023,12 @@ strip-json-comments "^3.1.1" "@formatjs/cli@^4.2.21": - version "4.3.2" - resolved "https://registry.yarnpkg.com/@formatjs/cli/-/cli-4.3.2.tgz#dd7dea955d362284794bb48c6ee9ea50bd5b87eb" - integrity sha512-SCUvjCNZA4Y8SoDH5cBl6n/kk3T13SmbAkR1L9UQ+CdafRyab+P+WrDzgzybngmK3CzOqxoucDWd2xmDxEtOVw== + version "4.5.0" + resolved "https://registry.yarnpkg.com/@formatjs/cli/-/cli-4.5.0.tgz#27906f6bf2f29bc5fa2194ec897843755756fa73" + integrity sha512-WUo/QRCUwQ/bpEYtjpbhrM+Hi4UE7GBOTr5cHwbxwZL6+pTLkIOvod8ShsrZf+LmSTT64ZSwLIQaRAp12T5BSw== dependencies: - "@formatjs/icu-messageformat-parser" "2.0.13" - "@formatjs/ts-transformer" "3.5.1" + "@formatjs/icu-messageformat-parser" "2.0.15" + "@formatjs/ts-transformer" "3.7.0" "@types/estree" "^0.0.50" "@types/fs-extra" "^9.0.1" "@types/json-stable-stringify" "^1.0.32" @@ -1034,7 +1042,7 @@ json-stable-stringify "^1.0.1" loud-rejection "^2.2.0" tslib "^2.1.0" - typescript "^4.3" + typescript "^4.5" "@formatjs/ecma402-abstract@1.10.0": version "1.10.0" @@ -1044,6 +1052,14 @@ "@formatjs/intl-localematcher" "0.2.21" tslib "^2.1.0" +"@formatjs/ecma402-abstract@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@formatjs/ecma402-abstract/-/ecma402-abstract-1.11.0.tgz#7e91e6cc7cfebdc07171e00a3288719705e0108c" + integrity sha512-TOp5La9wmSh9G5bqFGN/ApmOXtJDzBGkYW+OTRd3ukY7J32RVGZPpN4O9BD651JUy66nj3g9CIENTNCgm4IRXQ== + dependencies: + "@formatjs/intl-localematcher" "0.2.21" + tslib "^2.1.0" + "@formatjs/fast-memoize@1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@formatjs/fast-memoize/-/fast-memoize-1.2.0.tgz#1123bfcc5d21d761f15d8b1c32d10e1b6530355d" @@ -1060,6 +1076,15 @@ "@formatjs/icu-skeleton-parser" "1.3.0" tslib "^2.1.0" +"@formatjs/icu-messageformat-parser@2.0.15": + version "2.0.15" + resolved "https://registry.yarnpkg.com/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.0.15.tgz#9e3ccadc582dbf076481bb95f98a689cfb10e7d5" + integrity sha512-nnRbkK+nz4ZL1l1lUbztL8qrEUGQKF/NU38itLnzLm8QLEacFS5qGOxxp/0DSIehhX99tNroNtudtjdOvzruAQ== + dependencies: + "@formatjs/ecma402-abstract" "1.11.0" + "@formatjs/icu-skeleton-parser" "1.3.2" + tslib "^2.1.0" + "@formatjs/icu-skeleton-parser@1.3.0": version "1.3.0" resolved "https://registry.yarnpkg.com/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.3.0.tgz#fedf604bf788a587b23c9a03ec148c1f2c3177f7" @@ -1068,6 +1093,14 @@ "@formatjs/ecma402-abstract" "1.10.0" tslib "^2.1.0" +"@formatjs/icu-skeleton-parser@1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.3.2.tgz#a8ab9c668ea7f044ceba2043ac1d872d71307e22" + integrity sha512-ChKmnVCE/LbJzedRgA/EeL5+tfjx/6ZWunqNiEC5BtqHnnwmLN/oPuCPb8b3NhuGiwTqp+LkaS70tga5kXRHxg== + dependencies: + "@formatjs/ecma402-abstract" "1.11.0" + tslib "^2.1.0" + "@formatjs/intl-displaynames@5.2.5": version "5.2.5" resolved "https://registry.yarnpkg.com/@formatjs/intl-displaynames/-/intl-displaynames-5.2.5.tgz#c8cb4983a3ce3bdc18d11e22cffc7dad9ceb3050" @@ -1094,20 +1127,20 @@ tslib "^2.1.0" "@formatjs/intl-pluralrules@^4.0.27": - version "4.1.5" - resolved "https://registry.yarnpkg.com/@formatjs/intl-pluralrules/-/intl-pluralrules-4.1.5.tgz#d4188ca83bfc4eddef183ec87feaad9c774e334f" - integrity sha512-CdxMiWzWZbPJLsVRBDMIoGGHUuqoRN+4R2Ic8dKn+oYjcr4AY1ESf+LKr6/M76JbRbb7/NxQzt9LllNttQt5Og== + version "4.1.6" + resolved "https://registry.yarnpkg.com/@formatjs/intl-pluralrules/-/intl-pluralrules-4.1.6.tgz#f452000de001f6540cfea01bd0f8c9eb7de9fa9a" + integrity sha512-pVo1x8nAC72SF2CBCLSa/3ec6e/6+UcgEJyJN67lsLmXePSwWeGv1Bn7FpNcvQJ7LxbmxAk/ErfuTa3ZM6UKFw== dependencies: - "@formatjs/ecma402-abstract" "1.10.0" + "@formatjs/ecma402-abstract" "1.11.0" "@formatjs/intl-localematcher" "0.2.21" tslib "^2.1.0" "@formatjs/intl-relativetimeformat@^9.1.6": - version "9.3.2" - resolved "https://registry.yarnpkg.com/@formatjs/intl-relativetimeformat/-/intl-relativetimeformat-9.3.2.tgz#783b6d61d76b433f35862b1ce7645000ca8abfee" - integrity sha512-WI1fCcPXGAVp10Dk3QziXuIqEo4VqnjJJ3uWgKxKSfMy7aVLHTD1ZWH+8M5egzkMQ4/Tyo2nkun9eIbiTjTqhg== + version "9.3.3" + resolved "https://registry.yarnpkg.com/@formatjs/intl-relativetimeformat/-/intl-relativetimeformat-9.3.3.tgz#dbef1103694393907297ee409424378cbb8354f1" + integrity sha512-+kPEHPEjTmLN32WoNmUQA62d/UT69s4qjE2BNt93HvwmQIbJiRmx12N3hq+8+OTi3MHq//pCPCZeGJIoySev9A== dependencies: - "@formatjs/ecma402-abstract" "1.10.0" + "@formatjs/ecma402-abstract" "1.11.0" "@formatjs/intl-localematcher" "0.2.21" tslib "^2.1.0" @@ -1124,16 +1157,16 @@ intl-messageformat "9.9.3" tslib "^2.1.0" -"@formatjs/ts-transformer@3.5.1": - version "3.5.1" - resolved "https://registry.yarnpkg.com/@formatjs/ts-transformer/-/ts-transformer-3.5.1.tgz#5039d052d61316134ebf1bba8b9054e8885ebc53" - integrity sha512-O3ESBBYZQRIsoyqdes5bj+GUwdGnwQRC5WO1CMiCdj9YMgIONrOyzFkNW/ZsB0vlHzTERBXeXvlWZuA0XWP0Eg== +"@formatjs/ts-transformer@3.7.0": + version "3.7.0" + resolved "https://registry.yarnpkg.com/@formatjs/ts-transformer/-/ts-transformer-3.7.0.tgz#eba02a640cfaa5f7abbbb2b88032e055a54da7e9" + integrity sha512-VfWryCzZErgU9e5zp4qQVNgwveMJETa8mGglKtCe4J+j/spnFa59oHqmhPos6eeMe3NV7PUdG9pDCPkDcUFVRA== dependencies: - "@formatjs/icu-messageformat-parser" "2.0.13" + "@formatjs/icu-messageformat-parser" "2.0.15" "@types/node" "14 || 16" chalk "^4.0.0" tslib "^2.1.0" - typescript "^4.3" + typescript "^4.5" "@fortawesome/fontawesome-common-types@^0.2.36": version "0.2.36" @@ -1190,9 +1223,9 @@ minimatch "^3.0.4" "@humanwhocodes/object-schema@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz#87de7af9c231826fdd68ac7258f77c429e0e5fcf" - integrity sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w== + version "1.2.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" + integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== "@iktakahiro/markdown-it-katex@^4.0.1": version "4.0.1" @@ -1233,9 +1266,9 @@ fastq "^1.6.0" "@popperjs/core@^2.8.6": - version "2.10.2" - resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.10.2.tgz#0798c03351f0dea1a5a4cabddf26a55a7cbee590" - integrity sha512-IXf3XA7+XyN7CP9gGh/XB0UxVMlvARGEgGXLubFICsUMGz6Q+DU+i4gGlpOxTjKvXjkJDJC8YdqdKkDj9qZHEQ== + version "2.11.0" + resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.0.tgz#6734f8ebc106a0860dff7f92bf90df193f0935d7" + integrity sha512-zrsUxjLOKAzdewIDRWy9nsV1GQsKBCWaGwsZQlCgr6/q+vjyZhFgqedLfFBuI9anTPEUT4APq9Mu0SZBTzIcGQ== "@restart/context@^2.1.4": version "2.1.4" @@ -1275,9 +1308,9 @@ integrity sha512-gAj8qNy/VYwQDBkACm0USM66kxFai8flX83ayRXPNhzZckEgSqIBB9sM74SCM3ssgeX+ZVy4BifTnLis+KpIyg== "@types/babel__core@*", "@types/babel__core@^7.1.7": - version "7.1.16" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.16.tgz#bc12c74b7d65e82d29876b5d0baf5c625ac58702" - integrity sha512-EAEHtisTMM+KaKwfWdC3oyllIqswlznXCIVCt7/oRNrh+DhgT4UEBNC/jlADNjvw7UnfbcdkGQcPVZ1xYiLcrQ== + version "7.1.17" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.17.tgz#f50ac9d20d64153b510578d84f9643f9a3afbe64" + integrity sha512-6zzkezS9QEIL8yCBvXWxPTJPNuMeECJVxSOhxNY/jfq9LxOTHivaYTqr37n9LknWWRTIkzqH2UilS5QFvfa90A== dependencies: "@babel/parser" "^7.1.0" "@babel/types" "^7.0.0" @@ -1323,9 +1356,9 @@ "@types/estree" "*" "@types/eslint@*": - version "7.28.1" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.28.1.tgz#50b07747f1f84c2ba8cd394cf0fe0ba07afce320" - integrity sha512-XhZKznR3i/W5dXqUhgU9fFdJekufbeBd5DALmkuXoeFcjbQcPk+2cL+WLHf6Q81HWAnM2vrslIHpGVyCAviRwg== + version "8.2.1" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.2.1.tgz#13f3d69bac93c2ae008019c28783868d0a1d6605" + integrity sha512-UP9rzNn/XyGwb5RQ2fok+DzcIRIYwc16qTXse5+Smsy8MOIccCChT15KAwnsgQx4PzJkaMq4myFyZ4CL5TjhIQ== dependencies: "@types/estree" "*" "@types/json-schema" "*" @@ -1343,9 +1376,9 @@ "@types/node" "*" "@types/glob@^7.1.1": - version "7.1.4" - resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.4.tgz#ea59e21d2ee5c517914cb4bc8e4153b99e566672" - integrity sha512-w+LsMxKyYQm347Otw+IfBXOv9UWVjpHpCDdbBMt8Kz/xbvCYNjP+0qPh91Km3iKfSRLBB0P7fAMf0KHrPu+MyA== + version "7.2.0" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb" + integrity sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA== dependencies: "@types/minimatch" "*" "@types/node" "*" @@ -1370,7 +1403,7 @@ resolved "https://registry.yarnpkg.com/@types/invariant/-/invariant-2.2.35.tgz#cd3ebf581a6557452735688d8daba6cf0bd5a3be" integrity sha512-DxX1V9P8zdJPYQat1gHyY0xj3efl8gnMVjiM9iCY6y27lj+PoQWkgjt8jDqmovPqULkKVpKRg8J36iQiA+EtEg== -"@types/json-schema@*", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8": +"@types/json-schema@*", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": version "7.0.9" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== @@ -1391,14 +1424,14 @@ integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ== "@types/node@*", "@types/node@14 || 16": - version "16.11.1" - resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.1.tgz#2e50a649a50fc403433a14f829eface1a3443e97" - integrity sha512-PYGcJHL9mwl1Ek3PLiYgyEKtwTMmkMw4vbiyz/ps3pfdRYLVv+SN7qHVAImrjdAXxgluDEw6Ph4lyv+m9UpRmA== + version "16.11.12" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.12.tgz#ac7fb693ac587ee182c3780c26eb65546a1a3c10" + integrity sha512-+2Iggwg7PxoO5Kyhvsq9VarmPbIelXP070HMImEpbtGCoyWNINQj4wzjbQCXzdHTRXnqufutJb5KAURZANNBAw== "@types/node@14": - version "14.17.27" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.17.27.tgz#5054610d37bb5f6e21342d0e6d24c494231f3b85" - integrity sha512-94+Ahf9IcaDuJTle/2b+wzvjmutxXAEXU6O81JHblYXUg2BDG+dnBy7VxIPHKAyEEDHzCMQydTJuWvrE+Aanzw== + version "14.18.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.0.tgz#98df2397f6936bfbff4f089e40e06fa5dd88d32a" + integrity sha512-0GeIl2kmVMXEnx8tg1SlG6Gg8vkqirrW752KqolYo1PHevhhZN3bhJ67qHj+bQaINhX0Ra3TlWwRvMCd9iEfNQ== "@types/parse-json@^4.0.0": version "4.0.0" @@ -1410,10 +1443,10 @@ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11" integrity sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ== -"@types/react-redux@^7.1.16": - version "7.1.19" - resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.19.tgz#477bd0a9b01bae6d6bf809418cdfa7d3c16d4c62" - integrity sha512-L37dSCT0aoJnCgpR8Iuginlbxoh7qhWOXiaDqEsxVMrER1CmVhFD+63NxgJeT4pkmEM28oX0NH4S4f+sXHTZjA== +"@types/react-redux@^7.1.20": + version "7.1.20" + resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.20.tgz#42f0e61ababb621e12c66c96dda94c58423bd7df" + integrity sha512-q42es4c8iIeTgcnB+yJgRTTzftv3eYYvCZOh1Ckn2eX/3o5TdsQYKUWpLoLuGlcY/p+VAhV9IOEZJcWk/vfkXw== dependencies: "@types/hoist-non-react-statics" "^3.3.0" "@types/react" "*" @@ -1421,16 +1454,16 @@ redux "^4.0.0" "@types/react-transition-group@^4.4.1": - version "4.4.3" - resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.3.tgz#b0994da0a7023d67dbb4a8910a62112bc00d5688" - integrity sha512-fUx5muOWSYP8Bw2BUQ9M9RK9+W1XBK/7FLJ8PTQpnpTEkn0ccyMffyEQvan4C3h53gHdx7KE5Qrxi/LnUGQtdg== + version "4.4.4" + resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.4.tgz#acd4cceaa2be6b757db61ed7b432e103242d163e" + integrity sha512-7gAPz7anVK5xzbeQW9wFBDg7G++aPLAFY0QaSMOou9rJZpbuI58WAuJrgu+qR92l61grlnCUe7AFX8KGahAgug== dependencies: "@types/react" "*" "@types/react@*", "@types/react@16 || 17", "@types/react@>=16.14.8", "@types/react@>=16.9.11": - version "17.0.30" - resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.30.tgz#2f8e6f5ab6415c091cc5e571942ee9064b17609e" - integrity sha512-3Dt/A8gd3TCXi2aRe84y7cK1K8G+N9CZRDG8kDGguOKa0kf/ZkSwTmVIDPsm/KbQOVMaDJXwhBtuOXxqwdpWVg== + version "17.0.37" + resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.37.tgz#6884d0aa402605935c397ae689deed115caad959" + integrity sha512-2FS1oTqBGcH/s0E+CjrCCR9+JMpsu9b69RTFO+40ua43ZqP5MmQ4iUde/dMjWR909KxZwmOQIFq6AV6NjEG5xg== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" @@ -1456,63 +1489,63 @@ resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== -"@vue/compiler-core@3.2.20", "@vue/compiler-core@^3.2.19": - version "3.2.20" - resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.2.20.tgz#af5a3c5237818835b0d0be837eb5885a8d21c160" - integrity sha512-vcEXlKXoPwBXFP5aUTHN9GTZaDfwCofa9Yu9bbW2C5O/QSa9Esdt7OG4+0RRd3EHEMxUvEdj4RZrd/KpQeiJbA== +"@vue/compiler-core@3.2.24", "@vue/compiler-core@^3.2.19": + version "3.2.24" + resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.2.24.tgz#cadcda0e026e7f1cd453ce87160be51a5f313fe0" + integrity sha512-A0SxB2HAggKzP57LDin5gfgWOTwFyGCtQ5MTMNBADnfQYALWnYuC8kMI0DhRSplGTWRvn9Z2DAnG8f35BnojuA== dependencies: "@babel/parser" "^7.15.0" - "@vue/shared" "3.2.20" + "@vue/shared" "3.2.24" estree-walker "^2.0.2" source-map "^0.6.1" -"@vue/compiler-dom@3.2.20": - version "3.2.20" - resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.2.20.tgz#8e0ef354449c0faf41519b00bfc2045eae01dcb5" - integrity sha512-QnI77ec/JtV7R0YBbcVayYTDCRcI9OCbxiUQK6izVyqQO0658n0zQuoNwe+bYgtqnvGAIqTR3FShTd5y4oOjdg== +"@vue/compiler-dom@3.2.24": + version "3.2.24" + resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.2.24.tgz#32235cb444660245be5cc58f4beb76747400505c" + integrity sha512-KQEm8r0JFsrNNIfbD28pcwMvHpcJcwjVR1XWFcD0yyQ8eREd7IXhT7J6j7iNCSE/TIo78NOvkwbyX+lnIm836w== dependencies: - "@vue/compiler-core" "3.2.20" - "@vue/shared" "3.2.20" + "@vue/compiler-core" "3.2.24" + "@vue/shared" "3.2.24" "@vue/compiler-sfc@^3.2.19": - version "3.2.20" - resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.2.20.tgz#2d7668e76f066c566dd7c09c15c9acce4e876e0a" - integrity sha512-03aZo+6tQKiFLfunHKSPZvdK4Jsn/ftRCyaro8AQIWkuxJbvSosbKK6HTTn+D2c3nPScG155akJoxKENw7rftQ== + version "3.2.24" + resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.2.24.tgz#803a309e1935fc85981218d88fd4fb5db05afdb1" + integrity sha512-YGPcIvVJp2qTPkuT6kT43Eo1xjstyY4bmuiSV31my4bQMBFVR26ANmifUSt759Blok71gK0WzfIZHbcOKYOeKA== dependencies: "@babel/parser" "^7.15.0" - "@vue/compiler-core" "3.2.20" - "@vue/compiler-dom" "3.2.20" - "@vue/compiler-ssr" "3.2.20" - "@vue/ref-transform" "3.2.20" - "@vue/shared" "3.2.20" + "@vue/compiler-core" "3.2.24" + "@vue/compiler-dom" "3.2.24" + "@vue/compiler-ssr" "3.2.24" + "@vue/ref-transform" "3.2.24" + "@vue/shared" "3.2.24" estree-walker "^2.0.2" magic-string "^0.25.7" postcss "^8.1.10" source-map "^0.6.1" -"@vue/compiler-ssr@3.2.20": - version "3.2.20" - resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.2.20.tgz#9cceb6261d9932cb5568202610c1c28f86c5e521" - integrity sha512-rzzVVYivm+EjbfiGQvNeyiYZWzr6Hkej97RZLZvcumacQlnKv9176Xo9rRyeWwFbBlxmtNdrVMslRXtipMXk2w== +"@vue/compiler-ssr@3.2.24": + version "3.2.24" + resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.2.24.tgz#edd0b7e7cd28d6c2578bb770ce0128bfdef9c948" + integrity sha512-E1HHShNsGVWXxs68LDOUuI+Bzak9W/Ier/366aKDBFuwvfwgruwq6abhMfj6pSDZpwZ/PXnfliyl/m7qBSq6gw== dependencies: - "@vue/compiler-dom" "3.2.20" - "@vue/shared" "3.2.20" + "@vue/compiler-dom" "3.2.24" + "@vue/shared" "3.2.24" -"@vue/ref-transform@3.2.20": - version "3.2.20" - resolved "https://registry.yarnpkg.com/@vue/ref-transform/-/ref-transform-3.2.20.tgz#2a59ec90caf8e5c7336776a0900bff0a8b81c090" - integrity sha512-Y42d3PGlYZ1lXcF3dbd3+qU/C/a3wYEZ949fyOI5ptzkjDWlkfU6vn74fmOjsLjEcjs10BXK2qO99FqQIK2r1Q== +"@vue/ref-transform@3.2.24": + version "3.2.24" + resolved "https://registry.yarnpkg.com/@vue/ref-transform/-/ref-transform-3.2.24.tgz#335bf06e0b25be16e7056cc4117c51a79f0c9122" + integrity sha512-j6oNbsGLvea2rF8GQB9w6q7UFL1So7J+t6ducaMeWPSyjYZ+slWpwPVK6mmyghg5oGqC41R+HC5BV036Y0KhXQ== dependencies: "@babel/parser" "^7.15.0" - "@vue/compiler-core" "3.2.20" - "@vue/shared" "3.2.20" + "@vue/compiler-core" "3.2.24" + "@vue/shared" "3.2.24" estree-walker "^2.0.2" magic-string "^0.25.7" -"@vue/shared@3.2.20": - version "3.2.20" - resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.20.tgz#53746961f731a8ea666e3316271e944238dc31db" - integrity sha512-FbpX+hD5BvXCQerEYO7jtAGHlhAkhTQ4KIV73kmLWNlawWhTiVuQxizgVb0BOkX5oG9cIRZ42EG++d/k/Efp0w== +"@vue/shared@3.2.24": + version "3.2.24" + resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.24.tgz#d74615e856013b17fb60b19b09d712729ad5e090" + integrity sha512-BUgRiZCkCrqDps5aQ9av05xcge3rn092ztKIh17tHkeEFgP4zfXMQWBA2zfdoCdCEdBL26xtOv+FZYiOp9RUDA== "@webassemblyjs/ast@1.11.1": version "1.11.1" @@ -1675,7 +1708,7 @@ accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7: mime-types "~2.1.24" negotiator "0.6.2" -ace-builds@^1.4.12: +ace-builds@^1.4.13: version "1.4.13" resolved "https://registry.yarnpkg.com/ace-builds/-/ace-builds-1.4.13.tgz#186f42d3849ebcc6a48b93088a058489897514c1" integrity sha512-SOLzdaQkY6ecPKYRDDg+MY1WoGgXA34cIvYJNNoBMGGUswHmlauU2Hy0UL96vW0Fs/LgFbMUjD+6vqzWTldIYQ== @@ -1718,9 +1751,9 @@ acorn@^7.0.0, acorn@^7.1.1, acorn@^7.4.0: integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== acorn@^8.4.1, acorn@^8.5.0: - version "8.5.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.5.0.tgz#4512ccb99b3698c752591e9bb4472e38ad43cee2" - integrity sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q== + version "8.6.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.6.0.tgz#e3692ba0eb1a0c83eaa4f37f5fa7368dd7142895" + integrity sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw== admin-lte@3.1.0: version "3.1.0" @@ -1804,11 +1837,25 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" +ajv-formats@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" + integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== + dependencies: + ajv "^8.0.0" + ajv-keywords@^3.5.2: version "3.5.2" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== +ajv-keywords@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" + integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== + dependencies: + fast-deep-equal "^3.1.3" + ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -1819,10 +1866,10 @@ ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^8.0.1: - version "8.6.3" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.6.3.tgz#11a66527761dc3e9a3845ea775d2d3c0414e8764" - integrity sha512-SMJOdDP6LqTkD0Uq8qLi+gMwSt0imXLSV080qFVwJCpH9U6Mb+SUGHAXM0KNbcBPguytWyvFxcHgMLe2D2XSpw== +ajv@^8.0.0, ajv@^8.0.1, ajv@^8.8.0: + version "8.8.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.8.2.tgz#01b4fef2007a28bf75f0b7fc009f62679de4abbb" + integrity sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw== dependencies: fast-deep-equal "^3.1.1" json-schema-traverse "^1.0.0" @@ -1964,7 +2011,7 @@ array.prototype.flat@^1.2.5: define-properties "^1.1.3" es-abstract "^1.19.0" -array.prototype.flatmap@^1.2.4: +array.prototype.flatmap@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.2.5.tgz#908dc82d8a406930fdf38598d51e7411d18d4446" integrity sha512-08u6rVyi1Lj7oqWbS9nUxliETrtIROT4XGTA4D/LWGten6E3ocm7cy9SIrmNHOL5XVbVuckUp3X6Xyg8/zpvHA== @@ -1979,9 +2026,9 @@ asap@~2.0.3: integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= asn1@~0.2.3: - version "0.2.4" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" - integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== + version "0.2.6" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" + integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== dependencies: safer-buffer "~2.1.0" @@ -2027,9 +2074,9 @@ async@^2.6.2: lodash "^4.17.14" async@^3.1.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/async/-/async-3.2.1.tgz#d3274ec66d107a47476a4c49136aacdb00665fc8" - integrity sha512-XdD5lRO/87udXCMC9meWdYiR+Nq6ZjUfXidViUZGu2F1MO4T3XwZ1et0hb2++BgLfhyJwy44BGB/yx80ABx8hg== + version "3.2.2" + resolved "https://registry.yarnpkg.com/async/-/async-3.2.2.tgz#2eb7671034bb2194d45d30e31e24ec7e7f9670cd" + integrity sha512-H0E+qZaDEfx/FY4t7iLRv1W2fFI6+pyCeTw1uN20AQPiwqwM6ojPxHxdLv4z8hi2DtnW9BOckSspLucW7pIE5g== asynckit@^0.4.0: version "0.4.0" @@ -2216,9 +2263,9 @@ babel-helper-replace-supers@^6.24.1: babel-types "^6.24.1" babel-loader@^8.2.2: - version "8.2.2" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.2.tgz#9363ce84c10c9a40e6c753748e1441b60c8a0b81" - integrity sha512-JvTd0/D889PQBtUXJ2PXaKU/pjZDMtHA9V2ecm+eNRmmBCMR09a+fmpGTNwnJtFmFl5Ei7Vy47LjBb+L0wQ99g== + version "8.2.3" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.3.tgz#8986b40f1a64cacfcb4b8429320085ef68b1342d" + integrity sha512-n4Zeta8NC3QAsuyiizu0GkmRcQ6clkV9WFUnUf1iXP//IeSKbWjofW3UHyZVwlOB4y039YQKefawyTn64Zwbuw== dependencies: find-cache-dir "^3.3.1" loader-utils "^1.4.0" @@ -2247,44 +2294,44 @@ babel-plugin-dynamic-import-node@^2.3.3: object.assign "^4.1.0" babel-plugin-formatjs@^10.3.0: - version "10.3.10" - resolved "https://registry.yarnpkg.com/babel-plugin-formatjs/-/babel-plugin-formatjs-10.3.10.tgz#27101c64050c8be35a07c3d5b56d5f903732f9b9" - integrity sha512-kAQKSovnOGhw3Xu9xx/HGvmV+ldrXp/pw+ldxDfU5S8M989TNOEH79z+vG5+qEJtvGVYD2tjpDRBQhDsxTXaUg== + version "10.3.12" + resolved "https://registry.yarnpkg.com/babel-plugin-formatjs/-/babel-plugin-formatjs-10.3.12.tgz#f15e69483b408b384689f32c9f6ea6bebb96bbb9" + integrity sha512-PR3wwfqt1LiSH3gR6ID+lfkr4N8oUtffT67GS7kT+2ME6phxIoA8NbrlJw/bTSsM0uGoAPfXu128EHvEGDWQlQ== dependencies: "@babel/core" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-jsx" "7" "@babel/traverse" "7" "@babel/types" "^7.12.11" - "@formatjs/icu-messageformat-parser" "2.0.13" - "@formatjs/ts-transformer" "3.5.1" + "@formatjs/icu-messageformat-parser" "2.0.15" + "@formatjs/ts-transformer" "3.7.0" "@types/babel__core" "^7.1.7" "@types/babel__helper-plugin-utils" "^7.10.0" tslib "^2.1.0" -babel-plugin-polyfill-corejs2@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.2.tgz#e9124785e6fd94f94b618a7954e5693053bf5327" - integrity sha512-kISrENsJ0z5dNPq5eRvcctITNHYXWOA4DUZRFYCz3jYCcvTb/A546LIddmoGNMVYg2U38OyFeNosQwI9ENTqIQ== +babel-plugin-polyfill-corejs2@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.0.tgz#407082d0d355ba565af24126fb6cb8e9115251fd" + integrity sha512-wMDoBJ6uG4u4PNFh72Ty6t3EgfA91puCuAwKIazbQlci+ENb/UU9A3xG5lutjUIiXCIn1CY5L15r9LimiJyrSA== dependencies: "@babel/compat-data" "^7.13.11" - "@babel/helper-define-polyfill-provider" "^0.2.2" + "@babel/helper-define-polyfill-provider" "^0.3.0" semver "^6.1.1" -babel-plugin-polyfill-corejs3@^0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.5.tgz#2779846a16a1652244ae268b1e906ada107faf92" - integrity sha512-ninF5MQNwAX9Z7c9ED+H2pGt1mXdP4TqzlHKyPIYmJIYz0N+++uwdM7RnJukklhzJ54Q84vA4ZJkgs7lu5vqcw== +babel-plugin-polyfill-corejs3@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.4.0.tgz#0b571f4cf3d67f911512f5c04842a7b8e8263087" + integrity sha512-YxFreYwUfglYKdLUGvIF2nJEsGwj+RhWSX/ije3D2vQPOXuyMLMtg/cCGMDpOA7Nd+MwlNdnGODbd2EwUZPlsw== dependencies: - "@babel/helper-define-polyfill-provider" "^0.2.2" - core-js-compat "^3.16.2" + "@babel/helper-define-polyfill-provider" "^0.3.0" + core-js-compat "^3.18.0" -babel-plugin-polyfill-regenerator@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.2.2.tgz#b310c8d642acada348c1fa3b3e6ce0e851bee077" - integrity sha512-Goy5ghsc21HgPDFtzRkSirpZVW35meGoTmTOb2bxqdl60ghub4xOidgNTHaZfQ2FaxQsKmwvXtOAkcIS4SMBWg== +babel-plugin-polyfill-regenerator@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.0.tgz#9ebbcd7186e1a33e21c5e20cae4e7983949533be" + integrity sha512-dhAPTDLGoMW5/84wkgwiLRwMnio2i1fUe53EuvtKMv0pn2p3S8OCoV1xAzfJPl0KOX7IB89s2ib85vbYiea3jg== dependencies: - "@babel/helper-define-polyfill-provider" "^0.2.2" + "@babel/helper-define-polyfill-provider" "^0.3.0" babel-plugin-syntax-async-functions@^6.8.0: version "6.13.0" @@ -2970,9 +3017,9 @@ bootstrap@>=4.0: integrity sha512-fcQztozJ8jToQWXxVuEyXWW+dSo8AiXWKwiSSrKWsRB/Qt+Ewwza+JWoLKiTuQLaEPhdNAJ7+Dosc9DOIqNy7Q== bootstrap@^4.5.2, bootstrap@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.6.0.tgz#97b9f29ac98f98dfa43bf7468262d84392552fd7" - integrity sha512-Io55IuQY3kydzHtbGvQya3H+KorS/M9rSNyfCGCg9WZ4pyT/lCxIlpJgG1GXW/PswzC84Tr2fBYi+7+jFVQQBw== + version "4.6.1" + resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.6.1.tgz#bc25380c2c14192374e8dec07cf01b2742d222a2" + integrity sha512-0dj+VgI9Ecom+rvvpNZ4MUZJz8dcX7WCX+eTID9+/8HgOkv3dsRzi8BGeZJCQU6flWQVYxwTQnEZFrmJSEO7og== brace-expansion@^1.1.7: version "1.1.11" @@ -3037,15 +3084,15 @@ browserify-optional@^1.0.0, browserify-optional@^1.0.1: ast-types "^0.7.0" browser-resolve "^1.8.1" -browserslist@^4.14.5, browserslist@^4.16.6, browserslist@^4.17.3: - version "4.17.4" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.17.4.tgz#72e2508af2a403aec0a49847ef31bd823c57ead4" - integrity sha512-Zg7RpbZpIJRW3am9Lyckue7PLytvVxxhJj1CaJVlCWENsGEAOlnlt8X0ZxGRPp7Bt9o8tIRM5SEXy4BCPMJjLQ== +browserslist@^4.14.5, browserslist@^4.17.5, browserslist@^4.18.1: + version "4.18.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.18.1.tgz#60d3920f25b6860eb917c6c7b185576f4d8b017f" + integrity sha512-8ScCzdpPwR2wQh8IT82CA2VgDwjHyqMovPBZSNH54+tm4Jk2pCuv90gmAdH6J84OCRWi0b4gMe6O6XPXuJnjgQ== dependencies: - caniuse-lite "^1.0.30001265" - electron-to-chromium "^1.3.867" + caniuse-lite "^1.0.30001280" + electron-to-chromium "^1.3.896" escalade "^3.1.1" - node-releases "^2.0.0" + node-releases "^2.0.1" picocolors "^1.0.0" bs-custom-file-input@^1.3.4: @@ -3167,14 +3214,14 @@ camelcase@^2.0.0: integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8= camelcase@^6.0.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" - integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== + version "6.2.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.1.tgz#250fd350cfd555d0d2160b1d51510eaf8326e86e" + integrity sha512-tVI4q5jjFV5CavAU8DXfza/TJcZutVKo/5Foskmsqcm0MsL91moHvwiGNnqaa2o6PF/7yT5ikDRcVcl8Rj6LCA== -caniuse-lite@^1.0.30001265: - version "1.0.30001269" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001269.tgz#3a71bee03df627364418f9fd31adfc7aa1cc2d56" - integrity sha512-UOy8okEVs48MyHYgV+RdW1Oiudl1H6KolybD6ZquD0VcrPSgj25omXO1S7rDydjpqaISCwA8Pyx+jUQKZwWO5w== +caniuse-lite@^1.0.30001280: + version "1.0.30001285" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001285.tgz#fe1e52229187e11d6670590790d669b9e03315b7" + integrity sha512-KAOkuUtcQ901MtmvxfKD+ODHH9YVDYnBt+TGYSz2KIfnq22CiArbUxXPN9067gNbgMlnNYRSwho8OPXZPALB9Q== caseless@~0.11.0: version "0.11.0" @@ -3282,7 +3329,7 @@ check-error@^1.0.2: resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= -chokidar@3.5.2, chokidar@^3.4.0, chokidar@^3.5.1: +chokidar@3.5.2, chokidar@^3.4.0, chokidar@^3.5.2: version "3.5.2" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75" integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ== @@ -3352,9 +3399,9 @@ clone@^1.0.4: integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= codemirror@^5.60.0, codemirror@^5.62.0: - version "5.63.3" - resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.63.3.tgz#97042a242027fe0c87c09b36bc01931d37b76527" - integrity sha512-1C+LELr+5grgJYqwZKqxrcbPsHFHapVaVAloBsFBASbpLnQqLw1U8yXJ3gT5D+rhxIiSpo+kTqN+hQ+9ialIXw== + version "5.64.0" + resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.64.0.tgz#182eec65b62178e3cd1de8f9d88ab819cfe5f625" + integrity sha512-fqr6CtDQdJ6iNMbD8NX2gH2G876nNDk+TO1rrYkgWnqQdO3O1Xa9tK6q+psqhJJgE5SpbaDcgdfLmukoUVE8pg== color-convert@^1.9.0, color-convert@^1.9.3: version "1.9.3" @@ -3398,9 +3445,9 @@ combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: delayed-stream "~1.0.0" commander@8: - version "8.2.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-8.2.0.tgz#37fe2bde301d87d47a53adeff8b5915db1381ca8" - integrity sha512-LLKxDvHeL91/8MIyTAD5BFMNtoIwztGPMiM/7Bl8rIPmHCZXRxmSWr91h57dpOpnQ6jIUqEWdXE/uBYMfiVZDA== + version "8.3.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" + integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== commander@^2.19.0, commander@^2.20.0, commander@^2.8.1: version "2.20.3" @@ -3495,11 +3542,11 @@ convert-source-map@^1.1.0, convert-source-map@^1.5.1, convert-source-map@^1.7.0: safe-buffer "~5.1.1" cookie-parser@^1.4.1: - version "1.4.5" - resolved "https://registry.yarnpkg.com/cookie-parser/-/cookie-parser-1.4.5.tgz#3e572d4b7c0c80f9c61daf604e4336831b5d1d49" - integrity sha512-f13bPUj/gG/5mDr+xLmSxxDsB9DQiTIfhJS/sqjrmfAWiAN+x2O4i/XguTL9yDZ+/IFDanJ+5x7hC4CXT9Tdzw== + version "1.4.6" + resolved "https://registry.yarnpkg.com/cookie-parser/-/cookie-parser-1.4.6.tgz#3ac3a7d35a7a03bbc7e365073a26074824214594" + integrity sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA== dependencies: - cookie "0.4.0" + cookie "0.4.1" cookie-signature "1.0.6" cookie-signature@1.0.6: @@ -3512,6 +3559,11 @@ cookie@0.4.0: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== +cookie@0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1" + integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== + copy-anything@^2.0.1: version "2.0.3" resolved "https://registry.yarnpkg.com/copy-anything/-/copy-anything-2.0.3.tgz#842407ba02466b0df844819bbe3baebbe5d45d87" @@ -3526,28 +3578,23 @@ copy-to-clipboard@^3: dependencies: toggle-selection "^1.0.6" -core-js-compat@^3.16.0, core-js-compat@^3.16.2: - version "3.18.3" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.18.3.tgz#e0e7e87abc55efb547e7fa19169e45fa9df27a67" - integrity sha512-4zP6/y0a2RTHN5bRGT7PTq9lVt3WzvffTNjqnTKsXhkAYNDTkdCLOIfAdOLcQ/7TDdyRj3c+NeHe1NmF1eDScw== +core-js-compat@^3.18.0, core-js-compat@^3.19.1: + version "3.19.3" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.19.3.tgz#de75e5821c5ce924a0a1e7b7d5c2cb973ff388aa" + integrity sha512-59tYzuWgEEVU9r+SRgceIGXSSUn47JknoiXW6Oq7RW8QHjXWz3/vp8pa7dbtuVu40sewz3OP3JmQEcDdztrLhA== dependencies: - browserslist "^4.17.3" + browserslist "^4.18.1" semver "7.0.0" -core-js@^0.8.3: - version "0.8.4" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-0.8.4.tgz#c22665f1e0d1b9c3c5e1b08dabd1f108695e4fcf" - integrity sha1-wiZl8eDRucPF4bCNq9HxCGleT88= - core-js@^2.4.0: version "2.6.12" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== -core-js@^3.0.0, core-js@^3.15.2, core-js@^3.16.0: - version "3.18.3" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.18.3.tgz#86a0bba2d8ec3df860fefcc07a8d119779f01509" - integrity sha512-tReEhtMReZaPFVw7dajMx0vlsz3oOb8ajgPoHVYGxr8ErnZ6PcYEvvmjGmXlfpnxpkYSdOQttjB+MvVbCGfvLw== +core-js@^3.0.0, core-js@^3.15.2, core-js@^3.19.0: + version "3.19.3" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.19.3.tgz#6df8142a996337503019ff3235a7022d7cdf4559" + integrity sha512-LeLBMgEGSsG7giquSzvgBrTS7V5UL6ks3eQlUSbN8dJStlLFiRzUm5iqsRyzUB8carhfKjkJ2vzKqE6z1Vga9g== core-util-is@1.0.2: version "1.0.2" @@ -3612,9 +3659,9 @@ crypto-js@^4.0.0: integrity sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw== css-loader@^6.3.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.4.0.tgz#01c57ea776024e18ca193428dcad3ff6b42a0130" - integrity sha512-Dlt6qfsxI/w1vU0r8qDd4BtMPxWqJeY5qQU7SmmZfvbpe6Xl18McO4GhyaMLns24Y2VNPiZwJPQ8JSbg4qvQLw== + version "6.5.1" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.5.1.tgz#0c43d4fbe0d97f699c91e9818cb585759091d1b1" + integrity sha512-gEy2w9AnJNnD9Kuo4XAP9VflW/ujKoS9c/syO+uWMlm5igc7LysKzPXaDoR2vroROkSwsTS2tGr1yGGEbZOYZQ== dependencies: icss-utils "^5.1.0" postcss "^8.2.15" @@ -3705,9 +3752,9 @@ cssstyle@^2.3.0: cssom "~0.3.6" csstype@^3.0.2: - version "3.0.9" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.9.tgz#6410af31b26bd0520933d02cbc64fce9ce3fbf0b" - integrity sha512-rpw6JPxK6Rfg1zLOYCSwle2GFOOsnjmDYDaBwEcwoOg4qlsIVCN789VkBZDJAGi4T07gI4YSutR43t9Zz4Lzuw== + version "3.0.10" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.10.tgz#2ad3a7bed70f35b965707c092e5f30b327c290e5" + integrity sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA== currently-unhandled@^0.4.1: version "0.4.1" @@ -3771,7 +3818,7 @@ datatables.net-autofill@>=2.3.7: datatables.net ">=1.10.25" jquery ">=1.7" -datatables.net-bs4@>=1.10.25, datatables.net-bs4@^1.10.15, datatables.net-bs4@^1.10.24: +datatables.net-bs4@>=1.10.25, datatables.net-bs4@>=1.11.3, datatables.net-bs4@^1.10.15, datatables.net-bs4@^1.10.24: version "1.11.3" resolved "https://registry.yarnpkg.com/datatables.net-bs4/-/datatables.net-bs4-1.11.3.tgz#04817c5d9457f1b9807a1330f12c37a541596328" integrity sha512-UPT2F1nvZZzKJSSHb+3+bTeQy1ULLMT1BexBHCkh5PhMnAZNPbTEZD+6To1RCBfUF1rtPwIJTwJ+Jjjxy86xRw== @@ -3797,20 +3844,20 @@ datatables.net-buttons@1.7.1: jquery ">=1.7" datatables.net-colreorder-bs4@^1.5.3: - version "1.5.4" - resolved "https://registry.yarnpkg.com/datatables.net-colreorder-bs4/-/datatables.net-colreorder-bs4-1.5.4.tgz#9fbdb86462e36bd508b0aa8a610db7b416a44cc8" - integrity sha512-k4qDgJTyN2pkhtuFIWSaGMT1EmC6e++CYzVz2CwZjnrOcK5pCnCSX8tN2ZCx5KAf9bvMAxDeHTSY1Uvl++MPTA== + version "1.5.5" + resolved "https://registry.yarnpkg.com/datatables.net-colreorder-bs4/-/datatables.net-colreorder-bs4-1.5.5.tgz#52ca2f95148572583ad619d6c9cdb44f1952d355" + integrity sha512-MGAJ/k/FeSK2Kccio5k0oBRacBpmaIKP2wXYfC64ONZFjOFxKBSmFevfg7yPdipYdYDwoQqDnmw0MpdIL7UUug== dependencies: - datatables.net-bs4 "^1.10.15" - datatables.net-colreorder "1.5.4" + datatables.net-bs4 ">=1.11.3" + datatables.net-colreorder ">=1.5.4" jquery ">=1.7" -datatables.net-colreorder@1.5.4: - version "1.5.4" - resolved "https://registry.yarnpkg.com/datatables.net-colreorder/-/datatables.net-colreorder-1.5.4.tgz#60f9a937c46bbc77c4fd1c909d746238daa0c1d2" - integrity sha512-Y9J2DvjBiFw/ADRce7aSaWhLN9yea9ZxK5FA8MDoLmMXtAR7AnKoe0XoTXAPD5aoHCUMiQKEt91qU7CT05KhEg== +datatables.net-colreorder@>=1.5.4: + version "1.5.5" + resolved "https://registry.yarnpkg.com/datatables.net-colreorder/-/datatables.net-colreorder-1.5.5.tgz#0de93e460cba5eb0167c0c491a2da0c76a2e3b12" + integrity sha512-AUwv5A/87I4hg7GY/WbhRrDhqng9b019jLvvKutHibSPCEtMDWqyNtuP0q8zYoquqU9UQ1/nqXLW/ld8TzIDYQ== dependencies: - datatables.net "^1.10.15" + datatables.net ">=1.11.3" jquery ">=1.7" datatables.net-fixedcolumns-bs4@^3.3.2: @@ -3882,20 +3929,20 @@ datatables.net-responsive@2.2.9: jquery ">=1.7" datatables.net-rowgroup-bs4@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/datatables.net-rowgroup-bs4/-/datatables.net-rowgroup-bs4-1.1.3.tgz#f040377a2303610f0ddf41c5f8e5503d9509f0f4" - integrity sha512-NObGthHYZXy2IewkEApO02W1LKeDf6dAFZS5VH0KgMTJqslJkQNxgczoEJT/ZZI36mFjhvBGkghN6cqqWP6V3g== + version "1.1.4" + resolved "https://registry.yarnpkg.com/datatables.net-rowgroup-bs4/-/datatables.net-rowgroup-bs4-1.1.4.tgz#dd4fad888edea895acd06fe8cf66816809d78eec" + integrity sha512-D0+LxraRjvV1RpPNtXJuW9Z4Jn90Sykb7ytJC/5eJsEYc9WnLUvxWEok7fqPpl3dWphQKg5ZbWpKG55Gd1IIXA== dependencies: - datatables.net-bs4 "^1.10.15" - datatables.net-rowgroup "1.1.3" + datatables.net-bs4 ">=1.11.3" + datatables.net-rowgroup ">=1.1.3" jquery ">=1.7" -datatables.net-rowgroup@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/datatables.net-rowgroup/-/datatables.net-rowgroup-1.1.3.tgz#64ee0fbe1a64fb54cc2991fc8b1ddb4e5cf94d6b" - integrity sha512-gGxPFVYKr/WXAi3HFy6Q0wIP8GrWnZTatt98bdcOs2yS7PjL/FlPECFDnMbkLMjVTXrKeZweKRqrpQeL8NmVNw== +datatables.net-rowgroup@>=1.1.3: + version "1.1.4" + resolved "https://registry.yarnpkg.com/datatables.net-rowgroup/-/datatables.net-rowgroup-1.1.4.tgz#3eea91951d46f6c207d2e0c03cb3d635b7b09689" + integrity sha512-Oe9mL3X8RXLOQZblJVWTYD0melyw3xoPeQ3T2x1k2guTFxob8/2caKuzn95oFJau6tvbhsvY/QneTaCzHRKnnQ== dependencies: - datatables.net "^1.10.15" + datatables.net ">=1.11.3" jquery ">=1.7" datatables.net-rowreorder-bs4@^1.2.7: @@ -3933,20 +3980,20 @@ datatables.net-scroller@>=2.0.4: jquery ">=1.7" datatables.net-searchbuilder-bs4@^1.0.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/datatables.net-searchbuilder-bs4/-/datatables.net-searchbuilder-bs4-1.2.2.tgz#b515fa41e9622af72b9085832a48fe31423f58e2" - integrity sha512-iyWWmIYCMRLxEgGhUMhYGoBhLkdo+Ai+ZBQN/znvjxD/zNpA1PBAxT7Gi+GJ3L+qKRWd1HNwpyIbVZpA8Lc5uQ== + version "1.3.0" + resolved "https://registry.yarnpkg.com/datatables.net-searchbuilder-bs4/-/datatables.net-searchbuilder-bs4-1.3.0.tgz#985ca63aaea8a4f6655161f55da966198c8ba047" + integrity sha512-rFEQzL4C09upfv19Bqfy9MA9Tw4Zaj1xnqN0UtRFnOtnXLkg0kTKYr6XRQJ26EllR/73VGE1PFkl6URES4MbiQ== dependencies: - datatables.net-bs4 ">=1.10.25" - datatables.net-searchbuilder ">=1.1.0" + datatables.net-bs4 ">=1.11.3" + datatables.net-searchbuilder ">=1.2.2" jquery ">=1.7" -datatables.net-searchbuilder@>=1.1.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/datatables.net-searchbuilder/-/datatables.net-searchbuilder-1.2.2.tgz#903bea1412f7c5347f40bc93eeae21cc13b0d12e" - integrity sha512-19t5c/05xMi5703Iv9lCrrJKBEHBgjYCCQHdx17ar9Cdd2iHD5Z6VpV9b6Z9M5c/Cqdke+9TMYnZOuSnVLNxjA== +datatables.net-searchbuilder@>=1.2.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/datatables.net-searchbuilder/-/datatables.net-searchbuilder-1.3.0.tgz#0c60f0b7edd3032401b74640bdfe17a715991d7f" + integrity sha512-qks7lT8Rxeh/D7N7xlZLqKzO4CE3j+dHU+J0v8CqV4/6XIIRs+NROi+3/jmtwkx6GbdzYtRNHuOTCAVH4lQ6ZA== dependencies: - datatables.net ">=1.10.25" + datatables.net ">=1.11.3" jquery ">=1.7" datatables.net-searchpanes-bs4@^1.2.2: @@ -3983,7 +4030,7 @@ datatables.net-select@1.3.3: datatables.net "^1.10.15" jquery ">=1.7" -datatables.net@>=1.10.25, datatables.net@^1.10.15, datatables.net@^1.10.24: +datatables.net@>=1.10.25, datatables.net@>=1.11.3, datatables.net@^1.10.15, datatables.net@^1.10.24: version "1.11.3" resolved "https://registry.yarnpkg.com/datatables.net/-/datatables.net-1.11.3.tgz#80e691036efcd62467558ee64c07dd566cb761b4" integrity sha512-VMj5qEaTebpNurySkM6jy6sGpl+s6onPK8xJhYr296R/vUBnz1+id16NVqNf9z5aR076OGcpGHCuiTuy4E05oQ== @@ -4005,7 +4052,14 @@ debug@2.6.9, debug@^2.2.0, debug@^2.6.8, debug@^2.6.9: dependencies: ms "2.0.0" -debug@4, debug@4.3.2, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: +debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: + version "4.3.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" + integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== + dependencies: + ms "2.1.2" + +debug@4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== @@ -4144,7 +4198,7 @@ deep-is@^0.1.3, deep-is@~0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== -default-gateway@^6.0.0: +default-gateway@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71" integrity sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg== @@ -4293,9 +4347,9 @@ domexception@^4.0.0: webidl-conversions "^7.0.0" domhandler@^4.2.0: - version "4.2.2" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.2.2.tgz#e825d721d19a86b8c201a35264e226c678ee755f" - integrity sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w== + version "4.3.0" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.0.tgz#16c658c626cf966967e306f966b431f77d4a5626" + integrity sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g== dependencies: domelementtype "^2.2.0" @@ -4390,10 +4444,10 @@ ekko-lightbox@^5.3.0: resolved "https://registry.yarnpkg.com/ekko-lightbox/-/ekko-lightbox-5.3.0.tgz#fbfcd9df93a8d1cdbf8770adc8c05aaac4d24f56" integrity sha512-mbacwySuVD3Ad6F2hTkjSTvJt59bcVv2l/TmBerp4xZnLak8tPtA4AScUn4DL42c1ksTiAO6sGhJZ52P/1Qgew== -electron-to-chromium@^1.3.867: - version "1.3.872" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.872.tgz#2311a82f344d828bab6904818adc4afb57b35369" - integrity sha512-qG96atLFY0agKyEETiBFNhpRLSXGSXOBuhXWpbkYqrLKKASpRyRBUtfkn0ZjIf/yXfA7FA4nScVOMpXSHFlUCQ== +electron-to-chromium@^1.3.896: + version "1.4.13" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.13.tgz#6b8a21a71c6f30b4a4def54d3afe94e0ddbc58b3" + integrity sha512-ih5tIhzEuf78pBY70FXLo+Pw73R5MPPPcXb4CGBMJaCQt/qo/IGIesKXmswpemVCKSE2Bulr5FslUv7gAWJoOw== emoji-regex@^8.0.0: version "8.0.0" @@ -4660,7 +4714,7 @@ eslint-import-resolver-node@^0.3.6: debug "^3.2.7" resolve "^1.20.0" -eslint-module-utils@^2.7.0: +eslint-module-utils@^2.7.1: version "2.7.1" resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.1.tgz#b435001c9f8dd4ab7f6d0efcae4b9696d4c24b7c" integrity sha512-fjoetBXQZq2tSTWZ9yWVl2KuFrTZZH3V+9iD1V1RfpDgxzJR+mPd/KZmMiA8gbPqdBzpNiEHOuT7IYEWxrH0zQ== @@ -4685,18 +4739,18 @@ eslint-plugin-es@^3.0.0: regexpp "^3.0.0" eslint-plugin-import@^2.23.4: - version "2.25.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.25.2.tgz#b3b9160efddb702fc1636659e71ba1d10adbe9e9" - integrity sha512-qCwQr9TYfoBHOFcVGKY9C9unq05uOxxdklmBXLVvcwo68y5Hta6/GzCZEMx2zQiu0woKNEER0LE7ZgaOfBU14g== + version "2.25.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.25.3.tgz#a554b5f66e08fb4f6dc99221866e57cfff824766" + integrity sha512-RzAVbby+72IB3iOEL8clzPLzL3wpDrlwjsTBAQXgyp5SeTqqY+0bFubwuo+y/HLhNZcXV4XqTBO4LGsfyHIDXg== dependencies: array-includes "^3.1.4" array.prototype.flat "^1.2.5" debug "^2.6.9" doctrine "^2.1.0" eslint-import-resolver-node "^0.3.6" - eslint-module-utils "^2.7.0" + eslint-module-utils "^2.7.1" has "^1.0.3" - is-core-module "^2.7.0" + is-core-module "^2.8.0" is-glob "^4.0.3" minimatch "^3.0.4" object.values "^1.1.5" @@ -4716,29 +4770,29 @@ eslint-plugin-node@11.1.0: semver "^6.1.0" eslint-plugin-promise@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-5.1.0.tgz#fb2188fb734e4557993733b41aa1a688f46c6f24" - integrity sha512-NGmI6BH5L12pl7ScQHbg7tvtk4wPxxj8yPHH47NvSmMtFneC077PSeY3huFj06ZWZvtbfxSPt3RuOQD5XcR4ng== + version "5.2.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-5.2.0.tgz#a596acc32981627eb36d9d75f9666ac1a4564971" + integrity sha512-SftLb1pUG01QYq2A/hGAWfDRXqYD82zE7j7TopDOyNdU+7SvvoXREls/+PRTY17vUXzXnZA/zfnyKgRH6x4JJw== eslint-plugin-react@^7.24.0: - version "7.26.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.26.1.tgz#41bcfe3e39e6a5ac040971c1af94437c80daa40e" - integrity sha512-Lug0+NOFXeOE+ORZ5pbsh6mSKjBKXDXItUD2sQoT+5Yl0eoT82DqnXeTMfUare4QVCn9QwXbfzO/dBLjLXwVjQ== + version "7.27.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.27.1.tgz#469202442506616f77a854d91babaae1ec174b45" + integrity sha512-meyunDjMMYeWr/4EBLTV1op3iSG3mjT/pz5gti38UzfM4OPpNc2m0t2xvKCOMU5D6FSdd34BIMFOvQbW+i8GAA== dependencies: - array-includes "^3.1.3" - array.prototype.flatmap "^1.2.4" + array-includes "^3.1.4" + array.prototype.flatmap "^1.2.5" doctrine "^2.1.0" - estraverse "^5.2.0" + estraverse "^5.3.0" jsx-ast-utils "^2.4.1 || ^3.0.0" minimatch "^3.0.4" - object.entries "^1.1.4" - object.fromentries "^2.0.4" - object.hasown "^1.0.0" - object.values "^1.1.4" + object.entries "^1.1.5" + object.fromentries "^2.0.5" + object.hasown "^1.1.0" + object.values "^1.1.5" prop-types "^15.7.2" resolve "^2.0.0-next.3" semver "^6.3.0" - string.prototype.matchall "^4.0.5" + string.prototype.matchall "^4.0.6" eslint-plugin-standard@^5.0.0: version "5.0.0" @@ -4859,10 +4913,10 @@ estraverse@^4.1.1, estraverse@^4.2.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== -estraverse@^5.1.0, estraverse@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" - integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== +estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== estraverse@~1.5.0: version "1.5.1" @@ -5070,9 +5124,9 @@ extsprintf@1.3.0: integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= extsprintf@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= + version "1.4.1" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" + integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" @@ -5106,9 +5160,9 @@ fast-memoize@^2.5.1: integrity sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw== fast-xml-parser@^3.19.0: - version "3.20.3" - resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-3.20.3.tgz#c171425356d4d929efeca4e4f67f24231a31c786" - integrity sha512-FfHJ/QCpo4K2gquBX7dIAcmShSBG4dMtYJ3ghSiR4w7YqlUujuamrM57C+mKLNWS3mvZzmm2B2Qx8Q6Gfw+lDQ== + version "3.21.1" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-3.21.1.tgz#152a1d51d445380f7046b304672dd55d15c9e736" + integrity sha512-FTFVjYoBOZTJekiUsawGsSYV9QL0A+zDYCRj7y34IO6Jg+2IMYEtQa+bbictpdpV8dHxXywqU7C0gRDEOFtBFg== dependencies: strnum "^1.0.4" @@ -5365,9 +5419,9 @@ flat@^5.0.2: integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== flatted@^3.1.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.2.tgz#64bfed5cb68fe3ca78b3eb214ad97b63bedce561" - integrity sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA== + version "3.2.4" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.4.tgz#28d9969ea90661b5134259f312ab6aa7929ac5e2" + integrity sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw== flot@^4.2.2: version "4.2.2" @@ -5375,9 +5429,9 @@ flot@^4.2.2: integrity sha512-Strct/A27o0TA25X7Z0pxKhwK4djiP1Kjeqj0tkiqrkRu1qYPqfbp5BYuxEL8CWDNtj85Uc0PnG2E2plo1+VMg== follow-redirects@^1.0.0: - version "1.14.4" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.4.tgz#838fdf48a8bbdd79e52ee51fb1c94e3ed98b9379" - integrity sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g== + version "1.14.5" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.5.tgz#f09a5848981d3c772b5392309778523f8d85c381" + integrity sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA== font-awesome-animation@^1.1.1: version "1.1.1" @@ -5503,9 +5557,9 @@ fsevents@~2.3.2: integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== fullcalendar@^5.5.1: - version "5.10.0" - resolved "https://registry.yarnpkg.com/fullcalendar/-/fullcalendar-5.10.0.tgz#41b34abdc9922b987d51dd879a8a46ebc508d981" - integrity sha512-gl1szCz8c9R8idqDM2eurDPvoXg0z7BqhVIxZPNsD4r4GVG2mpidD6tiPeBXMlmWM6J1IJctUXdnveN1ckDwJg== + version "5.10.1" + resolved "https://registry.yarnpkg.com/fullcalendar/-/fullcalendar-5.10.1.tgz#b3fd67ed1698df05d6bd0516d81bbf2f45a872da" + integrity sha512-0jgDxiWRuC36MzAUK3+Equmu4R0+vAPEtttsXLX9GNNDUHEZ5HjcH+dUtWut4vlJtxGJgVZ+eZ76/7qhcu+RMA== function-bind@^1.1.1: version "1.1.1" @@ -5613,9 +5667,9 @@ getpass@^0.1.1: assert-plus "^1.0.0" gifsicle@^5.0.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/gifsicle/-/gifsicle-5.2.1.tgz#efadab266a493ef0b4178e34597493349937369e" - integrity sha512-9ewIQQCAnSmkU2DhuWafd1DdsgzAkKqIWnY+023xBLSiK9Az2TDUozWQW+SyRQgFMclbe6RQldUk/49TRO3Aqw== + version "5.3.0" + resolved "https://registry.yarnpkg.com/gifsicle/-/gifsicle-5.3.0.tgz#499713c6f1e89ebbc3630da3a74fdb4697913b4e" + integrity sha512-FJTpgdj1Ow/FITB7SVza5HlzXa+/lqEY0tHQazAJbuAdvyJtkH4wIdsR2K414oaTwRXHFLLF+tYbipj+OpYg+Q== dependencies: bin-build "^3.0.0" bin-wrapper "^4.0.0" @@ -5681,9 +5735,9 @@ globals@^11.1.0: integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== globals@^13.6.0, globals@^13.9.0: - version "13.11.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.11.0.tgz#40ef678da117fe7bd2e28f1fab24951bd0255be7" - integrity sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g== + version "13.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.12.0.tgz#4d733760304230a0082ed96e21e5c565f898089e" + integrity sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg== dependencies: type-fest "^0.20.2" @@ -5957,9 +6011,9 @@ http-errors@~1.7.2: toidentifier "1.0.0" http-parser-js@>=0.5.1: - version "0.5.3" - resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.3.tgz#01d2709c79d41698bb01d4decc5e9da4e4a033d9" - integrity sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg== + version "0.5.5" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.5.tgz#d7c30d5d3c90d865b4a2e870181f9d6f22ac7ac5" + integrity sha512-x+JVEkO2PoM8qqpbPbOL3cqHPwerep7OwzK7Ay+sMQjKzaKCqWvjoXm5tqMP9tXWWTnTzAjIhXg+J99XYuPhPA== http-proxy-agent@^5.0.0: version "5.0.0" @@ -6069,9 +6123,9 @@ ignore@^4.0.6: integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== ignore@^5.1.1, ignore@^5.1.4: - version "5.1.8" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" - integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== + version "5.1.9" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.9.tgz#9ec1a5cbe8e1446ec60d4420060d43aa6e7382fb" + integrity sha512-2zeMQpbKz5dhZ9IwL0gbxSW5w0NK/MSAMtNuhgIHEPmaU3vPdKPL0UdvUCXs5SS4JAwsBxysK5sFMW8ocFiVjQ== image-size@~0.5.0: version "0.5.5" @@ -6246,16 +6300,6 @@ inputmask@^5.0.5: resolved "https://registry.yarnpkg.com/inputmask/-/inputmask-5.0.6.tgz#c537a197b0c15ff926db4c2ea654f9768015b1c4" integrity sha512-/QjZuOEB7fJKMEu3xKL3LlycctMmK53Zr/fGSFtcjrfYxXks93iptutYowWNR1oUsHr2QIzy6V3MMYz07P2Cfw== -internal-ip@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-6.2.0.tgz#d5541e79716e406b74ac6b07b856ef18dc1621c1" - integrity sha512-D8WGsR6yDt8uq7vDMu7mjcR+yRMm3dW8yufyChmszWRjcSHuxLBkR3GdS2HZAjodsaGuCvXeEJpueisXJULghg== - dependencies: - default-gateway "^6.0.0" - ipaddr.js "^1.9.1" - is-ip "^3.1.0" - p-event "^4.2.0" - internal-slot@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" @@ -6299,17 +6343,12 @@ ion-rangeslider@^2.3.1: resolved "https://registry.yarnpkg.com/ion-rangeslider/-/ion-rangeslider-2.3.1.tgz#92ade52cb56fc30b9162d0483ff02b6f9ed237c2" integrity sha512-6V+24FD13/feliI485gnRHZYD9Ev64M5NAFTxnVib516ATHa9PlXQrC+nOiPngouRYTCLPJyokAJEi3e1Umi5g== -ip-regex@^4.0.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-4.3.0.tgz#687275ab0f57fa76978ff8f4dddc8a23d5990db5" - integrity sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q== - ip@^1.1.0: version "1.1.5" resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= -ipaddr.js@1.9.1, ipaddr.js@^1.9.1: +ipaddr.js@1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== @@ -6364,7 +6403,7 @@ is-callable@^1.1.4, is-callable@^1.2.4: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== -is-core-module@^2.2.0, is-core-module@^2.7.0: +is-core-module@^2.2.0, is-core-module@^2.8.0: version "2.8.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.0.tgz#0321336c3d0925e497fd97f5d95cb114a5ccd548" integrity sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw== @@ -6419,13 +6458,6 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" -is-ip@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-ip/-/is-ip-3.1.0.tgz#2ae5ddfafaf05cb8008a62093cf29734f657c5d8" - integrity sha512-35vd5necO7IitFPjd/YBeqwWnyDWbuLH9ZXQdMfDA8TEo7pv5X8yfrvVO3xbJbLUlERCMvf6X0hTUamQxCYJ9Q== - dependencies: - ip-regex "^4.0.0" - is-jpg@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-jpg/-/is-jpg-2.0.0.tgz#2e1997fa6e9166eaac0242daae443403e4ef1d97" @@ -6556,9 +6588,9 @@ is-subset@^0.1.1: integrity sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY= is-svg@^4.2.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-4.3.1.tgz#8c63ec8c67c8c7f0a8de0a71c8c7d58eccf4406b" - integrity sha512-h2CGs+yPUyvkgTJQS9cJzo9lYK06WgRiXUqBBHtglSzVKAuH4/oWsqk7LGfbSa1hGk9QcZ0SyQtVggvBA8LZXA== + version "4.3.2" + resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-4.3.2.tgz#a119e9932e1af53f6be1969d1790d6cc5fd947d3" + integrity sha512-mM90duy00JGMyjqIVHu9gNTjywdZV+8qNasX8cm/EEYZ53PHDgajvbBwNVvty5dwSAxLUD3p3bdo+7sR/UMrpw== dependencies: fast-xml-parser "^3.19.0" @@ -6682,9 +6714,9 @@ jake@^10.6.1: minimatch "^3.0.4" jest-worker@^27.0.6: - version "27.3.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.3.0.tgz#6b636b63b6672208b91b92d8dcde112d1d4dba2d" - integrity sha512-xTTvvJqOjKBqE1AmwDHiQN8qzp9VoT981LtfXA+XiJVxHn4435vpnrzVcJ6v/ESiuB+IXPjZakn/ppT00xBCWA== + version "27.4.2" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.4.2.tgz#0fb123d50955af1a450267787f340a1bf7e12bc4" + integrity sha512-0QMy/zPovLfUPyHuOuuU4E+kGACXXE84nRnq6lBVI9GJg5DCBiA97SATi+ZP8CpiJwEQy1oCPjRBf8AnLjN+Ag== dependencies: "@types/node" "*" merge-stream "^2.0.0" @@ -6763,9 +6795,9 @@ jsbn@~0.1.0: integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= jsdom@^18.0.0: - version "18.0.0" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-18.0.0.tgz#0fa974638cd26dfc33f0d84c7526d0a3e5df5dc8" - integrity sha512-HVLuBcFmwdWulStv5U+J59b1AyzXhM92KXlM8HQ3ecYtRM2OQEUCPMa4oNuDeCBmtRcC7tJvb0Xz5OeFXMOKTA== + version "18.1.1" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-18.1.1.tgz#15ec896f5ab7df9669a62375606f47c8c09551aa" + integrity sha512-NmJQbjQ/gpS/1at/ce3nCx89HbXL/f5OcenBe8wU1Eik0ROhyUc3LtmG3567dEHAGXkN8rmILW/qtCOPxPHQJw== dependencies: abab "^2.0.5" acorn "^8.5.0" @@ -6840,10 +6872,10 @@ json-schema-traverse@^1.0.0: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== -json-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= +json-schema@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" + integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" @@ -6903,13 +6935,13 @@ jsonify@~0.0.0: integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= jsprim@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= + version "1.4.2" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" + integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== dependencies: assert-plus "1.0.0" extsprintf "1.3.0" - json-schema "0.2.3" + json-schema "0.4.0" verror "1.10.0" "jsx-ast-utils@^2.4.1 || ^3.0.0": @@ -6978,10 +7010,10 @@ klaw@^1.0.0: optionalDependencies: graceful-fs "^4.1.9" -klona@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.4.tgz#7bb1e3affb0cb8624547ef7e8f6708ea2e39dfc0" - integrity sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA== +klona@^2.0.4, klona@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.5.tgz#d166574d90076395d9963aa7a928fabb8d76afbc" + integrity sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ== lazy-cache@^1.0.3: version "1.0.4" @@ -7045,9 +7077,9 @@ linebreak@^1.0.2: unicode-trie "^1.0.0" lines-and-columns@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" - integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== linkify-it@^3.0.1: version "3.0.3" @@ -7092,9 +7124,9 @@ loader-utils@^1.2.3, loader-utils@^1.4.0: json5 "^1.0.1" loader-utils@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.0.tgz#e4cace5b816d425a166b5f097e10cd12b36064b0" - integrity sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ== + version "2.0.2" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.2.tgz#d6e3b4fb81870721ae4e0868ab11dd638368c129" + integrity sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A== dependencies: big.js "^5.2.2" emojis-list "^3.0.0" @@ -7130,11 +7162,6 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" -lodash.clonedeep@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" - integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= - lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" @@ -7203,7 +7230,7 @@ log-symbols@4.1.0: chalk "^4.1.0" is-unicode-supported "^0.1.0" -logalot@^2.0.0, logalot@^2.1.0: +logalot@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/logalot/-/logalot-2.1.0.tgz#5f8e8c90d304edf12530951a5554abb8c5e3f552" integrity sha1-X46MkNME7fElMJUaVVSruMXj9VI= @@ -7342,9 +7369,9 @@ media-typer@0.3.0: integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= memfs@^3.2.2: - version "3.3.0" - resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.3.0.tgz#4da2d1fc40a04b170a56622c7164c6be2c4cbef2" - integrity sha512-BEE62uMfKOavX3iG7GYX43QJ+hAeeWnwIAuJ/R6q96jaMtiLzhsxHJC8B1L7fK7Pt/vXDRwb3SG/yBpNGDPqzg== + version "3.4.0" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.0.tgz#8bc12062b973be6b295d4340595736a656f0a257" + integrity sha512-o/RfP0J1d03YwsAxyHxAYs2kyJp55AFkMazlFAZFR2I2IXkxiUTXRabJ6RmNNCQ83LAD2jy52Khj0m3OffpNdA== dependencies: fs-monkey "1.0.3" @@ -7399,17 +7426,17 @@ micromatch@^4.0.2, micromatch@^4.0.4: braces "^3.0.1" picomatch "^2.2.3" -mime-db@1.50.0, "mime-db@>= 1.43.0 < 2", mime-db@^1.28.0: - version "1.50.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.50.0.tgz#abd4ac94e98d3c0e185016c67ab45d5fde40c11f" - integrity sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A== +mime-db@1.51.0, "mime-db@>= 1.43.0 < 2", mime-db@^1.28.0: + version "1.51.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" + integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: - version "2.1.33" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.33.tgz#1fa12a904472fafd068e48d9e8401f74d3f70edb" - integrity sha512-plLElXp7pRDd0bNZHw+nMd52vRYjLwQjygaNg7ddJ2uJtTlmnTCjWuPKxVu6//AdaRuME84SvLW91sIkBqGT0g== + version "2.1.34" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" + integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== dependencies: - mime-db "1.50.0" + mime-db "1.51.0" mime@1.6.0, mime@^1.4.1: version "1.6.0" @@ -7442,11 +7469,11 @@ mini-create-react-context@^0.4.0: tiny-warning "^1.0.3" mini-css-extract-plugin@^2.3.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.4.2.tgz#b3508191ea479388a4715018c99dd3e6dd40d2d2" - integrity sha512-ZmqShkn79D36uerdED+9qdo1ZYG8C1YsWvXu0UMJxurZnSdgz7gQKO2EGv8T55MhDqG3DYmGtizZNpM/UbTlcA== + version "2.4.5" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.4.5.tgz#191d6c170226037212c483af1180b4010b7b9eef" + integrity sha512-oEIhRucyn1JbT/1tU2BhnwO6ft1jjH1iCX9Gc59WFMg0n5773rQU0oyQ0zzeYFFuBfONaRbQJyGoPtuNseMxjA== dependencies: - schema-utils "^3.1.0" + schema-utils "^4.0.0" minimalistic-assert@^1.0.0: version "1.0.1" @@ -7508,17 +7535,17 @@ mocha@^9.0.1: yargs-unparser "2.0.0" mock-local-storage@^1.1.17: - version "1.1.17" - resolved "https://registry.yarnpkg.com/mock-local-storage/-/mock-local-storage-1.1.17.tgz#13325dad4e3b696374c2984fa8af33941f54239e" - integrity sha512-vF5571cY3N/XFw8Oxr+0HmY6PedvO6i2IZrpnDV35sh7alhrh1RYYFZzItuh5OhJrQoulNSruiw1KHk5QB/EQg== + version "1.1.19" + resolved "https://registry.yarnpkg.com/mock-local-storage/-/mock-local-storage-1.1.19.tgz#baf00a0b7f1991871fdf9bb51932b9ab3a257c34" + integrity sha512-YwTEsgWqFw6uRBvhKScanKwfSIpjING50y9UaHb6BGfsdlFY3Zumdnf8RLBvHRVkLh31+G2WEz0xNeYhd5f5fA== dependencies: - core-js "^0.8.3" + core-js "^3.19.0" global "^4.3.2" moment-timezone@^0.5.31: - version "0.5.33" - resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.33.tgz#b252fd6bb57f341c9b59a5ab61a8e51a73bbd22c" - integrity sha512-PTc2vcT8K9J5/9rDEPe5czSIKgLoGsH8UNpA4qZTVw0Vd/Uz19geE9abbIOQKaAQFcnQ3v5YEXrbSc5BpshH+w== + version "0.5.34" + resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.34.tgz#a75938f7476b88f155d3504a9343f7519d9a405c" + integrity sha512-3zAEHh2hKUs3EXLESx/wsgw6IQdusOT8Bxm3D9UrHPQR7zlMmzwybC8zHEM1tQ4LJwP7fcxrWr8tuBg05fFCbg== dependencies: moment ">= 2.9.0" @@ -7568,17 +7595,12 @@ multicast-dns@^6.0.1: dns-packet "^1.3.1" thunky "^1.0.2" -nanocolors@^0.1.12: - version "0.1.12" - resolved "https://registry.yarnpkg.com/nanocolors/-/nanocolors-0.1.12.tgz#8577482c58cbd7b5bb1681db4cf48f11a87fd5f6" - integrity sha512-2nMHqg1x5PU+unxX7PGY7AuYxl2qDx7PSrTRjizr8sxdd3l/3hBuWWaki62qmtYm2U5i4Z5E7GbjlyDFhs9/EQ== - nanoid@3.1.25: version "3.1.25" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.25.tgz#09ca32747c0e543f0e1814b7d3793477f9c8e152" integrity sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q== -nanoid@^3.1.28: +nanoid@^3.1.30: version "3.1.30" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.30.tgz#63f93cc548d2a113dc5dfbc63bfa09e2b9b64362" integrity sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ== @@ -7635,15 +7657,10 @@ node-forge@^0.10.0: resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3" integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA== -node-modules-regexp@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40" - integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA= - -node-releases@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.0.tgz#67dc74903100a7deb044037b8a2e5f453bb05400" - integrity sha512-aA87l0flFYMzCHpTM3DERFSYxc6lv/BltdbRTOMZuxZ0cwZCD3mejE5n9vLhSJCN++/eOqr77G1IO5uXxlQYWA== +node-releases@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.1.tgz#3d1d395f204f1f2f29a54358b9fb678765ad2fc5" + integrity sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA== normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: version "2.5.0" @@ -7714,9 +7731,9 @@ object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= object-inspect@^1.11.0, object-inspect@^1.6.0, object-inspect@^1.9.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1" - integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg== + version "1.11.1" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.1.tgz#d4bd7d7de54b9a75599f59a00bd698c1f1c6549b" + integrity sha512-If7BjFlpkzzBeV1cqgT3OSWT3azyoxDGajR+iGnFBfVV2EWyDyWaZZW2ERDjUaY2QM8i5jI3Sj7mhsM4DDAqWA== object-is@^1.0.1, object-is@^1.1.4: version "1.1.5" @@ -7741,7 +7758,7 @@ object.assign@^4.1.0, object.assign@^4.1.2: has-symbols "^1.0.1" object-keys "^1.1.1" -object.entries@^1.1.4: +object.entries@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.5.tgz#e1acdd17c4de2cd96d5a08487cfb9db84d881861" integrity sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g== @@ -7750,7 +7767,7 @@ object.entries@^1.1.4: define-properties "^1.1.3" es-abstract "^1.19.1" -object.fromentries@^2.0.4: +object.fromentries@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.5.tgz#7b37b205109c21e741e605727fe8b0ad5fa08251" integrity sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw== @@ -7768,7 +7785,7 @@ object.getownpropertydescriptors@^2.0.3: define-properties "^1.1.3" es-abstract "^1.19.1" -object.hasown@^1.0.0: +object.hasown@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.0.tgz#7232ed266f34d197d15cac5880232f7a4790afe5" integrity sha512-MhjYRfj3GBlhSkDHo6QmvgjRLXQ2zndabdf3nX0yTyZK9rPfxb6uRpAac8HXNLy1GpqWtZ81Qh4v3uOls2sRAg== @@ -7776,7 +7793,7 @@ object.hasown@^1.0.0: define-properties "^1.1.3" es-abstract "^1.19.1" -object.values@^1.1.4, object.values@^1.1.5: +object.values@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.5.tgz#959f63e3ce9ef108720333082131e4a459b716ac" integrity sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg== @@ -7817,9 +7834,9 @@ onetime@^5.1.0, onetime@^5.1.2: mimic-fn "^2.1.0" open@^8.0.9: - version "8.3.0" - resolved "https://registry.yarnpkg.com/open/-/open-8.3.0.tgz#fdef1cdfe405e60dec8ebd18889e7e812f39c59f" - integrity sha512-7INcPWb1UcOwSQxAXTnBJ+FxVV4MPs/X++FWWBtgY69/J5lc+tCteMt/oFK1MnkyHC4VILLa9ntmwKTwDR4Q9w== + version "8.4.0" + resolved "https://registry.yarnpkg.com/open/-/open-8.4.0.tgz#345321ae18f8138f82565a910fdc6b39e8c244f8" + integrity sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q== dependencies: define-lazy-prop "^2.0.0" is-docker "^2.1.1" @@ -7850,13 +7867,12 @@ optionator@^0.9.1: word-wrap "^1.2.3" optipng-bin@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/optipng-bin/-/optipng-bin-7.0.0.tgz#2dfcc68a5f006e7746e76ad64d317d6fb7c7f9ed" - integrity sha512-mesUAwfedu5p9gRQwlYgD6Svw5IH3VUIWDJj/9cNpP3yFNbbEVqkTMWYhrIEn/cxmbGA3LpZrdoV2Yl8OfmnIA== + version "7.0.1" + resolved "https://registry.yarnpkg.com/optipng-bin/-/optipng-bin-7.0.1.tgz#beb8e55a52f8a26f885ee57ab44fcf62397d6972" + integrity sha512-W99mpdW7Nt2PpFiaO+74pkht7KEqkXkeRomdWXfEz3SALZ6hns81y/pm1dsGZ6ItUIfchiNIP6ORDr1zETU1jA== dependencies: bin-build "^3.0.0" bin-wrapper "^4.0.0" - logalot "^2.0.0" os-filter-obj@^2.0.0: version "2.0.0" @@ -7901,13 +7917,6 @@ p-event@^2.1.0: dependencies: p-timeout "^2.0.1" -p-event@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/p-event/-/p-event-4.2.0.tgz#af4b049c8acd91ae81083ebd1e6f5cae2044c1b5" - integrity sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ== - dependencies: - p-timeout "^3.1.0" - p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" @@ -7932,7 +7941,7 @@ p-limit@^2.0.0, p-limit@^2.2.0: dependencies: p-try "^2.0.0" -p-limit@^3.0.2, p-limit@^3.1.0: +p-limit@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== @@ -8013,13 +8022,6 @@ p-timeout@^2.0.1: dependencies: p-finally "^1.0.0" -p-timeout@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-3.2.0.tgz#c7e17abc971d2a7962ef83626b35d635acf23dfe" - integrity sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg== - dependencies: - p-finally "^1.0.0" - p-try@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" @@ -8167,7 +8169,17 @@ pathval@^1.1.1: resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== -pdfkit@>=0.8.1, pdfkit@^0.12.0: +pdfkit@>=0.8.1: + version "0.13.0" + resolved "https://registry.yarnpkg.com/pdfkit/-/pdfkit-0.13.0.tgz#da4c2becd63a129e3aae448fdaed4ee7be790f8f" + integrity sha512-AW79eHU5eLd2vgRDS9z3bSoi0FA+gYm+100LLosrQQMLUzOBGVOhG7ABcMFpJu7Bpg+MT74XYHi4k9EuU/9EZw== + dependencies: + crypto-js "^4.0.0" + fontkit "^1.8.1" + linebreak "^1.0.2" + png-js "^1.0.0" + +pdfkit@^0.12.0: version "0.12.3" resolved "https://registry.yarnpkg.com/pdfkit/-/pdfkit-0.12.3.tgz#527da4a4bad9a6b456a6939037d63d5ff9306302" integrity sha512-+qDLgm2yq6WOKcxTb43lDeo3EtMIDQs0CK1RNqhHC9iT6u0KOmgwAClkYh9xFw2ATbmUZzt4f7KMwDCOfPDluA== @@ -8203,11 +8215,6 @@ performance-now@^2.1.0: resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= -picocolors@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f" - integrity sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA== - picocolors@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" @@ -8246,11 +8253,9 @@ pinkie@^2.0.0: integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= pirates@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87" - integrity sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA== - dependencies: - node-modules-regexp "^1.0.0" + version "4.0.4" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.4.tgz#07df81e61028e402735cdd49db701e4885b4e6e6" + integrity sha512-ZIrVPH+A52Dw84R0L3/VS9Op04PuQ2SEoJL6bkshmiTic/HldyW9Tf7oH5mhJZBK7NmDx27vSMrYEXPXclpDKw== pkg-dir@^2.0.0: version "2.0.0" @@ -8302,12 +8307,12 @@ portfinder@^1.0.28: mkdirp "^0.5.5" postcss-loader@^6.1.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-6.2.0.tgz#714370a3f567141cf4cadcdf9575f5234d186bc5" - integrity sha512-H9hv447QjQJVDbHj3OUdciyAXY3v5+UDduzEytAlZCVHCpNAAg/mCSwhYYqZr9BiGYhmYspU8QXxZwiHTLn3yA== + version "6.2.1" + resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-6.2.1.tgz#0895f7346b1702103d30fdc66e4d494a93c008ef" + integrity sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q== dependencies: cosmiconfig "^7.0.0" - klona "^2.0.4" + klona "^2.0.5" semver "^7.3.5" postcss-modules-extract-imports@^1.0.0: @@ -8387,9 +8392,9 @@ postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4: util-deprecate "^1.0.2" postcss-value-parser@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" - integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== + version "4.2.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" + integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== postcss@^6.0.1, postcss@^6.0.2: version "6.0.23" @@ -8401,13 +8406,13 @@ postcss@^6.0.1, postcss@^6.0.2: supports-color "^5.4.0" postcss@^8.1.10, postcss@^8.2.15: - version "8.3.9" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.9.tgz#98754caa06c4ee9eb59cc48bd073bb6bd3437c31" - integrity sha512-f/ZFyAKh9Dnqytx5X62jgjhhzttjZS7hMsohcI7HEI5tjELX/HxCy3EFhsRxyzGvrzFF+82XPvCS8T9TFleVJw== + version "8.4.4" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.4.tgz#d53d4ec6a75fd62557a66bb41978bf47ff0c2869" + integrity sha512-joU6fBsN6EIer28Lj6GDFoC/5yOZzLCfn0zHAn/MYXI7aPt4m4hK5KC5ovEZXy+lnCjmYIbQWngvju2ddyEr8Q== dependencies: - nanoid "^3.1.28" - picocolors "^0.2.1" - source-map-js "^0.6.2" + nanoid "^3.1.30" + picocolors "^1.0.0" + source-map-js "^1.0.1" prelude-ls@^1.2.1: version "1.2.1" @@ -8430,9 +8435,9 @@ prepend-http@^2.0.0: integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= prettier@^2.3.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.4.1.tgz#671e11c89c14a4cfc876ce564106c4a6726c9f5c" - integrity sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA== + version "2.5.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.5.1.tgz#fff75fa9d519c54cf0fce328c1017d94546bc56a" + integrity sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg== pretty-ms@^7.0.1: version "7.0.1" @@ -8537,9 +8542,9 @@ qs@6.7.0: integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== qs@^6.1.0: - version "6.10.1" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.1.tgz#4931482fa8d647a5aab799c5271d2133b981fb6a" - integrity sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg== + version "6.10.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.2.tgz#c1431bea37fc5b24c5bdbafa20f16bdf2a4b9ffe" + integrity sha512-mSIdjzqznWgfd4pMii7sHtaYF8rx8861hBO80SraY5GT0XQibWZWJSid0avzHGkDIZLImux2S5mXO0Hfct2QCw== dependencies: side-channel "^1.0.4" @@ -8618,11 +8623,11 @@ raw-body@2.4.0: unpipe "1.0.0" react-ace@^9.4.1: - version "9.4.4" - resolved "https://registry.yarnpkg.com/react-ace/-/react-ace-9.4.4.tgz#2ae0d9fd199daec0bb62353d92356eaf8edfc4f8" - integrity sha512-gHSH4Wm+jE28pcr4hXKeSwG2DHPZhVlfAfR+VI/dgStnUFWJMPClpRI8emLEYEK/g4cZ4cHY80HTfFwfc4020w== + version "9.5.0" + resolved "https://registry.yarnpkg.com/react-ace/-/react-ace-9.5.0.tgz#b6c32b70d404dd821a7e01accc2d76da667ff1f7" + integrity sha512-4l5FgwGh6K7A0yWVMQlPIXDItM4Q9zzXRqOae8KkCl6MkOob7sC1CzHxZdOGvV+QioKWbX2p5HcdOVUv6cAdSg== dependencies: - ace-builds "^1.4.12" + ace-builds "^1.4.13" diff-match-patch "^1.0.5" lodash.get "^4.4.2" lodash.isequal "^4.5.0" @@ -8652,9 +8657,9 @@ react-bootstrap@1.6.4: warning "^4.0.3" react-collapse@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/react-collapse/-/react-collapse-5.1.0.tgz#36f69ecb0fe797f976aaf5e4f2b2c248d2760140" - integrity sha512-5v0ywsn9HjiR/odNzbRDs0RZfrnbdSippJebWOBCFFDA12Vx8DddrbI4qWVf1P2wTiVagrpcSy07AU0b6+gM9Q== + version "5.1.1" + resolved "https://registry.yarnpkg.com/react-collapse/-/react-collapse-5.1.1.tgz#a2fa08ef13f372141b02e6a7d49ef72427bcbc2b" + integrity sha512-k6cd7csF1o9LBhQ4AGBIdxB60SUEUMQDAnL2z1YvYNr9KoKr+nDkhN6FK7uGaBd/rYrYfrMpzpmJEIeHRYogBw== react-copy-to-clipboard@^5.0.3: version "5.0.4" @@ -8744,11 +8749,16 @@ react-intl@5.20.13: intl-messageformat "9.9.3" tslib "^2.1.0" -react-is@^16.13.1, react-is@^16.3.2, react-is@^16.4.2, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1: +react-is@^16.3.2, react-is@^16.4.2, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== +react-is@^17.0.2: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== + react-lifecycles-compat@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" @@ -8778,16 +8788,16 @@ react-overlays@^5.1.1: warning "^4.0.3" react-redux@^7.2.0: - version "7.2.5" - resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.5.tgz#213c1b05aa1187d9c940ddfc0b29450957f6a3b8" - integrity sha512-Dt29bNyBsbQaysp6s/dN0gUodcq+dVKKER8Qv82UrpeygwYeX1raTtil7O/fftw/rFqzaf6gJhDZRkkZnn6bjg== + version "7.2.6" + resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.6.tgz#49633a24fe552b5f9caf58feb8a138936ddfe9aa" + integrity sha512-10RPdsz0UUrRL1NZE0ejTkucnclYSgXp5q+tB5SWx2qeG2ZJQJyymgAhwKy73yiL/13btfB6fPr+rgbMAaZIAQ== dependencies: - "@babel/runtime" "^7.12.1" - "@types/react-redux" "^7.1.16" + "@babel/runtime" "^7.15.4" + "@types/react-redux" "^7.1.20" hoist-non-react-statics "^3.3.2" loose-envify "^1.4.0" prop-types "^15.7.2" - react-is "^16.13.1" + react-is "^17.0.2" react-router-dom@^5.2.0: version "5.3.0" @@ -8938,9 +8948,9 @@ redux-actions@^2.6.5: to-camel-case "^1.0.0" redux-form@^8.3.7: - version "8.3.7" - resolved "https://registry.yarnpkg.com/redux-form/-/redux-form-8.3.7.tgz#24eb6d8b8b37098b4702fc4c52b6596b01a71c82" - integrity sha512-CUv6z5Gpog3shB3Ptsd+x6dmeQ1AzIlx1Tniri3j7Gf+oBBtLrD7dHMLOcTbJKsaEwG49SB/z1Pik3Hy04mNcQ== + version "8.3.8" + resolved "https://registry.yarnpkg.com/redux-form/-/redux-form-8.3.8.tgz#cd1a76c914655e3c599a375d6486a43bf8b4c1e3" + integrity sha512-PzXhA0d+awIc4PkuhbDa6dCEiraMrGMyyDlYEVNX6qEyW/G2SqZXrjav5zrpXb0CCeqQSc9iqwbMtYQXbJbOAQ== dependencies: "@babel/runtime" "^7.9.2" es6-error "^4.1.1" @@ -8993,14 +9003,14 @@ redux-storage@^4.1.2: redux-storage-merger-simple "^1.0.2" redux-thunk@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.3.0.tgz#51c2c19a185ed5187aaa9a2d08b666d0d6467622" - integrity sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw== + version "2.4.1" + resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.4.1.tgz#0dd8042cf47868f4b29699941de03c9301a75714" + integrity sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q== redux@^4.0.0, redux@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/redux/-/redux-4.1.1.tgz#76f1c439bb42043f985fbd9bf21990e60bd67f47" - integrity sha512-hZQZdDEM25UY2P493kPYuKqviVwZ58lEmGQNeQ+gXa+U0gYPUBf7NKYazbe3m+bs/DzM/ahN12DbF+NG8i0CWw== + version "4.1.2" + resolved "https://registry.yarnpkg.com/redux/-/redux-4.1.2.tgz#140f35426d99bb4729af760afcf79eaaac407104" + integrity sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw== dependencies: "@babel/runtime" "^7.9.2" @@ -9167,9 +9177,9 @@ requires-port@^1.0.0: integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= reselect@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.0.0.tgz#f2529830e5d3d0e021408b246a206ef4ea4437f7" - integrity sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA== + version "4.1.5" + resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.1.5.tgz#852c361247198da6756d07d9296c2b51eddb79f6" + integrity sha512-uVdlz8J7OO+ASpBYoz1Zypgx0KasCY20H+N8JD13oUMtPvSHQuscrHop4KbXrbsBcdB9Ds7lVK7eRkBIfO43vQ== resolve-cwd@^3.0.0: version "3.0.0" @@ -9319,6 +9329,16 @@ schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: ajv "^6.12.5" ajv-keywords "^3.5.2" +schema-utils@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.0.0.tgz#60331e9e3ae78ec5d16353c467c34b3a0a1d3df7" + integrity sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg== + dependencies: + "@types/json-schema" "^7.0.9" + ajv "^8.8.0" + ajv-formats "^2.1.1" + ajv-keywords "^5.0.0" + scope-analyzer@^2.0.1: version "2.1.2" resolved "https://registry.yarnpkg.com/scope-analyzer/-/scope-analyzer-2.1.2.tgz#b958162feb59823c2835c7b0229187a97c77e9cd" @@ -9514,9 +9534,9 @@ side-channel@^1.0.3, side-channel@^1.0.4: object-inspect "^1.9.0" signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3: - version "3.0.5" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.5.tgz#9e3e8cc0c75a99472b44321033a7702e7738252f" - integrity sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ== + version "3.0.6" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af" + integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ== slash@^2.0.0: version "2.0.0" @@ -9538,12 +9558,12 @@ slice-ansi@^4.0.0: is-fullwidth-code-point "^3.0.0" sockjs@^0.3.21: - version "0.3.21" - resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.21.tgz#b34ffb98e796930b60a0cfa11904d6a339a7d417" - integrity sha512-DhbPFGpxjc6Z3I+uX07Id5ZO2XwYsWOrYjaSeieES78cq+JaJvVe5q/m1uvjIQhXinhIeCFRH6JgXe+mvVMyXw== + version "0.3.24" + resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce" + integrity sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ== dependencies: faye-websocket "^0.11.3" - uuid "^3.4.0" + uuid "^8.3.2" websocket-driver "^0.7.4" sort-keys-length@^1.0.0: @@ -9567,15 +9587,15 @@ sort-keys@^2.0.0: dependencies: is-plain-obj "^1.0.0" -source-map-js@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-0.6.2.tgz#0bb5de631b41cfbda6cfba8bd05a80efdfd2385e" - integrity sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug== +source-map-js@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.1.tgz#a1741c131e3c77d048252adfa24e23b908670caf" + integrity sha512-4+TN2b3tqOCd/kaGRJ/sTYA0tR0mdXx26ipdolxcwtJVqEnqNYvlCAt1q3ypy4QMlYus+Zh34RNtYLoq2oQ4IA== source-map-support@^0.5.16, source-map-support@~0.5.20: - version "0.5.20" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.20.tgz#12166089f8f5e5e8c56926b377633392dd2cb6c9" - integrity sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw== + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" @@ -9634,9 +9654,9 @@ spdx-expression-parse@^3.0.0: spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.10" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz#0d9becccde7003d6c658d487dd48a32f0bf3014b" - integrity sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA== + version "3.0.11" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz#50c0d8c40a14ec1bf449bae69a0ea4685a9d9f95" + integrity sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g== spdy-transport@^3.0.0: version "3.0.0" @@ -9746,7 +9766,7 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string.prototype.matchall@^4.0.5: +string.prototype.matchall@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.6.tgz#5abb5dabc94c7b0ea2380f65ba610b3a544b15fa" integrity sha512-6WgDX8HmQqvEd7J+G6VtAahhsQIssiZ8zl7zKh1VDMFyL3hRTJP4FTNA3RbIp2TOQ9AYNDcc7e3fH0Qbup+DBg== @@ -9867,14 +9887,14 @@ strip-outer@^1.0.0: escape-string-regexp "^1.0.2" strnum@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.4.tgz#e97e36a7d6ba9f93d0d6b496b2ed0678d422832b" - integrity sha512-lMzNMfDpaQOLt4B2mEbfzYS0+T7dvCXeojnlGf6f1AygvWDMcWyXYaLbyICfjVu29sErR8fnRagQfBW/N/hGgw== + version "1.0.5" + resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db" + integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA== style-loader@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.0.tgz#d66ea95fc50b22f8b79b69a9e414760fcf58d8d8" - integrity sha512-szANub7ksJtQioJYtpbWwh1hUl99uK15n5HDlikeCRil/zYMZgSxucHddyF/4A3qJMUiAjPhFowrrQuNMA7jwQ== + version "3.3.1" + resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.1.tgz#057dfa6b3d4d7c7064462830f9113ed417d38575" + integrity sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ== summernote@^0.8.18: version "0.8.20" @@ -9915,16 +9935,16 @@ svg-to-pdfkit@^0.1.8: pdfkit ">=0.8.1" svgo@^2.1.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-2.7.0.tgz#e164cded22f4408fe4978f082be80159caea1e2d" - integrity sha512-aDLsGkre4fTDCWvolyW+fs8ZJFABpzLXbtdK1y71CKnHzAnpDxKXPj2mNKj+pyOXUCzFHzuxRJ94XOFygOWV3w== + version "2.8.0" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-2.8.0.tgz#4ff80cce6710dc2795f0c7c74101e6764cfccd24" + integrity sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg== dependencies: "@trysound/sax" "0.2.0" commander "^7.2.0" css-select "^4.1.3" css-tree "^1.1.3" csso "^4.2.0" - nanocolors "^0.1.12" + picocolors "^1.0.0" stable "^0.1.8" sweetalert2@^10.15.6: @@ -9947,12 +9967,11 @@ sync-request@^3.0.1: then-request "^2.0.1" table@^6.0.9: - version "6.7.2" - resolved "https://registry.yarnpkg.com/table/-/table-6.7.2.tgz#a8d39b9f5966693ca8b0feba270a78722cbaf3b0" - integrity sha512-UFZK67uvyNivLeQbVtkiUs8Uuuxv24aSL4/Vil2PJVtMgU8Lx0CYkP12uCGa3kjyQzOSgV1+z9Wkb82fCGsO0g== + version "6.7.5" + resolved "https://registry.yarnpkg.com/table/-/table-6.7.5.tgz#f04478c351ef3d8c7904f0e8be90a1b62417d238" + integrity sha512-LFNeryOqiQHqCVKzhkymKwt6ozeRhlm8IL1mE8rNUurkir4heF6PzMyRgaTa4tlyPTGGgXuvVOF/OLWiH09Lqw== dependencies: ajv "^8.0.1" - lodash.clonedeep "^4.5.0" lodash.truncate "^4.4.2" slice-ansi "^4.0.0" string-width "^4.2.3" @@ -10001,21 +10020,20 @@ tempusdominus-bootstrap-4@^5.39.0: popper.js "^1.16.1" terser-webpack-plugin@^5.1.3: - version "5.2.4" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.2.4.tgz#ad1be7639b1cbe3ea49fab995cbe7224b31747a1" - integrity sha512-E2CkNMN+1cho04YpdANyRrn8CyN4yMy+WdFKZIySFZrGXZxJwJP6PMNGGc/Mcr6qygQHUUqRxnAPmi0M9f00XA== + version "5.2.5" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.2.5.tgz#ce65b9880a0c36872555c4874f45bbdb02ee32c9" + integrity sha512-3luOVHku5l0QBeYS8r4CdHYWEGMmIj3H1U64jgkdZzECcSOJAyJ9TjuqcQZvw1Y+4AOBN9SeYJPJmFn2cM4/2g== dependencies: jest-worker "^27.0.6" - p-limit "^3.1.0" schema-utils "^3.1.1" serialize-javascript "^6.0.0" source-map "^0.6.1" terser "^5.7.2" terser@^5.7.2: - version "5.9.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.9.0.tgz#47d6e629a522963240f2b55fcaa3c99083d2c351" - integrity sha512-h5hxa23sCdpzcye/7b8YqbE5OwKca/ni0RQz1uRX3tGh8haaGHqcuSqbGRybuAKNdntZ0mDgFNXPJ48xQ2RXKQ== + version "5.10.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.10.0.tgz#b86390809c0389105eb0a0b62397563096ddafcc" + integrity sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA== dependencies: commander "^2.20.0" source-map "~0.7.2" @@ -10067,9 +10085,9 @@ tiny-inflate@^1.0.0, tiny-inflate@^1.0.2: integrity sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw== tiny-invariant@^1.0.2: - version "1.1.0" - resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.1.0.tgz#634c5f8efdc27714b7f386c35e6760991d230875" - integrity sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw== + version "1.2.0" + resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.2.0.tgz#a1141f86b672a9148c72e978a19a73b9b94a15a9" + integrity sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg== tiny-warning@^1.0.0, tiny-warning@^1.0.3: version "1.0.3" @@ -10178,9 +10196,9 @@ trim-repeated@^1.0.0: escape-string-regexp "^1.0.2" tsconfig-paths@^3.11.0: - version "3.11.0" - resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.11.0.tgz#954c1fe973da6339c78e06b03ce2e48810b65f36" - integrity sha512-7ecdYDnIdmv639mmDwslG6KQg1Z9STTz1j7Gcz0xa+nshh/gKDAHcPxRbWOsA3SPp0tXP2leTcY9Kw+NAkfZzA== + version "3.12.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz#19769aca6ee8f6a1a341e38c8fa45dd9fb18899b" + integrity sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg== dependencies: "@types/json5" "^0.0.29" json5 "^1.0.1" @@ -10256,10 +10274,10 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@^4.3: - version "4.4.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.4.tgz#2cd01a1a1f160704d3101fd5a58ff0f9fcb8030c" - integrity sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA== +typescript@^4.5: + version "4.5.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.2.tgz#8ac1fba9f52256fdb06fb89e4122fa6a346c2998" + integrity sha512-5BlMof9H1yGt0P8/WF+wPNw6GfctgGjXp5hkblpyT+8rkASSmkUKMXrxR0Xg8ThVCi/JnHQiKXeBaEwCeQwMFw== uc.micro@^1.0.1, uc.micro@^1.0.5: version "1.0.6" @@ -10380,9 +10398,9 @@ unpipe@1.0.0, unpipe@~1.0.0: integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= uplot@^1.6.7: - version "1.6.16" - resolved "https://registry.yarnpkg.com/uplot/-/uplot-1.6.16.tgz#0c90c40dff52e9cbd7f24eb0d709c8cbf84be803" - integrity sha512-Rh0WtFgtZdYk70Knu1VyZYbwlx5GuoIFBezZuHwlEUiREsIjOKpe3CXLXLaKc7/49Z7XhQ/bazgF/f1zercxgw== + version "1.6.17" + resolved "https://registry.yarnpkg.com/uplot/-/uplot-1.6.17.tgz#1f8fc07a0e48008798beca463523621ad66dcc46" + integrity sha512-WHNHvDCXURn+Qwb3QUUzP6rOxx+3kUZUspREyhkqmXCxFIND99l5z9intTh+uPEt+/EEu7lCaMjSd1uTfuTXfg== uri-js@^4.2.2: version "4.4.1" @@ -10428,11 +10446,16 @@ utils-merge@1.0.1: resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= -uuid@^3.0.1, uuid@^3.3.2, uuid@^3.4.0: +uuid@^3.0.1, uuid@^3.3.2: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + v8-compile-cache@^2.0.3: version "2.3.0" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" @@ -10503,10 +10526,10 @@ warning@^4.0.0, warning@^4.0.3: dependencies: loose-envify "^1.0.0" -watchpack@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.2.0.tgz#47d78f5415fe550ecd740f99fe2882323a58b1ce" - integrity sha512-up4YAn/XHgZHIxFBVCdlMiWDj6WaLKpwVeGQk2I5thdYxF/KmF0aaz6TfJZ/hfl1h/XlcDr7k1KH7ThDagpFaA== +watchpack@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.3.1.tgz#4200d9447b401156eeca7767ee610f8809bc9d25" + integrity sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA== dependencies: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" @@ -10547,38 +10570,38 @@ webpack-cli@^4.7.2: webpack-merge "^5.7.3" webpack-dev-middleware@^5.0.0, webpack-dev-middleware@^5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.2.1.tgz#97c948144349177856a3d2d9c612cc3fee180cf1" - integrity sha512-Kx1X+36Rn9JaZcQMrJ7qN3PMAuKmEDD9ZISjUj3Cgq4A6PtwYsC4mpaKotSRYH3iOF6HsUa8viHKS59FlyVifQ== + version "5.2.2" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.2.2.tgz#eb5193faa5479ca1086b9f7bed68b89c731bff62" + integrity sha512-DjZyYrsHhkikAFNvSNKrpnziXukU1EChFAh9j4LAm6ndPLPW8cN0KhM7T+RAiOqsQ6ABfQ8hoKIs9IWMTjov+w== dependencies: colorette "^2.0.10" memfs "^3.2.2" mime-types "^2.1.31" range-parser "^1.2.1" - schema-utils "^3.1.0" + schema-utils "^4.0.0" webpack-dev-server@^4.3.0: - version "4.3.1" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.3.1.tgz#759d3337f0fbea297fbd1e433ab04ccfc000076b" - integrity sha512-qNXQCVYo1kYhH9pgLtm8LRNkXX3XzTfHSj/zqzaqYzGPca+Qjr+81wj1jgPMCHhIhso9WEQ+kX9z23iG9PzQ7w== + version "4.6.0" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.6.0.tgz#e8648601c440172d9b6f248d28db98bed335315a" + integrity sha512-oojcBIKvx3Ya7qs1/AVWHDgmP1Xml8rGsEBnSobxU/UJSX1xP1GPM3MwsAnDzvqcVmVki8tV7lbcsjEjk0PtYg== dependencies: ansi-html-community "^0.0.8" bonjour "^3.5.0" - chokidar "^3.5.1" + chokidar "^3.5.2" colorette "^2.0.10" compression "^1.7.4" connect-history-api-fallback "^1.6.0" + default-gateway "^6.0.3" del "^6.0.0" express "^4.17.1" graceful-fs "^4.2.6" html-entities "^2.3.2" http-proxy-middleware "^2.0.0" - internal-ip "^6.2.0" ipaddr.js "^2.0.1" open "^8.0.9" p-retry "^4.5.0" portfinder "^1.0.28" - schema-utils "^3.1.0" + schema-utils "^4.0.0" selfsigned "^1.10.11" serve-index "^1.9.1" sockjs "^0.3.21" @@ -10609,15 +10632,15 @@ webpack-merge@^5.7.3: clone-deep "^4.0.1" wildcard "^2.0.0" -webpack-sources@^3.2.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.1.tgz#251a7d9720d75ada1469ca07dbb62f3641a05b6d" - integrity sha512-t6BMVLQ0AkjBOoRTZgqrWm7xbXMBzD+XDq2EZ96+vMfn3qKgsvdXZhbPZ4ElUOpdv4u+iiGe+w3+J75iy/bYGA== +webpack-sources@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.2.tgz#d88e3741833efec57c4c789b6010db9977545260" + integrity sha512-cp5qdmHnu5T8wRg2G3vZZHoJPN14aqQ89SyQ11NpGH5zEMDCclt49rzo+MaRazk7/UeILhAI+/sEtcM+7Fr0nw== webpack@^5.40.0: - version "5.58.2" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.58.2.tgz#6b4af12fc9bd5cbedc00dc0a2fc2b9592db16b44" - integrity sha512-3S6e9Vo1W2ijk4F4PPWRIu6D/uGgqaPmqw+av3W3jLDujuNkdxX5h5c+RQ6GkjVR+WwIPOfgY8av+j5j4tMqJw== + version "5.65.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.65.0.tgz#ed2891d9145ba1f0d318e4ea4f89c3fa18e6f9be" + integrity sha512-Q5or2o6EKs7+oKmJo7LaqZaMOlDWQse9Tm5l1WAfU/ujLGN5Pb0SqGeVkN/4bpPmEqEP5RnVhiqsOtWtUVwGRw== dependencies: "@types/eslint-scope" "^3.7.0" "@types/estree" "^0.0.50" @@ -10641,8 +10664,8 @@ webpack@^5.40.0: schema-utils "^3.1.0" tapable "^2.1.1" terser-webpack-plugin "^5.1.3" - watchpack "^2.2.0" - webpack-sources "^3.2.0" + watchpack "^2.3.1" + webpack-sources "^3.2.2" websocket-driver@>=0.5.1, websocket-driver@^0.7.4: version "0.7.4" @@ -10774,9 +10797,9 @@ wrappy@1: integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= ws@^8.1.0, ws@^8.2.3: - version "8.2.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.2.3.tgz#63a56456db1b04367d0b721a0b80cae6d8becbba" - integrity sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA== + version "8.3.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.3.0.tgz#7185e252c8973a60d57170175ff55fdbd116070d" + integrity sha512-Gs5EZtpqZzLvmIM59w4igITU57lrtYVFneaa434VROv4thzJyV6UjIL3D42lslWlI+D4KzLYnxSwtfuiO79sNw== xml-name-validator@^4.0.0: version "4.0.0" From 318aedefec5c3b0a869aba76ddc7741ffcb5d85b Mon Sep 17 00:00:00 2001 From: Martin Krulis Date: Fri, 17 Dec 2021 19:57:42 +0100 Subject: [PATCH 09/20] Using new pipeline graph for read-only visualization as well. Subsequent cleanup of deprecated pipeline code. --- .../Pipelines/BoxForm/AddBoxForm.js | 36 ----- .../Pipelines/BoxForm/EditBoxForm.js | 48 ------ .../Pipelines/PipelineGraph/PipelineGraph.js | 6 +- .../PipelineVisualEditor.js | 124 --------------- .../Pipelines/PipelineVisualEditor/index.js | 2 - .../PipelineVisualEditor/pipeline.css | 26 ---- .../PipelineVisualisation.js | 40 ----- .../Pipelines/PipelineVisualisation/index.js | 2 - .../PipelineVisualisation/pipeline.less | 9 -- src/components/forms/Fields/PipelineField.js | 45 ------ .../forms/Fields/PipelineVariablesField.js | 100 ------------ src/components/forms/Fields/PortField.js | 62 -------- src/components/forms/Fields/PortsField.js | 23 --- src/components/forms/Fields/index.js | 4 - .../forms/NiceCheckbox/NiceCheckbox.css | 4 +- .../forms/NiceCheckbox/NiceCheckbox.js | 6 +- .../PipelineEditContainer.js | 1 - src/helpers/boxes.js | 143 ------------------ src/helpers/dot.js | 85 ----------- src/helpers/pipelineGraph.js | 99 ------------ src/locales/cs.json | 5 - src/locales/en.json | 5 - src/pages/Pipeline/Pipeline.js | 41 ++--- test/helpers/boxes.js | 111 -------------- 24 files changed, 22 insertions(+), 1005 deletions(-) delete mode 100644 src/components/Pipelines/BoxForm/AddBoxForm.js delete mode 100644 src/components/Pipelines/BoxForm/EditBoxForm.js delete mode 100644 src/components/Pipelines/PipelineVisualEditor/PipelineVisualEditor.js delete mode 100644 src/components/Pipelines/PipelineVisualEditor/index.js delete mode 100644 src/components/Pipelines/PipelineVisualEditor/pipeline.css delete mode 100644 src/components/Pipelines/PipelineVisualisation/PipelineVisualisation.js delete mode 100644 src/components/Pipelines/PipelineVisualisation/index.js delete mode 100644 src/components/Pipelines/PipelineVisualisation/pipeline.less delete mode 100644 src/components/forms/Fields/PipelineField.js delete mode 100644 src/components/forms/Fields/PipelineVariablesField.js delete mode 100644 src/components/forms/Fields/PortField.js delete mode 100644 src/components/forms/Fields/PortsField.js delete mode 100644 src/helpers/boxes.js delete mode 100644 src/helpers/dot.js delete mode 100644 src/helpers/pipelineGraph.js delete mode 100644 test/helpers/boxes.js diff --git a/src/components/Pipelines/BoxForm/AddBoxForm.js b/src/components/Pipelines/BoxForm/AddBoxForm.js deleted file mode 100644 index fd3eb2d8a..000000000 --- a/src/components/Pipelines/BoxForm/AddBoxForm.js +++ /dev/null @@ -1,36 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { FormattedMessage } from 'react-intl'; -import { connect } from 'react-redux'; - -import BoxForm from './BoxForm'; -import { getBoxTypes } from '../../../redux/selectors/boxes'; -import { createBoxFromFormInputs } from '../../../helpers/boxes'; - -const AddBoxForm = ({ add, onHide, boxTypes, ...props }) => ( - } - onSubmit={data => { - const { name, portsIn = {}, portsOut = {}, type } = createBoxFromFormInputs(data, boxTypes); - add(name, portsIn, portsOut, type); - onHide(); - }} - onHide={onHide} - onDelete={() => { - onHide(); - }} - /> -); - -AddBoxForm.propTypes = { - add: PropTypes.func.isRequired, - onHide: PropTypes.func.isRequired, - boxTypes: PropTypes.array.isRequired, -}; - -const mapStateToProps = state => ({ - boxTypes: getBoxTypes(state), -}); - -export default connect(mapStateToProps)(AddBoxForm); diff --git a/src/components/Pipelines/BoxForm/EditBoxForm.js b/src/components/Pipelines/BoxForm/EditBoxForm.js deleted file mode 100644 index 1a86dc0e1..000000000 --- a/src/components/Pipelines/BoxForm/EditBoxForm.js +++ /dev/null @@ -1,48 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { FormattedMessage } from 'react-intl'; -import { connect } from 'react-redux'; - -import BoxForm from './BoxForm'; -import { getBoxTypes } from '../../../redux/selectors/boxes'; -import { createBoxFromFormInputs } from '../../../helpers/boxes'; - -const EditBoxForm = ({ item, edit, onHide, boxTypes, onDelete, ...props }) => - item ? ( - - } - show={Boolean(item)} - initialValues={item} - onHide={onHide} - onSubmit={data => { - const box = createBoxFromFormInputs(data, boxTypes); - edit(box); - onHide(); - }} - onDelete={() => { - onDelete(); - onHide(); - }} - /> - ) : null; - -EditBoxForm.propTypes = { - item: PropTypes.object, - boxTypes: PropTypes.array.isRequired, - edit: PropTypes.func.isRequired, - onHide: PropTypes.func.isRequired, - onDelete: PropTypes.func.isRequired, -}; - -const mapStateToProps = state => ({ - boxTypes: getBoxTypes(state), -}); - -export default connect(mapStateToProps)(EditBoxForm); diff --git a/src/components/Pipelines/PipelineGraph/PipelineGraph.js b/src/components/Pipelines/PipelineGraph/PipelineGraph.js index 20d9a0a43..e4fe1f742 100644 --- a/src/components/Pipelines/PipelineGraph/PipelineGraph.js +++ b/src/components/Pipelines/PipelineGraph/PipelineGraph.js @@ -76,7 +76,7 @@ const technicalBoxLabels = { 'file-to-array': '{ file | [file] }', 'string-to-array': '{ str | [str] }', 'file-name': '{ file | str }', - 'file-names': '{ [files] | [strs] }', + 'files-names': '{ [files] | [strs] }', }; /** @@ -242,7 +242,6 @@ const preprocessClickEvent = (ev, boxIds, variableIds) => { const PipelineGraph = ({ boxes, - boxTypes, variables, utilization, selectedBox = null, @@ -269,7 +268,7 @@ const PipelineGraph = ({ setBoxIds(boxIds); setVariableIds(variableIds); startRenderingToSvg(dot).then(result => setSvg(result)); - }, [boxes, boxTypes, variables, utilization, selectedBox, selectedVariable]); + }, [boxes, variables, utilization, selectedBox, selectedVariable]); return ( @@ -305,7 +304,6 @@ const PipelineGraph = ({ PipelineGraph.propTypes = { boxes: PropTypes.array.isRequired, - boxTypes: PropTypes.object.isRequired, variables: PropTypes.array.isRequired, utilization: PropTypes.object.isRequired, selectedBox: PropTypes.string, diff --git a/src/components/Pipelines/PipelineVisualEditor/PipelineVisualEditor.js b/src/components/Pipelines/PipelineVisualEditor/PipelineVisualEditor.js deleted file mode 100644 index 2be85036c..000000000 --- a/src/components/Pipelines/PipelineVisualEditor/PipelineVisualEditor.js +++ /dev/null @@ -1,124 +0,0 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import { FormattedMessage } from 'react-intl'; - -import Button from '../../widgets/TheButton'; -import { AddIcon } from '../../icons'; - -import AddBoxForm from '../BoxForm/AddBoxForm'; -import EditBoxForm from '../BoxForm/EditBoxForm'; -import PipelineVisualisation from '../PipelineVisualisation'; - -import { addNode, replaceNode, removeNode, createGraphFromNodes } from '../../../helpers/pipelineGraph'; -import InsetPanel from '../../widgets/InsetPanel'; - -import './pipeline.css'; - -class PipelineVisualEditor extends Component { - state = { - graph: { dependencies: [], nodes: [] }, - addItem: false, - nodeToEdit: null, - }; - - componentDidMount = () => { - // initialize the graph, if the source is valid - const { source } = this.props; - const graph = createGraphFromNodes(source); - this.setState({ graph }); - - const { editorWrapper } = this; - editorWrapper.addEventListener('click', e => this.onClick(e.target)); - }; - - componentWillUnmount = () => { - const { editorWrapper } = this; - editorWrapper.removeEventListener('click', this.onClick); - }; - - onClick = target => { - const boxId = this.findTopmostCluster(target); - const nodeToEdit = boxId ? this.state.graph.nodes.find(node => node.name === boxId) : null; - - this.setState({ nodeToEdit }); - }; - - findTopmostCluster = el => { - let cluster = null; - while (el !== null && el.nodeName !== 'svg') { - if (el.classList.contains('cluster')) { - cluster = el.id.substr(2); // remove prefix ("B-", "I-", "O-") - break; - } - el = el.parentElement; - } - - return cluster; - }; - - addNode = (name, portsIn, portsOut, type) => { - const node = { name, portsIn, portsOut, type }; - const graph = addNode(this.state.graph, node); - - this.save(graph); - }; - - editNode = (oldNode, newNode) => { - const graph = replaceNode(this.state.graph, oldNode, newNode); - this.save(graph); - }; - - deleteNode = node => { - const graph = removeNode(this.state.graph, node); - this.save(graph); - }; - - showAddNodeForm = () => { - this.setState({ addItem: true }); - }; - - save = graph => { - const { onChange } = this.props; - onChange(graph.nodes); - this.setState({ graph }); - }; - - onHideModal = () => { - this.setState({ addItem: false, nodeToEdit: null }); - }; - - render() { - const { graph, nodeToEdit, addItem } = this.state; - return ( -
    { - this.editorWrapper = el; - }}> - - {graph.nodes.length > 0 && } -

    - -

    -
    - - this.editNode(nodeToEdit, data)} - show={Boolean(nodeToEdit)} - onHide={this.onHideModal} - onDelete={() => this.deleteNode(nodeToEdit)} - /> -
    - ); - } -} - -PipelineVisualEditor.propTypes = { - source: PropTypes.oneOfType([PropTypes.string, PropTypes.array]).isRequired, - onChange: PropTypes.func.isRequired, -}; - -export default PipelineVisualEditor; diff --git a/src/components/Pipelines/PipelineVisualEditor/index.js b/src/components/Pipelines/PipelineVisualEditor/index.js deleted file mode 100644 index 41af53c57..000000000 --- a/src/components/Pipelines/PipelineVisualEditor/index.js +++ /dev/null @@ -1,2 +0,0 @@ -import PipelineVisualEditor from './PipelineVisualEditor'; -export default PipelineVisualEditor; diff --git a/src/components/Pipelines/PipelineVisualEditor/pipeline.css b/src/components/Pipelines/PipelineVisualEditor/pipeline.css deleted file mode 100644 index ea0e1ab8c..000000000 --- a/src/components/Pipelines/PipelineVisualEditor/pipeline.css +++ /dev/null @@ -1,26 +0,0 @@ -.pipeline svg { - max-width: 100%; -} - -.pipeline svg .graph > polygon { - fill: transparent; -} - -.pipeline svg .cluster { - cursor: pointer; -} - -.pipeline svg .cluster, -.pipeline svg .cluster[id^="B-"] > polygon { - transition: all 0.15s ease-in-out; -} - -.pipeline svg .cluster[id^="B-"]:hover > polygon { - fill: #fffdf8; -} - -.pipeline svg .cluster[id^="I-"], -.pipeline svg .cluster[id^="O-"], -.pipeline svg .node { - pointer-events: none; -} diff --git a/src/components/Pipelines/PipelineVisualisation/PipelineVisualisation.js b/src/components/Pipelines/PipelineVisualisation/PipelineVisualisation.js deleted file mode 100644 index c6dcbef0a..000000000 --- a/src/components/Pipelines/PipelineVisualisation/PipelineVisualisation.js +++ /dev/null @@ -1,40 +0,0 @@ -import React, { useState, useEffect } from 'react'; -import PropTypes from 'prop-types'; -import { FormattedMessage } from 'react-intl'; - -import { convertGraphToSvg } from '../../../helpers/dot'; -import { canUseDOM } from 'exenv'; -import style from './pipeline.less'; -import { LoadingIcon } from '../../icons'; - -const PipelineVisualisation = ({ graph }) => { - if (canUseDOM) { - const [svg, setSvg] = useState(null); - useEffect(() => { - setSvg(null); - convertGraphToSvg(graph).then(result => setSvg(result)); - }, [graph]); - - return svg !== null ? ( -
    - ) : ( -
    - - -
    - ); - } else { - return
    ; - } -}; - -PipelineVisualisation.propTypes = { - graph: PropTypes.object, -}; - -export default PipelineVisualisation; diff --git a/src/components/Pipelines/PipelineVisualisation/index.js b/src/components/Pipelines/PipelineVisualisation/index.js deleted file mode 100644 index a6d257322..000000000 --- a/src/components/Pipelines/PipelineVisualisation/index.js +++ /dev/null @@ -1,2 +0,0 @@ -import PipelineVisualisation from './PipelineVisualisation'; -export default PipelineVisualisation; diff --git a/src/components/Pipelines/PipelineVisualisation/pipeline.less b/src/components/Pipelines/PipelineVisualisation/pipeline.less deleted file mode 100644 index b5c281939..000000000 --- a/src/components/Pipelines/PipelineVisualisation/pipeline.less +++ /dev/null @@ -1,9 +0,0 @@ -.pipeline { - padding: 20px 0; - width: 100%; - text-align: center; - - svg { - max-width: 100%; - } -} diff --git a/src/components/forms/Fields/PipelineField.js b/src/components/forms/Fields/PipelineField.js deleted file mode 100644 index 153f20c12..000000000 --- a/src/components/forms/Fields/PipelineField.js +++ /dev/null @@ -1,45 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { FormattedMessage } from 'react-intl'; - -import { Form, FormGroup, FormControl, FormLabel } from 'react-bootstrap'; - -import PipelineVisualEditor from '../../Pipelines/PipelineVisualEditor'; - -const PipelineField = ({ input, meta: { touched, error }, label, ...props }) => ( - - {label} -
    - -
    - {' '} - {error && ( - - {' '} - {touched ? error : }{' '} - - )} -
    -); - -PipelineField.propTypes = { - input: PropTypes.shape({ - name: PropTypes.string.isRequired, - value: PropTypes.oneOfType([PropTypes.string, PropTypes.array]).isRequired, - onChange: PropTypes.func.isRequired, - }).isRequired, - label: PropTypes.oneOfType([PropTypes.string, PropTypes.element]).isRequired, - meta: PropTypes.shape({ - touched: PropTypes.bool, - error: PropTypes.oneOfType([PropTypes.string, PropTypes.element]), - }), -}; - -export default PipelineField; diff --git a/src/components/forms/Fields/PipelineVariablesField.js b/src/components/forms/Fields/PipelineVariablesField.js deleted file mode 100644 index 63f5d216d..000000000 --- a/src/components/forms/Fields/PipelineVariablesField.js +++ /dev/null @@ -1,100 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { Field, FieldArray } from 'redux-form'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import { injectIntl, FormattedMessage } from 'react-intl'; -import { Row, Col, Container } from 'react-bootstrap'; -import { TextField, SelectField, ExpandingTextField, ExpandingSelectField } from '../Fields'; -import ResourceRenderer from '../../helpers/ResourceRenderer'; - -const isArray = (firstVal, type = '') => - firstVal && - firstVal.length > 0 && - firstVal[0] !== '$' && - typeof type === 'string' && - type.indexOf('[]') === type.length - 2; - -const firstValue = value => (Array.isArray(value) ? value[0] || '' : value); - -const PipelineVariablesField = ({ input, label, variables, supplementaryFiles, intl }) => ( - - -

    {label}

    - {variables.length === 0 && } - {variables - .reduce((acc, variable) => (acc.find(used => used.value === variable.value) ? acc : [...acc, variable]), []) - .map(({ value, type }, i) => ( - - {(type === 'remote-file' || type === 'remote-file[]') && ( - - {(...supplementaryFiles) => - isArray(firstValue(input.value[value]), type) ? ( - a.name.localeCompare(b.name, intl.locale)) - .filter((item, pos, arr) => arr.indexOf(item) === pos) - .map(data => ({ - key: data.hashName, - name: data.name, - })) - )} - label={`${atob(value)}: `} - /> - ) : ( - a.name.localeCompare(b.name, intl.locale)) - .filter((item, pos, arr) => arr.indexOf(item) === pos) - .map(data => ({ - key: data.hashName, - name: data.name, - })) - )} - label={`${atob(value)}: `} - /> - ) - } - - )} - {type !== 'remote-file' && - type !== 'remote-file[]' && - (isArray(firstValue(input.value[value]), type) ? ( - - ) : ( - - ))} - - ))} -
    -
    -); - -PipelineVariablesField.propTypes = { - input: PropTypes.shape({ - name: PropTypes.string.isRequired, - value: PropTypes.object, - }).isRequired, - label: PropTypes.oneOfType([PropTypes.string, PropTypes.element]).isRequired, - variables: PropTypes.array, - supplementaryFiles: ImmutablePropTypes.map, - intl: PropTypes.shape({ locale: PropTypes.string.isRequired }).isRequired, -}; - -export default injectIntl(PipelineVariablesField); diff --git a/src/components/forms/Fields/PortField.js b/src/components/forms/Fields/PortField.js deleted file mode 100644 index 03ee7bfd6..000000000 --- a/src/components/forms/Fields/PortField.js +++ /dev/null @@ -1,62 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -import { Form, FormGroup, FormControl, FormLabel, Badge } from 'react-bootstrap'; -import classnames from 'classnames'; - -import { isArrayType } from '../../../helpers/boxes'; - -import styles from './commonStyles.less'; - -const getLabelStyle = portType => (isArrayType(portType) ? 'primary' : 'info'); - -const PortField = ({ - input, - meta: { active, dirty, error, warning }, - label, - portType, - ignoreDirty = false, - ...props -}) => ( - - - {label}{' '} - - {portType} - - - - {error && {error} } - {!error && warning && {warning} } - -); - -PortField.propTypes = { - input: PropTypes.shape({ - name: PropTypes.string.isRequired, - value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, - }).isRequired, - meta: PropTypes.shape({ - active: PropTypes.bool, - dirty: PropTypes.bool, - error: PropTypes.any, - warning: PropTypes.any, - }).isRequired, - label: PropTypes.oneOfType([PropTypes.string, PropTypes.element]).isRequired, - portType: PropTypes.string.isRequired, - ignoreDirty: PropTypes.bool, -}; - -export default PortField; diff --git a/src/components/forms/Fields/PortsField.js b/src/components/forms/Fields/PortsField.js deleted file mode 100644 index 7d23fc876..000000000 --- a/src/components/forms/Fields/PortsField.js +++ /dev/null @@ -1,23 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { Field } from 'redux-form'; -import { PortField } from '../Fields'; -import { FormattedMessage } from 'react-intl'; - -const PortsField = ({ label, prefix, ports }) => ( -
    -

    {label}

    - {ports.length === 0 && } - {ports.map(({ name, type, value }) => ( - - ))} -
    -); - -PortsField.propTypes = { - label: PropTypes.oneOfType([PropTypes.string, PropTypes.element]).isRequired, - prefix: PropTypes.string.isRequired, - ports: PropTypes.array, -}; - -export default PortsField; diff --git a/src/components/forms/Fields/index.js b/src/components/forms/Fields/index.js index b6252c1a4..7f7f6ab0c 100644 --- a/src/components/forms/Fields/index.js +++ b/src/components/forms/Fields/index.js @@ -8,10 +8,6 @@ export { default as NumericTextField } from './NumericTextField'; export { default as PasswordField } from './PasswordField'; export { default as PasswordStrength } from './PasswordStrength'; export { default as LanguageSelectField } from './LanguageSelectField'; -export { default as PipelineField } from './PipelineField'; -export { default as PipelineVariablesField } from './PipelineVariablesField'; -export { default as PortField } from './PortField'; -export { default as PortsField } from './PortsField'; export { default as RadioField } from './RadioField'; export { default as SelectField } from './SelectField'; export { default as SimpleCheckboxField } from './SimpleCheckboxField'; diff --git a/src/components/forms/NiceCheckbox/NiceCheckbox.css b/src/components/forms/NiceCheckbox/NiceCheckbox.css index 86a645566..6145d6b17 100644 --- a/src/components/forms/NiceCheckbox/NiceCheckbox.css +++ b/src/components/forms/NiceCheckbox/NiceCheckbox.css @@ -28,8 +28,10 @@ box-shadow: #fe9 0 0 0.4em 0.1em; } -.nice-checkbox-container label.nice-checkbox-label { +.nice-checkbox-container .nice-checkbox-label { vertical-align: top; margin: 0.1rem 0.5rem; white-space: normal; + font-weight: 700; + line-height: 1.15; } diff --git a/src/components/forms/NiceCheckbox/NiceCheckbox.js b/src/components/forms/NiceCheckbox/NiceCheckbox.js index ae1849428..90e2a30b5 100644 --- a/src/components/forms/NiceCheckbox/NiceCheckbox.js +++ b/src/components/forms/NiceCheckbox/NiceCheckbox.js @@ -1,6 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { FormLabel, FormCheck, OverlayTrigger, Tooltip } from 'react-bootstrap'; +import { FormCheck, OverlayTrigger, Tooltip } from 'react-bootstrap'; import classnames from 'classnames'; import Icon, { WarningIcon } from '../../icons'; @@ -61,10 +61,10 @@ const NiceCheckbox = ({ {!children && warningIcon} {Boolean(children) && ( - + {children} {warningIcon} - + )} diff --git a/src/containers/PipelineEditContainer/PipelineEditContainer.js b/src/containers/PipelineEditContainer/PipelineEditContainer.js index 437ce676d..b34dc9678 100644 --- a/src/containers/PipelineEditContainer/PipelineEditContainer.js +++ b/src/containers/PipelineEditContainer/PipelineEditContainer.js @@ -653,7 +653,6 @@ class PipelineEditContainer extends Component { type.indexOf('[]') > 0; - -export const getVariablesTypes = (boxTypes, boxes) => { - const variablesTypes = {}; - for (const box of boxes) { - const boxType = boxTypes.find(boxType => boxType.type === box.type); - for (const port of Object.keys(box.portsIn || {})) { - const { value } = box.portsIn[port]; - const { type } = boxType.portsIn[port]; - variablesTypes[value] = { - type, - examplePort: box.name, - }; - } - for (const port of Object.keys(box.portsOut)) { - const { value } = box.portsOut[port]; - const { type } = boxType.portsOut[port]; - variablesTypes[value] = { - type, - examplePort: box.name, - }; - } - } - - return variablesTypes; -}; - -const transformPortTypes = (ports, boxTypePorts, variableTypes) => - Object.keys(boxTypePorts).reduce( - (acc, name) => ({ - ...acc, - [name]: ports[name] ? ports[name] : { value: '', type: boxTypePorts[name].type }, - }), - {} - ); - -export const transformPipelineDataForApi = (boxTypes, { boxes, variables }, extractedVariables) => { - const variableTypes = getVariablesTypes(boxTypes, boxes); - const transformedData = { - boxes: boxes.map(box => { - const boxType = boxTypes.find(boxType => boxType.type === box.type); - - if (Object.keys(boxType.portsIn).length === 0) { - delete box.portsIn; - } else { - box.portsIn = transformPortTypes(box.portsIn, boxType.portsIn, variableTypes); - } - - if (Object.keys(boxType.portsOut).length === 0) { - delete box.portsOut; - } else { - box.portsOut = transformPortTypes(box.portsOut, boxType.portsOut, variableTypes); - } - - return box; - }), - variables: extractedVariables - .map(({ value }) => value) - .map(key => ({ - name: atob(key), - value: variables[key] ? variables[key] : '', - })) - .filter(({ name }) => variableTypes[name]) - .map(({ name, ...variable }) => ({ - ...variable, - name, - type: variableTypes[name].type, - })), - }; - - return transformedData; -}; - -export const createBoxFromFormInputs = (data, boxTypes) => { - const boxType = boxTypes.find(box => box.type === data.type); - if (!boxType) { - throw new Error('No box type was selected.'); - } - - const allowedPortsIn = Object.keys(boxType.portsIn); - const allowedPortsOut = Object.keys(boxType.portsOut); - - const portsIn = data.portsIn - ? allowedPortsIn.reduce( - (acc, port) => - data.portsIn[port] - ? { - ...acc, - [port]: { - ...data.portsIn[port], - type: boxType.portsIn[port].type, - }, - } - : acc, - {} - ) - : {}; - - const portsOut = data.portsOut - ? allowedPortsOut.reduce( - (acc, port) => - data.portsOut[port] - ? { - ...acc, - [port]: { - ...data.portsOut[port], - type: boxType.portsOut[port].type, - }, - } - : acc, - {} - ) - : {}; - - return { ...data, portsIn, portsOut }; -}; - -const flattenPorts = boxes => - boxes.reduce( - (acc, ports) => [ - ...acc, - ...Object.keys(ports).map(port => ({ - name: port, - type: ports[port].type, - value: btoa(ports[port].value), - })), - ], - [] - ); - -export const extractVariables = (boxes = []) => { - const inputs = flattenPorts(boxes.map(box => ({ ...box.portsIn })).filter(ports => ports)).filter( - ({ value }) => value.length > 0 - ); - - // remove duplicities - return inputs.reduce((acc, port) => (!acc.find(item => item.name === port.name) ? [...acc, port] : acc), []); -}; diff --git a/src/helpers/dot.js b/src/helpers/dot.js deleted file mode 100644 index 17d69ee4e..000000000 --- a/src/helpers/dot.js +++ /dev/null @@ -1,85 +0,0 @@ -/* - * DEPRECATED - all relevant stuff moved to pipelines.js - * TODO DELETE - */ - -import Viz from 'viz.js'; -const { Module, render } = require('viz.js/lite.render.js'); - -const subnode = (node, port) => `"${node}__${port}"`; - -const createDependency = (from, to, clusterTo = null) => { - const dep = `${from} -> ${to}` + (clusterTo === null ? '' : `[lhead = cluster_${clusterTo}]`); - return dep; -}; - -const createDotForPorts = (name, ports) => - Object.keys(ports) - .map(portName => ports[portName].value) - .filter(value => value.length > 0) - .map(port => `${subnode(name, port)} [label="${port}"]`); - -const createDotForNodeFactory = - dependencies => - (name, portsIn = {}, portsOut = {}, i) => { - const hasFullSupport = true; - const inputs = createDotForPorts(name, portsIn); - const outputs = createDotForPorts(name, portsOut); - - return ` - subgraph cluster_${i} { - label = "${name}"; - id = "B-${name}"; - ${!hasFullSupport ? 'fontcolor = "red"; color = "red";' : 'color = "black"; style = "filled, solid";'} - fillcolor = "#f9f9f9"; - subgraph cluster_inputs { - style = "filled, solid"; - id = "I-${name}"; - label = "inputs"; - color = "#fcffc6"; - fillcolor = "#fcffc6"; - fontcolor = black; - ${inputs.join(';')} - } - subgraph cluster_outputs { - style = "filled, solid"; - id = "O-${name}"; - label = "outputs"; - color = "#d1f9e9"; - fillcolor = "#d1f9e9"; - fontcolor = black; - ${outputs.join(';')} - } - ${inputs.length === 0 && outputs.length === 0 ? `"E-${name}" [label="void"]` : ''} - }`; - }; - -const createDotForDependencyFactory = nodes => (from, to, name) => { - const nodeTo = nodes.find(node => node.name === to); - const clusterTo = nodes.indexOf(nodeTo); - return createDependency(subnode(from, name), subnode(to, name), clusterTo); -}; - -const createDotForGraph = (nodes, commands) => ` - digraph { - node [shape=rect]; - compound = true; - ${nodes.join('\n')} - ${commands.join(';')} - }`; - -export const convertGraphToDot = ({ nodes, dependencies }) => { - const createDotForDependency = createDotForDependencyFactory(nodes); - const commands = dependencies.map(({ from, to, name }) => createDotForDependency(from, to, name)); - - const createDotForNode = createDotForNodeFactory(dependencies); - const nodesDot = nodes.map(({ name, portsIn, portsOut }, i) => createDotForNode(name, portsIn, portsOut, i)); - - return createDotForGraph(nodesDot, commands); -}; - -export const convertGraphToSvg = graph => { - const dot = graph ? convertGraphToDot(graph) : ''; - const viz = new Viz({ Module, render }); - return viz.renderString(dot); -}; diff --git a/src/helpers/pipelineGraph.js b/src/helpers/pipelineGraph.js deleted file mode 100644 index b7cd0e727..000000000 --- a/src/helpers/pipelineGraph.js +++ /dev/null @@ -1,99 +0,0 @@ -export const addNode = (graph, node) => { - graph.nodes.push(node); - return addDependencies(graph, node); -}; - -export const addDependencies = (graph, node) => { - const dependencies = graph.dependencies; - const candidates = []; - - const nodePortsIn = node.portsIn ? Object.keys(node.portsIn) : {}; - const nodePortsOut = node.portsOut ? Object.keys(node.portsOut) : {}; - - for (const old of graph.nodes) { - const oldPortsIn = old.portsIn ? Object.keys(old.portsIn) : {}; - const oldPortsOut = old.portsOut ? Object.keys(old.portsOut) : {}; - for (const portInName of oldPortsIn) { - const portIn = old.portsIn[portInName]; - if (portIn.value.length === 0) { - continue; - } - - for (const portOutName of nodePortsOut) { - const portOut = node.portsOut[portOutName]; - if (portOut.value.length > 0 && portIn.value === portOut.value) { - candidates.push({ - from: node.name, - to: old.name, - name: portIn.value, - }); - } - } - } - - for (const portInName of nodePortsIn) { - const portIn = node.portsIn[portInName]; - if (portIn.value.length === 0) { - continue; - } - - for (const portOutName of oldPortsOut) { - const portOut = old.portsOut[portOutName]; - if (portOut.value.length > 0 && portIn.value === portOut.value) { - candidates.push({ - from: old.name, - to: node.name, - name: portIn.value, - }); - } - } - } - } - - for (const candidate of candidates) { - let unique = true; - for (const dependency of dependencies) { - if (candidate.name === dependency.name && candidate.from === dependency.from && candidate.to === dependency.to) { - unique = false; - break; - } - } - - if (unique === true) { - dependencies.push(candidate); - } - } - - return { - nodes: graph.nodes, - dependencies, - }; -}; - -export const removeNode = ({ nodes, dependencies }, node) => ({ - nodes: nodes.filter(n => n.name !== node.name), - dependencies: dependencies.filter(dep => dep.from !== node.name && dep.to !== node.name), -}); - -export const replaceNode = (graph, oldNode, newNode) => addNode(removeNode(graph, oldNode), newNode); - -export const createGraphFromNodes = nodes => { - let graph = { nodes, dependencies: [] }; - - for (const node of graph.nodes) { - graph = addDependencies(graph, node); - } - - return graph; -}; - -/* - * Manipulation with the JSON source code - */ - -export const createGraphFromSource = source => { - const nodes = JSON.parse(source); - return createGraphFromNodes(nodes); -}; - -export const graphToSource = graph => JSON.stringify(graph.nodes); diff --git a/src/locales/cs.json b/src/locales/cs.json index adbc55842..bf80cec06 100644 --- a/src/locales/cs.json +++ b/src/locales/cs.json @@ -849,7 +849,6 @@ "app.failureListItem.referenceAssignment": "Referenční úloha", "app.failureListItem.studentAssignment": "Studentská úloha", "app.faq.title": "Často kladené dotazy (FAQ)", - "app.field.isRequired": "Tato položka je povinná.", "app.fields.limits.memory": "Paměť [KiB]:", "app.fields.limits.time": "Čas [s]:", "app.filesTable.downloadArchive": "Stáhnout vše jako ZIP soubor", @@ -1121,8 +1120,6 @@ "app.pipelineEditContainer.showAsTableIcon": "Zobrazit jako tabulku", "app.pipelineEditContainer.title": "Struktura pipeline", "app.pipelineEditContainer.variablesTitle": "Proměnné", - "app.pipelineEditor.AddBoxForm.title": "Přidat krabičku", - "app.pipelineEditor.EditBoxForm.title": "Upravit krabičku \"{name}\"", "app.pipelineFilesTable.description": "Testovací soubory jsou soubory, které mohou být odkazované v konfiguraci pipeline.", "app.pipelineFilesTable.title": "Soubory pipeline", "app.pipelineParams.hasEntryPoint": "Testované řešení by mělo specifikovat vstupní bod aplikace", @@ -1132,7 +1129,6 @@ "app.pipelineParams.judgeOnlyPipeline": "Pipeline pouze se sudím", "app.pipelineParams.producesFiles": "Testované řešení by mělo vypsat svoje výsledky do daného souboru", "app.pipelineParams.producesStdout": "Testované řešení by mělo vypsat svoje výsledky na standardní výstup", - "app.pipelineVisualEditor.addBoxButton": "Přidat krabičku", "app.pipelines.boxForm.duplicitName": "Toto jméno již bylo přiděleno pro jinou krabičku.", "app.pipelines.boxForm.emptyName": "Jméno krabičky nemůže zůstat prázdné.", "app.pipelines.boxForm.inputPorts": "Vstupní porty", @@ -1249,7 +1245,6 @@ "app.pointsForm.scoredPoints": "Body udělené z poslední evaluace", "app.pointsForm.title": "Přidělené body", "app.pointsForm.validation.overrideOutOfRange": "Přenastavené body jsou mimo běžný rozsah. Běžný rozsah pro tuto zadanou úlohu je mezi 0 a {maxPointsEver}.", - "app.portsField.empty": "Nejsou zde žádné porty.", "app.randomMessages.error": "Nastala chyba při komunikaci se serverem a bohužel Vám nemůžeme ukázat, jaký ja aktuální průběh, ale nic hrozného se neděje. Výsledky budou dostupné tak jako tak již brzy po skončení vyhodnocení.", "app.randomMessages.last": "Vygenerovat náhodné ohodnocení odevzdaného řešení", "app.randomMessages.m1": "Koupit mléko", diff --git a/src/locales/en.json b/src/locales/en.json index dc1fc7dc3..679c0f4e8 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -849,7 +849,6 @@ "app.failureListItem.referenceAssignment": "Reference assignment", "app.failureListItem.studentAssignment": "Student assignment", "app.faq.title": "Frequently Asked Questions", - "app.field.isRequired": "This field is required.", "app.fields.limits.memory": "Memory [KiB]:", "app.fields.limits.time": "Time [s]:", "app.filesTable.downloadArchive": "Download all as ZIP archive", @@ -1121,8 +1120,6 @@ "app.pipelineEditContainer.showAsTableIcon": "Show as table", "app.pipelineEditContainer.title": "Edit Pipeline Structure", "app.pipelineEditContainer.variablesTitle": "Variables", - "app.pipelineEditor.AddBoxForm.title": "Add a box", - "app.pipelineEditor.EditBoxForm.title": "Edit the box \"{name}\"", "app.pipelineFilesTable.description": "Supplementary files are files which can be referenced as remote file in pipeline configuration.", "app.pipelineFilesTable.title": "Pipeline files", "app.pipelineParams.hasEntryPoint": "Tested solution is expected to specify entry point of the application", @@ -1132,7 +1129,6 @@ "app.pipelineParams.judgeOnlyPipeline": "Judge-only pipeline", "app.pipelineParams.producesFiles": "Tested solution is expected to yield results into a specific file", "app.pipelineParams.producesStdout": "Tested solution is expected to yield results to standard output", - "app.pipelineVisualEditor.addBoxButton": "Add box", "app.pipelines.boxForm.duplicitName": "This name is already taken by another box.", "app.pipelines.boxForm.emptyName": "Box name cannot be empty.", "app.pipelines.boxForm.inputPorts": "Input ports", @@ -1249,7 +1245,6 @@ "app.pointsForm.scoredPoints": "Scored points from last evaluation", "app.pointsForm.title": "Awarded Points", "app.pointsForm.validation.overrideOutOfRange": "Points override is out of regular range. Regular score for this assignment is between 0 and {maxPointsEver}.", - "app.portsField.empty": "There are no ports.", "app.randomMessages.error": "Unexpected error during communication with server occured. We cannot show you actual progress of the evaluation, but do not worry. The results will be available as well after evaluation finishes.", "app.randomMessages.last": "Generate random evaluation of submitted solution", "app.randomMessages.m1": "Buy some milk", diff --git a/src/pages/Pipeline/Pipeline.js b/src/pages/Pipeline/Pipeline.js index 8405c342c..792a16e0d 100644 --- a/src/pages/Pipeline/Pipeline.js +++ b/src/pages/Pipeline/Pipeline.js @@ -9,7 +9,6 @@ import { Link } from 'react-router-dom'; import Page from '../../components/layout/Page'; import Box from '../../components/widgets/Box'; import Button from '../../components/widgets/TheButton'; -import InsetPanel from '../../components/widgets/InsetPanel'; import { EditIcon, PipelineIcon } from '../../components/icons'; // import ForkPipelineForm from '../../components/forms/ForkPipelineForm'; @@ -18,46 +17,35 @@ import { getPipeline, pipelineEnvironmentsSelector } from '../../redux/selectors import { loggedInUserIdSelector } from '../../redux/selectors/auth'; import { canEditPipeline } from '../../redux/selectors/users'; -import { createGraphFromNodes } from '../../helpers/pipelineGraph'; +import { getVariablesUtilization } from '../../helpers/pipelines'; import withLinks from '../../helpers/withLinks'; import PipelineDetail from '../../components/Pipelines/PipelineDetail'; -import PipelineVisualisation from '../../components/Pipelines/PipelineVisualisation'; +import PipelineGraph from '../../components/Pipelines/PipelineGraph'; import ResourceRenderer from '../../components/helpers/ResourceRenderer'; import { fetchRuntimeEnvironments } from '../../redux/modules/runtimeEnvironments'; class Pipeline extends Component { state = { - graph: { dependencies: [], nodes: [] }, forkId: null, }; + static loadAsync = ({ pipelineId }, dispatch) => + Promise.all([dispatch(fetchPipelineIfNeeded(pipelineId)), dispatch(fetchRuntimeEnvironments())]); + componentDidMount() { - this.props.loadAsync(val => this.setState(val)); + this.props.loadAsync(); this.reset(); } componentDidUpdate(prevProps) { if (this.props.match.params.pipelineId !== prevProps.match.params.pipelineId) { - this.props.loadAsync(val => this.setState(val)); + this.props.loadAsync(); this.reset(); } } reset = () => this.setState({ forkId: Math.random().toString() }); - static loadAsync = ({ pipelineId }, dispatch, { setState = null }) => - Promise.all([ - dispatch(fetchPipelineIfNeeded(pipelineId)) - .then(res => res.value) - .then(pipeline => { - const graph = createGraphFromNodes(pipeline.pipeline.boxes); - if (setState) { - setState({ graph }); - } - }), - dispatch(fetchRuntimeEnvironments()), - ]); - render() { const { links: { PIPELINE_EDIT_URI_FACTORY }, @@ -66,7 +54,6 @@ class Pipeline extends Component { // forkPipeline, runtimeEnvironments, } = this.props; - const { graph } = this.state; return ( @@ -108,11 +94,12 @@ class Pipeline extends Component { } - noPadding unlimitedHeight> - - {graph.nodes.length > 0 && } - + @@ -164,7 +151,7 @@ export default withLinks( }, } ) => ({ - loadAsync: setState => Pipeline.loadAsync({ pipelineId }, dispatch, { setState }), + loadAsync: () => Pipeline.loadAsync({ pipelineId }, dispatch), forkPipeline: (forkId, data) => dispatch(forkPipeline(pipelineId, forkId, data)), }) )(Pipeline) diff --git a/test/helpers/boxes.js b/test/helpers/boxes.js deleted file mode 100644 index 8cd66750f..000000000 --- a/test/helpers/boxes.js +++ /dev/null @@ -1,111 +0,0 @@ -import { expect } from 'chai'; -import { createBoxFromFormInputs, transformPipelineDataForApi } from '../../src/helpers/boxes'; - -global.atob = b64Encoded => Buffer.from(b64Encoded, 'base64').toString(); -global.Buffer = global.Buffer || require('buffer').Buffer; - -describe('helpers', () => { - describe('Boxes for pipelines editor', () => { - it('must correctly transform input data to the data that can be sent to the server', () => { - const data = { - name: 'X', - type: 'box-type-A', - portsIn: { - A: { type: 'file[]' }, - B: { type: 'file' }, - }, - portsOut: { - C: { type: 'string' }, - }, - }; - const boxTypes = [ - { - type: 'box-type-A', - portsIn: { - A: { - type: 'file[]', - }, - B: { - type: 'file', - }, - }, - portsOut: {}, - }, - ]; - - const transformedBox = createBoxFromFormInputs(data, boxTypes); - - expect(transformedBox).to.eql({ - name: 'X', - type: 'box-type-A', - portsIn: { - A: { type: 'file[]' }, - B: { type: 'file' }, - }, - portsOut: {}, - }); - }); - }); - - describe('Sending graph to the server', () => { - it('should preprocess the data before sending to the server', () => { - const boxTypes = [ - { - name: 'Input Data', - type: 'data-in', - portsIn: [], - portsOut: { 'in-data': { type: '?', value: '' } }, - }, - { - name: 'GCC Compilation', - type: 'gcc', - portsIn: { 'source-files': { type: 'file[]', value: '' } }, - portsOut: { 'binary-file': { type: 'file', value: '' } }, - }, - ]; - const pipeline = { - boxes: [ - { - name: 'A', - portsIn: {}, - portsOut: { 'in-data': { value: 'a', type: 'file[]' } }, - type: 'data-in', - }, - { - name: 'B', - portsIn: { 'source-files': { value: 'a', type: 'file[]' } }, - portsOut: {}, - type: 'gcc', - }, - ], - variables: { 'YQ==': ['ABC'] }, - }; - const extractedVariables = [{ name: 'in-data', type: 'file[]', value: 'YQ==' }]; - - const transformedData = transformPipelineDataForApi(boxTypes, pipeline, extractedVariables); - - expect(transformedData).to.eql({ - boxes: [ - { - name: 'A', - portsOut: { 'in-data': { value: 'a', type: 'file[]' } }, - type: 'data-in', - }, - { - name: 'B', - portsIn: { 'source-files': { value: 'a', type: 'file[]' } }, - portsOut: { 'binary-file': { value: '', type: 'file' } }, - type: 'gcc', - }, - ], - variables: [ - { - name: 'a', - type: 'file[]', - value: ['ABC'], - }, - ], - }); - }); - }); -}); From 1b57b92e2a73f6a1b99557777fb4e3e5fed9a8b8 Mon Sep 17 00:00:00 2001 From: Martin Krulis Date: Thu, 23 Dec 2021 17:17:14 +0100 Subject: [PATCH 10/20] Performing structural checks when pipeline is loaded into edit container. --- .../PipelineEditContainer.js | 403 ++++++++++-------- src/helpers/common.js | 14 + src/helpers/pipelines.js | 57 ++- src/locales/cs.json | 5 + src/locales/en.json | 5 + 5 files changed, 312 insertions(+), 172 deletions(-) diff --git a/src/containers/PipelineEditContainer/PipelineEditContainer.js b/src/containers/PipelineEditContainer/PipelineEditContainer.js index b34dc9678..e9ede98d4 100644 --- a/src/containers/PipelineEditContainer/PipelineEditContainer.js +++ b/src/containers/PipelineEditContainer/PipelineEditContainer.js @@ -13,7 +13,7 @@ import VariableForm, { newVariableInitialData } from '../../components/Pipelines import BoxForm, { newBoxInitialData } from '../../components/Pipelines/BoxForm'; import Button, { TheButtonGroup } from '../../components/widgets/TheButton'; import Callout from '../../components/widgets/Callout'; -import Icon, { RefreshIcon, SaveIcon, UndoIcon, RedoIcon } from '../../components/icons'; +import Icon, { RefreshIcon, SaveIcon, SuccessIcon, UndoIcon, RedoIcon } from '../../components/icons'; import { getVariablesUtilization, @@ -23,12 +23,14 @@ import { getReferenceIdentifier, makeExternalReference, getVariablesTypes, + checkPipelineStructure, validatePipeline, } from '../../helpers/pipelines'; import { getBoxTypes } from '../../redux/selectors/boxes'; import { objectMap, arrayToObject, encodeId, deepCompare, identity } from '../../helpers/common'; import styles from '../../components/Pipelines/styles.less'; +import InsetPanel from '../../components/widgets/InsetPanel'; const getFormattedErrorAsKey = element => { const values = element.props.values ? { ...element.props.values } : {}; @@ -108,17 +110,16 @@ class PipelineEditContainer extends Component { static getDerivedStateFromProps(nextProps, prevState) { if (prevState.pipelineId !== nextProps.pipeline.id) { // pipeline was changed whilst component was kept mounted => complete reload + const pipeline = checkPipelineStructure(nextProps.pipeline.pipeline); + const pipelineStructureCoerced = pipeline !== nextProps.pipeline.pipeline; return { pipelineId: nextProps.pipeline.id, version: nextProps.pipeline.version, - boxes: nextProps.pipeline.pipeline.boxes, - variables: nextProps.pipeline.pipeline.variables, + boxes: pipeline.boxes, + variables: pipeline.variables, boxTypes: nextProps.boxTypes, - errors: validatePipeline( - nextProps.pipeline.pipeline.boxes, - nextProps.pipeline.pipeline.variables, - nextProps.boxTypes - ), + pipelineStructureCoerced, + errors: validatePipeline(pipeline.boxes, pipeline.variables, nextProps.boxTypes), history: [], future: [], ...STATE_DEFAULTS, @@ -504,7 +505,7 @@ class PipelineEditContainer extends Component { showTableAndGraph = () => this.setState({ showTable: true, showGraph: true }); render() { - const { boxTypes } = this.props; + const { boxTypes, pipeline } = this.props; const utilization = getVariablesUtilization(this.state.boxes); return ( 0 ? 'danger' : 'light'} customIcons={ - <> - - - - }> - - - - - - }> - - - - - - }> - - - + !this.state.pipelineStructureCoerced ? ( + <> + + + + }> + + + + + + }> + + + + + + }> + + + + ) : null } footer={ -
    - - - - - - - - - - - - - - -
    +
    + ) : ( +
    + + + + + + + + + + + + + + +
    + ) }> <> - - {this.state.showTable && ( - - -

    - -

    - {this.state.boxes && ( - + +

    + +

    +

    + +

    +
    + + + + + + + : + +
    {JSON.stringify(pipeline.pipeline, undefined, 4)}
    +
    + + + + + + : + +
    +                        {JSON.stringify({ boxes: this.state.boxes, variables: this.state.variables }, undefined, 4)}
    +                      
    +
    + +
    +
    + + ) : ( + + {this.state.showTable && ( + + +

    + +

    + {this.state.boxes && ( + + )} + + + +

    + +

    + {this.state.variables && ( + + )} + +
    + )} + + {this.state.showGraph && ( + + + - )} - - - -

    - -

    - {this.state.variables && ( - - )} - -
    - )} - - {this.state.showGraph && ( - - - - - - )} - - {this.state.errors && this.state.errors.length > 0 && ( - - - -
    - - : -
    -
      - {this.state.errors.map(error => ( -
    • {error}
    • - ))} -
    -
    - -
    - )} -
    + +
    + )} + + {this.state.errors && this.state.errors.length > 0 && ( + + + +
    + + : +
    +
      + {this.state.errors.map(error => ( +
    • {error}
    • + ))} +
    +
    + +
    + )} +
    + )} const idSelector = obj => obj.id; +/** + * Similar to array.filter, but applied on an object. + * @param {Object} obj to be filtered + * @param {Function} predicate called on every entry, returns true should the entry remain + * @returns {Object} clone of obj with entries filtered out + */ +export const objectFilter = (obj, predicate) => { + const res = {}; + Object.keys(obj) + .filter(key => predicate(obj[key], key)) + .forEach(key => (res[key] = obj[key])); + return res; +}; + /** * Convert array into object. Values of the array remain the values of the object. * Keys are computed from values using indexer function diff --git a/src/helpers/pipelines.js b/src/helpers/pipelines.js index 3eee8d642..fd949bdb3 100644 --- a/src/helpers/pipelines.js +++ b/src/helpers/pipelines.js @@ -4,7 +4,7 @@ import React from 'react'; import { FormattedMessage } from 'react-intl'; import { defaultMemoize } from 'reselect'; -import { arrayToObject, identity } from './common'; +import { arrayToObject, identity, objectFilter } from './common'; export const KNOWN_DATA_TYPES = ['file', 'remote-file', 'string'] .reduce((acc, type) => [...acc, type, type + '[]'], []) @@ -107,6 +107,61 @@ export const getVariablesTypes = defaultMemoize(variables => ) ); +/* + * Structural checks + */ + +const isPortStructureOk = port => { + return port && typeof port === 'object' && typeof port.type === 'string' && typeof port.value === 'string'; +}; + +const checkBoxStructure = box => { + if (!box || typeof box !== 'object' || typeof box.name !== 'string' || typeof box.type !== 'string') { + return null; + } + const portsIn = box.portsIn && typeof box.portsIn === 'object' && objectFilter(box.portsIn, isPortStructureOk); + const portsOut = box.portsOut && typeof box.portsOut === 'object' && objectFilter(box.portsOut, isPortStructureOk); + + if ( + !portsIn || + !portsOut || + Object.keys(portsIn).length !== Object.keys(box.portsIn).length || + Object.keys(portsOut).length !== Object.keys(box.portsOut).length + ) { + return { ...box, portsIn: portsIn || {}, portsOut: portsOut || {} }; + } else { + return box; // input object returned => everything was fine + } +}; + +const checkVariableStructure = variable => { + return variable && + typeof variable === 'object' && + typeof variable.name === 'string' && + typeof variable.type === 'string' + ? variable // input object returned => everything was fine + : null; +}; + +const _cmpArrays = (a1, a2) => + Array.isArray(a1) && Array.isArray(a2) && a1.length === a2.length && a1.every((val, idx) => val === a2[idx]); + +/** + * Make sure a pipeline structure is ok. If not, a fix is attempted. + * @param {Object} pipeline the pipeline structure to be verified + * @returns {Object} the input pipeline object if it passes the checks, a newly constructed obejct with corrections otherwise + */ +export const checkPipelineStructure = pipeline => { + const boxes = (Array.isArray(pipeline.boxes) ? pipeline.boxes : []).map(checkBoxStructure).filter(identity); + const variables = (Array.isArray(pipeline.variables) ? pipeline.variables : []) + .map(checkVariableStructure) + .filter(identity); + + return !_cmpArrays(boxes, pipeline.boxes) || !_cmpArrays(variables, pipeline.variables) + ? { ...pipeline, boxes, variables } + : pipeline; +}; + /* * Validation */ diff --git a/src/locales/cs.json b/src/locales/cs.json index bf80cec06..0ad03c494 100644 --- a/src/locales/cs.json +++ b/src/locales/cs.json @@ -1118,6 +1118,10 @@ "app.pipelineEditContainer.showAsBothIcon": "Zobrazit zároveň tabulku i diagram", "app.pipelineEditContainer.showAsGraphIcon": "Zobrazit jako diagram", "app.pipelineEditContainer.showAsTableIcon": "Zobrazit jako tabulku", + "app.pipelineEditContainer.structureCoercedFixed": "Opravená struktura", + "app.pipelineEditContainer.structureCoercedOriginal": "Originál", + "app.pipelineEditContainer.structureCoercedWarning": "Struktura pipeline neodpovídá předepsanému schématu a musela být opravena. Něktré údaje mohly být ztraceny. Originální a opravenou strukturu můžete vidět níže.", + "app.pipelineEditContainer.structureCoercedWarningTitle": "Struktura pipeline je rozbitá", "app.pipelineEditContainer.title": "Struktura pipeline", "app.pipelineEditContainer.variablesTitle": "Proměnné", "app.pipelineFilesTable.description": "Testovací soubory jsou soubory, které mohou být odkazované v konfiguraci pipeline.", @@ -1711,6 +1715,7 @@ "app.usersStats.description": "Body získané ve skupině {name}.", "app.usersname.notVerified.description": "Tento uživatel si neověřil svou e-mailovou adresu přes aktivační odkaz, který mu byl na tuto adresu zaslán.", "diff": "Sudí binárních dat", + "generic.accept": "Akceptovat", "generic.accessDenied": "Nemáte oprávnění vidět tuto stránku. Pokud došlo k přesměrování na tuto stránku po kliknutí na zdánlivě legitimní odkaz nebo tlačítko, prosíme nahlaste chybu.", "generic.acknowledge": "Beru na vědomí", "generic.assignedAt": "Zadáno", diff --git a/src/locales/en.json b/src/locales/en.json index 679c0f4e8..2ab2d9a6a 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -1118,6 +1118,10 @@ "app.pipelineEditContainer.showAsBothIcon": "Show both data table and diagram", "app.pipelineEditContainer.showAsGraphIcon": "Show as visual diagram", "app.pipelineEditContainer.showAsTableIcon": "Show as table", + "app.pipelineEditContainer.structureCoercedFixed": "Fixed structure", + "app.pipelineEditContainer.structureCoercedOriginal": "Original", + "app.pipelineEditContainer.structureCoercedWarning": "The pipeline structure was not upholding the prescribed schema and had to be fixed. Some information may have been lost. The original and the fixed pipeline structure is serialized below.", + "app.pipelineEditContainer.structureCoercedWarningTitle": "The pipeline structure was broken", "app.pipelineEditContainer.title": "Edit Pipeline Structure", "app.pipelineEditContainer.variablesTitle": "Variables", "app.pipelineFilesTable.description": "Supplementary files are files which can be referenced as remote file in pipeline configuration.", @@ -1711,6 +1715,7 @@ "app.usersStats.description": "Points gained from {name}.", "app.usersname.notVerified.description": "This user has not verified his/her email address via an activation link he has received to his email address.", "diff": "Binary-safe judge", + "generic.accept": "Accept", "generic.accessDenied": "You do not have permissions to see this page. If you got to this page via a seemingly legitimate link or button, please report a bug.", "generic.acknowledge": "Acknowledge", "generic.assignedAt": "Assigned at", From 4bf684b4225a868a9216f2c369a6bf773f32946a Mon Sep 17 00:00:00 2001 From: Martin Krulis Date: Sat, 25 Dec 2021 00:53:42 +0100 Subject: [PATCH 11/20] Pipeline import and export added to editor container. --- .../PipelineEditContainer.js | 111 +++++++++++++++++- src/locales/cs.json | 5 + src/locales/en.json | 5 + 3 files changed, 117 insertions(+), 4 deletions(-) diff --git a/src/containers/PipelineEditContainer/PipelineEditContainer.js b/src/containers/PipelineEditContainer/PipelineEditContainer.js index e9ede98d4..e6e4b8fbb 100644 --- a/src/containers/PipelineEditContainer/PipelineEditContainer.js +++ b/src/containers/PipelineEditContainer/PipelineEditContainer.js @@ -2,7 +2,7 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import { FormattedMessage } from 'react-intl'; +import { FormattedMessage, defineMessages, injectIntl } from 'react-intl'; import { Container, Row, Col, OverlayTrigger, Tooltip } from 'react-bootstrap'; import Box from '../../components/widgets/Box'; @@ -13,7 +13,15 @@ import VariableForm, { newVariableInitialData } from '../../components/Pipelines import BoxForm, { newBoxInitialData } from '../../components/Pipelines/BoxForm'; import Button, { TheButtonGroup } from '../../components/widgets/TheButton'; import Callout from '../../components/widgets/Callout'; -import Icon, { RefreshIcon, SaveIcon, SuccessIcon, UndoIcon, RedoIcon } from '../../components/icons'; +import Icon, { + RefreshIcon, + SaveIcon, + DownloadIcon, + UploadIcon, + SuccessIcon, + UndoIcon, + RedoIcon, +} from '../../components/icons'; import { getVariablesUtilization, @@ -28,6 +36,7 @@ import { } from '../../helpers/pipelines'; import { getBoxTypes } from '../../redux/selectors/boxes'; import { objectMap, arrayToObject, encodeId, deepCompare, identity } from '../../helpers/common'; +import { downloadString } from '../../redux/helpers/api/download'; import styles from '../../components/Pipelines/styles.less'; import InsetPanel from '../../components/widgets/InsetPanel'; @@ -92,6 +101,21 @@ const STATE_DEFAULTS = { selectedVariableBoxes: null, // boxes associated with selected var }; +const importErrorMessages = defineMessages({ + exception: { + id: 'app.pipelineEditContainer.importError.exception', + defaultMessage: 'Import of file {name} failed: {error}', + }, + parser: { + id: 'app.pipelineEditContainer.importError.parser', + defaultMessage: 'Parsing of JSON file {name} failed: {error}', + }, + structure: { + id: 'app.pipelineEditContainer.importError.structure', + defaultMessage: 'Pipeline in file {name} has invalid structure!', + }, +}); + class PipelineEditContainer extends Component { state = { pipelineId: null, @@ -142,6 +166,11 @@ class PipelineEditContainer extends Component { return null; } + constructor(props) { + super(props); + this.inputFileRef = React.createRef(); + } + undo = () => { if (this.state.history.length === 0) { return; @@ -500,6 +529,65 @@ class PipelineEditContainer extends Component { ); }; + /** + * Read a JSON file in hidden file-input, parse it, and load it as the pipeline (if it checks out). + */ + import = () => { + const { + intl: { formatMessage }, + } = this.props; + const files = this.inputFileRef.current.files; + if (files.length === 1) { + files[0].text().then( + content => { + try { + const pipeline = JSON.parse(content); + const fixedPipeline = checkPipelineStructure(pipeline); + if (fixedPipeline === pipeline) { + this.setState({ + boxes: fixedPipeline.boxes, + variables: fixedPipeline.variables, + history: [{ boxes: this.state.boxes, variables: this.state.variables }, ...this.state.history], + future: [], + errors: validatePipeline(fixedPipeline.boxes, fixedPipeline.variables, this.props.boxTypes), + selectedBox: null, + selectedBoxVariables: null, + selectedVariable: null, + selectedVariableBoxes: null, + }); + } else { + const msg = formatMessage(importErrorMessages.structure, { name: files[0].name }); + window.alert(msg); // eslint-disable-line no-alert + } + } catch (e) { + const msg = formatMessage(importErrorMessages.parser, { name: files[0].name, error: e.message }); + window.alert(msg); // eslint-disable-line no-alert + } + }, + error => { + const msg = formatMessage(importErrorMessages.exception, { name: files[0].name, error }); + window.alert(msg); // eslint-disable-line no-alert + } + ); + } + }; + + /** + * Serialize the pipeline in JSON string and offer it to be downloaded as a file. + */ + export = () => { + downloadString( + 'pipeline.json', + JSON.stringify( + { ...this.props.pipeline.pipeline, boxes: this.state.boxes, variables: this.state.variables }, + undefined, + 4 + ), + 'text/json', + false + ); + }; + showAsTable = () => this.setState({ showTable: true, showGraph: false }); showAsGraph = () => this.setState({ showTable: false, showGraph: true }); showTableAndGraph = () => this.setState({ showTable: true, showGraph: true }); @@ -609,6 +697,16 @@ class PipelineEditContainer extends Component {
    + + + + -

    - } - isOpen - > - - {pipelines => - -
    - - - - deletePipeline(pipelineId)} - question={ - - } - > - - -
    } - />} -
    - - */} )} @@ -724,7 +636,6 @@ export default withLinks( exerciseScoreConfig: exerciseScoreConfigSelector(state, exerciseId), exerciseTests: exerciseTestsSelector(exerciseId)(state), pipelines: pipelinesSelector(state), - // exercisePipelines: exercisePipelinesSelector(exerciseId)(state), environmentsWithEntryPoints: getPipelinesEnvironmentsWhichHasEntryPoint(state), pipelinesVariables: getExercisePielinesVariablesJS(exerciseId)(state), supplementaryFiles: getSupplementaryFilesForExercise(exerciseId)(state), diff --git a/src/pages/Exercise/Exercise.js b/src/pages/Exercise/Exercise.js index 1c045577e..c06ecd5ac 100644 --- a/src/pages/Exercise/Exercise.js +++ b/src/pages/Exercise/Exercise.js @@ -77,7 +77,6 @@ class Exercise extends Component { dispatch(fetchRuntimeEnvironments()), dispatch(fetchReferenceSolutions(exerciseId)), dispatch(fetchHardwareGroups()), - // dispatch(fetchExercisePipelines(exerciseId)), // TODO - awaiting modification (many-to-many relation with exercises) ]); componentDidMount() { diff --git a/src/redux/modules/pipelines.js b/src/redux/modules/pipelines.js index 3d8cd8d9e..7cb5c9334 100644 --- a/src/redux/modules/pipelines.js +++ b/src/redux/modules/pipelines.js @@ -89,27 +89,6 @@ const reducer = handleActions( [pipelineFilesActionTypes.ADD_FILES_FULFILLED]: (state, { payload: files, meta: { pipelineId } }) => state.hasIn(['resources', pipelineId]) ? updateFiles(state, pipelineId, files, 'supplementaryFilesIds') : state, - /* - [additionalActionTypes.FORK_PIPELINE_PENDING]: (state, { meta: { id, forkId } }) => - state.updateIn(['resources', id], pipeline => { - if (!pipeline.has('forks')) { - pipeline = pipeline.set('forks', new Map()); - } - - return pipeline.update('forks', forks => forks.set(forkId, { status: forkStatuses.PENDING })); - }), - - [additionalActionTypes.FORK_PIPELINE_REJECTED]: (state, { meta: { id, forkId } }) => - state.setIn(['resources', id, 'forks', forkId], { - status: forkStatuses.REJECTED, - }), - - [additionalActionTypes.FORK_PIPELINE_FULFILLED]: (state, { payload: { id: pipelineId }, meta: { id, forkId } }) => - state.setIn(['resources', id, 'forks', forkId], { - status: forkStatuses.FULFILLED, - pipelineId, - }), -*/ [additionalActionTypes.SET_ENVIRONMENTS_FULFILLED]: (state, { payload }) => state.setIn( ['resources', payload.id], From 8832a2a9f2a6b03a8a2831f181889dd0fe223dbe Mon Sep 17 00:00:00 2001 From: Martin Krulis Date: Sun, 9 Jan 2022 19:16:52 +0100 Subject: [PATCH 18/20] Fixing bugs. --- .../ExercisesListItem/ExercisesListItem.js | 2 +- .../PipelineExercisesList.js | 52 ++++++++++--------- .../DeletePipelineButtonContainer.js | 6 ++- src/helpers/pipelines.js | 2 +- src/locales/en.json | 2 +- src/pages/EditExercise/EditExercise.js | 2 +- .../EditExerciseConfig/EditExerciseConfig.js | 2 +- .../EditExerciseLimits/EditExerciseLimits.js | 2 +- src/pages/Exercise/Exercise.js | 2 +- .../ExerciseAssignments.js | 2 +- src/pages/Pipeline/Pipeline.js | 2 +- .../ReferenceSolution/ReferenceSolution.js | 2 +- 12 files changed, 41 insertions(+), 37 deletions(-) diff --git a/src/components/Exercises/ExercisesListItem/ExercisesListItem.js b/src/components/Exercises/ExercisesListItem/ExercisesListItem.js index b5f43f63d..7e310936d 100644 --- a/src/components/Exercises/ExercisesListItem/ExercisesListItem.js +++ b/src/components/Exercises/ExercisesListItem/ExercisesListItem.js @@ -147,7 +147,7 @@ const ExercisesListItem = ({ )} - {permissionHints.viewPipelines && permissionHints.viewScoreConfig && ( + {permissionHints.viewConfig && permissionHints.viewScoreConfig && ( - - - - - - - - - - {pipelineExercises.size > 5 && ( - - - - )} - - - + 0} className="mb-1" size="xs"> + {pipelineExercises.size > 0 && ( + + + + + + + + )} {exercises.map(exercise => ( @@ -133,12 +135,12 @@ const PipelineExercisesList = ({ ))} - {exercises.length === 0 && ( + {pipelineExercises.size === 0 && ( - diff --git a/src/containers/DeletePipelineButtonContainer/DeletePipelineButtonContainer.js b/src/containers/DeletePipelineButtonContainer/DeletePipelineButtonContainer.js index 2197712ff..7a935e32a 100644 --- a/src/containers/DeletePipelineButtonContainer/DeletePipelineButtonContainer.js +++ b/src/containers/DeletePipelineButtonContainer/DeletePipelineButtonContainer.js @@ -28,8 +28,10 @@ export default connect( }), (dispatch, { id, onDeleted }) => ({ deletePipeline: () => { - onDeleted && onDeleted(); - return dispatch(deletePipeline(id)); + return dispatch(deletePipeline(id)).then(res => { + onDeleted && onDeleted(); + return res; + }); }, }) )(DeletePipelineButtonContainer); diff --git a/src/helpers/pipelines.js b/src/helpers/pipelines.js index 81ffd913b..704cb1c40 100644 --- a/src/helpers/pipelines.js +++ b/src/helpers/pipelines.js @@ -81,7 +81,7 @@ export const getVariablesUtilization = defaultMemoize(boxes => { boxes.forEach(box => ['portsIn', 'portsOut'].forEach(ports => Object.keys(box[ports]) - .filter(port => box[ports][port]) + .filter(port => box[ports][port] && box[ports][port].value) .forEach(port => { const { value } = box[ports][port]; if (!utils[value]) { diff --git a/src/locales/en.json b/src/locales/en.json index 254690fad..9c2eb9ba9 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -1137,7 +1137,7 @@ "app.pipelineEditContainer.versionChanged": "The pipeline structure was updated whilst you were editing it. If you load the new pipeline, it will be pushed as a new state in editor (you can use undo button to revert it).", "app.pipelineEditContainer.versionChangedTitle": "The pipeline was updated", "app.pipelineExercisessList.collapse": "Collapse the list and show only short preview.", - "app.pipelineExercisessList.empty": "There are no exercises using this pipelines at the moment.", + "app.pipelineExercisessList.empty": "There are no exercises using this pipeline at the moment.", "app.pipelineExercisessList.expand": "Expand the list and show all {count} exercises.", "app.pipelineExercisessList.totalCount": "Total exercises: {count}", "app.pipelineFilesTable.description": "Supplementary files are files which can be referenced as remote file in pipeline configuration.", diff --git a/src/pages/EditExercise/EditExercise.js b/src/pages/EditExercise/EditExercise.js index e29e31d36..87e57aa31 100644 --- a/src/pages/EditExercise/EditExercise.js +++ b/src/pages/EditExercise/EditExercise.js @@ -101,7 +101,7 @@ class EditExercise extends Component { diff --git a/src/pages/EditExerciseConfig/EditExerciseConfig.js b/src/pages/EditExerciseConfig/EditExerciseConfig.js index 1543a5c51..169db6731 100644 --- a/src/pages/EditExerciseConfig/EditExerciseConfig.js +++ b/src/pages/EditExerciseConfig/EditExerciseConfig.js @@ -288,7 +288,7 @@ class EditExerciseConfig extends Component { diff --git a/src/pages/EditExerciseLimits/EditExerciseLimits.js b/src/pages/EditExerciseLimits/EditExerciseLimits.js index 10ee28720..1535316a8 100644 --- a/src/pages/EditExerciseLimits/EditExerciseLimits.js +++ b/src/pages/EditExerciseLimits/EditExerciseLimits.js @@ -157,7 +157,7 @@ class EditExerciseLimits extends Component { diff --git a/src/pages/Exercise/Exercise.js b/src/pages/Exercise/Exercise.js index c06ecd5ac..2e941b80d 100644 --- a/src/pages/Exercise/Exercise.js +++ b/src/pages/Exercise/Exercise.js @@ -129,7 +129,7 @@ class Exercise extends Component { diff --git a/src/pages/ExerciseAssignments/ExerciseAssignments.js b/src/pages/ExerciseAssignments/ExerciseAssignments.js index c08b58482..d0b603e16 100644 --- a/src/pages/ExerciseAssignments/ExerciseAssignments.js +++ b/src/pages/ExerciseAssignments/ExerciseAssignments.js @@ -131,7 +131,7 @@ class ExerciseAssignments extends Component { diff --git a/src/pages/Pipeline/Pipeline.js b/src/pages/Pipeline/Pipeline.js index 473a839a5..27849cc89 100644 --- a/src/pages/Pipeline/Pipeline.js +++ b/src/pages/Pipeline/Pipeline.js @@ -140,7 +140,7 @@ class Pipeline extends Component { />

    - diff --git a/src/pages/ReferenceSolution/ReferenceSolution.js b/src/pages/ReferenceSolution/ReferenceSolution.js index 448456440..237573f2e 100644 --- a/src/pages/ReferenceSolution/ReferenceSolution.js +++ b/src/pages/ReferenceSolution/ReferenceSolution.js @@ -87,7 +87,7 @@ class ReferenceSolution extends Component { exerciseId={exercise.id} userId={referenceSolution.authorId} canEdit={hasPermissions(exercise, 'update')} - canViewTests={hasPermissions(exercise, 'viewPipelines', 'viewScoreConfig')} + canViewTests={hasPermissions(exercise, 'viewConfig', 'viewScoreConfig')} canViewLimits={hasPermissions(exercise, 'viewLimits')} canViewAssignments={hasPermissions(exercise, 'viewAssignments')} /> From 94130b3c9dc9c58c2ea6232333bcaa12fd9d67f1 Mon Sep 17 00:00:00 2001 From: Martin Krulis Date: Thu, 20 Jan 2022 02:34:06 +0100 Subject: [PATCH 19/20] Improving visualization of solution points computation (rounding and epsilon). --- .../EvaluationDetail/EvaluationDetail.js | 2 +- .../Solutions/SolutionStatus/SolutionStatus.js | 17 +++++++++++++++-- .../ScoreConfigInfo/ScoreConfigInfoWeighted.js | 2 +- src/locales/cs.json | 3 +-- src/locales/en.json | 3 +-- 5 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/components/Solutions/EvaluationDetail/EvaluationDetail.js b/src/components/Solutions/EvaluationDetail/EvaluationDetail.js index 9dcdfb316..21fe1392d 100644 --- a/src/components/Solutions/EvaluationDetail/EvaluationDetail.js +++ b/src/components/Solutions/EvaluationDetail/EvaluationDetail.js @@ -84,7 +84,7 @@ const EvaluationDetail = ({ 'text-success': isCorrect, })}> - + {showScoreDetail && ( diff --git a/src/components/Solutions/SolutionStatus/SolutionStatus.js b/src/components/Solutions/SolutionStatus/SolutionStatus.js index 3210367cc..c5b5e3a4b 100644 --- a/src/components/Solutions/SolutionStatus/SolutionStatus.js +++ b/src/components/Solutions/SolutionStatus/SolutionStatus.js @@ -421,8 +421,21 @@ class SolutionStatus extends Component {

    - floor({maxPoints} × ) ={' '} - {actualPoints} + floor({maxPoints} ×{' '} + + + + + }> + {' + '}ε + + ) = {actualPoints}

    diff --git a/src/components/scoreConfig/ScoreConfigInfo/ScoreConfigInfoWeighted.js b/src/components/scoreConfig/ScoreConfigInfo/ScoreConfigInfoWeighted.js index 688060a3e..d96f3a76c 100644 --- a/src/components/scoreConfig/ScoreConfigInfo/ScoreConfigInfoWeighted.js +++ b/src/components/scoreConfig/ScoreConfigInfo/ScoreConfigInfoWeighted.js @@ -21,7 +21,7 @@ const ScoreConfigInfoWeighted = ({ scoreConfig, testResults }) => { .map(test => ({ test, weight: weightsObj[test] })); const weightsSum = weights.reduce((acc, { weight }) => acc + weight, 0); const testsSum = results && weights.reduce((acc, { test, weight }) => acc + weight * results[test], 0); - const totalScore = weightsSum !== 0 ? Math.round((testsSum * 1000) / weightsSum) / 1000 : '?'; + const totalScore = weightsSum !== 0 ? Math.round((testsSum * 100000) / weightsSum) / 100000 : '?'; return (
    diff --git a/src/locales/cs.json b/src/locales/cs.json index 07bde14a9..9e7f87357 100644 --- a/src/locales/cs.json +++ b/src/locales/cs.json @@ -1251,8 +1251,6 @@ "app.pipelinesList.judgeOnlyIconTooltip": "Pipeline pouze se sudím", "app.pipelinesList.stdoutIconTooltip": "Testované řešení by mělo vypsat svoje výsledky na standardní výstup", "app.pipelinesList.universalPipelineIconTooltip": "Univerzální pipeline, která se používá v konfiguracích běžných úloh.", - "app.pipelinesSimpleList.actions": "Akce", - "app.pipelinesSimpleList.empty": "Na seznamu nejsou žádné pipelines.", "app.plantSisTerm.noGroupsSelected": "Musí být vybrána alespoň jedna rodičovská skupina.", "app.plantSisTerm.plantGroups": "Osadit skupiny", "app.plantSisTerm.planted": "Osazeno", @@ -1554,6 +1552,7 @@ "app.solution.pointsExplainDialog.correctnessAboveThreshold": "Řešení překročilo požadovanou hranici správnosti.", "app.solution.pointsExplainDialog.correctnessBelowThreshold": "Správnost řešení je pod minimální požadovanou hranicí, takže nebyly uděleny žádné body.", "app.solution.pointsExplainDialog.deadlinesGraphNotUsedSuffix": "(graf je pouze informativní, bodový limit nebyl použit při výpočtu správnosti)", + "app.solution.pointsExplainDialog.epsilonExplain": "Epsilon (1e-6) je přičteno, aby kompenzovalo zaokrouhlovací chyby.", "app.solution.pointsExplainDialog.overriddenPoints": "Vedoucí ručně přepsal hodnocení úlohy na {overriddenPoints} {overriddenPoints, plural, one {bod} =2 {body} =3 {body} =4 {body} other {bodů}} (a {bonusPoints} {bonusPoints, plural, one {bonusový bod} =2 {bonusové body} =3 {bonusové body} =4 {bonusové body} other {bonusových bodů}}).", "app.solution.pointsExplainDialog.title": "Vysvětlení hodnotícího procesu", "app.solution.reviewed": "Revidováno", diff --git a/src/locales/en.json b/src/locales/en.json index 9c2eb9ba9..517d3713d 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -1251,8 +1251,6 @@ "app.pipelinesList.judgeOnlyIconTooltip": "Judge-only pipeline", "app.pipelinesList.stdoutIconTooltip": "Tested solution is expected to yield results to standard output", "app.pipelinesList.universalPipelineIconTooltip": "Universal pipeline which is used in common (simple) exercise configurations.", - "app.pipelinesSimpleList.actions": "Actions", - "app.pipelinesSimpleList.empty": "There are no pipelines in this list.", "app.plantSisTerm.noGroupsSelected": "At least one parent group needs to be selected.", "app.plantSisTerm.plantGroups": "Plant Groups", "app.plantSisTerm.planted": "Planted", @@ -1554,6 +1552,7 @@ "app.solution.pointsExplainDialog.correctnessAboveThreshold": "The solution correctness is above threshold.", "app.solution.pointsExplainDialog.correctnessBelowThreshold": "The solution correcntess is below threshold. No points are granted.", "app.solution.pointsExplainDialog.deadlinesGraphNotUsedSuffix": "(but it was not used in the scoring process of this solution)", + "app.solution.pointsExplainDialog.epsilonExplain": "The epsilon (1e-6) is added to compensate for rounding errors.", "app.solution.pointsExplainDialog.overriddenPoints": "A supervisor has manually overridden the points to {overriddenPoints} (and {bonusPoints} {bonusPoints, plural, one {point} other {points}}).", "app.solution.pointsExplainDialog.title": "Explanation of the scoring process", "app.solution.reviewed": "Reviewed", From 605c1bfa5c07975cde9ee14425dc60945062d26e Mon Sep 17 00:00:00 2001 From: Martin Krulis Date: Sat, 29 Jan 2022 17:03:53 +0100 Subject: [PATCH 20/20] Code cleanup. --- src/components/Pipelines/VariableForm/VariableForm.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/components/Pipelines/VariableForm/VariableForm.js b/src/components/Pipelines/VariableForm/VariableForm.js index 77074912c..812b29cd9 100644 --- a/src/components/Pipelines/VariableForm/VariableForm.js +++ b/src/components/Pipelines/VariableForm/VariableForm.js @@ -39,9 +39,6 @@ class VariableForm extends Component { onHide, } = this.props; - // const currentBoxType = boxTypes.find(box => box.type === selectedType); - // const getPortsArray = ports => Object.keys(ports).map(port => ({ name: port, ...ports[port] })); - return (
    + + + + + {pipelineExercises.size > 5 && ( + + + + )} +
    +