From 6d06138fd845fe8c1b3f82e9ec72d0bd53d9a718 Mon Sep 17 00:00:00 2001 From: Aram Zadikian Date: Sun, 23 Apr 2017 20:40:29 -0700 Subject: [PATCH] fixes tests --- app/components/flash-card/component.js | 78 --------------- app/components/flash-card/template.hbs | 9 +- .../inputs/pinyin-input/component.js | 97 +++++++++++++++++++ .../inputs/pinyin-input/template.hbs | 9 ++ .../study/modes/eng-to-pin/component.js | 53 ++++++++++ .../study/modes/eng-to-pin/styles.styl | 35 +++++++ .../study/modes/eng-to-pin/template.hbs | 22 +++++ .../study/study-canvas/component.js | 42 ++++++++ app/components/study/study-canvas/styles.styl | 2 + .../study/study-canvas/template.hbs | 12 +++ app/router.js | 1 + app/routes/study.js | 7 ++ app/templates/study.hbs | 1 + .../inputs/pinyin-input/component-test.js | 23 +++++ .../study/modes/eng-to-pin/component-test.js | 16 +++ tests/unit/routes/study-test.js | 11 +++ 16 files changed, 333 insertions(+), 85 deletions(-) create mode 100644 app/components/inputs/pinyin-input/component.js create mode 100644 app/components/inputs/pinyin-input/template.hbs create mode 100644 app/components/study/modes/eng-to-pin/component.js create mode 100644 app/components/study/modes/eng-to-pin/styles.styl create mode 100644 app/components/study/modes/eng-to-pin/template.hbs create mode 100644 app/components/study/study-canvas/component.js create mode 100644 app/components/study/study-canvas/styles.styl create mode 100644 app/components/study/study-canvas/template.hbs create mode 100644 app/routes/study.js create mode 100644 app/templates/study.hbs create mode 100644 tests/integration/components/inputs/pinyin-input/component-test.js create mode 100644 tests/integration/components/study/modes/eng-to-pin/component-test.js create mode 100644 tests/unit/routes/study-test.js diff --git a/app/components/flash-card/component.js b/app/components/flash-card/component.js index 4fe660c..97e7133 100644 --- a/app/components/flash-card/component.js +++ b/app/components/flash-card/component.js @@ -1,87 +1,9 @@ import Ember from 'ember'; -import _ from 'lodash'; - -const TONE_REGEX = /([aeiouAEIOU][1234])/g; - -const TONE_MAPPING = { - "a1": "ā", - "a2": "á", - "a3": "ǎ", - "a4": "à", - - "A1": "Ā", - "A2": "Á", - "A3": "Ǎ", - "A4": "À", - - "e1": "ē", - "e2": "é", - "e3": "ě", - "e4": "è", - - "E1": "Ē", - "E2": "É", - "E3": "Ě", - "E4": "È", - - "i1": "ī", - "i2": "í", - "i3": "ǐ", - "i4": "ì", - - "I1": "Ī", - "I2": "Í", - "I3": "Ǐ", - "I4": "Ì", - - "o1": "ō", - "o2": "ó", - "o3": "ǒ", - "o4": "ò", - - "O1": "Ō", - "O2": "Ó", - "O3": "Ǒ", - "O4": "Ò", - - "u1": "ū", - "u2": "ú", - "u3": "ǔ", - "u4": "ù", - - "U1": "Ū", - "U2": "Ú", - "U3": "Ǔ", - "U4": "Ù" -}; export default Ember.Component.extend({ classNames: ['card-2', 'stretch'], - setSelection(elm, start, end) { - elm.selectionStart = start; - elm.selectionEnd = end; - }, - actions: { - processChange(model, str) { - const editor = this.$(".pinyinEditor")[0]; - let cursorPosition = editor.selectionStart; - let newStr = str; - const matches = str.match(TONE_REGEX); - - if(!_.isEmpty(matches)) { - newStr = str.replace(TONE_REGEX, match => TONE_MAPPING[match]); - cursorPosition = cursorPosition - matches.length; - } - - model.set("text", newStr); - - this.get("saveModel")(model); - - Ember.run.scheduleOnce('afterRender', this, this.setSelection, editor, cursorPosition, cursorPosition); - }, - handleUpdate(model, str) { model.set('text', str); this.get("saveModel")(model); diff --git a/app/components/flash-card/template.hbs b/app/components/flash-card/template.hbs index ae305cf..4eef8ea 100644 --- a/app/components/flash-card/template.hbs +++ b/app/components/flash-card/template.hbs @@ -25,14 +25,9 @@
- {{one-way-textarea model.pinyin.text + {{inputs/pinyin-input model.pinyin.text placeholder='Pinyin...' - class="pinyinEditor" - update=(action 'processChange' model.pinyin) - autocomplete="off" - autocorrect="off" - autocapitalize="off" - spellcheck=false}} + update=(action "handleUpdate" model.pinyin)}}
diff --git a/app/components/inputs/pinyin-input/component.js b/app/components/inputs/pinyin-input/component.js new file mode 100644 index 0000000..659c663 --- /dev/null +++ b/app/components/inputs/pinyin-input/component.js @@ -0,0 +1,97 @@ +import Ember from 'ember'; +import _ from 'lodash'; + +const TONE_REGEX = /([aeiouAEIOU][1234])/g; + +const TONE_MAPPING = { + "a1": "ā", + "a2": "á", + "a3": "ǎ", + "a4": "à", + + "A1": "Ā", + "A2": "Á", + "A3": "Ǎ", + "A4": "À", + + "e1": "ē", + "e2": "é", + "e3": "ě", + "e4": "è", + + "E1": "Ē", + "E2": "É", + "E3": "Ě", + "E4": "È", + + "i1": "ī", + "i2": "í", + "i3": "ǐ", + "i4": "ì", + + "I1": "Ī", + "I2": "Í", + "I3": "Ǐ", + "I4": "Ì", + + "o1": "ō", + "o2": "ó", + "o3": "ǒ", + "o4": "ò", + + "O1": "Ō", + "O2": "Ó", + "O3": "Ǒ", + "O4": "Ò", + + "u1": "ū", + "u2": "ú", + "u3": "ǔ", + "u4": "ù", + + "U1": "Ū", + "U2": "Ú", + "U3": "Ǔ", + "U4": "Ù" +}; + +const PinyinInput = Ember.Component.extend({ + classNames: ['pinyin-input'], + + setSelection(elm, start, end) { + elm.selectionStart = start; + elm.selectionEnd = end; + }, + + actions: { + processTones(str) { + const editor = this.$("textarea")[0]; + let cursorPosition = editor.selectionStart; + let newStr = str; + const matches = str.match(TONE_REGEX); + + if(!_.isEmpty(matches)) { + newStr = str.replace(TONE_REGEX, match => TONE_MAPPING[match]); + cursorPosition = cursorPosition - matches.length; + } + + this.get("update")(newStr); + + Ember.run.scheduleOnce('afterRender', this, this.setSelection, editor, cursorPosition, cursorPosition); + }, + + processKeydown(e) { + if(e.code === "Enter") { + const enterKeyFun = this.get('onReturn'); + if(enterKeyFun !== undefined) { + e.preventDefault(); + enterKeyFun(this.get('value')); + } + } + } + } +}); + +export default PinyinInput.reopenClass({ + positionalParams: ['value'] +}); diff --git a/app/components/inputs/pinyin-input/template.hbs b/app/components/inputs/pinyin-input/template.hbs new file mode 100644 index 0000000..e04024b --- /dev/null +++ b/app/components/inputs/pinyin-input/template.hbs @@ -0,0 +1,9 @@ +{{one-way-textarea value + placeholder=placeholder + class=class + update=(action 'processTones') + onkeydown=(action 'processKeydown') + autocomplete='off' + autocorrect='off' + autocapitalize='off' + spellcheck=false}} diff --git a/app/components/study/modes/eng-to-pin/component.js b/app/components/study/modes/eng-to-pin/component.js new file mode 100644 index 0000000..aef7334 --- /dev/null +++ b/app/components/study/modes/eng-to-pin/component.js @@ -0,0 +1,53 @@ +import Ember from 'ember'; + +const STRIP_PUNCTUATION = /[.,\/#!$%\^&\*;:{}=\-_?`~()]/g; + +export default Ember.Component.extend({ + classNames: ['row', 'card-2'], + currentAnswer: '', + + didInsertElement() { + this.$('textarea').focus(); + window.yo = this.$; + }, + + didReceiveAttrs() { + this.reset(); + }, + + processAnswer(isCorrect) { + this.set('wasAnswered', true); + this.set('isCorrect', isCorrect); + + if(isCorrect) { + Ember.run.later(() => this.get('onComplete')(), 400); + } + }, + + reset() { + this.set('wasAnswered', undefined); + this.set('isCorrect', undefined); + this.set('currentAnswer', ''); + }, + + actions: { + handleUpdate(str) { + this.set('wasAnswered', false); + this.set("currentAnswer", str); + }, + + async submit() { + const pinyin = await this.get('model.pinyin'); + + const answer = this.get('currentAnswer') + .replace(STRIP_PUNCTUATION, "") + .toLowerCase(); + + const solution = pinyin.get("text") + .replace(STRIP_PUNCTUATION, "") + .toLowerCase(); + + this.processAnswer(answer === solution); + } + } +}); diff --git a/app/components/study/modes/eng-to-pin/styles.styl b/app/components/study/modes/eng-to-pin/styles.styl new file mode 100644 index 0000000..8af7c36 --- /dev/null +++ b/app/components/study/modes/eng-to-pin/styles.styl @@ -0,0 +1,35 @@ +& + background: dope-blue + margin-bottom: 1em + +.content + padding: 1em + +.english + font-size: 1.3em + margin-bottom: 1em + color: white + height: 1.3em + +textarea + resize: none + font-weight: 600 + font-size: 1.6em + height: 1.6em + width: 15em + border: 0 + padding: 0.35em + color: rgba(slate, 0.75) + background: rgba(white, 0.75) + +.status + background: rgba(white, 0.7) + font-size: 2em + font-weight: 700 + height: 2em + + .incorrect + color: hot-pink + + .correct + color: dope-blue diff --git a/app/components/study/modes/eng-to-pin/template.hbs b/app/components/study/modes/eng-to-pin/template.hbs new file mode 100644 index 0000000..400cb42 --- /dev/null +++ b/app/components/study/modes/eng-to-pin/template.hbs @@ -0,0 +1,22 @@ +
+
+ + {{model.english.text}} + + + {{inputs/pinyin-input currentAnswer + class='solution-field' + onReturn=(action 'submit') + update=(action "handleUpdate")}} +
+ + {{#if wasAnswered}} +
+ {{#if isCorrect}} + Correct {{fa-icon 'thumbs-up'}} + {{else}} + That was incorrect + {{/if}} +
+ {{/if}} +
diff --git a/app/components/study/study-canvas/component.js b/app/components/study/study-canvas/component.js new file mode 100644 index 0000000..adbf04a --- /dev/null +++ b/app/components/study/study-canvas/component.js @@ -0,0 +1,42 @@ +import Ember from 'ember'; + +const { + notEmpty +} = Ember.computed; + +export default Ember.Component.extend({ + hasFlashCards: notEmpty('flashCards'), + + didInsertElement() { + this.setupNextStudyCard(); + }, + + setupNextStudyCard() { + const flashCards = this.get('model').toArray(); + const current = this.get('current'); + + let flashCard; + + if(Ember.isPresent(current)) { + const currentIndex = flashCards.indexOf(current.flashCard); + if(currentIndex + 1 > flashCards.length-1) { + flashCard = flashCards[0]; + } else { + flashCard = flashCards[currentIndex + 1]; + } + } else { + flashCard = flashCards[0]; + } + + this.set('current', { + type:'study/modes/eng-to-pin', + flashCard + }); + }, + + actions: { + next() { + this.setupNextStudyCard(); + } + } +}); diff --git a/app/components/study/study-canvas/styles.styl b/app/components/study/study-canvas/styles.styl new file mode 100644 index 0000000..4803028 --- /dev/null +++ b/app/components/study/study-canvas/styles.styl @@ -0,0 +1,2 @@ +& + margin: 2em diff --git a/app/components/study/study-canvas/template.hbs b/app/components/study/study-canvas/template.hbs new file mode 100644 index 0000000..10c95ee --- /dev/null +++ b/app/components/study/study-canvas/template.hbs @@ -0,0 +1,12 @@ +
+
+ {{component current.type model=current.flashCard onComplete=(action 'next')}} +
+ +
+ {{ui/icon-button + click=(action "next") + label="skip" + rightIcon="arrow-right"}} +
+
diff --git a/app/router.js b/app/router.js index 46d8eb6..d3f6bb5 100644 --- a/app/router.js +++ b/app/router.js @@ -8,6 +8,7 @@ const Router = Ember.Router.extend({ Router.map(function() { this.route('lesson', {path:'/lesson/:id'}); + this.route('study'); }); export default Router; diff --git a/app/routes/study.js b/app/routes/study.js new file mode 100644 index 0000000..0e7e15b --- /dev/null +++ b/app/routes/study.js @@ -0,0 +1,7 @@ +import Ember from 'ember'; + +export default Ember.Route.extend({ + model() { + return this.store.findAll('flash-card'); + } +}); diff --git a/app/templates/study.hbs b/app/templates/study.hbs new file mode 100644 index 0000000..f3c454f --- /dev/null +++ b/app/templates/study.hbs @@ -0,0 +1 @@ +{{study/study-canvas model=model}} diff --git a/tests/integration/components/inputs/pinyin-input/component-test.js b/tests/integration/components/inputs/pinyin-input/component-test.js new file mode 100644 index 0000000..0f532e0 --- /dev/null +++ b/tests/integration/components/inputs/pinyin-input/component-test.js @@ -0,0 +1,23 @@ +import { moduleForComponent, test } from 'ember-qunit'; +import hbs from 'htmlbars-inline-precompile'; + +moduleForComponent('inputs/pinyin-input', 'Integration | Component | inputs/pinyin input', { + integration: true +}); + +test('it renders', function(assert) { + this.on('handleUpdate', function(str){ + this.set('value', str); + }); + + this.set('value', 'o1o2o'); + + this.render(hbs`{{inputs/pinyin-input value update=(action 'handleUpdate')}}`); + + assert.equal(this.$('textarea').val(), 'o1o2o'); + + this.$('textarea').val('o1o2o3o4'); + this.$('textarea').change(); + + assert.equal(this.$('textarea').val(), 'ōóǒò'); +}); diff --git a/tests/integration/components/study/modes/eng-to-pin/component-test.js b/tests/integration/components/study/modes/eng-to-pin/component-test.js new file mode 100644 index 0000000..c1b025b --- /dev/null +++ b/tests/integration/components/study/modes/eng-to-pin/component-test.js @@ -0,0 +1,16 @@ +import { moduleForComponent, test } from 'ember-qunit'; +import hbs from 'htmlbars-inline-precompile'; + +moduleForComponent('study/modes/eng-to-pin', 'Integration | Component | study/modes/eng to pin', { + integration: true +}); + +test('it renders', function(assert) { + + // Set any properties with this.set('myProperty', 'value'); + // Handle any actions with this.on('myAction', function(val) { ... }); + + this.render(hbs`{{study/modes/eng-to-pin}}`); + + assert.equal(this.$().text().trim(), ''); +}); diff --git a/tests/unit/routes/study-test.js b/tests/unit/routes/study-test.js new file mode 100644 index 0000000..390ccc4 --- /dev/null +++ b/tests/unit/routes/study-test.js @@ -0,0 +1,11 @@ +import { moduleFor, test } from 'ember-qunit'; + +moduleFor('route:study', 'Unit | Route | study', { + // Specify the other units that are required for this test. + // needs: ['controller:foo'] +}); + +test('it exists', function(assert) { + let route = this.subject(); + assert.ok(route); +});