Skip to content

Commit

Permalink
Add support for an autocomplete livesearch widget
Browse files Browse the repository at this point in the history
  • Loading branch information
reebalazs committed Jun 5, 2024
1 parent 12837df commit 41b7b19
Show file tree
Hide file tree
Showing 15 changed files with 776 additions and 18 deletions.
1 change: 1 addition & 0 deletions news/25.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add support for an autocomplete livesearch widget @reebalazs
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,12 @@
},
"devDependencies": {
"@plone/scripts": "^2.3.0",
"react-autosuggest": "10.1.0",
"release-it": "^16.1.0"
},
"peerDependencies": {
"@plone/volto": "^16.20.0 || ^17.0.0-alpha.4"
"@plone/volto": "^16.20.0 || ^17.0.0-alpha.4",
"react-autosuggest": "10.1.0"
},
"packageManager": "[email protected]"
}
3 changes: 2 additions & 1 deletion src/actions/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
import { solrSearchContent, copyContentForSolr } from './solrsearch/solrsearch';
export { solrSearchContent, copyContentForSolr };
import { solrSearchSuggestions } from './solrsearch/solrSearchSuggestions';
export { solrSearchContent, copyContentForSolr, solrSearchSuggestions };
11 changes: 11 additions & 0 deletions src/actions/solrsearch/solrSearchSuggestions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export const GET_SOLR_SEARCH_SUGGESTIONS = 'GET_SOLR_SEARCH_SUGGESTIONS';

export function solrSearchSuggestions(term) {
return {
type: GET_SOLR_SEARCH_SUGGESTIONS,
request: {
op: 'get',
path: `/@solr-suggest?query=${term}`,
},
};
}
3 changes: 3 additions & 0 deletions src/components/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
export SolrSearch from '@kitconcept/volto-solr/components/theme/SolrSearch/SolrSearch';
export SolrFormattedDate from '@kitconcept/volto-solr/components/theme/SolrSearch/resultItems/helpers/SolrFormattedDate';
export SolrSearchWidget, {
SolrSearchAutosuggest,
} from '@kitconcept/volto-solr/components/theme/SolrSearchWidget/SolrSearchWidget';
68 changes: 52 additions & 16 deletions src/components/theme/SolrSearch/SolrSearch.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,51 @@ const messages = defineMessages({
},
});

const SearchInput = forwardRef(
({ forwardRef, placeholder, className, value, onChange, onSubmit }, ref) => {
const SolrSearchAutosuggest = config.widgets.SolrSearchAutosuggest;
return (
<SolrSearchAutosuggest
inputRef={ref}
placeholder={placeholder}
className={className}
value={value || ''}
onChange={onChange}
onSubmit={onSubmit}
/>
);
},
);

// XXX The original input - left here for testing.
// const SearchInputDefault = forwardRef(
// ({ forwardRef, placeholder, className, value, onChange }, ref) => {
// return (
// <input
// ref={ref}
// placeholder={placeholder}
// className={className}
// value={value}
// onChange={onChange}
// />
// );
// },
// );

// XXX for some reason formatMessage is missing from this.props.intl.
// Until we figure this out, just acquire it directly from hook.
// This should not be necessary.. @reebalazs
const TranslatedInput = forwardRef(
({ forwardRef, placeholder, className, value, onChange }, ref) => {
({ forwardRef, placeholder, className, value, onChange, onSubmit }, ref) => {
const intl = useIntl();
return (
<input
<SearchInput
ref={ref}
placeholder={intl.formatMessage(placeholder)}
className={className}
value={value}
onChange={onChange}
onSubmit={onSubmit}
/>
);
},
Expand Down Expand Up @@ -236,6 +268,7 @@ class SolrSearch extends Component {
path_prefix: getPathPrefix(window.location),
doEmptySearch: this.props.doEmptySearch,
});
this.setState({ searchwordResult: params.SearchableText });
};

updateSearch = () => {
Expand Down Expand Up @@ -301,19 +334,22 @@ class SolrSearch extends Component {
<Container>
{this.props.showSearchInput ? (
<div className="search-input">
<form onSubmit={this.onSubmit}>
<TranslatedInput
ref={this.inputRef}
placeholder={messages.TypeSearchWords}
className="searchinput"
value={this.state.searchword}
onChange={(e) =>
this.setState({ searchword: e.target.value })
}
/>
<Button onClick={this.onSubmit}>
<FormattedMessage id="Search" defaultMessage="Search" />{' '}
</Button>
<form className="ui form" onSubmit={this.onSubmit}>
<div className="field searchbox">
<TranslatedInput
ref={this.inputRef}
placeholder={messages.TypeSearchWords}
className="searchinput"
value={this.state.searchword}
onChange={(e) =>
this.setState({ searchword: e.target.value })
}
onSubmit={this.onSubmit}
/>
<Button onClick={this.onSubmit}>
<FormattedMessage id="Search" defaultMessage="Search" />{' '}
</Button>
</div>
</form>
</div>
) : null}
Expand All @@ -325,7 +361,7 @@ class SolrSearch extends Component {
/>
) : null}
<SearchResultInfo
searchableText={this.state.searchword}
searchableText={this.state.searchwordResult}
total={this.props.total}
/>
<SearchTabs
Expand Down
53 changes: 53 additions & 0 deletions src/components/theme/SolrSearchWidget/MailTo.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { useIntl, defineMessages } from 'react-intl';
import { Icon } from '@plone/volto/components';
import mailSVG from '@plone/volto/icons/email.svg';

const messages = defineMessages({
openMailTo: {
id: 'Open a Mailto Link to the Members Email Address',
defaultMessage: 'Open a Mailto Link to the Members Email Address',
},
});

export default ({ email, className }) => {
let decoded;
if (!email.includes('@')) {
const buffer = Buffer.from(email, 'base64');
decoded = buffer.toString('ascii');
}

const intl = useIntl();

const rot10 = (s) => {
return s.replace(
/[a-z]/g,
(c) =>
'abcdefghijklmnopqrstuvwxyz'['klmnopqrstuvwxyzabcdefghij'.indexOf(c)],
);
};

const onClickEmail = (e) => {
const emailClear = email.includes('@') ? email : rot10(decoded);
window.open(`mailto:${emailClear}`, '_self');
e.preventDefault();
e.stopPropagation();
};

return (
<span
className={className}
onClick={(e) => onClickEmail(e)}
onKeyDown={(e) => {
if (e.key === 'Enter') {
onClickEmail();
}
}}
title={intl.formatMessage(messages.openMailTo)}
role="button"
tabIndex={0}
>
<Icon className="mail" color="#555555" size="24px" name={mailSVG} />
E-Mail
</span>
);
};
Loading

0 comments on commit 41b7b19

Please sign in to comment.