diff --git a/src/actions/search.js b/src/actions/search.js index cb0c70178..4bd1df991 100644 --- a/src/actions/search.js +++ b/src/actions/search.js @@ -1,7 +1,7 @@ import get from 'lodash/get'; import { getSearchResult, isSearchDirty, isSearchPending } from '../reducers'; import getSession from '../helpers/session'; -import { convertAdvancedSearchConditionToNXQL } from '../helpers/searchHelpers'; +import { convertAdvancedSearchConditionToNXQL, deriveSearchType } from '../helpers/searchHelpers'; import { ERR_UNKNOWN_RECORD_TYPE, @@ -94,7 +94,16 @@ const buildSearchPath = (csid, subresource, config, recordServicePath, vocabular */ const buildAdvancedSearchPath = () => '/advancedsearch'; -export const search = (config, searchName, searchDescriptor, listType = 'common', columnSetName = 'default', isNewSearch = false) => (dispatch, getState) => { +/** + * Build and dispatch a search + * + * @param {*} config The cspace configuration + * @param {*} searchName The search being executed (e.g. SEARCH_RESULT_PAGE_SEARCH_NAME) + * @param {*} searchDescriptor The search descriptor (record type, query params, etc) + * @param {*} columnSetName The columns for the view being returned, used for sort fields + * @returns + */ +export const search = (config, searchName, searchDescriptor, columnSetName = 'default') => (dispatch, getState) => { const recordType = searchDescriptor.get('recordType'); const vocabulary = searchDescriptor.get('vocabulary'); const csid = searchDescriptor.get('csid'); @@ -121,6 +130,11 @@ export const search = (config, searchName, searchDescriptor, listType = 'common' return Promise.resolve(); } + const { + listType, + searchType, + } = deriveSearchType(config, searchName, searchDescriptor); + const listTypeConfig = config.listTypes[listType]; dispatch({ @@ -269,7 +283,7 @@ export const search = (config, searchName, searchDescriptor, listType = 'common' pathParts.push(subresourceServicePath); } - const path = isNewSearch + const path = searchType === 'advanced' ? buildAdvancedSearchPath() : buildSearchPath(csid, subresource, config, recordTypeServicePath, vocabularyServicePath); diff --git a/src/components/media/MediaViewerPanel.jsx b/src/components/media/MediaViewerPanel.jsx index 77f4cc9ea..00504be49 100644 --- a/src/components/media/MediaViewerPanel.jsx +++ b/src/components/media/MediaViewerPanel.jsx @@ -65,14 +65,13 @@ export default class MediaViewerPanel extends Component { const { columnSetName, config, - listType, name, search, searchDescriptor, } = this.props; if (search) { - search(config, name, searchDescriptor, listType, columnSetName); + search(config, name, searchDescriptor, columnSetName); } } diff --git a/src/components/pages/AccountPage.jsx b/src/components/pages/AccountPage.jsx index 5ea6913b4..111c38094 100644 --- a/src/components/pages/AccountPage.jsx +++ b/src/components/pages/AccountPage.jsx @@ -12,6 +12,7 @@ import { canCreate, canRead } from '../../helpers/permissionHelpers'; import AdminTabButtonBar from '../admin/AdminTabButtonBar'; import AccountSearchBar from '../admin/AccountSearchBar'; import styles from '../../../styles/cspace-ui/AdminTab.css'; +import { SEARCH_RESULT_ACCOUNT_PAGE } from '../../constants/searchNames'; const propTypes = { history: PropTypes.shape({ @@ -295,7 +296,7 @@ export default class AccountPage extends Component { isFiltered={!!filterValue} linkItems={false} listType="account" - name="accountPage" + name={SEARCH_RESULT_ACCOUNT_PAGE} pageSizeOptionListName="searchResultPagePageSizes" searchDescriptor={searchDescriptor} title={title} diff --git a/src/components/pages/AuthRolePage.jsx b/src/components/pages/AuthRolePage.jsx index 8efecdbba..7dde8abcf 100644 --- a/src/components/pages/AuthRolePage.jsx +++ b/src/components/pages/AuthRolePage.jsx @@ -12,6 +12,7 @@ import { canCreate, canRead } from '../../helpers/permissionHelpers'; import AdminTabButtonBar from '../admin/AdminTabButtonBar'; import AuthRoleSearchBar from '../admin/AuthRoleSearchBar'; import styles from '../../../styles/cspace-ui/AdminTab.css'; +import { SEARCH_RESULT_AUTH_ROLE_PAGE } from '../../constants/searchNames'; const propTypes = { history: PropTypes.shape({ @@ -282,7 +283,7 @@ export default class AuthRolePage extends Component { isFiltered={!!filterValue} linkItems={false} listType="role" - name="authRolePage" + name={SEARCH_RESULT_AUTH_ROLE_PAGE} pageSizeOptionListName="searchResultPagePageSizes" searchDescriptor={searchDescriptor} title={title} diff --git a/src/components/pages/SearchResultPage.jsx b/src/components/pages/SearchResultPage.jsx index 4e7abafc2..af1b623d0 100644 --- a/src/components/pages/SearchResultPage.jsx +++ b/src/components/pages/SearchResultPage.jsx @@ -13,7 +13,7 @@ import SearchResultSummary from '../search/SearchResultSummary'; import SearchResultTitleBar from '../search/SearchResultTitleBar'; import SelectBar from '../search/SelectBar'; import WatchedSearchResultTableContainer from '../../containers/search/WatchedSearchResultTableContainer'; -import { getListType } from '../../helpers/searchHelpers'; +import { deriveSearchType, getListTypeFromResult } from '../../helpers/searchHelpers'; import { SEARCH_RESULT_PAGE_SEARCH_NAME } from '../../constants/searchNames'; import { @@ -181,7 +181,9 @@ export default class SearchResultPage extends Component { if (onItemSelectChange) { const searchDescriptor = this.getSearchDescriptor(); - const listType = this.getListType(searchDescriptor); + const { + listType, + } = deriveSearchType(config, SEARCH_RESULT_PAGE_SEARCH_NAME, searchDescriptor); onItemSelectChange( config, SEARCH_RESULT_PAGE_SEARCH_NAME, searchDescriptor, listType, index, selected, @@ -319,14 +321,6 @@ export default class SearchResultPage extends Component { } } - getListType(searchDescriptor) { - const { - config, - } = this.context; - - return getListType(config, searchDescriptor); - } - getSearchDescriptor() { // FIXME: Refactor this into a wrapper component that calculates the search descriptor from // location and params, and passes it into a child. This will eliminate the multiple calls to @@ -449,9 +443,7 @@ export default class SearchResultPage extends Component { // has set them to the defaults. if (!Number.isNaN(searchQuery.get('p')) && !Number.isNaN(searchQuery.get('size')) && search) { - const listType = this.getListType(searchDescriptor); - - search(config, SEARCH_RESULT_PAGE_SEARCH_NAME, searchDescriptor, listType); + search(config, SEARCH_RESULT_PAGE_SEARCH_NAME, searchDescriptor); } } @@ -490,7 +482,7 @@ export default class SearchResultPage extends Component { } = this.context; const searchDescriptor = this.getSearchDescriptor(); - const listType = this.getListType(searchDescriptor); + const { listType } = deriveSearchType(config, SEARCH_RESULT_PAGE_SEARCH_NAME, searchDescriptor); let selectBar; @@ -533,9 +525,8 @@ export default class SearchResultPage extends Component { @@ -550,8 +541,7 @@ export default class SearchResultPage extends Component { config, } = this.context; - const searchDescriptor = this.getSearchDescriptor(); - const listType = this.getListType(searchDescriptor); + const listType = getListTypeFromResult(config, searchResult); const listTypeConfig = config.listTypes[listType]; const { listNodeName } = listTypeConfig; @@ -596,7 +586,7 @@ export default class SearchResultPage extends Component { const searchDescriptor = this.getSearchDescriptor(); - const listType = this.getListType(searchDescriptor); + const { listType } = deriveSearchType(config, SEARCH_RESULT_PAGE_SEARCH_NAME, searchDescriptor); const recordType = searchDescriptor.get('recordType'); const vocabulary = searchDescriptor.get('vocabulary'); diff --git a/src/components/pages/search/SearchResultRoute.jsx b/src/components/pages/search/SearchResultRoute.jsx index c71c62d81..821160f2d 100644 --- a/src/components/pages/search/SearchResultRoute.jsx +++ b/src/components/pages/search/SearchResultRoute.jsx @@ -13,10 +13,10 @@ import { useConfig } from '../../config/ConfigProvider'; * @returns the component to render */ export default function SearchResultRoute(props) { - const { recordType } = useParams(); + const { recordType, subresource } = useParams(); const config = useConfig(); - const isNewSearch = get(config, + const isNewSearch = !subresource && get(config, ['recordTypes', recordType, 'serviceConfig', 'features', 'updatedSearch']); return isNewSearch diff --git a/src/components/pages/search/SearchResults.jsx b/src/components/pages/search/SearchResults.jsx index 90e4db2d8..1cdeb0a28 100644 --- a/src/components/pages/search/SearchResults.jsx +++ b/src/components/pages/search/SearchResults.jsx @@ -25,11 +25,12 @@ import { search, setAllResultItemsSelected, } from '../../../actions/search'; import { - getSearchError, getSearchResult, isSearchResultSidebarOpen, getSearchSelectedItems, getUserPerms, + getSearchResult, isSearchResultSidebarOpen, getSearchSelectedItems, getUserPerms, } from '../../../reducers'; import SelectBar from '../../search/SelectBar'; import RelateResults from '../../search/RelateResults'; import ExportResults from '../../search/ExportResults'; +import { getListTypeFromResult } from '../../../helpers/searchHelpers'; const selectBarPropTypes = { toggleBar: PropTypes.object, @@ -78,12 +79,11 @@ export function SelectExportRelateToggleBar({ ); - // toggle bar (grid/table/etc) - + const listType = getListTypeFromResult(config, searchResult); return ( { setPreferredPageSize(props, dispatch); - dispatch(search(config, SEARCH_RESULT_PAGE_SEARCH_NAME, searchDescriptor, 'common')); // , 'common', true)); + dispatch(search(config, SEARCH_RESULT_PAGE_SEARCH_NAME, searchDescriptor)); }, [normalizedQuery, searchDescriptor]); - // todo: should these be called in each component? they're at the top level for now - // as to not make too many changes at once const searchResults = useSelector((state) => getSearchResult(state, SEARCH_RESULT_PAGE_SEARCH_NAME, searchDescriptor)); - const searchErrors = useSelector((state) => getSearchError(state, - SEARCH_RESULT_PAGE_SEARCH_NAME, - searchDescriptor)); const isSidebarOpen = useSelector((state) => isSearchResultSidebarOpen(state)); const toggles = [ @@ -262,7 +270,7 @@ export default function SearchResults(props) { let searchDisplay; if (display === 'table') { - searchDisplay = ; + searchDisplay = ; } else if (display === 'list') { searchDisplay = ; } else { @@ -293,10 +301,8 @@ export default function SearchResults(props) {
getSearchError(state, searchName, searchDescriptor)); + const searchResult = useSelector((state) => getSearchResult(state, searchName, searchDescriptor)); + if (searchError) { const error = searchError.toJS(); @@ -127,6 +128,7 @@ export default function SearchResultSummary(props) { let pageSize = null; if (searchResult) { + const listType = getListTypeFromResult(config, searchResult); const listTypeConfig = config.listTypes[listType]; const { listNodeName } = listTypeConfig; diff --git a/src/components/search/SearchResultTable.jsx b/src/components/search/SearchResultTable.jsx index 6f840cfcd..390f67259 100644 --- a/src/components/search/SearchResultTable.jsx +++ b/src/components/search/SearchResultTable.jsx @@ -8,6 +8,7 @@ import { Table } from 'cspace-layout'; import dimensions from '../../../styles/dimensions.css'; import styles from '../../../styles/cspace-ui/SearchResultTable.css'; import emptyResultStyles from '../../../styles/cspace-ui/SearchResultEmpty.css'; +import { getListTypeFromResult } from '../../helpers/searchHelpers'; const rowHeight = parseInt(dimensions.inputHeight, 10); @@ -185,12 +186,12 @@ export default class SearchResultTable extends Component { handleRowClick(index) { const { config, - listType, searchResult, onItemClick, } = this.props; if (onItemClick) { + const listType = getListTypeFromResult(config, searchResult); const listTypeConfig = config.listTypes[listType]; const { listNodeName, itemNodeName } = listTypeConfig; @@ -234,11 +235,12 @@ export default class SearchResultTable extends Component { const { config, linkState, - listType, perms, + searchResult, searchDescriptor, } = this.props; + const listType = getListTypeFromResult(config, searchResult); const getItemLocationPath = get(config, ['listTypes', listType, 'getItemLocationPath']); if (!getItemLocationPath) { @@ -342,7 +344,6 @@ export default class SearchResultTable extends Component { config, formatCellData, formatColumnLabel, - listType, searchDescriptor, searchResult, showCheckboxColumn, @@ -350,6 +351,7 @@ export default class SearchResultTable extends Component { } = this.props; if (searchResult) { + const listType = getListTypeFromResult(config, searchResult); const searchQuery = searchDescriptor.get('searchQuery'); const listTypeConfig = config.listTypes[listType]; diff --git a/src/components/search/SearchResultTraverser.jsx b/src/components/search/SearchResultTraverser.jsx index dee62a0c9..da1d676dc 100644 --- a/src/components/search/SearchResultTraverser.jsx +++ b/src/components/search/SearchResultTraverser.jsx @@ -6,7 +6,7 @@ import Immutable from 'immutable'; import SearchResultItemLink from './SearchResultItemLink'; import { - getListType, + deriveSearchType, searchDescriptorToLocation, } from '../../helpers/searchHelpers'; @@ -82,11 +82,11 @@ export default class SearchResultTraverser extends Component { // maintained in history state, but the search state is gone, since the app has been // reloaded. Initiate the search. - search(config, searchName, searchDescriptor, getListType(config, searchDescriptor)); + search(config, searchName, searchDescriptor); } if (searchState && !searchState.get('isPending') && searchState.get('result')) { - const listType = getListType(config, searchDescriptor); + const { listType } = deriveSearchType(config, searchName, searchDescriptor); const listTypeConfig = config.listTypes[listType]; const { listNodeName, itemNodeName } = listTypeConfig; @@ -125,7 +125,6 @@ export default class SearchResultTraverser extends Component { config, searchName, prevPageSearchDescriptor, - getListType(config, prevPageSearchDescriptor), ); } @@ -142,14 +141,13 @@ export default class SearchResultTraverser extends Component { config, searchName, nextPageSearchDescriptor, - getListType(config, nextPageSearchDescriptor), ); } } } } - renderPrevLink(items, index, currentNum, totalItems, locationState) { + renderPrevLink(items, index, currentNum, totalItems, locationState, listType) { const { config, searchName, @@ -175,7 +173,6 @@ export default class SearchResultTraverser extends Component { // We're at the beginning of the current page, but we have data for the previous page. Link // to the last item in its results. - const listType = getListType(config, prevPageSearchDescriptor); const listTypeConfig = config.listTypes[listType]; const { listNodeName, itemNodeName } = listTypeConfig; @@ -210,7 +207,7 @@ export default class SearchResultTraverser extends Component { return ; } - renderNextLink(items, index, currentNum, totalItems, locationState) { + renderNextLink(items, index, currentNum, totalItems, locationState, listType) { const { config, searchName, @@ -236,7 +233,6 @@ export default class SearchResultTraverser extends Component { // We're at the end of the current page, but we have data for the next page. Link to the // first item in its results. - const listType = getListType(config, nextPageSearchDescriptor); const listTypeConfig = config.listTypes[listType]; const { listNodeName, itemNodeName } = listTypeConfig; @@ -296,7 +292,7 @@ export default class SearchResultTraverser extends Component { ) { resultMessage = ; } else { - const listType = getListType(config, searchDescriptor); + const { listType } = deriveSearchType(config, searchName, searchDescriptor); const listTypeConfig = config.listTypes[listType]; const { listNodeName, itemNodeName } = listTypeConfig; @@ -332,8 +328,8 @@ export default class SearchResultTraverser extends Component { originSearchPage: originSearchPageState, }; - prevLink = this.renderPrevLink(items, index, currentNum, totalItems, locationState); - nextLink = this.renderNextLink(items, index, currentNum, totalItems, locationState); + prevLink = this.renderPrevLink(items, index, currentNum, totalItems, locationState, listType); + nextLink = this.renderNextLink(items, index, currentNum, totalItems, locationState, listType); } const searchLocation = Object.assign(searchDescriptorToLocation(searchDescriptor), { diff --git a/src/components/search/SearchToSelectModal.jsx b/src/components/search/SearchToSelectModal.jsx index 33bfe2473..de1da2e95 100644 --- a/src/components/search/SearchToSelectModal.jsx +++ b/src/components/search/SearchToSelectModal.jsx @@ -19,7 +19,7 @@ import SearchResultSummary from './SearchResultSummary'; import SearchToSelectTitleBar from './SearchToSelectTitleBar'; import SelectBar from './SelectBar'; import SearchResultTableContainer from '../../containers/search/SearchResultTableContainer'; -import { normalizeCondition } from '../../helpers/searchHelpers'; +import { deriveSearchType, getListTypeFromResult, normalizeCondition } from '../../helpers/searchHelpers'; import styles from '../../../styles/cspace-ui/SearchToSelectModal.css'; export const searchName = 'searchToSelect'; @@ -35,7 +35,6 @@ const messages = defineMessages({ }, }); -const listType = 'common'; // FIXME: Make default page size configurable const defaultPageSize = 20; @@ -421,6 +420,7 @@ export class BaseSearchToSelectModal extends Component { if (onItemSelectChange) { const searchDescriptor = this.getSearchDescriptor(); + const { listType } = deriveSearchType(config, searchName, searchDescriptor); if (singleSelect && selected) { setAllItemsSelected(config, searchName, searchDescriptor, listType, false); @@ -557,6 +557,7 @@ export class BaseSearchToSelectModal extends Component { return null; } + const listType = getListTypeFromResult(config, searchResult); const searchDescriptor = this.getSearchDescriptor(); let selectBar; @@ -585,8 +586,6 @@ export class BaseSearchToSelectModal extends Component { config={config} listType={listType} searchDescriptor={searchDescriptor} - searchError={searchError} - searchResult={searchResult} renderEditLink={this.renderEditSearchLink} onPageSizeChange={this.handlePageSizeChange} /> @@ -601,6 +600,7 @@ export class BaseSearchToSelectModal extends Component { } = this.props; if (searchResult) { + const listType = getListTypeFromResult(config, searchResult); const listTypeConfig = config.listTypes[listType]; const list = searchResult.get(listTypeConfig.listNodeName); @@ -641,7 +641,6 @@ export class BaseSearchToSelectModal extends Component { getSearchSelectedItems(state, SEARCH_RESULT_PAGE_SEARCH_NAME)); const selected = selectedItems ? selectedItems.has(csid) : false; - const listTypeConfig = config.listTypes.common; + const listTypeConfig = config.listTypes[listType]; const { getItemLocationPath } = listTypeConfig; let location; let state; @@ -48,12 +51,11 @@ export function SearchResultCard({ }; } - // todo: read fields from record config - // todo: loading image + // todo: image not found thumbnail + const blob = derivativeImage(blobCsid, 'Thumbnail'); return ( -
- {/* eslint-disable-next-line jsx-a11y/alt-text */} - +
+ {blob}
dispatch(setResultItemSelected(config, SEARCH_RESULT_PAGE_SEARCH_NAME, searchDescriptor, - 'common', + listType, parseInt(path[0], 10), value))} onClick={(event) => event.stopPropagation()} @@ -102,15 +104,10 @@ function SearchResultGrid({ searchDescriptor, intl }) { searchDescriptor)); const config = useConfig(); - if (!results) { - return null; - } - // Note: The items returned is an Immutable.Map, so we need to use get // in order to retrieve the data - // todo: read into the search results based on the list type - // todo: why do we need to do !results AND !items? - const items = readListItems(config, 'common', results); + const listType = getListTypeFromResult(config, results); + const { items } = readListItems(config, listType, results); if (!items) { return null; } @@ -149,8 +146,6 @@ function SearchResultGrid({ searchDescriptor, intl }) { const subtitleConfig = cardConfig.subtitle.fields; const subtitleFields = createFieldConfig(subtitleConfig); - // todo: sidebar is open prop to control grid size? - // or could try flexbox return (
{items.map((item, index) => ( @@ -158,6 +153,7 @@ function SearchResultGrid({ searchDescriptor, intl }) { key={item.get('csid')} index={index} result={item} + listType={listType} titleFields={titleFields} subtitleFields={subtitleFields} searchDescriptor={searchDescriptor} diff --git a/src/components/search/header/ToggleButtons.jsx b/src/components/search/header/ToggleButtons.jsx index 62f1d7117..2aff26777 100644 --- a/src/components/search/header/ToggleButtons.jsx +++ b/src/components/search/header/ToggleButtons.jsx @@ -49,9 +49,7 @@ const propTypes = { */ export function ToggleButtonContainer({ items, renderButton, renderSidebarToggle }) { const toggleStyles = { - flex: '1', - display: 'flex', - justifyContent: 'flex-end', + marginLeft: 'auto', }; return ( diff --git a/src/components/search/list/SearchList.jsx b/src/components/search/list/SearchList.jsx index 4bad30364..da0a0127c 100644 --- a/src/components/search/list/SearchList.jsx +++ b/src/components/search/list/SearchList.jsx @@ -6,23 +6,22 @@ import { useDispatch, useSelector } from 'react-redux'; import get from 'lodash/get'; import { injectIntl } from 'react-intl'; import { CheckboxInput } from '../../../helpers/configContextInputs'; -import deactivate from '../../../../images/deactivate.svg'; import { getColumnConfig, readListItems } from '../searchResultHelpers'; import { getSearchResult, getSearchSelectedItems } from '../../../reducers'; import { SEARCH_RESULT_PAGE_SEARCH_NAME } from '../../../constants/searchNames'; import { useConfig } from '../../config/ConfigProvider'; import { setResultItemSelected } from '../../../actions/search'; +import BlobImage from '../../media/BlobImage'; import styles from '../../../../styles/cspace-ui/SearchList.css'; +import { getListTypeFromResult } from '../../../helpers/searchHelpers'; const DETAIL_COLUMN_SET = 'list'; const itemPropTypes = { item: PropTypes.instanceOf(Immutable.Map), - // exact shape tbd index: PropTypes.number, listItems: PropTypes.array, - // render context like search table? or a better way to handle all this? searchDescriptor: PropTypes.object, listType: PropTypes.string, selectedItems: PropTypes.instanceOf(Immutable.Map), @@ -35,6 +34,7 @@ export function DetailItem({ const dispatch = useDispatch(); const csid = item.get('csid'); + const blobCsid = item.get('blobCsid'); const selected = selectedItems ? selectedItems.has(csid) : false; const listTypeConfig = config.listTypes[listType]; @@ -79,10 +79,13 @@ export function DetailItem({ ); // omit fields when no data is returned? + // todo: NoBlobFound image + const blob = blobCsid ? : null; return (
{/* eslint-disable-next-line jsx-a11y/alt-text */} - + {blob} + {list} event.stopPropagation()} /> - {list}
); } @@ -106,32 +108,22 @@ DetailItem.propTypes = itemPropTypes; const propTypes = { searchDescriptor: PropTypes.instanceOf(Immutable.Map), intl: PropTypes.object, - listType: PropTypes.string, }; -function SearchDetailList({ searchDescriptor, intl, listType = 'common' }) { +function SearchDetailList({ searchDescriptor, intl }) { const results = useSelector((state) => getSearchResult(state, SEARCH_RESULT_PAGE_SEARCH_NAME, searchDescriptor)); + const selectedItems = useSelector((state) => getSearchSelectedItems(state, + SEARCH_RESULT_PAGE_SEARCH_NAME)); const config = useConfig(); - if (!results) { - return null; - } - - // Note: The items returned is an Immutable.Map, so we need to use get - // in order to retrieve the data - // Note x2: This is only available for 'new' searches, so we don't need a list type prop - // todo: read into the search results based on the list type - // todo: why do we need to do !results AND !items? - const items = readListItems(config, listType, results); + const listType = getListTypeFromResult(config, results); + const { items } = readListItems(config, listType, results); if (!items) { return null; } - const selectedItems = useSelector((state) => getSearchSelectedItems(state, - SEARCH_RESULT_PAGE_SEARCH_NAME)); - // read headers const listConfig = getColumnConfig(config, searchDescriptor, DETAIL_COLUMN_SET); const listItems = Object.keys(listConfig) @@ -149,13 +141,6 @@ function SearchDetailList({ searchDescriptor, intl, listType = 'common' }) { const message = get(column, ['messages', 'label']); return message ? intl.formatMessage(message) : ''; }, - // Just an idea - a render 'prop' passed along with the listItems - renderRow: ({ dataKey, rowData }) => { - const label = get(column, ['message', 'label']); - const data = rowData.get(dataKey); - const formatted = `${label}: ${data}`; - return
  • {formatted}
  • ; - }, }; }); @@ -164,6 +149,7 @@ function SearchDetailList({ searchDescriptor, intl, listType = 'common' }) { {items.map((item, index) => ( getSearchResult(state, SEARCH_RESULT_PAGE_SEARCH_NAME, @@ -63,8 +63,11 @@ function SearchResultTable({ searchDescriptor, listType = 'common', intl }) { const selectedItems = useSelector((state) => getSearchSelectedItems(state, SEARCH_RESULT_PAGE_SEARCH_NAME)); - const list = readSearchResultList(config, listType, results); - const items = readSearchResultListItems(config, listType, list); + const listType = getListTypeFromResult(config, results); + const { + list, + items, + } = readListItems(config, listType, results); if (!items) { return null; @@ -127,7 +130,6 @@ function SearchResultTable({ searchDescriptor, listType = 'common', intl }) { - {/* todo: I think it probably make this visible if it exists */} {/* eslint-disable-next-line jsx-a11y/control-has-associated-label */}
    {columns.map((column) => (sortColumnName === column.dataKey diff --git a/src/constants/searchNames.js b/src/constants/searchNames.js index 84f369f58..72b5b791b 100644 --- a/src/constants/searchNames.js +++ b/src/constants/searchNames.js @@ -3,3 +3,7 @@ export const RECORD_BATCH_PANEL_SEARCH_NAME = 'recordBatchPanel'; export const RECORD_REPORT_PANEL_SEARCH_NAME = 'recordReportPanel'; export const SEARCH_RESULT_BATCH_PANEL_SEARCH_NAME = 'searchResultBatchPanel'; export const SEARCH_RESULT_REPORT_PANEL_SEARCH_NAME = 'searchResultReportPanel'; +export const SEARCH_RESULT_TERMS_USED_PANEL = 'termsUsedPanel'; +export const SEARCH_RESULT_USED_BY_PANEL = 'usedByPanel'; +export const SEARCH_RESULT_AUTH_ROLE_PAGE = 'authRolePage'; +export const SEARCH_RESULT_ACCOUNT_PAGE = 'accountPage'; diff --git a/src/helpers/searchHelpers.js b/src/helpers/searchHelpers.js index b993d33b6..784b5b4e5 100644 --- a/src/helpers/searchHelpers.js +++ b/src/helpers/searchHelpers.js @@ -19,6 +19,11 @@ import { DATA_TYPE_STRUCTURED_DATE, } from '../constants/dataTypes'; +import { + SEARCH_RESULT_ACCOUNT_PAGE, + SEARCH_RESULT_AUTH_ROLE_PAGE, +} from '../constants/searchNames'; + import { OP_AND, OP_OR, @@ -985,16 +990,54 @@ export const searchDescriptorToLocation = (searchDescriptor) => { }; }; -export const getListType = (config, searchDescriptor) => { +/** + * Attempt to derive list type and search type from a search's name and descriptor. + * + * @param {*} config the cspace configuration + * @param {*} searchName the name of the search + * @param {*} searchDescriptor the search descriptor + * @returns an object with the listType and searchType set + */ +export const deriveSearchType = (config, searchName, searchDescriptor) => { + let listType = 'common'; + let searchType = 'default'; + if (searchDescriptor) { + const recordType = searchDescriptor.get('recordType'); const subresource = searchDescriptor.get('subresource'); - if (subresource) { - return get(config, ['subresources', subresource, 'listType']); + // there are a few search apis which return different lists, so we account for them first + // because they should only need the listType. + // Note that we use the name of the key for the listType (role, account, etc). + // todo: it would be nice to update the backend to send a single paginated list type instead + if (SEARCH_RESULT_ACCOUNT_PAGE === searchName) { + listType = 'account'; + } else if (SEARCH_RESULT_AUTH_ROLE_PAGE === searchName) { + listType = 'role'; + } else if (subresource) { + listType = get(config, ['subresources', subresource, 'listType']) || 'common'; + } else if (get(config, ['recordTypes', recordType, 'serviceConfig', 'features', 'updatedSearch'])) { + listType = 'search'; + searchType = 'advanced'; } } - return 'common'; + return { + listType, + searchType, + }; +}; + +export const getListTypeFromResult = (config, searchResult) => { + let listType; + if (searchResult) { + listType = Object.keys(get(config, ['listTypes'])).find((key) => { + const listNodeName = get(config, ['listTypes', key, 'listNodeName']); + return searchResult.has(listNodeName); + }); + } + + return listType || 'common'; }; /** diff --git a/src/plugins/listTypes/search.js b/src/plugins/listTypes/search.js index 4b41d0cde..2c67980e8 100644 --- a/src/plugins/listTypes/search.js +++ b/src/plugins/listTypes/search.js @@ -19,7 +19,7 @@ export default () => ({ defaultMessage: 'Finding records...', }, }), - getItemLocationPath: (item) => item.get('uri'), + getItemLocationPath: (item) => `/record/collectionobject/${item.get('csid')}`, }, }, }); diff --git a/styles/cspace-ui/SearchGrid.css b/styles/cspace-ui/SearchGrid.css index 1db98b2f4..f51d9b8b0 100644 --- a/styles/cspace-ui/SearchGrid.css +++ b/styles/cspace-ui/SearchGrid.css @@ -13,8 +13,17 @@ } .card { - width: 250px; + background:rgb(255, 255, 255); + width: 100%; +} + +.card img { + padding: 10px; + max-width: 100%; height: 250px; - background:rgb(220, 220, 220); - background-image: url(../../images/deactivate.svg); + object-fit: cover; +} + +.summary { + padding: 5px 10px; } diff --git a/styles/cspace-ui/SearchList.css b/styles/cspace-ui/SearchList.css index 6f9691be7..0c4e88fcf 100644 --- a/styles/cspace-ui/SearchList.css +++ b/styles/cspace-ui/SearchList.css @@ -1,13 +1,21 @@ .detail { display: flex; flex-direction: column; - padding: 5px; + gap: calc(.25rem * 4); } .innerDetail { display: flex; flex-direction: row; - margin: 2px; + border: 1px solid rgb(220, 220, 220); + padding: 30px; +} + +.innerDetail img { + max-height: 128px; + max-width: 20%; + width: auto; + margin-right: 5px; } .detailImg { @@ -18,7 +26,7 @@ } .detailCheckbox { - margin-right: 5px; + margin-left: auto; } .detailList { diff --git a/test/specs/actions/search.spec.js b/test/specs/actions/search.spec.js index de811c4da..77a3bdc5d 100644 --- a/test/specs/actions/search.spec.js +++ b/test/specs/actions/search.spec.js @@ -98,6 +98,7 @@ describe('search action creator', () => { }, subresources: { terms: { + listType: 'common', serviceConfig: { servicePath: termsServicePath, }, diff --git a/test/specs/components/media/MediaViewerPanel.spec.jsx b/test/specs/components/media/MediaViewerPanel.spec.jsx index fb14dfcb7..cb37e26a1 100644 --- a/test/specs/components/media/MediaViewerPanel.spec.jsx +++ b/test/specs/components/media/MediaViewerPanel.spec.jsx @@ -158,16 +158,14 @@ describe('MediaViewerPanel', () => { let searchedConfig = null; let searchedSearchName = null; let searchedSearchDescriptor = null; - let searchedListType = null; let searchedColumnSetName = null; const search = ( - configArg, searchNameArg, searchDescriptorArg, listTypeArg, columnSetNameArg, + configArg, searchNameArg, searchDescriptorArg, columnSetNameArg, ) => { searchedConfig = configArg; searchedSearchName = searchNameArg; searchedSearchDescriptor = searchDescriptorArg; - searchedListType = listTypeArg; searchedColumnSetName = columnSetNameArg; }; @@ -185,7 +183,6 @@ describe('MediaViewerPanel', () => { searchedConfig.should.equal(config); searchedSearchName.should.equal(searchName); searchedSearchDescriptor.should.equal(searchDescriptor); - searchedListType.should.equal('common'); searchedColumnSetName.should.equal('default'); }); @@ -193,16 +190,14 @@ describe('MediaViewerPanel', () => { let searchedConfig = null; let searchedSearchName = null; let searchedSearchDescriptor = null; - let searchedListType = null; let searchedColumnSetName = null; const search = ( - configArg, searchNameArg, searchDescriptorArg, listTypeArg, columnSetNameArg, + configArg, searchNameArg, searchDescriptorArg, columnSetNameArg, ) => { searchedConfig = configArg; searchedSearchName = searchNameArg; searchedSearchDescriptor = searchDescriptorArg; - searchedListType = listTypeArg; searchedColumnSetName = columnSetNameArg; }; @@ -239,7 +234,6 @@ describe('MediaViewerPanel', () => { searchedConfig.should.equal(config); searchedSearchName.should.equal(searchName); searchedSearchDescriptor.should.equal(newSearchDescriptor); - searchedListType.should.equal('common'); searchedColumnSetName.should.equal('default'); }); }); diff --git a/test/specs/components/pages/SearchResultPage.spec.jsx b/test/specs/components/pages/SearchResultPage.spec.jsx index 37cb97475..d83d145b9 100644 --- a/test/specs/components/pages/SearchResultPage.spec.jsx +++ b/test/specs/components/pages/SearchResultPage.spec.jsx @@ -181,14 +181,16 @@ const searchDescriptor = Immutable.fromJS({ }, }); +const optionList = Immutable.Map({ + searchResultPagePageSizes: [ + { value: '10' }, + { value: '20' }, + { value: '40' }, + ], +}); + const store = mockStore({ - optionList: Immutable.Map({ - searchResultPagePageSizes: [ - { value: '10' }, - { value: '20' }, - { value: '40' }, - ], - }), + optionList, prefs: Immutable.Map(), search: Immutable.fromJS({ [SEARCH_RESULT_PAGE_SEARCH_NAME]: { @@ -637,9 +639,25 @@ describe('SearchResultPage', () => { 'ns2:abstract-common-list': {}, }); + const updatedStore = mockStore({ + optionList, + prefs: Immutable.Map(), + search: Immutable.fromJS({ + [SEARCH_RESULT_PAGE_SEARCH_NAME]: { + byKey: { + [searchKey(searchDescriptor)]: { + result: noTotalItemsSearchResult, + }, + }, + }, + }), + searchToSelect: Immutable.Map(), + user: Immutable.Map(), + }); + render( - + {searchResultPage.renderHeader({ searchResult: noTotalItemsSearchResult })} @@ -656,10 +674,6 @@ describe('SearchResultPage', () => { }); it('should render an error message if the search has an error', () => { - const searchError = Immutable.Map({ - code: 'ERROR_CODE', - }); - const pageContainer = document.createElement('div'); document.body.appendChild(pageContainer); @@ -686,9 +700,29 @@ describe('SearchResultPage', () => { document.body.appendChild(headerContainer); + const searchError = Immutable.Map({ + code: 'ERROR_CODE', + }); + + const updatedStore = mockStore({ + optionList, + prefs: Immutable.Map(), + search: Immutable.fromJS({ + [SEARCH_RESULT_PAGE_SEARCH_NAME]: { + byKey: { + [searchKey(searchDescriptor)]: { + error: searchError, + }, + }, + }, + }), + searchToSelect: Immutable.Map(), + user: Immutable.Map(), + }); + render( - + {searchResultPage.renderHeader({ searchError })} diff --git a/test/specs/components/pages/search/SearchResults.spec.jsx b/test/specs/components/pages/search/SearchResults.spec.jsx new file mode 100644 index 000000000..e69de29bb diff --git a/test/specs/components/search/SearchPanel.spec.jsx b/test/specs/components/search/SearchPanel.spec.jsx index 30a05faf8..0368eab53 100644 --- a/test/specs/components/search/SearchPanel.spec.jsx +++ b/test/specs/components/search/SearchPanel.spec.jsx @@ -172,16 +172,14 @@ describe('SearchPanel', () => { let searchedConfig = null; let searchedSearchName = null; let searchedSearchDescriptor = null; - let searchedListType = null; let searchedColumnSetName = null; const search = ( - configArg, searchNameArg, searchDescriptorArg, listTypeArg, columnSetNameArg, + configArg, searchNameArg, searchDescriptorArg, columnSetNameArg, ) => { searchedConfig = configArg; searchedSearchName = searchNameArg; searchedSearchDescriptor = searchDescriptorArg; - searchedListType = listTypeArg; searchedColumnSetName = columnSetNameArg; }; @@ -212,7 +210,6 @@ describe('SearchPanel', () => { searchedConfig.should.equal(config); searchedSearchName.should.equal(searchName); searchedSearchDescriptor.should.equal(searchDescriptor); - searchedListType.should.equal('common'); searchedColumnSetName.should.equal('default'); changedToSearchDescriptor.should.equal(searchDescriptor); @@ -222,16 +219,14 @@ describe('SearchPanel', () => { let searchedConfig = null; let searchedSearchName = null; let searchedSearchDescriptor = null; - let searchedListType = null; let searchedColumnSetName = null; const search = ( - configArg, searchNameArg, searchDescriptorArg, listTypeArg, columnSetNameArg, + configArg, searchNameArg, searchDescriptorArg, columnSetNameArg, ) => { searchedConfig = configArg; searchedSearchName = searchNameArg; searchedSearchDescriptor = searchDescriptorArg; - searchedListType = listTypeArg; searchedColumnSetName = columnSetNameArg; }; @@ -286,7 +281,6 @@ describe('SearchPanel', () => { searchedConfig.should.equal(config); searchedSearchName.should.equal(searchName); searchedSearchDescriptor.should.equal(newSearchDescriptor); - searchedListType.should.equal('common'); searchedColumnSetName.should.equal('default'); changedToSearchDescriptor.should.equal(newSearchDescriptor); diff --git a/test/specs/components/search/SearchResultSummary.spec.jsx b/test/specs/components/search/SearchResultSummary.spec.jsx index b4016cbde..c96d6e8b9 100644 --- a/test/specs/components/search/SearchResultSummary.spec.jsx +++ b/test/specs/components/search/SearchResultSummary.spec.jsx @@ -8,6 +8,7 @@ import { ERR_API } from '../../../../src/constants/errorCodes'; import createTestContainer from '../../../helpers/createTestContainer'; import { render } from '../../../helpers/renderHelpers'; import SearchResultSummary from '../../../../src/components/search/SearchResultSummary'; +import { searchKey } from '../../../../src/reducers/search'; chai.should(); @@ -21,6 +22,7 @@ const store = mockStore({ { value: '40' }, ], }), + search: Immutable.Map({}), }); const searchDescriptor = Immutable.fromJS({ @@ -50,6 +52,7 @@ describe('SearchResultSummary', () => { }); it('should render a not allowed message if a 401 search error is supplied', function test() { + const searchName = 'search-summary-test'; const searchError = Immutable.fromJS({ code: ERR_API, error: { @@ -59,13 +62,25 @@ describe('SearchResultSummary', () => { }, }); + const storeWithError = mockStore({ + search: Immutable.fromJS({ + [searchName]: { + byKey: { + [searchKey(searchDescriptor)]: { + error: searchError, + }, + }, + }, + }), + }); + render( - + diff --git a/test/specs/components/search/SearchResultTable.spec.jsx b/test/specs/components/search/SearchResultTable.spec.jsx index 693df9d16..7c3555936 100644 --- a/test/specs/components/search/SearchResultTable.spec.jsx +++ b/test/specs/components/search/SearchResultTable.spec.jsx @@ -35,11 +35,11 @@ const config = { getItemLocationPath: (item) => `itemLocation: ${item.get('csid')}`, }, foo: { - listNodeName: 'ns2:abstract-common-list', + listNodeName: 'ns2:foo-common-list', itemNodeName: 'list-item', }, bar: { - listNodeName: 'ns2:abstract-common-list', + listNodeName: 'ns2:bar-common-list', itemNodeName: 'list-item', getItemLocationPath: () => null, }, @@ -108,41 +108,52 @@ const config = { }, }; +const baseResult = { + pageNum: '0', + pageSize: '40', + itemsInPage: '5', + totalItems: '5', + 'list-item': [ + { + csid: 'ea399d7a-7ea3-4670-930b', + updatedAt: '2017-01-06T02:28:53.269Z', + objectNumber: '4', + title: 'Title', + }, + { + csid: '0abd85b5-46be-4a6c-aa14', + updatedAt: '2017-01-04T05:29:41.963Z', + objectNumber: '3', + }, + { + csid: '325b3337-9db5-45ae-a0a9', + updatedAt: '2017-01-04T05:27:50.225Z', + objectNumber: '32', + }, + { + csid: '12a6be7f-4ea8-49c1-b41c', + updatedAt: '2017-01-04T05:22:21.581Z', + objectNumber: '6.0221415', + }, + { + csid: '080b1ce2-598b-4340-b23a', + updatedAt: '2017-01-04T05:22:21.288Z', + objectNumber: '6.0221415', + }, + ], + +}; + const searchResult = Immutable.fromJS({ - 'ns2:abstract-common-list': { - pageNum: '0', - pageSize: '40', - itemsInPage: '5', - totalItems: '5', - 'list-item': [ - { - csid: 'ea399d7a-7ea3-4670-930b', - updatedAt: '2017-01-06T02:28:53.269Z', - objectNumber: '4', - title: 'Title', - }, - { - csid: '0abd85b5-46be-4a6c-aa14', - updatedAt: '2017-01-04T05:29:41.963Z', - objectNumber: '3', - }, - { - csid: '325b3337-9db5-45ae-a0a9', - updatedAt: '2017-01-04T05:27:50.225Z', - objectNumber: '32', - }, - { - csid: '12a6be7f-4ea8-49c1-b41c', - updatedAt: '2017-01-04T05:22:21.581Z', - objectNumber: '6.0221415', - }, - { - csid: '080b1ce2-598b-4340-b23a', - updatedAt: '2017-01-04T05:22:21.288Z', - objectNumber: '6.0221415', - }, - ], - }, + 'ns2:abstract-common-list': baseResult, +}); + +const fooResult = Immutable.fromJS({ + 'ns2:foo-common-list': baseResult, +}); + +const barResult = Immutable.fromJS({ + 'ns2:bar-common-list': baseResult, }); const intl = { @@ -275,7 +286,7 @@ describe('SearchResultTable', () => { intl={intl} listType="foo" searchDescriptor={searchDescriptor} - searchResult={searchResult} + searchResult={fooResult} /> , this.container, ); @@ -291,7 +302,7 @@ describe('SearchResultTable', () => { intl={intl} listType="bar" searchDescriptor={searchDescriptor} - searchResult={searchResult} + searchResult={barResult} /> , this.container, ); diff --git a/test/specs/components/search/SearchResultTraverser.spec.jsx b/test/specs/components/search/SearchResultTraverser.spec.jsx index 4880cbbe2..7bcaede70 100644 --- a/test/specs/components/search/SearchResultTraverser.spec.jsx +++ b/test/specs/components/search/SearchResultTraverser.spec.jsx @@ -621,13 +621,11 @@ describe('SearchResultTraverser', () => { let searchedConfig = null; let searchedSearchName = null; let searchedSearchDescriptor = null; - let searchedListType = null; - const search = (configArg, searchNameArg, searchDescriptorArg, listTypeArg) => { + const search = (configArg, searchNameArg, searchDescriptorArg) => { searchedConfig = configArg; searchedSearchName = searchNameArg; searchedSearchDescriptor = searchDescriptorArg; - searchedListType = listTypeArg; }; const csid = '2222'; @@ -649,20 +647,17 @@ describe('SearchResultTraverser', () => { searchedConfig.should.equal(config); searchedSearchName.should.equal(searchName); searchedSearchDescriptor.should.equal(searchDescriptor); - searchedListType.should.equal('common'); }); it('should call search when updated if a search state is not provided', function test() { let searchedConfig = null; let searchedSearchName = null; let searchedSearchDescriptor = null; - let searchedListType = null; - const search = (configArg, searchNameArg, searchDescriptorArg, listTypeArg) => { + const search = (configArg, searchNameArg, searchDescriptorArg) => { searchedConfig = configArg; searchedSearchName = searchNameArg; searchedSearchDescriptor = searchDescriptorArg; - searchedListType = listTypeArg; }; const csid = '2222'; @@ -701,20 +696,17 @@ describe('SearchResultTraverser', () => { searchedConfig.should.equal(config); searchedSearchName.should.equal(searchName); searchedSearchDescriptor.should.equal(searchDescriptor); - searchedListType.should.equal('common'); }); it('should call search when mounted if a previous page search state is not provided, and the current item is the first on its page', function test() { let searchedConfig = null; let searchedSearchName = null; let searchedSearchDescriptor = null; - let searchedListType = null; - const search = (configArg, searchNameArg, searchDescriptorArg, listTypeArg) => { + const search = (configArg, searchNameArg, searchDescriptorArg) => { searchedConfig = configArg; searchedSearchName = searchNameArg; searchedSearchDescriptor = searchDescriptorArg; - searchedListType = listTypeArg; }; const csid = '1111'; @@ -738,20 +730,17 @@ describe('SearchResultTraverser', () => { searchedConfig.should.equal(config); searchedSearchName.should.equal(searchName); searchedSearchDescriptor.should.equal(prevPageSearchDescriptor); - searchedListType.should.equal('common'); }); it('should call search when mounted if a next page search state is not provided, and the current item is the last on its page', function test() { let searchedConfig = null; let searchedSearchName = null; let searchedSearchDescriptor = null; - let searchedListType = null; - const search = (configArg, searchNameArg, searchDescriptorArg, listTypeArg) => { + const search = (configArg, searchNameArg, searchDescriptorArg) => { searchedConfig = configArg; searchedSearchName = searchNameArg; searchedSearchDescriptor = searchDescriptorArg; - searchedListType = listTypeArg; }; const csid = '3333'; @@ -775,20 +764,17 @@ describe('SearchResultTraverser', () => { searchedConfig.should.equal(config); searchedSearchName.should.equal(searchName); searchedSearchDescriptor.should.equal(nextPageSearchDescriptor); - searchedListType.should.equal('common'); }); it('should handle a single item (non-list) search result when deciding if the next page should be retrieved', function test() { let searchedConfig = null; let searchedSearchName = null; let searchedSearchDescriptor = null; - let searchedListType = null; - const search = (configArg, searchNameArg, searchDescriptorArg, listTypeArg) => { + const search = (configArg, searchNameArg, searchDescriptorArg) => { searchedConfig = configArg; searchedSearchName = searchNameArg; searchedSearchDescriptor = searchDescriptorArg; - searchedListType = listTypeArg; }; const csid = '1111'; @@ -828,6 +814,5 @@ describe('SearchResultTraverser', () => { searchedConfig.should.equal(config); searchedSearchName.should.equal(searchName); searchedSearchDescriptor.should.equal(nextPageSearchDescriptor); - searchedListType.should.equal('common'); }); }); diff --git a/test/specs/helpers/searchHelpers.spec.js b/test/specs/helpers/searchHelpers.spec.js index 86f6cdf67..737a1ccd6 100644 --- a/test/specs/helpers/searchHelpers.spec.js +++ b/test/specs/helpers/searchHelpers.spec.js @@ -63,12 +63,14 @@ import { structuredDateFieldConditionToNXQL, advancedSearchConditionToNXQL, searchDescriptorToLocation, - getListType, getNextPageSearchDescriptor, getPreviousPageSearchDescriptor, getFirstItem, getSubrecordSearchName, + deriveSearchType, + getListTypeFromResult, } from '../../../src/helpers/searchHelpers'; +import { SEARCH_RESULT_ACCOUNT_PAGE, SEARCH_RESULT_AUTH_ROLE_PAGE } from '../../../src/constants/searchNames'; const { expect } = chai; @@ -1559,8 +1561,8 @@ describe('searchHelpers', () => { }); }); - describe('getListType', () => { - it('should return the list type of the given search descriptor\'s subresource, if it has one', () => { + describe('deriveListType', () => { + it('should get the list type from a subresource', () => { const config = { subresources: { refs: { @@ -1575,23 +1577,153 @@ describe('searchHelpers', () => { subresource: 'refs', }); - getListType(config, searchDescriptor).should.equal('refDoc'); + const { + listType, + searchType, + } = deriveSearchType(config, undefined, searchDescriptor); + + listType.should.equal('refDoc'); + searchType.should.equal('default'); + }); + + it('should get the account list type when the account page is used', () => { + const config = { + recordTypes: { + account: { + }, + }, + }; + + const searchDescriptor = Immutable.fromJS({ + recordType: 'account', + }); + + const { + listType, + searchType, + } = deriveSearchType(config, SEARCH_RESULT_ACCOUNT_PAGE, searchDescriptor); + + listType.should.equal('account'); + searchType.should.equal('default'); + }); + + it('should get the role list type when the auth role page is used', () => { + const config = { + recordTypes: { + authRole: { + }, + }, + }; + + const searchDescriptor = Immutable.fromJS({ + recordType: 'authRole', + }); + + const { + listType, + searchType, + } = deriveSearchType(config, SEARCH_RESULT_AUTH_ROLE_PAGE, searchDescriptor); + + listType.should.equal('role'); + searchType.should.equal('default'); + }); + + it('should get the advanced search type when present', () => { + const config = { + recordTypes: { + acquisition: { + serviceConfig: { + features: { + updatedSearch: true, + }, + }, + }, + }, + }; + + const searchDescriptor = Immutable.fromJS({ + recordType: 'acquisition', + }); + + const { + listType, + searchType, + } = deriveSearchType(config, 'searchpage', searchDescriptor); + + listType.should.equal('search'); + searchType.should.equal('advanced'); + }); + + it('should default to common when no search descriptor is present', () => { + const config = { + }; + + const { + listType, + searchType, + } = deriveSearchType(config, '', undefined); + listType.should.equal('common'); + searchType.should.equal('default'); }); - it('should return \'common\' if the given search desriptor does not have a subresource', () => { + it('should default to common when a subresource doesn\'t specify a listType', () => { const config = { subresources: { refs: { - listType: 'refDoc', }, }, }; const searchDescriptor = Immutable.fromJS({ - recordType: 'group', + recordType: 'collectionobject', + subresource: 'refs', }); - getListType(config, searchDescriptor).should.equal('common'); + const { + listType, + searchType, + } = deriveSearchType(config, undefined, searchDescriptor); + + listType.should.equal('common'); + searchType.should.equal('default'); + }); + }); + + describe('getListTypeFromResults', () => { + const config = { + listTypes: { + common: { + listNodeName: 'ns2:abstract-common-list', + }, + account: { + listNodeName: 'ns2:accounts-common-list', + }, + }, + }; + it('should return the list type based on the search result', () => { + const searchResult = Immutable.fromJS({ + 'ns2:accounts-common-list': { + itemsInPage: 0, + size: 0, + }, + }); + + getListTypeFromResult(config, searchResult).should.equal('account'); + }); + + it('should default to common when no match is found', () => { + const searchResult = Immutable.fromJS({ + unnamedlist: { + itemsInPage: 0, + size: 0, + }, + }); + + getListTypeFromResult(config, searchResult).should.equal('common'); + }); + + it('should default to common when result is undefined', () => { + getListTypeFromResult(config, undefined).should.equal('common'); }); });