From 813146e592544b0ec7c06e4de28439313051c041 Mon Sep 17 00:00:00 2001 From: Nikhil Date: Thu, 18 Apr 2019 13:51:43 -0400 Subject: [PATCH 1/7] Added Spinner - Added a new state isSearching in Searcher.js to keep track of when a search is being done - Added a new Spinner component --- documentation/components/Spinner.md | 13 ++ src/components/Searcher.js | 241 +++++++++++++++------------- src/components/Spinner.js | 46 ++++++ src/index.js | 1 + 4 files changed, 191 insertions(+), 110 deletions(-) create mode 100644 documentation/components/Spinner.md create mode 100644 src/components/Spinner.js diff --git a/documentation/components/Spinner.md b/documentation/components/Spinner.md new file mode 100644 index 0000000..a1095a6 --- /dev/null +++ b/documentation/components/Spinner.md @@ -0,0 +1,13 @@ +#### Examples: + +__1.__ Simple spinner with height and width of 100px and with the label 'Loading Results...' below it. +These props are also configurable from the configuration file + +```jsx + +``` \ No newline at end of file diff --git a/src/components/Searcher.js b/src/components/Searcher.js index 41e0ad7..f901c1a 100644 --- a/src/components/Searcher.js +++ b/src/components/Searcher.js @@ -41,90 +41,90 @@ import Configuration from '../components/Configuration'; */ type SearcherProps = { - location: PropTypes.object.isRequired; - history: PropTypes.object.isRequired; + location: PropTypes.object.isRequired, + history: PropTypes.object.isRequired, /** * The engine backing the SUIT application. Defaults to 'attivio'. - * Set to 'solr' or 'elastic' to use one of those engines instesd. + * Set to 'solr' or 'elastic' to use one of those engines instead. */ - searchEngineType: 'attivio' | 'solr' | 'elastic'; + searchEngineType: 'attivio' | 'solr' | 'elastic', /** * If a search engine than 'attivio' is specified, this property contains * configuration mappings and other options for it. It is ignored when the * engine is 'attivio'. */ - customOptions: any; + customOptions: any, /** * Optional. The location of the node through which to interact with Attivio. * Defaults to the value in the configuration. */ - baseUri: string; + baseUri: string, /** The workflow to use when performing the search. Defaults to the "search" workflow. */ - searchWorkflow: string; + searchWorkflow: string, /** The list of document fields to return when performing the search. Defaults to all fields (*). */ - fields: Array; + fields: Array, /** The list of facets to request when performing the search. Defaults to just 'table'. */ - facets: Array; + facets: Array, /** The list of relevancy models to use when performing the search. Defaults to the 'default' model. */ - relevancyModels: Array; + relevancyModels: Array, /** The maximum number of facets for FacetFinder to add. Defaults to 0, which means FF is disabled. */ - facetFinderCount: number; + facetFinderCount: number, /** An optional filter to apply to all queries. */ - queryFilter?: string | null; + queryFilter?: string | null, /** * Highlight mode for the results of your query: 'on' enables highlighting * using your schema preferences and field expressions, 'off' disables * highlighting on the request, only highlighting field expressions specified, and * 'all' adds a teaser field expression to all your display fields when not in debug mode. */ - highlightResults: 'on' | 'off' | 'all'; + highlightResults: 'on' | 'off' | 'all', /** The join rollup mode to use. Defaults to 'TREE'. */ - joinRollupMode: 'TREE' | 'AGGREGATE' | 'SQL'; + joinRollupMode: 'TREE' | 'AGGREGATE' | 'SQL', /** An optional locale to use for the search. */ - locale?: string | null; + locale?: string | null, /** The default language to use for querying. Defaults to 'simple' if not specified. */ - defaultQueryLanguage: 'simple' | 'advanced'; + defaultQueryLanguage: 'simple' | 'advanced', /** A field expression to override what is used for the title, defaults to 'title' */ - title: string; + title: string, /** A field expression to override what is used for the URI, defaults to 'uri' */ - uri: string; + uri: string, /** A field expression to override what is used for the table, defaults to 'table' */ - table: string; + table: string, /** * A field expression to override what is used for the teaser, defaults to * 'SCOPETEASER(text, fragment=true, numFragments=4, fragmentScope=sentence)' */ - teaser: string; + teaser: string, /** * A field expression to override what is used for the text, defaults to * 'SCOPETEASER(text, fragment=true, numFragments=1, fragmentSize=2147483647)' */ - text: string; + text: string, /** * A field expression to override what is used for the URI to the preview image, * defaults to 'img.uri.preview' */ - previewImageUri: string; + previewImageUri: string, /** A field expression to override what is used for the UTI to the document’s * thumbnail, defaults to 'img.uri.thumbnail' */ - thumbnailImageUri: string; + thumbnailImageUri: string, /** A field expression to override what is used for the latitude, defaults to 'latitude' */ - latitude: string; + latitude: string, /** A field expression to override what is used for the longitude, defaults to 'longitude' */ - longitude: string; + longitude: string, /** * A field expression to override what is used for the query to use when asking * for similar documents, defaults to 'morelikethisquery' */ - moreLikeThisQuery: string; + moreLikeThisQuery: string, /** A field expression to override what is used for the MIME type, defaults to 'mimetype' */ - mimetype: string; + mimetype: string, /** * A field expression to override what is used for the path to the ingested document, * defaults to 'sourcepath' */ - sourcePath: string; + sourcePath: string, /** If true, include fields added by the query workflow, defaults to true */ // showWorkflowFields: boolean; /** The workflow to use when updating document properties, defaults to 'ingest' */ @@ -132,52 +132,52 @@ type SearcherProps = { /** Whether to override the format with the debug format. */ debug: boolean, /** The number of document results to display on each page of the results set */ - resultsPerPage: number; + resultsPerPage: number, /** * The name of the Business Center profile to use for queries. If set, this will enable Profile level campaigns and promotions. */ - businessCenterProfile: string | null; + businessCenterProfile: string | null, /** * The Searcher contains arbitrary children, including the components that * control its properties and display the search results. */ - children: Children; + children: Children, /** * The max resubmits property for enabling features such as And-To-Or resubmission, if desired */ - maxResubmits: number; + maxResubmits: number, }; type SearcherDefaultProps = { - searchEngineType: 'attivio' | 'elastic' | 'solr'; - customOptions: any; - baseUri: string; - searchWorkflow: string; - fields: Array; - facets: Array; - relevancyModels: Array; - facetFinderCount: number; - queryFilter: string | null; - highlightResults: 'on' | 'off' | 'all'; - joinRollupMode: 'TREE' | 'AGGREGATE' | 'SQL'; - locale: string | null; - title: string; - uri: string; - table: string; - teaser: string; - text: string; - previewImageUri: string; - thumbnailImageUri: string; - latitude: string; - longitude: string; - moreLikeThisQuery: string; - mimetype: string; - sourcePath: string; - debug: boolean; - resultsPerPage: number; - businessCenterProfile: string | null; - defaultQueryLanguage: 'simple' | 'advanced'; - maxResubmits: number; + searchEngineType: 'attivio' | 'elastic' | 'solr', + customOptions: any, + baseUri: string, + searchWorkflow: string, + fields: Array, + facets: Array, + relevancyModels: Array, + facetFinderCount: number, + queryFilter: string | null, + highlightResults: 'on' | 'off' | 'all', + joinRollupMode: 'TREE' | 'AGGREGATE' | 'SQL', + locale: string | null, + title: string, + uri: string, + table: string, + teaser: string, + text: string, + previewImageUri: string, + thumbnailImageUri: string, + latitude: string, + longitude: string, + moreLikeThisQuery: string, + mimetype: string, + sourcePath: string, + debug: boolean, + resultsPerPage: number, + businessCenterProfile: string | null, + defaultQueryLanguage: 'simple' | 'advanced', + maxResubmits: number, }; /* @@ -192,18 +192,19 @@ type SearcherDefaultProps = { * getDefaultState() */ type SearcherState = { - haveSearched: boolean; - response?: QueryResponse; - error?: string; - query: string; - queryLanguage: 'advanced' | 'simple'; + haveSearched: boolean, + response?: QueryResponse, + error?: string, + query: string, + queryLanguage: 'advanced' | 'simple', sort: Array, - relevancyModels: Array; - facetFilters: Array; - geoFilters: Array; - resultsPerPage: number; - resultsOffset: number; - debug: boolean; + relevancyModels: Array, + facetFilters: Array, + geoFilters: Array, + resultsPerPage: number, + resultsOffset: number, + debug: boolean, + isSearching: boolean, }; /** @@ -301,7 +302,7 @@ class Searcher extends React.Component): Array { - return facetFilters.map((facetFilter: FacetFilter): string => { - return `${facetFilter.facetName},+${facetFilter.bucketLabel},+${facetFilter.filter}`; - }); + return facetFilters.map( + (facetFilter: FacetFilter): string => { + return `${facetFilter.facetName},+${facetFilter.bucketLabel},+${facetFilter.filter}`; + }, + ); } /** * Convert an array of stringified facet filters to an array of actual FacetFilter objects. */ static deserializeFacetFilters(facetFilters: Array): Array { - return facetFilters.map((facetFilterString: string): FacetFilter => { - const parts: Array = facetFilterString.split(',+'); - const facetFilter = new FacetFilter(); - facetFilter.facetName = parts[0]; - facetFilter.bucketLabel = parts[1]; - facetFilter.filter = parts[2]; - return facetFilter; - }); + return facetFilters.map( + (facetFilterString: string): FacetFilter => { + const parts: Array = facetFilterString.split(',+'); + const facetFilter = new FacetFilter(); + facetFilter.facetName = parts[0]; + facetFilter.bucketLabel = parts[1]; + facetFilter.filter = parts[2]; + return facetFilter; + }, + ); } constructor(props: SearcherProps) { @@ -391,6 +396,7 @@ class Searcher extends React.Component { - this.updateSearchResults(response, error); - - // potentially do window.scrollTo(0, 0)? - // Update the URL if needed. - const oldQueryString = this.props.location.query; - const updatedQueryString = this.generateLocationQueryStringFromState(this.state, oldQueryString); - if (oldQueryString !== updatedQueryString) { - this.props.history.push(`?${updatedQueryString}`); - } - }); + const localCallBack = () => { + this.search.search(qr, (response: QueryResponse | null, error: string | null) => { + this.setState({ isSearching: false }, () => { + this.updateSearchResults(response, error); + + // potentially do window.scrollTo(0, 0)? + + // Update the URL if needed. + const oldQueryString = this.props.location.query; + const updatedQueryString = this.generateLocationQueryStringFromState(this.state, oldQueryString); + if (oldQueryString !== updatedQueryString) { + this.props.history.push(`?${updatedQueryString}`); + } + this.updateSearchResults(response, error); + }); + }); + }; + if (!this.state.isSearching) { + this.setState({ isSearching: true }, localCallBack); + } } /** @@ -875,11 +898,14 @@ class Searcher extends React.Component { this.updateStateResetAndSearch(this.getDefaultState()); }; - this.setState({ - haveSearched: false, - response: undefined, - error: undefined, - }, callBackWrapper); + this.setState( + { + haveSearched: false, + response: undefined, + error: undefined, + }, + callBackWrapper, + ); } /** @@ -899,7 +925,6 @@ class Searcher extends React.Component - {this.props.children} - - ); + return
{this.props.children}
; } } diff --git a/src/components/Spinner.js b/src/components/Spinner.js new file mode 100644 index 0000000..cd3d96f --- /dev/null +++ b/src/components/Spinner.js @@ -0,0 +1,46 @@ +// @flow + +import React from 'react'; +import Configurable from './Configurable'; + +type SpinnerProps = { + spinner?: string; + spinnerHeight?: string; + spinnerWidth?: string; + spinnerLabel?: string; +}; + +type SpinnerDefaultProps = { + spinner?: string; + spinnerHeight?: string; + spinnerWidth?: string; + spinnerLabel?: string; +}; + +class Spinner extends React.Component { + static defaultProps = { + spinner: 'img/spinner.gif', + spinnerHeight: '50%', + spinnerWidth: '50%', + spinnerLabel: '', + }; + + render() { + const label = this.props.spinnerLabel ? ( +
+
+ {this.props.spinnerLabel} +
+ ) : ( + '' + ); + return ( +
+ Spinner + {label} +
+ ); + } +} + +export default Configurable(Spinner); diff --git a/src/index.js b/src/index.js index 4a05f52..3536668 100644 --- a/src/index.js +++ b/src/index.js @@ -150,6 +150,7 @@ export SimpleSearchResult from './components/SimpleSearchResult'; export SimpleAutoCompleteInput from './components/SimpleAutoCompleteInput'; export SmallTabs from './components/SmallTabs'; export SpellCheckMessage from './components/SpellCheckMessage'; +export Spinner from './components/Spinner'; export SqlLog from './components/SqlLog'; export StarRating from './components/StarRating'; export StringListEditor from './components/StringListEditor'; From 1a563187b7cc68d780bb5e789810814a41f79a14 Mon Sep 17 00:00:00 2001 From: Nikhil Date: Thu, 18 Apr 2019 14:19:43 -0400 Subject: [PATCH 2/7] Update Spinner.js updated class name --- src/components/Spinner.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Spinner.js b/src/components/Spinner.js index cd3d96f..e2095a9 100644 --- a/src/components/Spinner.js +++ b/src/components/Spinner.js @@ -35,7 +35,7 @@ class Spinner extends React.Component { '' ); return ( -
+
Spinner {label}
From 3df804c674bf5bf9914250c57046e9ede7a1f5c3 Mon Sep 17 00:00:00 2001 From: Nikhil Date: Thu, 18 Apr 2019 15:40:27 -0400 Subject: [PATCH 3/7] Updated Spinner - Added displayName to Spinner - Added Spinner to the styleguide --- src/components/Spinner.js | 2 ++ styleguide.config.js | 1 + 2 files changed, 3 insertions(+) diff --git a/src/components/Spinner.js b/src/components/Spinner.js index e2095a9..9e134eb 100644 --- a/src/components/Spinner.js +++ b/src/components/Spinner.js @@ -25,6 +25,8 @@ class Spinner extends React.Component { spinnerLabel: '', }; + static displayName = 'Spinner'; + render() { const label = this.props.spinnerLabel ? (
diff --git a/styleguide.config.js b/styleguide.config.js index db42c40..40774a5 100644 --- a/styleguide.config.js +++ b/styleguide.config.js @@ -273,6 +273,7 @@ module.exports = { 'src/components/SecondaryNavBar.js', 'src/components/SeparatedList.js', 'src/components/SentimentTagCloud.js', + 'src/components/Spinner.js', 'src/components/SqlLog.js', 'src/components/StarRating.js', 'src/components/Subheader360.js', From dbe24a3e1f4b1fc71c3888da15c063656712790d Mon Sep 17 00:00:00 2001 From: Nikhil Date: Fri, 19 Apr 2019 12:19:36 -0400 Subject: [PATCH 4/7] Update Searcher.js - Fixed formaating issues --- src/components/Searcher.js | 226 ++++++++++++++++++------------------- 1 file changed, 111 insertions(+), 115 deletions(-) diff --git a/src/components/Searcher.js b/src/components/Searcher.js index f901c1a..d6030fc 100644 --- a/src/components/Searcher.js +++ b/src/components/Searcher.js @@ -41,143 +41,143 @@ import Configuration from '../components/Configuration'; */ type SearcherProps = { - location: PropTypes.object.isRequired, - history: PropTypes.object.isRequired, + location: PropTypes.object.isRequired; + history: PropTypes.object.isRequired; /** * The engine backing the SUIT application. Defaults to 'attivio'. * Set to 'solr' or 'elastic' to use one of those engines instead. */ - searchEngineType: 'attivio' | 'solr' | 'elastic', + searchEngineType: 'attivio' | 'solr' | 'elastic'; /** * If a search engine than 'attivio' is specified, this property contains * configuration mappings and other options for it. It is ignored when the * engine is 'attivio'. */ - customOptions: any, + customOptions: any; /** * Optional. The location of the node through which to interact with Attivio. * Defaults to the value in the configuration. */ - baseUri: string, + baseUri: string; /** The workflow to use when performing the search. Defaults to the "search" workflow. */ - searchWorkflow: string, + searchWorkflow: string; /** The list of document fields to return when performing the search. Defaults to all fields (*). */ - fields: Array, + fields: Array; /** The list of facets to request when performing the search. Defaults to just 'table'. */ - facets: Array, + facets: Array; /** The list of relevancy models to use when performing the search. Defaults to the 'default' model. */ - relevancyModels: Array, + relevancyModels: Array; /** The maximum number of facets for FacetFinder to add. Defaults to 0, which means FF is disabled. */ - facetFinderCount: number, + facetFinderCount: number; /** An optional filter to apply to all queries. */ - queryFilter?: string | null, + queryFilter?: string | null; /** * Highlight mode for the results of your query: 'on' enables highlighting * using your schema preferences and field expressions, 'off' disables * highlighting on the request, only highlighting field expressions specified, and * 'all' adds a teaser field expression to all your display fields when not in debug mode. */ - highlightResults: 'on' | 'off' | 'all', + highlightResults: 'on' | 'off' | 'all'; /** The join rollup mode to use. Defaults to 'TREE'. */ - joinRollupMode: 'TREE' | 'AGGREGATE' | 'SQL', + joinRollupMode: 'TREE' | 'AGGREGATE' | 'SQL'; /** An optional locale to use for the search. */ - locale?: string | null, + locale?: string | null; /** The default language to use for querying. Defaults to 'simple' if not specified. */ - defaultQueryLanguage: 'simple' | 'advanced', + defaultQueryLanguage: 'simple' | 'advanced'; /** A field expression to override what is used for the title, defaults to 'title' */ - title: string, + title: string; /** A field expression to override what is used for the URI, defaults to 'uri' */ - uri: string, + uri: string; /** A field expression to override what is used for the table, defaults to 'table' */ - table: string, + table: string; /** * A field expression to override what is used for the teaser, defaults to * 'SCOPETEASER(text, fragment=true, numFragments=4, fragmentScope=sentence)' */ - teaser: string, + teaser: string; /** * A field expression to override what is used for the text, defaults to * 'SCOPETEASER(text, fragment=true, numFragments=1, fragmentSize=2147483647)' */ - text: string, + text: string; /** * A field expression to override what is used for the URI to the preview image, * defaults to 'img.uri.preview' */ - previewImageUri: string, + previewImageUri: string; /** A field expression to override what is used for the UTI to the document’s * thumbnail, defaults to 'img.uri.thumbnail' */ - thumbnailImageUri: string, + thumbnailImageUri: string; /** A field expression to override what is used for the latitude, defaults to 'latitude' */ - latitude: string, + latitude: string; /** A field expression to override what is used for the longitude, defaults to 'longitude' */ - longitude: string, + longitude: string; /** * A field expression to override what is used for the query to use when asking * for similar documents, defaults to 'morelikethisquery' */ - moreLikeThisQuery: string, + moreLikeThisQuery: string; /** A field expression to override what is used for the MIME type, defaults to 'mimetype' */ - mimetype: string, + mimetype: string; /** * A field expression to override what is used for the path to the ingested document, * defaults to 'sourcepath' */ - sourcePath: string, + sourcePath: string; /** If true, include fields added by the query workflow, defaults to true */ // showWorkflowFields: boolean; /** The workflow to use when updating document properties, defaults to 'ingest' */ // ingestWorkflow: string; /** Whether to override the format with the debug format. */ - debug: boolean, + debug: boolean; /** The number of document results to display on each page of the results set */ - resultsPerPage: number, + resultsPerPage: number; /** * The name of the Business Center profile to use for queries. If set, this will enable Profile level campaigns and promotions. */ - businessCenterProfile: string | null, + businessCenterProfile: string | null; /** * The Searcher contains arbitrary children, including the components that * control its properties and display the search results. */ - children: Children, + children: Children; /** * The max resubmits property for enabling features such as And-To-Or resubmission, if desired */ - maxResubmits: number, + maxResubmits: number; }; type SearcherDefaultProps = { - searchEngineType: 'attivio' | 'elastic' | 'solr', - customOptions: any, - baseUri: string, - searchWorkflow: string, - fields: Array, - facets: Array, - relevancyModels: Array, - facetFinderCount: number, - queryFilter: string | null, - highlightResults: 'on' | 'off' | 'all', - joinRollupMode: 'TREE' | 'AGGREGATE' | 'SQL', - locale: string | null, - title: string, - uri: string, - table: string, - teaser: string, - text: string, - previewImageUri: string, - thumbnailImageUri: string, - latitude: string, - longitude: string, - moreLikeThisQuery: string, - mimetype: string, - sourcePath: string, - debug: boolean, - resultsPerPage: number, - businessCenterProfile: string | null, - defaultQueryLanguage: 'simple' | 'advanced', - maxResubmits: number, + searchEngineType: 'attivio' | 'elastic' | 'solr'; + customOptions: any; + baseUri: string; + searchWorkflow: string; + fields: Array; + facets: Array; + relevancyModels: Array; + facetFinderCount: number; + queryFilter: string | null; + highlightResults: 'on' | 'off' | 'all'; + joinRollupMode: 'TREE' | 'AGGREGATE' | 'SQL'; + locale: string | null; + title: string; + uri: string; + table: string; + teaser: string; + text: string; + previewImageUri: string; + thumbnailImageUri: string; + latitude: string; + longitude: string; + moreLikeThisQuery: string; + mimetype: string; + sourcePath: string; + debug: boolean; + resultsPerPage: number; + businessCenterProfile: string | null; + defaultQueryLanguage: 'simple' | 'advanced'; + maxResubmits: number; }; /* @@ -192,19 +192,19 @@ type SearcherDefaultProps = { * getDefaultState() */ type SearcherState = { - haveSearched: boolean, - response?: QueryResponse, - error?: string, - query: string, - queryLanguage: 'advanced' | 'simple', + haveSearched: boolean; + response?: QueryResponse; + error?: string; + query: string; + queryLanguage: 'advanced' | 'simple'; sort: Array, - relevancyModels: Array, - facetFilters: Array, - geoFilters: Array, - resultsPerPage: number, - resultsOffset: number, - debug: boolean, - isSearching: boolean, + relevancyModels: Array; + facetFilters: Array; + geoFilters: Array; + resultsPerPage: number; + resultsOffset: number; + debug: boolean; + isSearching: boolean; }; /** @@ -302,7 +302,7 @@ class Searcher extends React.Component): Array { - return facetFilters.map( - (facetFilter: FacetFilter): string => { - return `${facetFilter.facetName},+${facetFilter.bucketLabel},+${facetFilter.filter}`; - }, - ); + return facetFilters.map((facetFilter: FacetFilter): string => { + return `${facetFilter.facetName},+${facetFilter.bucketLabel},+${facetFilter.filter}`; + }); } /** * Convert an array of stringified facet filters to an array of actual FacetFilter objects. */ static deserializeFacetFilters(facetFilters: Array): Array { - return facetFilters.map( - (facetFilterString: string): FacetFilter => { - const parts: Array = facetFilterString.split(',+'); - const facetFilter = new FacetFilter(); - facetFilter.facetName = parts[0]; - facetFilter.bucketLabel = parts[1]; - facetFilter.filter = parts[2]; - return facetFilter; - }, - ); + return facetFilters.map((facetFilterString: string): FacetFilter => { + const parts: Array = facetFilterString.split(',+'); + const facetFilter = new FacetFilter(); + facetFilter.facetName = parts[0]; + facetFilter.bucketLabel = parts[1]; + facetFilter.filter = parts[2]; + return facetFilter; + }); } constructor(props: SearcherProps) { @@ -851,25 +847,24 @@ class Searcher extends React.Component { - this.search.search(qr, (response: QueryResponse | null, error: string | null) => { - this.setState({ isSearching: false }, () => { - this.updateSearchResults(response, error); - - // potentially do window.scrollTo(0, 0)? - - // Update the URL if needed. - const oldQueryString = this.props.location.query; - const updatedQueryString = this.generateLocationQueryStringFromState(this.state, oldQueryString); - if (oldQueryString !== updatedQueryString) { - this.props.history.push(`?${updatedQueryString}`); - } - this.updateSearchResults(response, error); + if (!this.state.isSearching) { + this.setState({ isSearching: true }, () => { + this.search.search(qr, (response: QueryResponse | null, error: string | null) => { + this.setState({ isSearching: false }, () => { + this.updateSearchResults(response, error); + + // potentially do window.scrollTo(0, 0)? + + // Update the URL if needed. + const oldQueryString = this.props.location.query; + const updatedQueryString = this.generateLocationQueryStringFromState(this.state, oldQueryString); + if (oldQueryString !== updatedQueryString) { + this.props.history.push(`?${updatedQueryString}`); + } + this.updateSearchResults(response, error); + }); }); }); - }; - if (!this.state.isSearching) { - this.setState({ isSearching: true }, localCallBack); } } @@ -898,14 +893,11 @@ class Searcher extends React.Component { this.updateStateResetAndSearch(this.getDefaultState()); }; - this.setState( - { - haveSearched: false, - response: undefined, - error: undefined, - }, - callBackWrapper, - ); + this.setState({ + haveSearched: false, + response: undefined, + error: undefined, + }, callBackWrapper); } /** @@ -1011,7 +1003,11 @@ class Searcher extends React.Component{this.props.children}
; + return ( +
+ {this.props.children} +
+ ); } } From 116c8be9795ef0e167500c651c087e4ee9189f4e Mon Sep 17 00:00:00 2001 From: Nikhil Date: Fri, 19 Apr 2019 12:21:08 -0400 Subject: [PATCH 5/7] Update Searcher.js fixed formatting --- src/components/Searcher.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Searcher.js b/src/components/Searcher.js index d6030fc..c59cf1f 100644 --- a/src/components/Searcher.js +++ b/src/components/Searcher.js @@ -130,7 +130,7 @@ type SearcherProps = { /** The workflow to use when updating document properties, defaults to 'ingest' */ // ingestWorkflow: string; /** Whether to override the format with the debug format. */ - debug: boolean; + debug: boolean, /** The number of document results to display on each page of the results set */ resultsPerPage: number; /** From 79160ce7e1d4a1ace607caf8a59ed386cdd4a186 Mon Sep 17 00:00:00 2001 From: Nikhil Date: Fri, 19 Apr 2019 15:15:30 -0400 Subject: [PATCH 6/7] Merged Spinner component into BusyIndicator --- documentation/components/BusyIndicator.md | 11 ++++ documentation/components/Spinner.md | 13 ----- src/components/BusyIndicator.js | 70 ++++++++++++++++++----- src/index.js | 1 - styleguide.config.js | 1 - 5 files changed, 68 insertions(+), 28 deletions(-) delete mode 100644 documentation/components/Spinner.md diff --git a/documentation/components/BusyIndicator.md b/documentation/components/BusyIndicator.md index 1a4b974..ef05956 100644 --- a/documentation/components/BusyIndicator.md +++ b/documentation/components/BusyIndicator.md @@ -68,3 +68,14 @@ __6:__ Another that can be shown and hidden... {button}
``` + +__7:__ Example of type 'spinnyCentered' with custom height and width. + +```jsx + +``` diff --git a/documentation/components/Spinner.md b/documentation/components/Spinner.md deleted file mode 100644 index a1095a6..0000000 --- a/documentation/components/Spinner.md +++ /dev/null @@ -1,13 +0,0 @@ -#### Examples: - -__1.__ Simple spinner with height and width of 100px and with the label 'Loading Results...' below it. -These props are also configurable from the configuration file - -```jsx - -``` \ No newline at end of file diff --git a/src/components/BusyIndicator.js b/src/components/BusyIndicator.js index ea31f64..2ef85d8 100644 --- a/src/components/BusyIndicator.js +++ b/src/components/BusyIndicator.js @@ -2,21 +2,34 @@ import React from 'react'; import DefaultImage from './DefaultImage'; +import Configurable from './Configurable'; import spinnyImage from '../img/spinner.gif'; type BusyIndicatorType = 'ellipsis' | 'spinny'; type BusyIndicatorProps = { /** - * If true, the component will be visible. + * Indicates if the component will be visible, default is true. */ show: boolean; + /** + * Optional path to the spinner file, defaults to 'img/spinner.gif'. + */ + spinner?: string; + /** + * Optional height for the spinner, default is the actual height of the spinner file. + */ + spinnerHeight?: string; + /** + * Optional width for the spinner, default is the actual height of the spinner file. + */ + spinnerWidth?: string; /** * Optional message to show before the animated part. Defaults to the empty string. */ message?: string; /** - * Indicates message placement in relation to the spinner. Has no impact on ellipsis type. Defaults to false. + * Indicates message placement in relation to the spinner. Has no impact on ellipsis or spinnyCentered type. Defaults to false. * If type is spinner, and this prop is omitted, the message will be positioned to the left of the spinner by default. */ positionMessageRight?: boolean; @@ -26,19 +39,24 @@ type BusyIndicatorProps = { messageStyle?: {}; /** * The type of busy indicator to show. Defaults to 'ellipsis' + * 'SpinnyCentered' type shows a spinner that is centered in the middle of it's container. */ type?: BusyIndicatorType; /** - * An optional CSS style to show for the component. + * An optional CSS style to show for the component. Has no impact on the spinnyCentered type. */ style?: {}; }; type BusyIndicatorDefaultProps = { + show: boolean, message: string; positionMessageRight: boolean; style: any; type: BusyIndicatorType; + spinner: string; + spinnerHeight: string; + spinnerWidth: string; }; type BusyIndicatorState = { @@ -48,12 +66,16 @@ type BusyIndicatorState = { /** * Component to indicate the app is busy with an animation and optional message. */ -export default class BusyIndicator extends React.Component { // eslint-disable-line max-len +class BusyIndicator extends React.Component { // eslint-disable-line max-len static defaultProps = { + show: true, message: '', positionMessageRight: false, style: {}, type: 'ellipsis', + spinner: 'img/spinner.gif', + spinnerHeight: '', + spinnerWidth: '', }; static displayName = 'BusyIndicator'; @@ -114,14 +136,23 @@ export default class BusyIndicator extends React.Component { - const { type } = this.props; + const { type, spinner, spinnerHeight, spinnerWidth } = this.props; const { dotCount } = this.state; switch (type) { case 'ellipsis': return '.'.repeat(dotCount); case 'spinny': - return ; + return ; + case 'spinnyCentered': + return ( + Spinner + ); default: return null; } @@ -138,13 +169,6 @@ export default class BusyIndicator extends React.Component{message} : ''; + if (type === 'spinnyCentered') { + return ( +
+ {this.renderBusySymbol()} +
+
+ {messageToShow} +
+ ); + } + + const containerStyle = { + display: 'flex', + flexFlow: 'row nowrap', + alignItems: 'center', + ...style, + }; + const leftContents = validRightPosition ? this.renderBusySymbol() : messageToShow; @@ -175,3 +217,5 @@ export default class BusyIndicator extends React.Component Date: Fri, 19 Apr 2019 15:31:29 -0400 Subject: [PATCH 7/7] Delete Spinner.js --- src/components/Spinner.js | 48 --------------------------------------- 1 file changed, 48 deletions(-) delete mode 100644 src/components/Spinner.js diff --git a/src/components/Spinner.js b/src/components/Spinner.js deleted file mode 100644 index 9e134eb..0000000 --- a/src/components/Spinner.js +++ /dev/null @@ -1,48 +0,0 @@ -// @flow - -import React from 'react'; -import Configurable from './Configurable'; - -type SpinnerProps = { - spinner?: string; - spinnerHeight?: string; - spinnerWidth?: string; - spinnerLabel?: string; -}; - -type SpinnerDefaultProps = { - spinner?: string; - spinnerHeight?: string; - spinnerWidth?: string; - spinnerLabel?: string; -}; - -class Spinner extends React.Component { - static defaultProps = { - spinner: 'img/spinner.gif', - spinnerHeight: '50%', - spinnerWidth: '50%', - spinnerLabel: '', - }; - - static displayName = 'Spinner'; - - render() { - const label = this.props.spinnerLabel ? ( -
-
- {this.props.spinnerLabel} -
- ) : ( - '' - ); - return ( -
- Spinner - {label} -
- ); - } -} - -export default Configurable(Spinner);