From ce75376dd6327c2370afd4435551da04a3c6cd90 Mon Sep 17 00:00:00 2001 From: Cesar Del Solar Date: Sat, 21 Jul 2018 18:07:48 -0400 Subject: [PATCH 01/18] Refactor to use a word search dialog container --- .../dialog.jsx} | 5 +- .../newtable/search/dialog_container.jsx | 165 +++++++++ .../js/wordwalls/newtable/search/row.jsx | 186 ++++++++++ .../{search_rows.jsx => search/rows.jsx} | 3 +- .../js/wordwalls/newtable/search/types.js | 125 +++++++ .../js/wordwalls/newtable/search_row.jsx | 232 ------------ .../js/wordwalls/newtable/table_creator.jsx | 163 ++------- .../static/js/wordwalls/wordwalls_api.js | 63 ++++ .../static/js/wordwalls/wordwalls_rpc.js | 13 +- package.json | 3 + yarn.lock | 330 +++++++++++++++++- 11 files changed, 906 insertions(+), 382 deletions(-) rename djAerolith/wordwalls/static/js/wordwalls/newtable/{word_search_dialog.jsx => search/dialog.jsx} (89%) create mode 100644 djAerolith/wordwalls/static/js/wordwalls/newtable/search/dialog_container.jsx create mode 100644 djAerolith/wordwalls/static/js/wordwalls/newtable/search/row.jsx rename djAerolith/wordwalls/static/js/wordwalls/newtable/{search_rows.jsx => search/rows.jsx} (94%) create mode 100644 djAerolith/wordwalls/static/js/wordwalls/newtable/search/types.js delete mode 100644 djAerolith/wordwalls/static/js/wordwalls/newtable/search_row.jsx create mode 100644 djAerolith/wordwalls/static/js/wordwalls/wordwalls_api.js diff --git a/djAerolith/wordwalls/static/js/wordwalls/newtable/word_search_dialog.jsx b/djAerolith/wordwalls/static/js/wordwalls/newtable/search/dialog.jsx similarity index 89% rename from djAerolith/wordwalls/static/js/wordwalls/newtable/word_search_dialog.jsx rename to djAerolith/wordwalls/static/js/wordwalls/newtable/search/dialog.jsx index 478af5f6..6641ad8c 100644 --- a/djAerolith/wordwalls/static/js/wordwalls/newtable/word_search_dialog.jsx +++ b/djAerolith/wordwalls/static/js/wordwalls/newtable/search/dialog.jsx @@ -1,7 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; -import SearchRows from './search_rows'; +import SearchRows from './rows'; const WordSearchDialog = props => (
@@ -18,6 +18,7 @@ const WordSearchDialog = props => ( style={{ marginTop: '0.75em' }} onClick={props.onSearchSubmit} data-dismiss="modal" + disabled={props.disabled ? 'disabled' : ''} >Play!
@@ -47,6 +49,7 @@ WordSearchDialog.propTypes = { removeSearchRow: PropTypes.func.isRequired, onSearchSubmit: PropTypes.func.isRequired, onFlashcardSubmit: PropTypes.func.isRequired, + disabled: PropTypes.bool.isRequired, }; export default WordSearchDialog; diff --git a/djAerolith/wordwalls/static/js/wordwalls/newtable/search/dialog_container.jsx b/djAerolith/wordwalls/static/js/wordwalls/newtable/search/dialog_container.jsx new file mode 100644 index 00000000..80339d13 --- /dev/null +++ b/djAerolith/wordwalls/static/js/wordwalls/newtable/search/dialog_container.jsx @@ -0,0 +1,165 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +import WordSearchDialog from './dialog'; +import { SearchTypesEnum, searchCriterionToAdd } from './types'; +import WordwallsAPI from '../../wordwalls_api'; + +const SEARCH_URL = 'wordwalls/api/new_search/'; +const FLASHCARD_URL = '/flashcards/'; + +class DialogContainer extends React.Component { + constructor(props) { + super(props); + this.state = { + searchCriteria: [{ + searchType: SearchTypesEnum.LENGTH, + minValue: 7, + maxValue: 7, + }, { + searchType: SearchTypesEnum.PROBABILITY, + minValue: 1, + maxValue: 100, + }], + }; + + this.searchSubmit = this.searchSubmit.bind(this); + this.flashcardSearchSubmit = this.flashcardSearchSubmit.bind(this); + + this.searchParamChange = this.searchParamChange.bind(this); + this.searchTypeChange = this.searchTypeChange.bind(this); + this.addSearchRow = this.addSearchRow.bind(this); + this.removeSearchRow = this.removeSearchRow.bind(this); + this.api = new WordwallsAPI(); + } + + addSearchRow() { + const toadd = searchCriterionToAdd(this.state.searchCriteria); + if (!toadd) { + return; // Don't add any more. + } + + const newCriteria = this.state.searchCriteria.concat(toadd); + this.setState({ + searchCriteria: newCriteria, + }); + } + + removeSearchRow(criteriaIndex) { + const currentCriteria = this.state.searchCriteria; + currentCriteria.splice(criteriaIndex, 1); + this.setState({ + searchCriteria: currentCriteria, + }); + } + + searchParamChange(index, paramName, paramValue) { + const criteria = this.state.searchCriteria; + const valueModifier = (val) => { + if (paramName === 'minValue' || paramName === 'maxValue') { + return parseInt(val, 10) || 0; + } else if (paramName === 'valueList') { + return val.trim(); + } + return val; + }; + + criteria[index][paramName] = valueModifier(paramValue); + this.setState({ + searchCriteria: criteria, + }); + } + + /** + * Turn the search criteria into something the back end would understand. + * @return {Array.} + */ + searchCriteriaMapper() { + // TODO modify me + return this.state.searchCriteria.map(criterion => Object.assign({}, criterion, { + searchType: SearchTypesEnum.properties[criterion.searchType].name, + })); + } + + searchTypeChange(index, value) { + const criteria = this.state.searchCriteria; + const searchType = parseInt(value, 10); + criteria[index].searchType = searchType; + // Reset the values. + if (searchType !== SearchTypesEnum.TAGS) { + criteria[index].minValue = SearchTypesEnum.properties[searchType].defaultMin; + criteria[index].maxValue = SearchTypesEnum.properties[searchType].defaultMax; + } + this.setState({ + searchCriteria: criteria, + }); + } + + searchSubmit() { + this.props.showSpinner(); + this.api.call(SEARCH_URL, { + lexicon: this.props.lexicon, + searchCriteria: this.searchCriteriaMapper(), + desiredTime: this.props.desiredTime, + questionsPerRound: this.props.questionsPerRound, + tablenum: this.props.tablenum, + }) + .then(data => this.props.onLoadNewList(data)) + .catch(error => this.props.notifyError(error)) + .finally(() => this.props.hideSpinner()); + } + + /** + * Submit search params to flashcard function. We use a legacy + * "WhitleyCards" API here, which is not quite JSON. This will have + * to be moved over to my new Cards program in the future. + */ + flashcardSearchSubmit() { + this.props.showSpinner(); + this.api.callLegacy(FLASHCARD_URL, { + action: 'searchParamsFlashcard', + lexicon: this.props.lexicon, + searchCriteria: this.searchCriteriaMapper(), + }) + .then(data => this.props.redirectUrl(data.url)) + .catch(resp => this.props.notifyError(resp)) + .finally(() => this.props.hideSpinner()); + } + + render() { + return ( + ); + } +} + +DialogContainer.propTypes = { + lexicon: PropTypes.number.isRequired, + desiredTime: PropTypes.number.isRequired, + questionsPerRound: PropTypes.number.isRequired, + notifyError: PropTypes.func.isRequired, + redirectUrl: PropTypes.func.isRequired, + // availableLexica: PropTypes.arrayOf(PropTypes.shape({ + // id: PropTypes.number, + // lexicon: PropTypes.string, + // description: PropTypes.string, + // counts: PropTypes.object, + // })).isRequired, + // onSearchSubmit: PropTypes.func.isRequired, + // onFlashcardSubmit: PropTypes.func.isRequired, + tablenum: PropTypes.number.isRequired, + onLoadNewList: PropTypes.func.isRequired, + disabled: PropTypes.bool.isRequired, + showSpinner: PropTypes.func.isRequired, + hideSpinner: PropTypes.func.isRequired, +}; + +export default DialogContainer; diff --git a/djAerolith/wordwalls/static/js/wordwalls/newtable/search/row.jsx b/djAerolith/wordwalls/static/js/wordwalls/newtable/search/row.jsx new file mode 100644 index 00000000..9ef476d8 --- /dev/null +++ b/djAerolith/wordwalls/static/js/wordwalls/newtable/search/row.jsx @@ -0,0 +1,186 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +import Select from '../../forms/select'; +import NumberInput from '../../forms/number_input'; +import TextInput from '../../forms/text_input'; + +import { SearchTypesEnum, searchCriteriaOptions } from './types'; + + +const NumberValue = props => ( +
+ props.modifySearchParam( + props.index, + props.paramName, + event.target.value, + )} + /> +
); + +NumberValue.propTypes = { + minAllowed: PropTypes.number.isRequired, + maxAllowed: PropTypes.number.isRequired, + defaultValue: PropTypes.number.isRequired, + modifySearchParam: PropTypes.func.isRequired, + index: PropTypes.number.isRequired, + paramName: PropTypes.string.isRequired, + label: PropTypes.string.isRequired, +}; + +const MinMaxValues = props => ( +
+ + +
); + +MinMaxValues.propTypes = { + minValue: PropTypes.number.isRequired, + maxValue: PropTypes.number.isRequired, + minAllowed: PropTypes.number.isRequired, + maxAllowed: PropTypes.number.isRequired, + modifySearchParam: PropTypes.func.isRequired, + index: PropTypes.number.isRequired, +}; + +const ListValue = props => ( +
+ props.modifySearchParam( + props.index, + 'valueList', + event.target.value, + )} + /> +
); + +ListValue.propTypes = { + valueList: PropTypes.string.isRequired, + index: PropTypes.number.isRequired, + modifySearchParam: PropTypes.func.isRequired, +}; + +const SearchRow = (props) => { + let specificForm; + switch (props.searchType) { + case SearchTypesEnum.PROBABILITY: + case SearchTypesEnum.POINTS: + case SearchTypesEnum.LENGTH: + case SearchTypesEnum.NUM_VOWELS: + case SearchTypesEnum.NUM_ANAGRAMS: + specificForm = ( + ); + break; + case SearchTypesEnum.FIXED_LENGTH: + specificForm = ( + ); + break; + case SearchTypesEnum.TAGS: + specificForm = ( + ); + break; + default: + break; + } + + return ( +
+
+ +
+
+ +
+
+ { - this.props.modifySearchType(this.props.index, event.target.value); - }} - /> -
- {specificForm} -
- ); - } -} - -SearchRow.propTypes = { - searchType: PropTypes.number.isRequired, - index: PropTypes.number.isRequired, - minValue: PropTypes.number, - minAllowedValue: PropTypes.number, - maxValue: PropTypes.number, - maxAllowedValue: PropTypes.number, - valueList: PropTypes.string, - addRow: PropTypes.func.isRequired, - removeRow: PropTypes.func.isRequired, - removeDisabled: PropTypes.bool.isRequired, - modifySearchType: PropTypes.func.isRequired, - modifySearchParam: PropTypes.func.isRequired, -}; - -SearchRow.defaultProps = { - minValue: 1, - minAllowedValue: 1, - maxValue: 100, - maxAllowedValue: 100, - valueList: '', -}; - -export default SearchRow; -export { SearchTypesEnum, searchCriterionToAdd }; - diff --git a/djAerolith/wordwalls/static/js/wordwalls/newtable/table_creator.jsx b/djAerolith/wordwalls/static/js/wordwalls/newtable/table_creator.jsx index 9ddf3524..d03f1875 100644 --- a/djAerolith/wordwalls/static/js/wordwalls/newtable/table_creator.jsx +++ b/djAerolith/wordwalls/static/js/wordwalls/newtable/table_creator.jsx @@ -11,14 +11,14 @@ import Notifications from '../notifications'; import Sidebar from './sidebar'; import ChallengeDialog from './challenge_dialog'; -import WordSearchDialog from './word_search_dialog'; +import WordSearchDialogContainer from './search/dialog_container'; import SavedListDialog, { PlayOptions } from './saved_list_dialog'; import AerolithListDialog from './aerolith_list_dialog'; -import { SearchTypesEnum, searchCriterionToAdd } from './search_row'; const GAME_TYPE_NEW = 'Load New List'; const LIST_TYPE_CHALLENGE = 'Single-Player Challenges'; const LIST_TYPE_WORDSEARCH = 'Word Search'; +const LIST_TYPE_BLANKS = 'Blanks'; const LIST_TYPE_AEROLITH_LISTS = 'Aerolith Lists'; const LIST_TYPE_SAVED_LIST = 'My Saved Lists'; const FLASHCARD_URL = '/flashcards/'; @@ -73,15 +73,11 @@ class TableCreator extends React.Component { challengeData: {}, currentChallenge: 0, // Word-search related - wordSearchCriteria: [{ - searchType: SearchTypesEnum.LENGTH, - minValue: 7, - maxValue: 7, - }, { - searchType: SearchTypesEnum.PROBABILITY, - minValue: 1, - maxValue: 100, - }], + + // blankSearchCriteria: [{ + // searchType: SearchTypesEnum.FIXED_LENGTH, + // value: 7, + // },], // Aerolith lists aerolithLists: [], @@ -100,18 +96,15 @@ class TableCreator extends React.Component { }; this.challengeSubmit = this.challengeSubmit.bind(this); this.onChallengeSelected = this.onChallengeSelected.bind(this); - this.searchParamChange = this.searchParamChange.bind(this); - this.searchTypeChange = this.searchTypeChange.bind(this); this.selectedListChange = this.selectedListChange.bind(this); - this.searchSubmit = this.searchSubmit.bind(this); - this.flashcardSearchSubmit = this.flashcardSearchSubmit.bind(this); this.aerolithListSubmit = this.aerolithListSubmit.bind(this); this.flashcardAerolithListSubmit = this.flashcardAerolithListSubmit.bind(this); this.savedListSubmit = this.savedListSubmit.bind(this); this.flashcardSavedListSubmit = this.flashcardSavedListSubmit.bind(this); this.listUpload = this.listUpload.bind(this); - this.addSearchRow = this.addSearchRow.bind(this); - this.removeSearchRow = this.removeSearchRow.bind(this); + + this.showSpinner = this.showSpinner.bind(this); + this.hideSpinner = this.hideSpinner.bind(this); } /** @@ -205,26 +198,6 @@ class TableCreator extends React.Component { this.props.setLoadingData(false); } - addSearchRow() { - const toadd = searchCriterionToAdd(this.state.wordSearchCriteria); - if (!toadd) { - return; // Don't add any more. - } - - const newCriteria = this.state.wordSearchCriteria.concat(toadd); - this.setState({ - wordSearchCriteria: newCriteria, - }); - } - - removeSearchRow(criteriaIndex) { - const currentCriteria = this.state.wordSearchCriteria; - currentCriteria.splice(criteriaIndex, 1); - this.setState({ - wordSearchCriteria: currentCriteria, - }); - } - /** * Submit a challenge to the backend. */ @@ -249,62 +222,6 @@ class TableCreator extends React.Component { .always(() => this.hideSpinner()); } - /** - * Turn the search criteria into something the back end would understand. - * @return {Array.} - */ - searchCriteriaMapper() { - return this.state.wordSearchCriteria.map(criterion => Object.assign({}, criterion, { - searchType: SearchTypesEnum.properties[criterion.searchType].name, - })); - } - - searchSubmit() { - this.showSpinner(); - $.ajax({ - url: '/wordwalls/api/new_search/', - data: JSON.stringify({ - lexicon: this.state.currentLexicon, - searchCriteria: this.searchCriteriaMapper(), - desiredTime: parseFloat(this.state.desiredTime), - questionsPerRound: this.state.questionsPerRound, - tablenum: this.props.tablenum, - }), - contentType: 'application/json; charset=utf-8', - method: 'POST', - }) - .done(data => this.props.onLoadNewList(data)) - .fail(jqXHR => Notifications.alert( - 'Error', - `Failed to load search: ${jqXHR.responseJSON}`, - )) - .always(() => this.hideSpinner()); - } - - /** - * Submit search params to flashcard function. We use a legacy - * "WhitleyCards" API here, which is not quite JSON. This will have - * to be moved over to my new Cards program in the future. - */ - flashcardSearchSubmit() { - this.showSpinner(); - $.ajax({ - url: FLASHCARD_URL, - method: 'POST', - data: { - action: 'searchParamsFlashcard', - lexicon: this.state.currentLexicon, - searchCriteria: this.searchCriteriaMapper(), - }, - }) - .done(data => TableCreator.redirectUrl(data.url)) - .fail(jqXHR => Notifications.alert( - 'Error', - `Failed to process: ${jqXHR.responseJSON.error}`, - )) - .always(() => this.hideSpinner()); - } - aerolithListSubmit() { this.showSpinner(); $.ajax({ @@ -481,37 +398,6 @@ class TableCreator extends React.Component { .always(() => this.hideSpinner()); } - searchParamChange(index, paramName, paramValue) { - const criteria = this.state.wordSearchCriteria; - const valueModifier = (val) => { - if (paramName === 'minValue' || paramName === 'maxValue') { - return parseInt(val, 10) || 0; - } else if (paramName === 'valueList') { - return val.trim(); - } - return val; - }; - - criteria[index][paramName] = valueModifier(paramValue); - this.setState({ - wordSearchCriteria: criteria, - }); - } - - searchTypeChange(index, value) { - const criteria = this.state.wordSearchCriteria; - const searchType = parseInt(value, 10); - criteria[index].searchType = searchType; - // Reset the values. - if (searchType !== SearchTypesEnum.TAGS) { - criteria[index].minValue = SearchTypesEnum.properties[searchType].defaultMin; - criteria[index].maxValue = SearchTypesEnum.properties[searchType].defaultMax; - } - this.setState({ - wordSearchCriteria: criteria, - }); - } - selectedListChange(listId) { this.setState({ selectedList: listId, @@ -555,19 +441,30 @@ class TableCreator extends React.Component { break; case LIST_TYPE_WORDSEARCH: selectedQuizSearchDialog = ( - this.preSubmitHook(this.searchSubmit)} - onFlashcardSubmit={() => this.preSubmitHook(this.flashcardSearchSubmit)} - onSearchTypeChange={this.searchTypeChange} - onSearchParamChange={this.searchParamChange} - removeSearchRow={this.removeSearchRow} - addSearchRow={this.addSearchRow} - searches={this.state.wordSearchCriteria} + desiredTime={parseFloat(this.state.desiredTime)} + questionsPerRound={this.state.questionsPerRound} + notifyError={error => Notifications.alert( + 'Error', + `Failed to process: ${error}`, + )} + redirectUrl={TableCreator.redirectUrl} />); break; + case LIST_TYPE_BLANKS: + // selectedQuizSearchDialog = ( + // ); + break; + case LIST_TYPE_SAVED_LIST: selectedQuizSearchDialog = ( =0.5 0" rimraf "2" -function-bind@^1.0.2, function-bind@^1.1.1: +function-bind@^1.0.2, function-bind@^1.1.0, function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" +function.prototype.name@^1.0.3: + version "1.1.0" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.0.tgz#8bd763cc0af860a859cc5d49384d74b932cd2327" + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + is-callable "^1.1.3" + functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" @@ -2704,12 +2810,20 @@ has-flag@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + has-gulplog@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce" dependencies: sparkles "^1.0.0" +has-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" + has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" @@ -2818,6 +2932,17 @@ htmlparser2@3.8.x: entities "1.0" readable-stream "1.1" +htmlparser2@^3.9.1: + version "3.9.2" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338" + dependencies: + domelementtype "^1.3.0" + domhandler "^2.3.0" + domutils "^1.5.1" + entities "^1.1.1" + inherits "^2.0.1" + readable-stream "^2.0.2" + http-deceiver@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" @@ -3004,6 +3129,10 @@ is-binary-path@^1.0.0: dependencies: binary-extensions "^1.0.0" +is-boolean-object@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.0.0.tgz#98f8b28030684219a95f375cfbd88ce3405dff93" + is-buffer@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.5.tgz#1f3b26ef613b214b88cbca23cc6c01d87961eecc" @@ -3078,6 +3207,10 @@ is-glob@^3.1.0: dependencies: is-extglob "^2.1.0" +is-number-object@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.3.tgz#f265ab89a9f445034ef6aff15a8f00b00f551799" + is-number@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" @@ -3138,6 +3271,14 @@ is-stream@^1.0.1, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" +is-string@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.4.tgz#cc3a9b69857d621e963725a24caeec873b826e64" + +is-subset@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-subset/-/is-subset-0.1.1.tgz#8a59117d932de1de00f245fcdd39ce43f1e939a6" + is-svg@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-2.1.0.tgz#cf61090da0d9efbcab8722deba6f032208dbb0e9" @@ -3613,6 +3754,10 @@ jsx-ast-utils@^2.0.0: dependencies: array-includes "^3.0.3" +just-extend@^1.1.27: + version "1.1.27" + resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-1.1.27.tgz#ec6e79410ff914e472652abfa0e603c03d60e905" + kind-of@^3.0.2: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" @@ -3781,6 +3926,14 @@ lodash.escape@^3.0.0: dependencies: lodash._root "^3.0.0" +lodash.flattendeep@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" + +lodash.get@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" + lodash.isarguments@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" @@ -3848,10 +4001,18 @@ lodash@^4.14.0, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.3.0: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" +lodash@^4.15.0: + version "4.17.10" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" + loglevel@^1.4.1: version "1.5.1" resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.5.1.tgz#189078c94ab9053ee215a0acdbf24244ea0f6502" +lolex@^2.3.2, lolex@^2.4.2: + version "2.7.1" + resolved "https://registry.yarnpkg.com/lolex/-/lolex-2.7.1.tgz#e40a8c4d1f14b536aa03e42a537c7adbaf0c20be" + longest@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" @@ -4034,6 +4195,10 @@ moment@^2.17.1: version "2.18.1" resolved "https://registry.yarnpkg.com/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f" +moo@^0.4.3: + version "0.4.3" + resolved "https://registry.yarnpkg.com/moo/-/moo-0.4.3.tgz#3f847a26f31cf625a956a87f2b10fbc013bfd10e" + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -4071,10 +4236,30 @@ natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" +nearley@^2.7.10: + version "2.15.0" + resolved "https://registry.yarnpkg.com/nearley/-/nearley-2.15.0.tgz#d1ff5406a58064615fe6eafb429cf06fbb1b7eab" + dependencies: + moo "^0.4.3" + nomnom "~1.6.2" + railroad-diagrams "^1.0.0" + randexp "0.4.6" + semver "^5.4.1" + negotiator@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" +nise@^1.3.3: + version "1.4.2" + resolved "https://registry.yarnpkg.com/nise/-/nise-1.4.2.tgz#a9a3800e3994994af9e452333d549d60f72b8e8c" + dependencies: + "@sinonjs/formatio" "^2.0.0" + just-extend "^1.1.27" + lolex "^2.3.2" + path-to-regexp "^1.7.0" + text-encoding "^0.6.4" + node-fetch@^1.0.1: version "1.7.3" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" @@ -4142,6 +4327,13 @@ node-pre-gyp@^0.6.36: tar "^2.2.1" tar-pack "^3.4.0" +nomnom@~1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/nomnom/-/nomnom-1.6.2.tgz#84a66a260174408fc5b77a18f888eccc44fb6971" + dependencies: + colors "0.5.x" + underscore "~1.4.4" + nopt@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" @@ -4192,6 +4384,12 @@ npmlog@^4.0.2: gauge "~2.7.3" set-blocking "~2.0.0" +nth-check@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.1.tgz#9929acdf628fc2c41098deab82ac580cf149aae4" + dependencies: + boolbase "~1.0.0" + num2fraction@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" @@ -4216,10 +4414,40 @@ object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" +object-inspect@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" + +object-is@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.1.tgz#0aa60ec9989a0b3ed795cf4d06f62cf1ad6539b6" + +object-keys@^1.0.11: + version "1.0.12" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2" + object-keys@^1.0.8: version "1.0.11" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d" +object.assign@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + +object.entries@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.0.4.tgz#1bf9a4dd2288f5b33f3a993d257661f05d161a5f" + dependencies: + define-properties "^1.1.2" + es-abstract "^1.6.1" + function-bind "^1.1.0" + has "^1.0.1" + object.omit@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" @@ -4227,6 +4455,15 @@ object.omit@^2.0.0: for-own "^0.1.4" is-extendable "^0.1.1" +object.values@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.0.4.tgz#e524da09b4f66ff05df457546ec72ac99f13069a" + dependencies: + define-properties "^1.1.2" + es-abstract "^1.6.1" + function-bind "^1.1.0" + has "^1.0.1" + obuf@^1.0.0, obuf@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.1.tgz#104124b6c602c6796881a042541d36db43a5264e" @@ -4379,6 +4616,12 @@ parse5@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/parse5/-/parse5-1.5.1.tgz#9b7f3b0de32be78dc2401b17573ccaf0f6f59d94" +parse5@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-3.0.3.tgz#042f792ffdd36851551cf4e9e066b3874ab45b5c" + dependencies: + "@types/node" "*" + parseurl@~1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" @@ -4417,6 +4660,12 @@ path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" +path-to-regexp@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d" + dependencies: + isarray "0.0.1" + path-type@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" @@ -4831,6 +5080,10 @@ qs@6.5.1, qs@~6.5.1: version "6.5.1" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" +qs@^6.5.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + qs@~6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" @@ -4858,6 +5111,23 @@ querystringify@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-1.0.0.tgz#6286242112c5b712fa654e526652bf6a13ff05cb" +raf@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.0.tgz#a28876881b4bc2ca9117d4138163ddb80f781575" + dependencies: + performance-now "^2.1.0" + +railroad-diagrams@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz#eb7e6267548ddedfb899c1b90e57374559cddb7e" + +randexp@0.4.6: + version "0.4.6" + resolved "https://registry.yarnpkg.com/randexp/-/randexp-0.4.6.tgz#e986ad5e5e31dae13ddd6f7b3019aa7c87f60ca3" + dependencies: + discontinuous-range "1.0.0" + ret "~0.1.10" + randomatic@^1.1.3: version "1.1.7" resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c" @@ -5192,6 +5462,10 @@ restore-cursor@^2.0.0: onetime "^2.0.0" signal-exit "^3.0.2" +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + right-align@^0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" @@ -5211,6 +5485,13 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^2.0.0" inherits "^2.0.1" +rst-selector-parser@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz#81b230ea2fcc6066c89e3472de794285d9b03d91" + dependencies: + lodash.flattendeep "^4.4.0" + nearley "^2.7.10" + run-async@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" @@ -5231,6 +5512,10 @@ safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, s version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" +samsam@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.3.0.tgz#8d1d9350e25622da30de3e44ba692b5221ab7c50" + sane@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/sane/-/sane-2.2.0.tgz#d6d2e2fcab00e3d283c93b912b7c3a20846f1d56" @@ -5269,6 +5554,10 @@ selfsigned@^1.9.1: version "5.4.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" +semver@^5.4.1: + version "5.5.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" + send@0.16.1: version "0.16.1" resolved "https://registry.yarnpkg.com/send/-/send-0.16.1.tgz#a70e1ca21d1382c11d0d9f6231deb281080d7ab3" @@ -5357,6 +5646,19 @@ signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" +sinon@^6.1.3: + version "6.1.3" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-6.1.3.tgz#98e7d716b7b11f7f1200e9c997e74f50ae094660" + dependencies: + "@sinonjs/formatio" "^2.0.0" + "@sinonjs/samsam" "^2.0.0" + diff "^3.5.0" + lodash.get "^4.4.2" + lolex "^2.4.2" + nise "^1.3.3" + supports-color "^5.4.0" + type-detect "^4.0.8" + slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" @@ -5613,6 +5915,12 @@ supports-color@^4.0.0, supports-color@^4.2.1, supports-color@^4.4.0: dependencies: has-flag "^2.0.0" +supports-color@^5.4.0: + version "5.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" + dependencies: + has-flag "^3.0.0" + svgo@^0.7.0: version "0.7.2" resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.2.tgz#9f5772413952135c6fefbf40afe6a4faa88b4bb5" @@ -5685,6 +5993,10 @@ tether@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/tether/-/tether-1.4.0.tgz#0f9fa171f75bf58485d8149e94799d7ae74d1c1a" +text-encoding@^0.6.4: + version "0.6.4" + resolved "https://registry.yarnpkg.com/text-encoding/-/text-encoding-0.6.4.tgz#e399a982257a276dae428bb92845cb71bdc26d19" + text-loader@^0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/text-loader/-/text-loader-0.0.1.tgz#8bf75d749b7c0579c939920051c69ea572ebddc1" @@ -5786,6 +6098,10 @@ type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" +type-detect@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + type-is@~1.6.15: version "1.6.15" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.15.tgz#cab10fb4909e441c82842eafe1ad646c81804410" @@ -5830,6 +6146,10 @@ underscore@>=1.8.3, underscore@^1.8.3: version "1.8.3" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022" +underscore@~1.4.4: + version "1.4.4" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.4.4.tgz#61a6a32010622afa07963bf325203cf12239d604" + uniq@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" From 8e31c14215bc1b947054b4169b3cf9f42fd05858 Mon Sep 17 00:00:00 2001 From: Cesar Del Solar Date: Mon, 23 Jul 2018 22:09:23 -0400 Subject: [PATCH 02/18] more progress, using enzyme for tests --- .../js/wordwalls/newtable/search/dialog.jsx | 13 +++- .../newtable/search/dialog_container.jsx | 10 ++-- .../js/wordwalls/newtable/search/row.jsx | 5 +- .../js/wordwalls/newtable/search/rows.jsx | 2 + .../js/wordwalls/newtable/search/types.js | 12 ++-- .../js/wordwalls/newtable/table_creator.jsx | 3 + .../newtable/search/search_dialog.test.jsx | 59 +++++++++++++++++++ .../static/js/wordwalls/test/setup_enzyme.js | 8 +++ .../static/js/wordwalls/test/shim.js | 4 ++ .../static/js/wordwalls/wordwalls_api.js | 16 ++++- package.json | 7 +++ yarn.lock | 43 +++++++++++++- 12 files changed, 164 insertions(+), 18 deletions(-) create mode 100644 djAerolith/wordwalls/static/js/wordwalls/test/newtable/search/search_dialog.test.jsx create mode 100644 djAerolith/wordwalls/static/js/wordwalls/test/setup_enzyme.js create mode 100644 djAerolith/wordwalls/static/js/wordwalls/test/shim.js diff --git a/djAerolith/wordwalls/static/js/wordwalls/newtable/search/dialog.jsx b/djAerolith/wordwalls/static/js/wordwalls/newtable/search/dialog.jsx index 6641ad8c..cdc0b8db 100644 --- a/djAerolith/wordwalls/static/js/wordwalls/newtable/search/dialog.jsx +++ b/djAerolith/wordwalls/static/js/wordwalls/newtable/search/dialog.jsx @@ -2,6 +2,16 @@ import React from 'react'; import PropTypes from 'prop-types'; import SearchRows from './rows'; +import { SearchTypesEnum } from './types'; + +const allowedSearchTypes = new Set([ + SearchTypesEnum.PROBABILITY, + SearchTypesEnum.LENGTH, + SearchTypesEnum.TAGS, + SearchTypesEnum.POINTS, + SearchTypesEnum.NUM_ANAGRAMS, + SearchTypesEnum.NUM_VOWELS, +]); const WordSearchDialog = props => (
@@ -12,9 +22,10 @@ const WordSearchDialog = props => ( removeSearchRow={props.removeSearchRow} modifySearchType={props.onSearchTypeChange} modifySearchParam={props.onSearchParamChange} + allowedSearchTypes={allowedSearchTypes} />