@@ -36,6 +36,7 @@ const propTypes = {
3636 formatCloneOptionLabel : PropTypes . func ,
3737 formatCreateNewOptionLabel : PropTypes . func ,
3838 formatMoreCharsRequiredMessage : PropTypes . func ,
39+ formatNarrowResultsMessage : PropTypes . func ,
3940 formatSearchResultMessage : PropTypes . func ,
4041 formatSourceName : PropTypes . func ,
4142 matchFilter : PropTypes . func ,
@@ -60,6 +61,7 @@ const defaultProps = {
6061 formatCloneOptionLabel : undefined ,
6162 formatCreateNewOptionLabel : undefined ,
6263 formatMoreCharsRequiredMessage : ( ) => 'Continue typing to find matching terms' ,
64+ formatNarrowResultsMessage : ( ) => 'Continue typing to narrow results' ,
6365 formatSearchResultMessage : ( count ) => {
6466 const matches = count === 1 ? 'matching term' : 'matching terms' ;
6567 const num = count === 0 ? 'No' : count ;
@@ -167,6 +169,50 @@ const isPending = (sourceID, matches, partialTerm) => {
167169 return foundPending ;
168170} ;
169171
172+ const isSearchTruncated = ( sourceID , matches , partialTerm ) => {
173+ const sources = parseResourceID ( sourceID ) ;
174+ let foundTruncated = false ;
175+
176+ if ( matches ) {
177+ const partialTermMatch = matches . get ( partialTerm ) ;
178+
179+ if ( partialTermMatch ) {
180+ sources . forEach ( ( source ) => {
181+ const {
182+ recordType,
183+ vocabulary,
184+ } = source ;
185+
186+ const sourceMatch = partialTermMatch . getIn ( [ recordType , vocabulary ] ) ;
187+
188+ if ( sourceMatch ) {
189+ const items = sourceMatch . get ( 'items' ) ;
190+ const pageSize = sourceMatch . get ( 'pageSize' ) ;
191+ const totalItems = sourceMatch . get ( 'totalItems' ) ;
192+
193+ if ( items ) {
194+ // The search service reports at most one page of matches in totalItems, even when
195+ // more terms match.https://collectionspace.atlassian.net/browse/DRYD-2157
196+ // A source is considered truncated if more matches are reported
197+ // than were returned, or if a full page was returned, since in that case there are
198+ // likely more matches than the server is willing to report.
199+ // TODO: update condition when DRYD-2157 is fixed
200+
201+ if (
202+ ( typeof totalItems === 'number' && totalItems > items . length )
203+ || ( typeof pageSize === 'number' && pageSize > 0 && items . length >= pageSize )
204+ ) {
205+ foundTruncated = true ;
206+ }
207+ }
208+ }
209+ } ) ;
210+ }
211+ }
212+
213+ return foundTruncated ;
214+ } ;
215+
170216const getNewTerm = ( sourceID , matches , partialTerm ) => {
171217 const sources = parseResourceID ( sourceID ) ;
172218
@@ -272,6 +318,7 @@ export default class AutocompleteInput extends Component {
272318
273319 if ( ! isPending ( nextProps . source , nextProps . matches , partialTerm ) ) {
274320 nextState . options = getOptions ( partialTerm , nextProps ) ;
321+ nextState . optionsPartialTerm = partialTerm ;
275322 }
276323
277324 this . setState ( nextState ) ;
@@ -351,6 +398,7 @@ export default class AutocompleteInput extends Component {
351398 commit ( value , meta ) {
352399 this . setState ( {
353400 options : [ ] ,
401+ optionsPartialTerm : null ,
354402 partialTerm : null ,
355403 value,
356404 } ) ;
@@ -404,6 +452,7 @@ export default class AutocompleteInput extends Component {
404452 } , findDelay ) ;
405453 } else {
406454 newState . options = getOptions ( partialTerm , this . props ) ;
455+ newState . optionsPartialTerm = partialTerm ;
407456 }
408457
409458 newState . isFindTimerActive = ! ! this . findTimer ;
@@ -509,6 +558,7 @@ export default class AutocompleteInput extends Component {
509558 formatCloneOptionLabel,
510559 formatCreateNewOptionLabel,
511560 formatMoreCharsRequiredMessage,
561+ formatNarrowResultsMessage,
512562 formatSearchResultMessage,
513563 formatSourceName,
514564 matches,
@@ -527,6 +577,7 @@ export default class AutocompleteInput extends Component {
527577 const {
528578 isFindTimerActive,
529579 options,
580+ optionsPartialTerm,
530581 partialTerm,
531582 value,
532583 } = this . state ;
@@ -541,9 +592,15 @@ export default class AutocompleteInput extends Component {
541592 && removePartialTermOperators ( partialTerm ) . length < minLength
542593 ) ;
543594
544- const formatStatusMessage = moreCharsRequired
545- ? formatMoreCharsRequiredMessage
546- : formatSearchResultMessage ;
595+ let formatStatusMessage ;
596+
597+ if ( moreCharsRequired ) {
598+ formatStatusMessage = formatMoreCharsRequiredMessage ;
599+ } else if ( isSearchTruncated ( source , matches , optionsPartialTerm ) ) {
600+ formatStatusMessage = formatNarrowResultsMessage ;
601+ } else {
602+ formatStatusMessage = formatSearchResultMessage ;
603+ }
547604
548605 const className = ( isFindTimerActive || isPending ( source , matches , partialTerm ) )
549606 ? styles . searching
0 commit comments