UNPKG

cspace-ui

Version:
200 lines (168 loc) 5.43 kB
import React, { useEffect, useMemo } from 'react'; import PropTypes from 'prop-types'; import Immutable from 'immutable'; import { useSelector, useDispatch } from 'react-redux'; import { defineMessages, FormattedMessage } from 'react-intl'; import { baseComponents as inputBaseComponents, components as inputComponents } from 'cspace-input'; import { moveFieldValue, saveRecord, setFieldValue, } from '../../actions/record'; import { getRecordData, getRecordRelationUpdatedTimestamp, getSearchResult, } from '../../reducers'; import { MEDIA_SNAPSHOT_PANEL_SEARCH_NAME } from '../../constants/searchNames'; import { readListItems } from '../search/searchResultHelpers'; import { ConnectedPanel as Panel } from '../../containers/layout/PanelContainer'; import { getSearchDescriptor, mediaPriorityPath } from './MediaSnapshotPanel'; import MediaPriorityRow from './MediaPriorityRow'; import styles from '../../../styles/cspace-ui/MediaPriorityOrderPanel.css'; const { MiniButton } = inputBaseComponents; const { RepeatingInput } = inputComponents; const listType = 'common'; const parentDataPath = mediaPriorityPath.slice(0, -1); const messages = defineMessages({ title: { id: 'mediaPriorityOrderPanel.title', defaultMessage: 'Media Priority', }, titleWithCount: { id: 'mediaPriorityOrderPanel.titleWithCount', defaultMessage: '{title}: {count, number}', }, }); const propTypes = { color: PropTypes.string, config: PropTypes.shape({ listTypes: PropTypes.object, recordTypes: PropTypes.object, mediaSnapshotSort: PropTypes.string, }), csid: PropTypes.string, recordType: PropTypes.string, }; const toRefNameArray = (value) => { if (!value) return []; if (Immutable.List.isList(value)) return value.toArray(); return [value]; }; export default function MediaPriorityOrderPanel(props) { const { color, config, csid, recordType, } = props; const dispatch = useDispatch(); const seqID = useSelector( (state) => getRecordRelationUpdatedTimestamp(state, csid), ); const searchDescriptor = useMemo( () => getSearchDescriptor({ csid, mediaRecordType: 'media', recordRelationUpdatedTimestamp: seqID, recordType, sort: config.mediaSnapshotSort || 'title', }), [config.mediaSnapshotSort, csid, recordType, seqID], ); const storedValue = useSelector( (state) => getRecordData(state, csid)?.getIn(mediaPriorityPath), ); const searchResult = useSelector( (state) => getSearchResult(state, MEDIA_SNAPSHOT_PANEL_SEARCH_NAME, searchDescriptor), ); const recordTypeConfig = config.recordTypes[recordType]; const onCommit = (path, value) => dispatch(setFieldValue(recordTypeConfig, csid, path, value)); const onMoveInstance = (path, newPosition) => dispatch( moveFieldValue(recordTypeConfig, csid, path, newPosition), ); const save = () => dispatch(saveRecord(config, recordTypeConfig, undefined, csid)) .catch(() => {}); const { labelsByRefName, searchLoaded } = useMemo(() => { const { list, items } = readListItems(config, listType, searchResult); const labels = new Map(); if (items) { items.forEach((item) => { const refName = item.get('refName'); if (refName) { const label = [item.get('identificationNumber'), item.get('title')] .filter((part) => !!part) .join(' – '); labels.set(refName, label); } }); } return { labelsByRefName: labels, searchLoaded: list?.get('totalItems') != null, }; }, [config, searchResult]); const mergedValue = useMemo(() => { if (!searchLoaded) return null; const orderedRefNames = toRefNameArray(storedValue) .filter((refName) => labelsByRefName.has(refName)); const orderedSet = new Set(orderedRefNames); labelsByRefName.forEach((label, refName) => { if (!orderedSet.has(refName)) orderedRefNames.push(refName); }); return Immutable.List(orderedRefNames); }, [labelsByRefName, searchLoaded, storedValue]); useEffect(() => { if (mergedValue && !mergedValue.equals(Immutable.List(toRefNameArray(storedValue)))) { onCommit(mediaPriorityPath, mergedValue); } }, [mergedValue]); if (!mergedValue) return null; const saveButton = ( <MiniButton autoWidth key="save" name="save" onClick={save} > Save </MiniButton> ); const title = <FormattedMessage {...messages.title} />; const header = ( <h3> { mergedValue.size === 0 ? <FormattedMessage {...messages.titleWithCount} values={{ title, count: 0 }} /> : title } </h3> ); return ( <Panel buttons={mergedValue.size > 0 ? [saveButton] : []} color={color} collapsible collapsed config={config} header={header} name="mediaPriorityPanel" recordType={recordType} > <div className={styles.panel}> {mergedValue.size > 0 && ( <RepeatingInput name="mediaPriority" parentPath={parentDataPath} value={mergedValue} onCommit={onCommit} onMoveInstance={onMoveInstance} > <MediaPriorityRow labelsByRefName={labelsByRefName} /> </RepeatingInput> )} </div> </Panel> ); } MediaPriorityOrderPanel.propTypes = propTypes;