From 180e3feb8f57e33741e2bf0bcab499f556573021 Mon Sep 17 00:00:00 2001 From: Tishasoumya-02 Date: Sun, 13 Aug 2023 17:03:43 +0530 Subject: [PATCH 1/4] refactor --- .../manage/Widgets/ReferenceWidget.jsx | 349 +++++++----------- 1 file changed, 141 insertions(+), 208 deletions(-) diff --git a/src/components/manage/Widgets/ReferenceWidget.jsx b/src/components/manage/Widgets/ReferenceWidget.jsx index 78fa1b7b8e..29ace4a8c5 100644 --- a/src/components/manage/Widgets/ReferenceWidget.jsx +++ b/src/components/manage/Widgets/ReferenceWidget.jsx @@ -1,15 +1,9 @@ -/** - * ReferenceWidget component. - * @module components/manage/Widgets/ReferenceWidget - */ - -import React, { Component } from 'react'; +import React, { useState, useEffect } from 'react'; import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; -import { compose } from 'redux'; +import { useDispatch, useSelector } from 'react-redux'; import { Label, Dropdown, Popup, Icon } from 'semantic-ui-react'; import { compact, concat, fromPairs, map, values, uniqBy } from 'lodash'; -import { defineMessages, injectIntl } from 'react-intl'; +import { defineMessages, useIntl } from 'react-intl'; import { FormFieldWrapper } from '@plone/volto/components'; import { resetSearchContent, searchContent } from '@plone/volto/actions'; @@ -26,130 +20,16 @@ const messages = defineMessages({ }, }); -/** - * ReferenceWidget component class. - * @class ReferenceWidget - * @extends Component - */ -class ReferenceWidget extends Component { - /** - * Property types. - * @property {Object} propTypes Property types. - * @static - */ - static propTypes = { - id: PropTypes.string.isRequired, - title: PropTypes.string.isRequired, - description: PropTypes.string, - required: PropTypes.bool, - multiple: PropTypes.bool, - error: PropTypes.arrayOf(PropTypes.string), - value: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.object), - PropTypes.object, - ]), - onChange: PropTypes.func.isRequired, - resetSearchContent: PropTypes.func.isRequired, - searchContent: PropTypes.func.isRequired, - search: PropTypes.arrayOf( - PropTypes.shape({ - '@id': PropTypes.string, - '@type': PropTypes.string, - title: PropTypes.string, - description: PropTypes.string, - }), - ), - wrapped: PropTypes.bool, - }; - - /** - * Default properties - * @property {Object} defaultProps Default properties. - * @static - */ - static defaultProps = { - description: null, - required: false, - error: [], - search: [], - value: null, - multiple: true, - }; - - /** - * Constructor - * @method constructor - * @param {Object} props Component properties - * @constructs Actions - */ - constructor(props) { - super(props); - this.onSearchChange = this.onSearchChange.bind(this); - - this.state = { - choices: props.value - ? props.multiple - ? fromPairs( - map(props.value, (value) => [ - value['@id'], - { - key: value['@id'], - text: flattenToAppURL(value['@id']), - value: value['@id'], - label: { - content: value.title, - }, - data: value, - }, - ]), - ) - : { - [props.value['@id']]: { - key: props.value['@id'], - text: flattenToAppURL(props.value), - value: props.value['@id'], - label: { - content: props.value.title, - }, - data: props.value, - }, - novalue: { - key: 'novalue', - text: this.props.intl.formatMessage(messages.no_value), - value: 'novalue', - data: null, - }, - } - : {}, - }; - } - - componentDidMount() { - this.props.resetSearchContent(); - } - - /** - * Component will receive props - * @method componentWillReceiveProps - * @param {Object} nextProps Next properties - * @returns {undefined} - */ - UNSAFE_componentWillReceiveProps(nextProps) { - this.setState({ - choices: { - ...fromPairs( - map( - uniqBy( - map( - compact(concat(nextProps.value, nextProps.search)), - (item) => ({ - ...item, - '@id': flattenToAppURL(item['@id']), - }), - ), - '@id', - ), - (value) => [ +const ReferenceWidget = (props) => { + const { id, title, value, multiple, onChange } = props; + const intl = useIntl(); + const dispatch = useDispatch(); + const search = useSelector((state) => state.search.items); + const [choices, setChoices] = useState( + value + ? multiple + ? fromPairs( + map(value, (value) => [ value['@id'], { key: value['@id'], @@ -160,37 +40,78 @@ class ReferenceWidget extends Component { }, data: value, }, - ], + ]), + ) + : { + [value['@id']]: { + key: value['@id'], + text: flattenToAppURL(value), + value: value['@id'], + label: { + content: value.title, + }, + data: value, + }, + novalue: { + key: 'novalue', + text: intl.formatMessage(messages.no_value), + value: 'novalue', + data: null, + }, + } + : {}, + ); + + useEffect(() => { + dispatch(resetSearchContent()); + }, [dispatch]); + + useEffect(() => { + setChoices({ + ...fromPairs( + map( + uniqBy( + map(compact(concat(value, search)), (item) => ({ + ...item, + '@id': flattenToAppURL(item['@id']), + })), + '@id', ), + (value) => [ + value['@id'], + { + key: value['@id'], + text: flattenToAppURL(value['@id']), + value: value['@id'], + label: { + content: value.title, + }, + data: value, + }, + ], ), - novalue: { - key: 'novalue', - text: this.props.intl.formatMessage(messages.no_value), - value: 'novalue', - data: null, - }, + ), + novalue: { + key: 'novalue', + text: intl.formatMessage(messages.no_value), + value: 'novalue', + data: null, }, }); - } - - /** - * On search change handler - * @method onSearchChange - * @param {object} event Event object. - * @param {object} data Event data. - * @returns {undefined} - */ + }, [intl, search, value]); - onSearchChange(event, data) { + const onSearchChange = (event, data) => { if (data.searchQuery && data.searchQuery !== '') { - this.props.searchContent('', { - Title: `*${data.searchQuery}*`, - }); + dispatch( + searchContent('', { + Title: `*${data.searchQuery}*`, + }), + ); } else { - this.props.resetSearchContent(); + dispatch(resetSearchContent()); } - } - renderLabel = (item, index, defaultProps) => { + }; + const renderLabel = (item, index, defaultProps) => { return ( - + + item && item['@id'] ? flattenToAppURL(item['@id']) : item, + ) + : [] + : value + ? flattenToAppURL(value['@id']) + : '' + } + onChange={(event, data) => { + return onChange( + id, multiple - ? value - ? map(value, (item) => - item && item['@id'] ? flattenToAppURL(item['@id']) : item, - ) - : [] - : value - ? flattenToAppURL(value['@id']) - : '' - } - onChange={(event, data) => { - return onChange( - id, - multiple - ? map(data.value, (item) => this.state.choices[item].data) - : this.state.choices[data.value].data, - ); - }} - onSearchChange={this.onSearchChange} - renderLabel={this.renderLabel} - /> - - ); - } -} + ? map(data.value, (item) => choices[item].data) + : choices[data.value].data, + ); + }} + onSearchChange={onSearchChange} + renderLabel={renderLabel} + /> + + ); +}; -export default compose( - injectIntl, - connect( - (state) => ({ - search: state.search.items, +ReferenceWidget.propTypes = { + id: PropTypes.string.isRequired, + title: PropTypes.string.isRequired, + description: PropTypes.string, + required: PropTypes.bool, + multiple: PropTypes.bool, + error: PropTypes.arrayOf(PropTypes.string), + value: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.object), + PropTypes.object, + ]), + onChange: PropTypes.func.isRequired, + search: PropTypes.arrayOf( + PropTypes.shape({ + '@id': PropTypes.string, + '@type': PropTypes.string, + title: PropTypes.string, + description: PropTypes.string, }), - { resetSearchContent, searchContent }, ), -)(ReferenceWidget); + wrapped: PropTypes.bool, +}; + +ReferenceWidget.defaultProps = { + description: null, + required: false, + error: [], + search: [], + value: null, + multiple: true, +}; +export default ReferenceWidget; From ba2b867640873d88e0df5bd85f3d30c797215f0e Mon Sep 17 00:00:00 2001 From: Tishasoumya-02 Date: Mon, 14 Aug 2023 10:50:01 +0530 Subject: [PATCH 2/4] news --- news/5093.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 news/5093.feature diff --git a/news/5093.feature b/news/5093.feature new file mode 100644 index 0000000000..e042a14dfb --- /dev/null +++ b/news/5093.feature @@ -0,0 +1 @@ +Refactor ReferenceWidget-@Tishasoumya \ No newline at end of file From d33ec5d6ae4300fd9a98d631a97747df20ae3d59 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Wed, 14 Aug 2024 01:18:17 -0700 Subject: [PATCH 3/4] Update packages/volto/news/5093.feature --- packages/volto/news/5093.feature | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/volto/news/5093.feature b/packages/volto/news/5093.feature index 1ed900c321..cb0a0ab525 100644 --- a/packages/volto/news/5093.feature +++ b/packages/volto/news/5093.feature @@ -1 +1 @@ -Refactor ReferenceWidget from class to functional component. @Tishasoumya \ No newline at end of file +Refactor `ReferenceWidget` from class-based to functional component. @Tishasoumya \ No newline at end of file From 029c6f5b72b1997dd9c37821065d399a6ab258b3 Mon Sep 17 00:00:00 2001 From: David Glick Date: Wed, 28 Aug 2024 22:38:01 -0700 Subject: [PATCH 4/4] fix widget --- .../manage/Widgets/ReferenceWidget.jsx | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/packages/volto/src/components/manage/Widgets/ReferenceWidget.jsx b/packages/volto/src/components/manage/Widgets/ReferenceWidget.jsx index 86fb27e933..93f90c9f1c 100644 --- a/packages/volto/src/components/manage/Widgets/ReferenceWidget.jsx +++ b/packages/volto/src/components/manage/Widgets/ReferenceWidget.jsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react'; +import { useState, useEffect } from 'react'; import PropTypes from 'prop-types'; import { useDispatch, useSelector } from 'react-redux'; import { Label, Dropdown, Popup, Icon } from 'semantic-ui-react'; @@ -100,7 +100,7 @@ const ReferenceWidget = (props) => { }); }, [intl, search, value]); - const onSearchChange = (data) => { + const onSearchChange = (event, data) => { if (data.searchQuery && data.searchQuery !== '') { dispatch( searchContent('', { @@ -111,7 +111,7 @@ const ReferenceWidget = (props) => { dispatch(resetSearchContent()); } }; - const renderLabel = (item, defaultProps) => { + const renderLabel = (item, index, defaultProps) => { return ( { ? flattenToAppURL(value['@id']) : '' } - onChange={(data) => { + onChange={(event, data) => { return onChange( id, multiple @@ -185,14 +185,6 @@ ReferenceWidget.propTypes = { PropTypes.object, ]), onChange: PropTypes.func.isRequired, - search: PropTypes.arrayOf( - PropTypes.shape({ - '@id': PropTypes.string, - '@type': PropTypes.string, - title: PropTypes.string, - description: PropTypes.string, - }), - ), wrapped: PropTypes.bool, }; @@ -200,7 +192,6 @@ ReferenceWidget.defaultProps = { description: null, required: false, error: [], - search: [], value: null, multiple: true, };