diff --git a/src/components/EditListingDescriptionPanel/EditListingDescriptionPanel.js b/src/components/EditListingDescriptionPanel/EditListingDescriptionPanel.js index 845bac4a..ecc9202f 100644 --- a/src/components/EditListingDescriptionPanel/EditListingDescriptionPanel.js +++ b/src/components/EditListingDescriptionPanel/EditListingDescriptionPanel.js @@ -6,6 +6,7 @@ import { ensureListing } from '../../util/data'; import { createSlug } from '../../util/urlHelpers'; import { NamedLink } from '../../components'; import { EditListingDescriptionForm } from '../../containers'; +import config from '../../config'; import css from './EditListingDescriptionPanel.css'; @@ -24,7 +25,7 @@ const EditListingDescriptionPanel = props => { const classes = classNames(rootClassName || css.root, className); const currentListing = ensureListing(listing); - const { description, title, customAttributes } = currentListing.attributes; + const { description, title, publicData } = currentListing.attributes; const listingTitle = title || ''; const listingLink = currentListing.id ? ( @@ -48,14 +49,19 @@ const EditListingDescriptionPanel = props => {

{panelTitle}

{ const { title, description, category } = values; const updateValues = { title, description, + + // Save category also to the deprecated customAttributes + // so it can be used in search. + // TODO: remove when publicData is used in search customAttributes: { category }, + publicData: { category }, }; @@ -65,6 +71,7 @@ const EditListingDescriptionPanel = props => { updated={panelUpdated} updateError={errors.updateListingError} updateInProgress={updateInProgress} + categories={config.custom.categories} /> ); diff --git a/src/components/EditListingWizard/EditListingWizard.js b/src/components/EditListingWizard/EditListingWizard.js index a23d7c42..44205bf3 100644 --- a/src/components/EditListingWizard/EditListingWizard.js +++ b/src/components/EditListingWizard/EditListingWizard.js @@ -191,7 +191,6 @@ EditListingWizard.propTypes = { // We cannot use propTypes.listing since the listing might be a draft. listing: shape({ attributes: shape({ - customAttributes: object, // structure (key: value) can be defined in management console publicData: object, description: string, geolocation: object, diff --git a/src/components/EditListingWizard/EditListingWizardTab.js b/src/components/EditListingWizard/EditListingWizardTab.js index 04e3f569..49b960df 100644 --- a/src/components/EditListingWizard/EditListingWizardTab.js +++ b/src/components/EditListingWizard/EditListingWizardTab.js @@ -219,7 +219,6 @@ EditListingWizardTab.propTypes = { // We cannot use propTypes.listing since the listing might be a draft. listing: shape({ attributes: shape({ - customAttributes: object, // structure (key: value) can be defined in management console publicData: object, description: string, geolocation: object, diff --git a/src/components/FieldCustomAttributeSelect/FieldCustomAttributeSelect.css b/src/components/FieldCustomAttributeSelect/FieldCustomAttributeSelect.css deleted file mode 100644 index 93adba15..00000000 --- a/src/components/FieldCustomAttributeSelect/FieldCustomAttributeSelect.css +++ /dev/null @@ -1,4 +0,0 @@ -@import '../../marketplace.css'; - -.root { -} diff --git a/src/components/FieldCustomAttributeSelect/FieldCustomAttributeSelect.js b/src/components/FieldCustomAttributeSelect/FieldCustomAttributeSelect.js deleted file mode 100644 index bb15a85c..00000000 --- a/src/components/FieldCustomAttributeSelect/FieldCustomAttributeSelect.js +++ /dev/null @@ -1,68 +0,0 @@ -import React from 'react'; -import { string } from 'prop-types'; -import { intlShape, injectIntl } from 'react-intl'; -import classNames from 'classnames'; -import config from '../../config'; -import { required } from '../../util/validators'; -import { SelectField } from '../../components'; - -import css from './FieldCustomAttributeSelect.css'; - -const FieldCustomAttributeSelect = props => { - const { className, rootClassName, id, customAttribute, intl } = props; - - // Does custom attribute 'customAttribute' exists in current marketplace configuration - const ca = config.customAttributes && config.customAttributes[customAttribute]; - const isSingleChoice = ca && ca.select === 'single' && ca.type === 'string'; - - // If custom attribute config for given 'customAttribute' doesn't exist, don't print SelectField - if (!isSingleChoice) { - return null; - } - - const caLabel = intl.formatMessage({ id: `FieldCustomAttributeSelect.${customAttribute}.label` }); - const caPlaceholder = intl.formatMessage({ - id: `FieldCustomAttributeSelect.${customAttribute}.placeholder`, - }); - const caRequired = required( - intl.formatMessage({ - id: `FieldCustomAttributeSelect.${customAttribute}.required`, - }) - ); - - const classes = classNames(rootClassName || css.root, className); - - return ( - - - {ca.values.map(c => ( - - ))} - - ); -}; - -FieldCustomAttributeSelect.defaultProps = { - className: null, - rootClassName: null, -}; - -FieldCustomAttributeSelect.propTypes = { - className: string, - rootClassName: string, - id: string.isRequired, - customAttribute: string.isRequired, - - // From react-intl - intl: intlShape.isRequired, -}; - -export default injectIntl(FieldCustomAttributeSelect); diff --git a/src/components/SearchFilters/SearchFilters.js b/src/components/SearchFilters/SearchFilters.js index d1e59f98..efaca602 100644 --- a/src/components/SearchFilters/SearchFilters.js +++ b/src/components/SearchFilters/SearchFilters.js @@ -1,6 +1,7 @@ import React from 'react'; -import PropTypes from 'prop-types'; -import { FormattedMessage } from 'react-intl'; +import { compose } from 'redux'; +import { object, string, bool, number, func, shape, array } from 'prop-types'; +import { injectIntl, intlShape, FormattedMessage } from 'react-intl'; import classNames from 'classnames'; import { withRouter } from 'react-router-dom'; import { omit } from 'lodash'; @@ -8,9 +9,10 @@ import { omit } from 'lodash'; import { SelectSingleFilter } from '../../components'; import routeConfiguration from '../../routeConfiguration'; import { createResourceLocatorString } from '../../util/routes'; -import config from '../../config'; import css from './SearchFilters.css'; +const CATEGORY_URL_PARAM = 'ca_category'; + const SearchFiltersComponent = props => { const { rootClassName, @@ -19,7 +21,9 @@ const SearchFiltersComponent = props => { listingsAreLoaded, resultsCount, searchInProgress, + categories, history, + intl, } = props; const loadingResults = ; @@ -32,27 +36,27 @@ const SearchFiltersComponent = props => { const classes = classNames(rootClassName || css.root, className); - const onSelectSingle = (customAttribute, option) => { - // Name of the corresponding query parameter. - // The custom attribute query parameters are named - // ca_ in the API. - const caParam = `ca_${customAttribute}`; + const categoryLabel = intl.formatMessage({ + id: 'SearchFilters.categoryLabel', + }); + const onSelectOption = (urlParam, option) => { // query parameters after selecting the option // if no option is passed, clear the selection for the filter const queryParams = option - ? { ...urlQueryParams, [caParam]: option } - : omit(urlQueryParams, caParam); + ? { ...urlQueryParams, [urlParam]: option } + : omit(urlQueryParams, urlParam); history.push(createResourceLocatorString('SearchPage', routeConfiguration(), {}, queryParams)); }; - const hasCategoryConfig = config.customAttributes && config.customAttributes.category; - const categoryFilter = hasCategoryConfig ? ( + const categoryFilter = categories ? ( ) : null; return ( @@ -68,13 +72,12 @@ const SearchFiltersComponent = props => { ); }; -const { object, string, bool, number, func, shape } = PropTypes; - SearchFiltersComponent.defaultProps = { rootClassName: null, className: null, resultsCount: null, searchingInProgress: false, + categories: null, }; SearchFiltersComponent.propTypes = { @@ -86,13 +89,17 @@ SearchFiltersComponent.propTypes = { searchingInProgress: bool, onMapIconClick: func.isRequired, onManageDisableScrolling: func.isRequired, + categories: array, // from withRouter history: shape({ push: func.isRequired, }).isRequired, + + // from injectIntl + intl: intlShape.isRequired, }; -const SearchFilters = withRouter(SearchFiltersComponent); +const SearchFilters = compose(withRouter, injectIntl)(SearchFiltersComponent); export default SearchFilters; diff --git a/src/components/SearchFiltersMobile/SearchFiltersMobile.js b/src/components/SearchFiltersMobile/SearchFiltersMobile.js index 0138bc76..4b7a20ca 100644 --- a/src/components/SearchFiltersMobile/SearchFiltersMobile.js +++ b/src/components/SearchFiltersMobile/SearchFiltersMobile.js @@ -1,5 +1,5 @@ import React, { Component } from 'react'; -import PropTypes from 'prop-types'; +import { object, string, bool, number, func, shape, array } from 'prop-types'; import classNames from 'classnames'; import { FormattedMessage, injectIntl, intlShape } from 'react-intl'; import { withRouter } from 'react-router-dom'; @@ -8,18 +8,16 @@ import { omit, toPairs } from 'lodash'; import routeConfiguration from '../../routeConfiguration'; import { createResourceLocatorString } from '../../util/routes'; import { SecondaryButton, ModalInMobile, Button, SelectSingleFilterMobile } from '../../components'; -import config from '../../config'; import css from './SearchFiltersMobile.css'; -// prefix for all custom attribute query params -const CA_PREFIX = 'ca_'; +const CATEGORY_URL_PARAM = 'ca_category'; const validateParamValue = value => value !== null && value !== undefined && value.length > 0; // Check if a filter parameter is included query parameters const hasFilterQueryParams = queryParams => { const firstFilterParam = toPairs(queryParams).find(entry => { - return !!(entry[0].startsWith(CA_PREFIX) && validateParamValue(entry[1])); + return validateParamValue(entry[1]); }); return !!firstFilterParam; }; @@ -29,9 +27,6 @@ class SearchFiltersMobileComponent extends Component { super(props); this.state = { isFiltersOpenOnMobile: false }; - //TODO: take as props - this.customAttribute = 'category'; - this.openFilters = this.openFilters.bind(this); this.cancelFilters = this.cancelFilters.bind(this); this.closeFilters = this.closeFilters.bind(this); @@ -68,19 +63,14 @@ class SearchFiltersMobileComponent extends Component { this.setState({ isFiltersOpenOnMobile: false }); } - onSelectSingle(customAttribute, option) { + onSelectSingle(urlParam, option) { const { urlQueryParams, history } = this.props; - // Name of the corresponding query parameter. - // The custom attribute query parameters are named - // ca_ in the API. - const caParam = `${CA_PREFIX}${customAttribute}`; - // query parameters after selecting the option // if no option is passed, clear the selection for the filter const queryParams = option - ? { ...urlQueryParams, [caParam]: option } - : omit(urlQueryParams, caParam); + ? { ...urlQueryParams, [urlParam]: option } + : omit(urlQueryParams, urlParam); history.push(createResourceLocatorString('SearchPage', routeConfiguration(), {}, queryParams)); } @@ -89,8 +79,7 @@ class SearchFiltersMobileComponent extends Component { resetAll(e) { const { urlQueryParams, history } = this.props; - const caParam = `${CA_PREFIX}${this.customAttribute}`; - const queryParams = omit(urlQueryParams, caParam); + const queryParams = omit(urlQueryParams, CATEGORY_URL_PARAM); history.push(createResourceLocatorString('SearchPage', routeConfiguration(), {}, queryParams)); // blur event target if event is passed @@ -110,6 +99,7 @@ class SearchFiltersMobileComponent extends Component { showAsModalMaxWidth, onMapIconClick, onManageDisableScrolling, + categories, intl, } = this.props; @@ -138,12 +128,16 @@ class SearchFiltersMobileComponent extends Component { ); - const hasCategoryConfig = config.customAttributes && config.customAttributes.category; - const categoryFilter = hasCategoryConfig ? ( + const categoryLabel = intl.formatMessage({ + id: 'SearchFiltersMobile.categoryLabel', + }); + const categoryFilter = categories ? ( ) : null; @@ -188,8 +182,6 @@ class SearchFiltersMobileComponent extends Component { } } -const { object, string, bool, number, func, shape } = PropTypes; - SearchFiltersMobileComponent.defaultProps = { rootClassName: null, className: null, @@ -211,6 +203,7 @@ SearchFiltersMobileComponent.propTypes = { onManageDisableScrolling: func.isRequired, onOpenModal: func, onCloseModal: func, + categories: array, // from injectIntl intl: intlShape.isRequired, diff --git a/src/components/SelectSingleFilter/SelectSingleFilter.js b/src/components/SelectSingleFilter/SelectSingleFilter.js index 8a44859c..cb2336ba 100644 --- a/src/components/SelectSingleFilter/SelectSingleFilter.js +++ b/src/components/SelectSingleFilter/SelectSingleFilter.js @@ -1,13 +1,17 @@ import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import { FormattedMessage, injectIntl, intlShape } from 'react-intl'; +import { object, string, func, arrayOf, shape } from 'prop-types'; +import { FormattedMessage } from 'react-intl'; import classNames from 'classnames'; -import config from '../../config'; import { Menu, MenuContent, MenuItem, MenuLabel } from '../../components'; import css from './SelectSingleFilter.css'; -class SelectSingleFilterComponent extends Component { +const optionLabel = (options, key) => { + const option = options.find(o => o.key === key); + return option ? option.label : key; +}; + +class SelectSingleFilter extends Component { constructor(props) { super(props); @@ -20,25 +24,19 @@ class SelectSingleFilterComponent extends Component { this.setState({ isOpen: isOpen }); } - selectOption(customAttribute, option) { + selectOption(urlParam, option) { this.setState({ isOpen: false }); - this.props.onSelect(customAttribute, option); + this.props.onSelect(urlParam, option); } render() { - const { rootClassName, className, customAttribute, urlQueryParams, intl } = this.props; + const { rootClassName, className, urlQueryParams, urlParam, paramLabel, options } = this.props; - // custom attribute content - const ca = customAttribute && config.customAttributes[customAttribute]; - // name of the corresponding query parameter - const caParam = `ca_${customAttribute}`; // current value of this custom attribute filter - const currentValue = urlQueryParams[caParam]; + const currentValue = urlQueryParams[urlParam]; // resolve menu label text and class - const menuLabel = currentValue - ? intl.formatMessage({ id: `SelectSingleFilter.category.option.${currentValue}` }) - : intl.formatMessage({ id: `SelectSingleFilter.${customAttribute}.label` }); + const menuLabel = currentValue ? optionLabel(options, currentValue) : paramLabel; const menuLabelClass = currentValue ? css.menuLabelSelected : css.menuLabel; const classes = classNames(rootClassName || css.root, className); @@ -53,29 +51,26 @@ class SelectSingleFilterComponent extends Component { > {menuLabel} - {ca.values.map(v => { + {options.map(option => { // check if this option is selected - const selected = currentValue === v; + const selected = currentValue === option.key; // menu item border class const menuItemBorderClass = selected ? css.menuItemBorderSelected : css.menuItemBorder; return ( - + ); })} - @@ -85,24 +80,25 @@ class SelectSingleFilterComponent extends Component { } } -const { object, string, func } = PropTypes; - -SelectSingleFilterComponent.defaultProps = { +SelectSingleFilter.defaultProps = { rootClassName: null, className: null, }; -SelectSingleFilterComponent.propTypes = { +SelectSingleFilter.propTypes = { rootClassName: string, className: string, - customAttribute: string.isRequired, urlQueryParams: object.isRequired, + urlParam: string.isRequired, + paramLabel: string.isRequired, onSelect: func.isRequired, - // from injectIntl - intl: intlShape.isRequired, + options: arrayOf( + shape({ + key: string.isRequired, + label: string.isRequired, + }) + ).isRequired, }; -const SelectSingleFilter = injectIntl(SelectSingleFilterComponent); - export default SelectSingleFilter; diff --git a/src/components/SelectSingleFilterMobile/SelectSingleFilterMobile.js b/src/components/SelectSingleFilterMobile/SelectSingleFilterMobile.js index 2484bf05..966e94a1 100644 --- a/src/components/SelectSingleFilterMobile/SelectSingleFilterMobile.js +++ b/src/components/SelectSingleFilterMobile/SelectSingleFilterMobile.js @@ -1,12 +1,11 @@ import React, { Component } from 'react'; -import PropTypes from 'prop-types'; +import { object, string, func, arrayOf, shape } from 'prop-types'; import classNames from 'classnames'; -import { FormattedMessage, injectIntl, intlShape } from 'react-intl'; +import { FormattedMessage } from 'react-intl'; -import config from '../../config'; import css from './SelectSingleFilterMobile.css'; -class SelectSingleFilterMobileComponent extends Component { +class SelectSingleFilterMobile extends Component { constructor(props) { super(props); this.state = { isOpen: true }; @@ -15,8 +14,8 @@ class SelectSingleFilterMobileComponent extends Component { } selectOption(option, e) { - const { customAttribute, onSelect } = this.props; - onSelect(customAttribute, option); + const { urlParam, onSelect } = this.props; + onSelect(urlParam, option); // blur event target if event is passed if (e && e.currentTarget) { @@ -29,17 +28,10 @@ class SelectSingleFilterMobileComponent extends Component { } render() { - const { rootClassName, className, customAttribute, urlQueryParams, intl } = this.props; + const { rootClassName, className, urlQueryParams, urlParam, paramLabel, options } = this.props; - const filterLabel = intl.formatMessage({ - id: `SelectSingleFilterMobile.${customAttribute}.label`, - }); - // custom attribute content - const ca = customAttribute && config.customAttributes[customAttribute]; - // name of the corresponding query parameter - const caParam = `ca_${customAttribute}`; // current value of this custom attribute filter - const currentValue = urlQueryParams[caParam]; + const currentValue = urlQueryParams[urlParam]; const labelClass = currentValue ? css.filterLabelSelected : css.filterLabel; @@ -53,22 +45,26 @@ class SelectSingleFilterMobileComponent extends Component {
- {ca.values.map(v => { + {options.map(option => { // check if this option is selected - const selected = currentValue === v; + const selected = currentValue === option.key; // menu item border class const optionBorderClass = selected ? css.optionBorderSelected : css.optionBorder; return ( - ); })} @@ -78,24 +74,25 @@ class SelectSingleFilterMobileComponent extends Component { } } -const { object, string, func } = PropTypes; - -SelectSingleFilterMobileComponent.defaultProps = { +SelectSingleFilterMobile.defaultProps = { rootClassName: null, className: null, }; -SelectSingleFilterMobileComponent.propTypes = { +SelectSingleFilterMobile.propTypes = { rootClassName: string, className: string, - customAttribute: string.isRequired, urlQueryParams: object.isRequired, + urlParam: string.isRequired, + paramLabel: string.isRequired, onSelect: func.isRequired, - // from injectIntl - intl: intlShape.isRequired, + options: arrayOf( + shape({ + key: string.isRequired, + label: string.isRequired, + }) + ).isRequired, }; -const SelectSingleFilterMobile = injectIntl(SelectSingleFilterMobileComponent); - export default SelectSingleFilterMobile; diff --git a/src/components/TransactionPanel/__snapshots__/TransactionPanel.test.js.snap b/src/components/TransactionPanel/__snapshots__/TransactionPanel.test.js.snap index 1474eb95..1094879a 100644 --- a/src/components/TransactionPanel/__snapshots__/TransactionPanel.test.js.snap +++ b/src/components/TransactionPanel/__snapshots__/TransactionPanel.test.js.snap @@ -55,7 +55,6 @@ exports[`TransactionPanel - Order accepted matches snapshot 1`] = ` currentListing={ Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -168,7 +167,6 @@ exports[`TransactionPanel - Order accepted matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -300,7 +298,6 @@ exports[`TransactionPanel - Order accepted matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -429,7 +426,6 @@ exports[`TransactionPanel - Order accepted matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -558,7 +554,6 @@ exports[`TransactionPanel - Order accepted matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -805,7 +800,6 @@ exports[`TransactionPanel - Order accepted matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -915,7 +909,6 @@ exports[`TransactionPanel - Order autodeclined matches snapshot 1`] = ` currentListing={ Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -1028,7 +1021,6 @@ exports[`TransactionPanel - Order autodeclined matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -1160,7 +1152,6 @@ exports[`TransactionPanel - Order autodeclined matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -1289,7 +1280,6 @@ exports[`TransactionPanel - Order autodeclined matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -1418,7 +1408,6 @@ exports[`TransactionPanel - Order autodeclined matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -1665,7 +1654,6 @@ exports[`TransactionPanel - Order autodeclined matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -1775,7 +1763,6 @@ exports[`TransactionPanel - Order canceled matches snapshot 1`] = ` currentListing={ Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -1888,7 +1875,6 @@ exports[`TransactionPanel - Order canceled matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -2020,7 +2006,6 @@ exports[`TransactionPanel - Order canceled matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -2149,7 +2134,6 @@ exports[`TransactionPanel - Order canceled matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -2278,7 +2262,6 @@ exports[`TransactionPanel - Order canceled matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -2525,7 +2508,6 @@ exports[`TransactionPanel - Order canceled matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -2635,7 +2617,6 @@ exports[`TransactionPanel - Order declined matches snapshot 1`] = ` currentListing={ Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -2748,7 +2729,6 @@ exports[`TransactionPanel - Order declined matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -2880,7 +2860,6 @@ exports[`TransactionPanel - Order declined matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -3009,7 +2988,6 @@ exports[`TransactionPanel - Order declined matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -3138,7 +3116,6 @@ exports[`TransactionPanel - Order declined matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -3385,7 +3362,6 @@ exports[`TransactionPanel - Order declined matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -3495,7 +3471,6 @@ exports[`TransactionPanel - Order delivered matches snapshot 1`] = ` currentListing={ Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -3608,7 +3583,6 @@ exports[`TransactionPanel - Order delivered matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -3740,7 +3714,6 @@ exports[`TransactionPanel - Order delivered matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -3869,7 +3842,6 @@ exports[`TransactionPanel - Order delivered matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -3998,7 +3970,6 @@ exports[`TransactionPanel - Order delivered matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -4245,7 +4216,6 @@ exports[`TransactionPanel - Order delivered matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -4355,7 +4325,6 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` currentListing={ Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -4468,7 +4437,6 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -4600,7 +4568,6 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -4729,7 +4696,6 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -4858,7 +4824,6 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -5105,7 +5070,6 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -5215,7 +5179,6 @@ exports[`TransactionPanel - Order preauthorized matches snapshot 1`] = ` currentListing={ Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -5328,7 +5291,6 @@ exports[`TransactionPanel - Order preauthorized matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -5460,7 +5422,6 @@ exports[`TransactionPanel - Order preauthorized matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -5589,7 +5550,6 @@ exports[`TransactionPanel - Order preauthorized matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -5718,7 +5678,6 @@ exports[`TransactionPanel - Order preauthorized matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -5965,7 +5924,6 @@ exports[`TransactionPanel - Order preauthorized matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -6069,7 +6027,6 @@ exports[`TransactionPanel - Sale accepted matches snapshot 1`] = ` currentListing={ Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -6182,7 +6139,6 @@ exports[`TransactionPanel - Sale accepted matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -6301,7 +6257,6 @@ exports[`TransactionPanel - Sale accepted matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -6418,7 +6373,6 @@ exports[`TransactionPanel - Sale accepted matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -6535,7 +6489,6 @@ exports[`TransactionPanel - Sale accepted matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -6770,7 +6723,6 @@ exports[`TransactionPanel - Sale accepted matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -6861,7 +6813,6 @@ exports[`TransactionPanel - Sale autodeclined matches snapshot 1`] = ` currentListing={ Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -6974,7 +6925,6 @@ exports[`TransactionPanel - Sale autodeclined matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -7093,7 +7043,6 @@ exports[`TransactionPanel - Sale autodeclined matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -7210,7 +7159,6 @@ exports[`TransactionPanel - Sale autodeclined matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -7327,7 +7275,6 @@ exports[`TransactionPanel - Sale autodeclined matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -7562,7 +7509,6 @@ exports[`TransactionPanel - Sale autodeclined matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -7653,7 +7599,6 @@ exports[`TransactionPanel - Sale canceled matches snapshot 1`] = ` currentListing={ Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -7766,7 +7711,6 @@ exports[`TransactionPanel - Sale canceled matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -7885,7 +7829,6 @@ exports[`TransactionPanel - Sale canceled matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -8002,7 +7945,6 @@ exports[`TransactionPanel - Sale canceled matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -8119,7 +8061,6 @@ exports[`TransactionPanel - Sale canceled matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -8354,7 +8295,6 @@ exports[`TransactionPanel - Sale canceled matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -8445,7 +8385,6 @@ exports[`TransactionPanel - Sale declined matches snapshot 1`] = ` currentListing={ Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -8558,7 +8497,6 @@ exports[`TransactionPanel - Sale declined matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -8677,7 +8615,6 @@ exports[`TransactionPanel - Sale declined matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -8794,7 +8731,6 @@ exports[`TransactionPanel - Sale declined matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -8911,7 +8847,6 @@ exports[`TransactionPanel - Sale declined matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -9146,7 +9081,6 @@ exports[`TransactionPanel - Sale declined matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -9237,7 +9171,6 @@ exports[`TransactionPanel - Sale delivered matches snapshot 1`] = ` currentListing={ Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -9350,7 +9283,6 @@ exports[`TransactionPanel - Sale delivered matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -9469,7 +9401,6 @@ exports[`TransactionPanel - Sale delivered matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -9586,7 +9517,6 @@ exports[`TransactionPanel - Sale delivered matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -9703,7 +9633,6 @@ exports[`TransactionPanel - Sale delivered matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -9938,7 +9867,6 @@ exports[`TransactionPanel - Sale delivered matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -10029,7 +9957,6 @@ exports[`TransactionPanel - Sale enquired matches snapshot 1`] = ` currentListing={ Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -10142,7 +10069,6 @@ exports[`TransactionPanel - Sale enquired matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -10261,7 +10187,6 @@ exports[`TransactionPanel - Sale enquired matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -10378,7 +10303,6 @@ exports[`TransactionPanel - Sale enquired matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -10495,7 +10419,6 @@ exports[`TransactionPanel - Sale enquired matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -10730,7 +10653,6 @@ exports[`TransactionPanel - Sale enquired matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -10821,7 +10743,6 @@ exports[`TransactionPanel - Sale preauthorized matches snapshot 1`] = ` currentListing={ Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -10934,7 +10855,6 @@ exports[`TransactionPanel - Sale preauthorized matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -11053,7 +10973,6 @@ exports[`TransactionPanel - Sale preauthorized matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -11170,7 +11089,6 @@ exports[`TransactionPanel - Sale preauthorized matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -11287,7 +11205,6 @@ exports[`TransactionPanel - Sale preauthorized matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { @@ -11522,7 +11439,6 @@ exports[`TransactionPanel - Sale preauthorized matches snapshot 1`] = ` }, "listing": Object { "attributes": Object { - "customAttributes": Object {}, "deleted": false, "description": "listing1 description", "geolocation": LatLng { diff --git a/src/components/index.js b/src/components/index.js index 9fa3a22e..91c3f887 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -31,9 +31,6 @@ export { default as ExpandingTextarea } from './ExpandingTextarea/ExpandingTexta export { default as ExternalLink } from './ExternalLink/ExternalLink'; export { default as FilterPanel } from './FilterPanel/FilterPanel'; export { default as FieldCheckbox } from './FieldCheckbox/FieldCheckbox'; -export { - default as FieldCustomAttributeSelect, -} from './FieldCustomAttributeSelect/FieldCustomAttributeSelect'; export { default as FieldGroupCheckbox } from './FieldGroupCheckbox/FieldGroupCheckbox'; export { default as FieldReviewRating } from './FieldReviewRating/FieldReviewRating'; export { default as Footer } from './Footer/Footer'; diff --git a/src/config.js b/src/config.js index 2d8002da..75fe03a2 100644 --- a/src/config.js +++ b/src/config.js @@ -211,41 +211,6 @@ const stripeSupportedCountries = [ }, ]; -// Custom attributes are marketplace specific listing data (e.g. listing could have a category). -// Custom attributes can be defined through management console and code related to custom -// attributes should be changed accordingly. -// -// Here's an example what custom attributes might look like for bicycle listings. This code -// assumes that a custom attribute, called 'category', is created through management console -// with 4 possible values: 'road', 'mountain', 'track', and 'other'. -// -// When listing information is queried customAttributes is returned among other attributes: -// { -// id: 1, -// type: 'listing', -// attributes: { -// title: 'sauna', -// // and description, price, etc. -// customAttributes: { -// category: "mountain", -// // and other added custom attributes as "key: value" pairs -// }, -// }, -// } -const exampleCustomAttributes = { - category: { - select: 'single', // possible values: 'single' (only type supported atm.) - type: 'string', - values: ['road', 'mountain', 'track', 'other'], - }, -}; - -// To use the example custom attributes, set the -// REACT_APP_USE_EXAMPLE_CUSTOM_ATTRIBUTES variable to `true` in the -// gitignored `.env.development.local` file -const useExampleCustomAttributes = process.env.REACT_APP_USE_EXAMPLE_CUSTOM_ATTRIBUTES === 'true'; -const customAttributes = useExampleCustomAttributes ? exampleCustomAttributes : {}; - // Address information is used in SEO schema for Organization (http://schema.org/PostalAddress) const addressCountry = 'FI'; const addressRegion = 'Helsinki'; @@ -284,7 +249,6 @@ const config = { sdk: { clientId: sdkClientId, baseUrl: sdkBaseUrl }, currency, currencyConfig, - customAttributes, stripe: { publishableKey: stripePublishableKey, supportedCountries: stripeSupportedCountries }, canonicalRootURL, address: { diff --git a/src/containers/EditListingDescriptionForm/CustomCategorySelectFieldMaybe.js b/src/containers/EditListingDescriptionForm/CustomCategorySelectFieldMaybe.js new file mode 100644 index 00000000..6e001fc0 --- /dev/null +++ b/src/containers/EditListingDescriptionForm/CustomCategorySelectFieldMaybe.js @@ -0,0 +1,38 @@ +import React from 'react'; +import { required } from '../../util/validators'; +import { SelectField } from '../../components'; + +import css from './EditListingDescriptionForm.css'; + +const CustomCategorySelectFieldMaybe = props => { + const { name, id, categories, intl } = props; + const categoryLabel = intl.formatMessage({ + id: 'EditListingDescriptionForm.categoryLabel', + }); + const categoryPlaceholder = intl.formatMessage({ + id: 'EditListingDescriptionForm.categoryPlaceholder', + }); + const categoryRequired = required( + intl.formatMessage({ + id: 'EditListingDescriptionForm.categoryRequired', + }) + ); + return categories ? ( + + + {categories.map(c => ( + + ))} + + ) : null; +}; + +export default CustomCategorySelectFieldMaybe; diff --git a/src/containers/EditListingDescriptionForm/EditListingDescriptionForm.js b/src/containers/EditListingDescriptionForm/EditListingDescriptionForm.js index 703d423c..e7241f5b 100644 --- a/src/containers/EditListingDescriptionForm/EditListingDescriptionForm.js +++ b/src/containers/EditListingDescriptionForm/EditListingDescriptionForm.js @@ -1,12 +1,13 @@ import React from 'react'; -import PropTypes from 'prop-types'; +import { bool, func, string, arrayOf, shape } from 'prop-types'; import { compose } from 'redux'; import { reduxForm, propTypes as formPropTypes } from 'redux-form'; import { intlShape, injectIntl, FormattedMessage } from 'react-intl'; import classNames from 'classnames'; import { propTypes } from '../../util/types'; import { maxLength, required } from '../../util/validators'; -import { FieldCustomAttributeSelect, Form, Button, TextInputField } from '../../components'; +import { Form, Button, TextInputField } from '../../components'; +import CustomCategorySelectFieldMaybe from './CustomCategorySelectFieldMaybe'; import css from './EditListingDescriptionForm.css'; @@ -25,6 +26,7 @@ const EditListingDescriptionFormComponent = props => { updated, updateError, updateInProgress, + categories, } = props; const titleMessage = intl.formatMessage({ id: 'EditListingDescriptionForm.title' }); @@ -86,10 +88,11 @@ const EditListingDescriptionFormComponent = props => { validate={[required(descriptionRequiredMessage)]} /> -
+
+ + +