Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only sync the content of the advanced and visual synonyms editors on submit or switch. Fixes #2392. #2411

Merged
merged 4 commits into from
Oct 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion assets/css/synonyms.css
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,13 @@ button.synonym__remove {
height: 0;
}

.synonym__validation {
.synonym__validation,
.synonym-solr-editor__validation p {
color: #a00;
font-style: italic;
}

.synonym__validation {
margin: 0 0 0.625em 0.5em;
}

Expand Down
11 changes: 11 additions & 0 deletions assets/js/synonyms/components/SynonymsEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,25 @@ const SynonymsEditor = () => {
* Handles submitting the form.
*/
const handleSubmit = () => {
if (isSolrEditable) {
dispatch({ type: 'REDUCE_SOLR_TO_STATE' });
}

dispatch({ type: 'VALIDATE_ALL' });
dispatch({ type: 'REDUCE_STATE_TO_SOLR' });
dispatch({ type: 'SUBMIT' });
};

/**
* Handle toggling the editor type.
*/
const handleToggleAdvance = () => {
if (isSolrEditable) {
dispatch({ type: 'REDUCE_SOLR_TO_STATE' });
} else {
dispatch({ type: 'REDUCE_STATE_TO_SOLR' });
}

dispatch({ type: 'SET_SOLR_EDITABLE', data: !isSolrEditable });
};

Expand Down
25 changes: 19 additions & 6 deletions assets/js/synonyms/components/editors/SolrEditor.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React, { useContext } from 'react';
import { State, Dispatch } from '../../context';
import { reduceStateToSolr } from '../../utils';

/**
* Synonym Inspector
Expand All @@ -10,9 +9,13 @@ import { reduceStateToSolr } from '../../utils';
const SolrEditor = () => {
const state = useContext(State);
const dispatch = useContext(Dispatch);
const reducedState = reduceStateToSolr(state);
const { isSolrEditable, isSolrVisible } = state;
const { synonymsTextareaInputName, solrInputHeading } = window.epSynonyms.i18n;
const { alternatives, isSolrEditable, isSolrVisible, sets, solr } = state;
const {
synonymsTextareaInputName,
solrInputHeading,
solrAlternativesErrorMessage,
solrSetsErrorMessage,
} = window.epSynonyms.i18n;

return (
<div className={`synonym-solr-editor metabox-holder ${!isSolrVisible ? 'hidden' : ''}`}>
Expand All @@ -26,12 +29,22 @@ const SolrEditor = () => {
id="ep-synonym-input"
name={synonymsTextareaInputName}
rows="20"
value={reducedState}
value={solr}
readOnly={!isSolrEditable}
onChange={(event) =>
dispatch({ type: 'REDUCE_STATE_FROM_SOLR', data: event.target.value })
dispatch({ type: 'UPDATE_SOLR', data: event.target.value })
}
/>
<div
role="region"
aria-live="assertive"
className="synonym-solr-editor__validation"
>
{alternatives.some((alternative) => !alternative.valid) && (
<p>{solrAlternativesErrorMessage}</p>
)}
{sets.some((set) => !set.valid) && <p>{solrSetsErrorMessage}</p>}
</div>
</div>
</div>
</div>
Expand Down
25 changes: 19 additions & 6 deletions assets/js/synonyms/reducers/editorReducer.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import { reduceSolrToState, mapEntry } from '../utils';
import { reduceSolrToState, reduceStateToSolr, mapEntry } from '../utils';

/**
* The synonym editor reducer.
*/

const { alternatives, sets, initialMode } = window.epSynonyms.data;

const mappedSets = sets ? sets.map(mapEntry) : [mapEntry()];
const mappedAlternatives = alternatives ? alternatives.map(mapEntry) : [mapEntry()];
const initialState = {
isSolrEditable: initialMode === 'advanced',
isSolrVisible: initialMode === 'advanced',
alternatives: alternatives ? alternatives.map(mapEntry) : [mapEntry()],
sets: sets ? sets.map(mapEntry) : [mapEntry()],
alternatives: mappedAlternatives,
sets: mappedSets,
solr: reduceStateToSolr({ sets: mappedSets, alternatives: mappedAlternatives }),
dirty: false,
submit: false,
};
Expand Down Expand Up @@ -97,11 +99,22 @@ const editorReducer = (state, action) => {
isSolrEditable: !!action.data,
isSolrVisible: !!action.data,
};
case 'REDUCE_STATE_FROM_SOLR':
case 'UPDATE_SOLR':
return {
...state,
solr: action.data,
dirty: true,
};
case 'REDUCE_SOLR_TO_STATE':
return {
...reduceSolrToState(action.data, state),
...reduceSolrToState(state.solr, state),
dirty: true,
};
case 'REDUCE_STATE_TO_SOLR':
return {
...state,
solr: reduceStateToSolr(state),
};
case 'VALIDATE_ALL':
return {
...state,
Expand Down
12 changes: 10 additions & 2 deletions assets/js/synonyms/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,10 @@ const reduceSolrToState = (solr, currentState) => {
...newState.alternatives,
mapEntry([
formatToken(parts[0].trim(), true),
...parts[1].split(',').map((token) => formatToken(token.trim())),
...parts[1]
.split(',')
.filter((v) => v.trim())
.map((token) => formatToken(token.trim())),
]),
],
};
Expand All @@ -110,7 +113,12 @@ const reduceSolrToState = (solr, currentState) => {
...newState,
sets: [
...newState.sets,
mapEntry([...line.split(',').map((token) => formatToken(token.trim()))]),
mapEntry([
...line
.split(',')
.filter((v) => v.trim())
.map((token) => formatToken(token.trim())),
]),
],
};
},
Expand Down
2 changes: 1 addition & 1 deletion dist/css/synonyms-styles.min.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/js/synonyms-script.min.js

Large diffs are not rendered by default.

54 changes: 28 additions & 26 deletions includes/classes/Feature/Search/Synonyms.php
Original file line number Diff line number Diff line change
Expand Up @@ -633,32 +633,34 @@ public function example_synonym_list( $as_array = false ) {
*/
public function get_localized_strings() {
return array(
'pageHeading' => __( 'Manage Synonyms', 'elasticpress' ),
'pageDescription' => __( 'Synonyms enable more flexible search results that show relevant results even without an exact match. Synonyms can be defined as a sets where all words are synonyms for each other, or as alternatives where searches for the primary word will also match the rest, but no vice versa.', 'elasticpress' ),
'pageToggleAdvanceText' => __( 'Switch to Advanced Text Editor', 'elasticpress' ),
'pageToggleSimpleText' => __( 'Switch to Visual Editor', 'elasticpress' ),

'setsTitle' => __( 'Sets', 'elasticpress' ),
'setsDescription' => __( 'Sets are terms that will all match each other for search results. This is useful where all words are considered equivalent, such as product renaming or regional variations like sneakers, tennis shoes, trainers, and runners.', 'elasticpress' ),
'setsInputHeading' => __( 'Comma separated list of terms', 'elasticpress' ),
'setsAddButtonText' => __( 'Add Set', 'elasticpress' ),
'setsErrorMessage' => __( 'This set must contain at least 2 terms.', 'elasticpress' ),

'alternativesTitle' => __( 'Alternatives', 'elasticpress' ),
'alternativesDescription' => __( 'Alternatives are terms that will also be matched when you search for the primary term. For instance, a search for shoes can also include results for sneaker, sandals, boots, and high heels.', 'elasticpress' ),
'alternativesPrimaryHeading' => __( 'Primary term', 'elasticpress' ),
'alternativesInputHeading' => __( 'Comma separated list of alternatives', 'elasticpress' ),
'alternativesAddButtonText' => __( 'Add Alternative', 'elasticpress' ),
'alternativesErrorMessage' => __( 'You must enter both a primary term and at least one alternative term.', 'elasticpress' ),

'solrTitle' => __( 'Advanced Synonym Editor', 'elasticpress' ),
'solrDescription' => __( 'When you add Sets and Alternatives above, we reduce them to SolrSynonyms which Elasticsearch can understand. If you are an advanced user, you can edit synonyms directly using Solr synonym formatting. This is beneficial if you want to import a large dictionary of synonyms, or want to export this site\'s synonyms for use on another site.', 'elasticpress' ),
'solrInputHeading' => __( 'SolrSynonym Text', 'elasticpress' ),

'removeItemText' => __( 'Remove', 'elasticpress' ),
'submitText' => __( 'Update Synonyms', 'elasticpress' ),

'synonymsTextareaInputName' => $this->get_synonym_field(),
'pageHeading' => __( 'Manage Synonyms', 'elasticpress' ),
'pageDescription' => __( 'Synonyms enable more flexible search results that show relevant results even without an exact match. Synonyms can be defined as a sets where all words are synonyms for each other, or as alternatives where searches for the primary word will also match the rest, but no vice versa.', 'elasticpress' ),
'pageToggleAdvanceText' => __( 'Switch to Advanced Text Editor', 'elasticpress' ),
'pageToggleSimpleText' => __( 'Switch to Visual Editor', 'elasticpress' ),

'setsTitle' => __( 'Sets', 'elasticpress' ),
'setsDescription' => __( 'Sets are terms that will all match each other for search results. This is useful where all words are considered equivalent, such as product renaming or regional variations like sneakers, tennis shoes, trainers, and runners.', 'elasticpress' ),
'setsInputHeading' => __( 'Comma separated list of terms', 'elasticpress' ),
'setsAddButtonText' => __( 'Add Set', 'elasticpress' ),
'setsErrorMessage' => __( 'This set must contain at least 2 terms.', 'elasticpress' ),

'alternativesTitle' => __( 'Alternatives', 'elasticpress' ),
'alternativesDescription' => __( 'Alternatives are terms that will also be matched when you search for the primary term. For instance, a search for shoes can also include results for sneaker, sandals, boots, and high heels.', 'elasticpress' ),
'alternativesPrimaryHeading' => __( 'Primary term', 'elasticpress' ),
'alternativesInputHeading' => __( 'Comma separated list of alternatives', 'elasticpress' ),
'alternativesAddButtonText' => __( 'Add Alternative', 'elasticpress' ),
'alternativesErrorMessage' => __( 'You must enter both a primary term and at least one alternative term.', 'elasticpress' ),

'solrTitle' => __( 'Advanced Synonym Editor', 'elasticpress' ),
'solrDescription' => __( 'When you add Sets and Alternatives above, we reduce them to SolrSynonyms which Elasticsearch can understand. If you are an advanced user, you can edit synonyms directly using Solr synonym formatting. This is beneficial if you want to import a large dictionary of synonyms, or want to export this site\'s synonyms for use on another site.', 'elasticpress' ),
'solrInputHeading' => __( 'SolrSynonym Text', 'elasticpress' ),
'solrAlternativesErrorMessage' => __( 'Alternatives must have both a primary term and at least one alternative term.', 'elasticpress' ),
'solrSetsErrorMessage' => __( 'Sets must contain at least 2 terms.', 'elasticpress' ),

'removeItemText' => __( 'Remove', 'elasticpress' ),
'submitText' => __( 'Update Synonyms', 'elasticpress' ),

'synonymsTextareaInputName' => $this->get_synonym_field(),
);
}

Expand Down