From 7d0b229ff386341b3ed953e56ba7dd89a6f3bffd Mon Sep 17 00:00:00 2001 From: Aram Zadikian Date: Sat, 22 Apr 2017 14:17:06 -0700 Subject: [PATCH] Various updates --- app/components/audio-recorder/component.js | 44 ++++++-- app/components/audio-recorder/styles.styl | 18 +++ app/components/audio-recorder/template.hbs | 11 +- .../communication/video-chat/component.js | 60 +++++----- .../communication/video-chat/styles.styl | 9 ++ .../communication/video-chat/template.hbs | 6 +- app/components/conversation-group/styles.styl | 13 +++ .../conversation-group/template.hbs | 31 ++--- app/components/flash-card-group/component.js | 16 +++ app/components/flash-card-group/styles.styl | 39 +++++++ app/components/flash-card-group/template.hbs | 33 ++++-- app/components/flash-card/component.js | 22 +--- app/components/flash-card/styles.styl | 66 ++++------- app/components/flash-card/template.hbs | 25 ++--- app/components/navs/lesson-nav/styles.styl | 4 + app/components/navs/lesson-nav/template.hbs | 13 +-- app/components/ui/icon-button/component.js | 2 +- app/components/ui/icon-button/styles.styl | 36 ++++-- app/components/ui/icon-button/template.hbs | 46 ++++---- app/models/conversation.js | 11 +- app/models/flash-card.js | 4 +- app/routes/lesson.js | 106 ++++++++++++++---- app/styles/app.styl | 2 + app/styles/color.styl | 19 ++++ app/styles/layout.styl | 5 +- app/styles/material.styl | 26 +++++ app/styles/reset.styl | 27 +++++ app/styles/variables.styl | 5 - app/templates/lesson.hbs | 6 +- 29 files changed, 483 insertions(+), 222 deletions(-) create mode 100644 app/components/conversation-group/styles.styl create mode 100644 app/components/flash-card-group/styles.styl create mode 100644 app/styles/color.styl create mode 100644 app/styles/material.styl diff --git a/app/components/audio-recorder/component.js b/app/components/audio-recorder/component.js index 1546fe4..c15c771 100644 --- a/app/components/audio-recorder/component.js +++ b/app/components/audio-recorder/component.js @@ -1,23 +1,47 @@ import Ember from 'ember'; +import firebase from 'firebase'; + +const { + computed: { notEmpty } +} = Ember; export default Ember.Component.extend({ + classNames: ['row'], audioRecorder: Ember.inject.service(), + hifi: Ember.inject.service(), + + hasAudio: notEmpty('model.audioUrl'), + saving: false, init() { this._super(...arguments); this.get("audioRecorder").requestAccess(); }, - mouseDown() { - const recorder = this.get("audioRecorder").createRecorder(); - this.set("recorder", recorder); - Ember.run.later(recorder.start, 100); - }, + actions: { + startRecording() { + const recorder = this.get("audioRecorder").createRecorder(); + this.set("recorder", recorder); + Ember.run.later(recorder.start, 100); + }, + + stopRecording() { + this.set("saving", true); + const recorder = this.get("recorder"); + recorder + .stop() + .then(this.get("created")) + .then(() => this.set("saving", false)); + }, + + play() { + const app = firebase.app(); + var storageRef = app.storage().ref(); + var audioRef = storageRef.child(this.get('model.audioUrl')); - mouseUp() { - const recorder = this.get("recorder"); - recorder - .stop() - .then(this.get("created")); + audioRef + .getDownloadURL() + .then(url => this.get("hifi").play(url)); + } } }); diff --git a/app/components/audio-recorder/styles.styl b/app/components/audio-recorder/styles.styl index 687a7da..701aefd 100644 --- a/app/components/audio-recorder/styles.styl +++ b/app/components/audio-recorder/styles.styl @@ -1,2 +1,20 @@ & border: none + +.btn + margin: 0.25em + display: block + border-radius: 50% + padding: 0.5em + background: rgba(off-white, 0.8) + height: 30px + width: 30px + transition: all 0.2s ease-in-out + +.btn:hover + background: rgba(off-white, 1) + +.btn:active + background: hot-pink + opacity: 1 + color: off-white diff --git a/app/components/audio-recorder/template.hbs b/app/components/audio-recorder/template.hbs index 6764e3b..f833fc2 100644 --- a/app/components/audio-recorder/template.hbs +++ b/app/components/audio-recorder/template.hbs @@ -1,3 +1,12 @@ {{ui/icon-button - label="Push & hold to record" + loading=saving + disabled=saving + mouseDown=(action 'startRecording') + mouseUp=(action 'stopRecording') leftIcon="microphone"}} + +{{#if hasAudio}} + {{ui/icon-button + click=(action "play") + leftIcon="play"}} +{{/if}} diff --git a/app/components/communication/video-chat/component.js b/app/components/communication/video-chat/component.js index 5d50bfd..085a101 100644 --- a/app/components/communication/video-chat/component.js +++ b/app/components/communication/video-chat/component.js @@ -3,11 +3,9 @@ import Ember from 'ember'; const Video = Twilio.Video; export default Ember.Component.extend({ - didInsertElement() { + startVideo() { const { token, identity } = this.get("twilioData"); - console.log(token, identity); - Video.connect(token, {name: "my-room"}) .then(room => { @@ -18,47 +16,41 @@ export default Ember.Component.extend({ room.on('participantDisconnected', ::this.participantDisconnected); room.once('disconnected', error => room.participants.forEach(::this.participantDisconnected)); - }, e => { - console.log(e); - }) + }, e => console.log(e)); }, attachTracks(tracks, container) { - tracks.forEach(track => { - container.appendChild(track.attach()) - }); + tracks.forEach(track => this.attachTrack(track, container)); }, - participantConnected(participant) { - this.attachTracks(participant.tracks, this.$(".others:first")[0]) - // console.log('Participant "%s" connected', participant.identity); - // - // const div = document.createElement('div'); - // div.id = participant.sid; - // div.innerText = participant.identity; - // - // participant.on('trackAdded', track => trackAdded(div, track)); - // participant.tracks.forEach(track => trackAdded(div, track)); - // participant.on('trackRemoved', trackRemoved); - // - // document.body.appendChild(div); + attachTrack(track, container) { + container.appendChild(track.attach()); }, - participantDisconnected(participant) { - console.log("Dis", participant); - // console.log('Participant "%s" disconnected', participant.identity); - // - // participant.tracks.forEach(trackRemoved); - // document.getElementById(participant.sid).remove(); + removeTracks(tracks) { + tracks.forEach(track => this.removeTrack(track)); }, - trackAdded(div, track) { - console.log("track added"); - // div.appendChild(track.attach()); + removeTrack(track) { + track.detach().forEach(element => element.remove()); + }, + + participantConnected(participant) { + const container = this.$(".others:first")[0]; + + participant.on('trackAdded', track => ::this.attachTrack(track, container)); + participant.on('trackRemoved', track => ::this.removeTrack(track)); + + this.attachTracks(participant.tracks, container); + }, + + participantDisconnected(participant) { + this.removeTracks(participant.tracks); }, - trackRemoved(track) { - console.log("trackRemoved"); - // track.detach().forEach(element => element.remove()); + actions: { + startVideo() { + this.startVideo(); + } } }); diff --git a/app/components/communication/video-chat/styles.styl b/app/components/communication/video-chat/styles.styl index 6d00b90..a212b12 100644 --- a/app/components/communication/video-chat/styles.styl +++ b/app/components/communication/video-chat/styles.styl @@ -14,3 +14,12 @@ video .vsc-controller display: none + +.start-video + background: dope-blue + // padding: 0.5em + width: 100px + height: 100px + .icon-container + // font-size: 1.5em + color: white diff --git a/app/components/communication/video-chat/template.hbs b/app/components/communication/video-chat/template.hbs index b398bf6..71f24c8 100644 --- a/app/components/communication/video-chat/template.hbs +++ b/app/components/communication/video-chat/template.hbs @@ -1,8 +1,12 @@ -
+
+ {{ui/icon-button + class="start-video" + rightIcon="video-camera" + click=(action startVideo)}}
diff --git a/app/components/conversation-group/styles.styl b/app/components/conversation-group/styles.styl new file mode 100644 index 0000000..eca0332 --- /dev/null +++ b/app/components/conversation-group/styles.styl @@ -0,0 +1,13 @@ +& + margin-top: 3em + +.create-conversation + width: 100% + padding: 1em + color: dark-grey + font-size: 1em + opacity: 0.15 + transition: all 0.2s ease-in-out + +.create-conversation:hover + opacity: 1 diff --git a/app/components/conversation-group/template.hbs b/app/components/conversation-group/template.hbs index 82fdcf4..7a85864 100644 --- a/app/components/conversation-group/template.hbs +++ b/app/components/conversation-group/template.hbs @@ -1,14 +1,19 @@ -
- {{#if hasConversations}} - {{#each sortedConversations as |conversation index|}} - {{flash-card-group - model=conversation - onAudioCreated=onAudioCreated - createFlashCard=createFlashCard - destroyFlashCard=destroyFlashCard - saveModel=saveModel}} - {{/each}} - {{else}} -

No conversations yet. Why not start one?

- {{/if}} +
+ {{ui/icon-button + class='create-conversation' + click=(action createConversation 0) + leftIcon="plus"}} + {{#each sortedConversations as |conversation index|}} + {{flash-card-group + model=conversation + index=(inc index) + onAudioCreated=onAudioCreated + createFlashCard=createFlashCard + destroyFlashCard=destroyFlashCard + saveModel=saveModel}} + {{ui/icon-button + class='create-conversation' + click=(action createConversation (inc index)) + leftIcon="plus"}} + {{/each}}
diff --git a/app/components/flash-card-group/component.js b/app/components/flash-card-group/component.js index 926b613..d5aebf0 100644 --- a/app/components/flash-card-group/component.js +++ b/app/components/flash-card-group/component.js @@ -1,4 +1,20 @@ import Ember from 'ember'; +import computed from 'ember-computed-decorators'; + +const { isPresent, computed: { alias, sort, gt } } = Ember; export default Ember.Component.extend({ + classNames: ['card-1'], + + sortAsc: ["position:asc"], + sortedFlashCards: sort('model.activeFlashCards', 'sortAsc'), + flashCardCount: alias("sortedFlashCards.length"), + hasFlashCards: gt("flashCardCount", 0), + + actions: { + handleUpdate(key, str) { + this.get("model").set(key, str); + this.get("saveModel")(this.get("model")); + } + } }); diff --git a/app/components/flash-card-group/styles.styl b/app/components/flash-card-group/styles.styl new file mode 100644 index 0000000..13191e9 --- /dev/null +++ b/app/components/flash-card-group/styles.styl @@ -0,0 +1,39 @@ +& + width: 100% + padding: 1em + background: dope-blue + height: 24em + +.conversation-header + margin-left: calc(2em - 1em) + color: off-white + font-size: 1.5em + align-items: baseline + .index + margin-right: 0.25em + +.conversation-title + background: 0 + border: 0 + border-bottom: 1px dashed + color: off-white + font-size: 1.3em + width: 16em + +.conversation-title::placeholder + color: rgba(off-white, 0.5) + +.flash-card-container + overflow-x: auto + overflow-y: hidden + margin: 1em 0 + +.create-flash-card + color: white + font-size: 1em + padding: 1em + opacity: 0.15 + transition: all 0.2s ease-in-out + +.create-flash-card:hover + opacity: 1 diff --git a/app/components/flash-card-group/template.hbs b/app/components/flash-card-group/template.hbs index 9e0522b..6ebbb40 100644 --- a/app/components/flash-card-group/template.hbs +++ b/app/components/flash-card-group/template.hbs @@ -1,16 +1,31 @@ -
- {{#each model.flashCards as |flashCard|}} +
+ + {{index}}. + + {{one-way-input model.title + class='conversation-title' + placeholder='What\'s this conversation about...' + update=(action "handleUpdate" "title") + autocomplete="off" + autocorrect="off" + autocapitalize="off" + spellcheck=false}} +
+
+ {{ui/icon-button + class="create-flash-card" + leftIcon="plus" + click=(action createFlashCard model 0)}} + {{#each sortedFlashCards as |flashCard index|}} {{flash-card model=flashCard - total=cardCount - index=index + index=(inc index) onAudioCreated=onAudioCreated destroyFlashCard=(action destroyFlashCard model) saveModel=saveModel}} + {{ui/icon-button + class="create-flash-card" + leftIcon="plus" + click=(action createFlashCard model (inc index))}} {{/each}}
- -{{ui/icon-button - label="Create" - leftIcon="add" - click=(action createFlashCard model)}} diff --git a/app/components/flash-card/component.js b/app/components/flash-card/component.js index 5b366bb..abcd94f 100644 --- a/app/components/flash-card/component.js +++ b/app/components/flash-card/component.js @@ -1,7 +1,6 @@ import Ember from 'ember'; import _ from 'lodash'; import computed from 'ember-computed-decorators'; -import firebase from 'firebase'; const TONE_REGEX = /([aeiouAEIOU][1234])/g; @@ -62,16 +61,7 @@ const { } = Ember; export default Ember.Component.extend({ - classNames: ['stretch'], - - hifi: Ember.inject.service(), - - @computed('total', 'index') - position(total, index) { - return total - index; - }, - - hasAudio: notEmpty('model.audioUrl'), + classNames: ['card-2', 'stretch'], setSelection(elm, start, end) { elm.selectionStart = start; @@ -100,16 +90,6 @@ export default Ember.Component.extend({ handleUpdate(key, str) { this.get("model").set(key, str); this.get("saveModel")(this.get("model")); - }, - - play() { - const app = firebase.app(); - var storageRef = app.storage().ref(); - var audioRef = storageRef.child(this.get('model.audioUrl')); - - audioRef - .getDownloadURL() - .then(url => this.get("hifi").play(url)); } } }); diff --git a/app/components/flash-card/styles.styl b/app/components/flash-card/styles.styl index 6b7deb1..91e868b 100644 --- a/app/components/flash-card/styles.styl +++ b/app/components/flash-card/styles.styl @@ -1,66 +1,46 @@ & - background: #FFB928 + background: dark-orange color: #2E282A - margin-bottom: 1em - border: 5px solid rgba(black, 0.25) - max-width: 80em - -&:nth-child(odd) - background: rgba(#59B5C1, 0.5) + min-width: 18em + width: 18em + margin: 0.5em .inputContainer - width: 100% - margin-right: 1em - .title - font-weight: 600 - height: 1.5em - padding-left: 0.2em - align-items: flex-end - -.inputContainer:last-child - margin-right: 0 + margin-left: 1em + margin-right: calc(1em + 0.25em) textarea + width: 100% resize: none - width: calc(100% - 10px - 0.2em) - padding: 0.2em - font-size: 1.5em - border: 5px solid rgba(black, 0.25) - - +below(950px) - font-size: 1.4em - +below(900px) - font-size: 1.3em - +below(850px) - font-size: 1.2em - +below(800px) - font-size: 1.1em - +below(750px) - font-size: 1em - +below(700px) - margin: 0.25em 0 - font-size: 1.4em - width: calc(100% - 10px - 0.2em) + font-weight: 600 + font-size: 1em + margin-bottom: 0.5em + border: 0 + padding: 0.25em + background: rgba(white, 0.75) .fieldsContainer - margin: 1em + // margin: 0.5em +below(700px) flex-direction: column header background: rgba(white, 0.5) - padding: 0.5em + align-items: baseline + margin-bottom: 1em + .delete + background: none + margin: 0 + padding: 0.5em + .index - margin-left: 1em - font-size: 1.5em + margin-left: 0.5em + font-size: 1.25em .audioUiContainer justify-content: flex-end margin: 1em - .btn - margin-left: 1em - border-radius: 3px hr border: 1px solid rgba(white, 0.5) diff --git a/app/components/flash-card/template.hbs b/app/components/flash-card/template.hbs index 5fddfb6..322488f 100644 --- a/app/components/flash-card/template.hbs +++ b/app/components/flash-card/template.hbs @@ -1,6 +1,6 @@
- {{position}}. + {{index}}.
@@ -8,14 +8,15 @@
{{ui/icon-button label="X" + class='delete' click=(action destroyFlashCard model)}}
-
+
-
汉语
{{one-way-textarea model.chinese + placeholder='汉语...' update=(action "handleUpdate" "chinese") autocomplete="off" autocorrect="off" @@ -24,8 +25,8 @@
-
Pinyin
{{one-way-textarea model.pinyin + placeholder='Pinyin...' class="pinyinEditor" update=(action 'processChange') autocomplete="off" @@ -35,8 +36,8 @@
-
English
{{one-way-textarea model.english + placeholder='English...' update=(action "handleUpdate" "english") autocomplete="off" autocorrect="off" @@ -45,16 +46,8 @@
-
-
- {{audio-recorder - created=onAudioCreated}} - - {{#if hasAudio}} - {{ui/icon-button - label="Play" - click=(action "play") - leftIcon="play"}} - {{/if}} + {{audio-recorder + model=model + created=(action onAudioCreated model)}}
diff --git a/app/components/navs/lesson-nav/styles.styl b/app/components/navs/lesson-nav/styles.styl index c93a10a..aafda8b 100644 --- a/app/components/navs/lesson-nav/styles.styl +++ b/app/components/navs/lesson-nav/styles.styl @@ -1,5 +1,6 @@ & position: relative + z-index: 1000 .uiContainer position: fixed @@ -13,6 +14,9 @@ +below(540px) flex-direction: column +.home-button + color: off-white + .leftContainer margin-left: 2em +below(540px) diff --git a/app/components/navs/lesson-nav/template.hbs b/app/components/navs/lesson-nav/template.hbs index 85dc1d6..a550e3a 100644 --- a/app/components/navs/lesson-nav/template.hbs +++ b/app/components/navs/lesson-nav/template.hbs @@ -1,20 +1,15 @@
{{ui/icon-button + class="home-button" label="Home" - click=navigateHome - leftIcon="arrow-left"}} + click=navigateHome}} - {{#copy-button +
- - {{ui/icon-button - label="Create Flashcard" - rightIcon="plus" - click=createConversation}}
diff --git a/app/components/ui/icon-button/component.js b/app/components/ui/icon-button/component.js index c566d49..55b8a36 100644 --- a/app/components/ui/icon-button/component.js +++ b/app/components/ui/icon-button/component.js @@ -3,7 +3,7 @@ import Ember from "ember"; const { notEmpty } = Ember.computed; export default Ember.Component.extend({ - classNames: ["row", "btn"], + classNames: ["btn"], hasLabel: notEmpty("label"), hasLeftIcon: notEmpty("leftIcon"), diff --git a/app/components/ui/icon-button/styles.styl b/app/components/ui/icon-button/styles.styl index 18ae556..d6e5b9f 100644 --- a/app/components/ui/icon-button/styles.styl +++ b/app/components/ui/icon-button/styles.styl @@ -2,8 +2,6 @@ cursor: pointer align-items: center justify-content: center - padding: 0.5rem - background: #F8F9F2 &:active opacity: 0.5 @@ -11,13 +9,33 @@ .label font-size: 1rem -.spacer - margin-right: 0.5rem - -.iconContainer - font-size: 0.5rem +.icon-container align-items: center justify-content: center -.content - padding: 0 1em +.spin-clockwise { + -webkit-animation: load8 1.1s infinite linear; + animation: load8 1.1s infinite linear; +} + +@-webkit-keyframes load8 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +@keyframes load8 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} diff --git a/app/components/ui/icon-button/template.hbs b/app/components/ui/icon-button/template.hbs index 853475f..438ac10 100644 --- a/app/components/ui/icon-button/template.hbs +++ b/app/components/ui/icon-button/template.hbs @@ -1,25 +1,33 @@ -
- {{#if hasLeftIcon}} -
- {{fa-icon leftIcon}} -
- {{/if}} +
+ {{#if loading}} +
+ {{fa-icon 'spinner'}} +
+ {{else}} + {{#if hasLeftIcon}} +
+ {{fa-icon leftIcon}} +
+ {{/if}} - {{#if (and hasLabel hasLeftIcon)}} -
- {{/if}} + {{#if (and hasLabel hasLeftIcon)}} +
+ {{/if}} - {{#if hasLabel}} - {{label}} - {{/if}} + {{#if hasLabel}} + {{label}} + {{/if}} + + {{#if (and hasLabel hasRightIcon)}} +
+ {{/if}} + + {{#if hasRightIcon}} +
+ {{fa-icon rightIcon}} +
+ {{/if}} - {{#if (and hasLabel hasRightIcon)}} -
- {{/if}} - {{#if hasRightIcon}} -
- {{fa-icon rightIcon}} -
{{/if}}
diff --git a/app/models/conversation.js b/app/models/conversation.js index 01ea3a7..0a3f425 100644 --- a/app/models/conversation.js +++ b/app/models/conversation.js @@ -1,12 +1,17 @@ import DS from 'ember-data'; +import computed from 'ember-computed-decorators'; -const { empty } = Ember.computed; +const { empty, filterBy } = Ember.computed; export default DS.Model.extend({ title: DS.attr('string'), lesson: DS.belongsTo('lesson'), - position: DS.attr('number'), + ts: DS.attr('number'), + position: DS.attr('number', {defaultValue: 1}), + flashCards: DS.hasMany('flash-card'), - isEmpty: empty("flashCards") + activeFlashCards: filterBy('flashCards', 'isDeleted', false), + + isEmpty: empty("activeFlashCards") }); diff --git a/app/models/flash-card.js b/app/models/flash-card.js index 561cd4c..7b0463d 100644 --- a/app/models/flash-card.js +++ b/app/models/flash-card.js @@ -6,7 +6,7 @@ export default DS.Model.extend({ english: DS.attr('string'), audioUrl: DS.attr('string'), ts: DS.attr('number'), - position: DS.attr('number'), - + position: DS.attr('number', {defaultValue: 1}), + conversation: DS.belongsTo('conversation') }); diff --git a/app/routes/lesson.js b/app/routes/lesson.js index a508600..6aff8b2 100644 --- a/app/routes/lesson.js +++ b/app/routes/lesson.js @@ -2,6 +2,7 @@ import Ember from 'ember'; import firebase from 'firebase'; import { v4 as uuid } from 'uuid'; import moment from 'moment'; +import _ from 'lodash'; export default Ember.Route.extend({ setupController(controller, model) { @@ -20,9 +21,14 @@ export default Ember.Route.extend({ const record = await this.store.findRecord('lesson', params.id) .catch(() => { - return this.store - .createRecord('lesson', {id:params.id, date:new Date()}) - .save(); + const lesson = this.store.createRecord('lesson', {id:params.id, date:new Date()}), + conversation = this.store.createRecord('conversation', {lesson}), + flashCard = this.store.createRecord('flash-card', {conversation}); + + return lesson.save() + .then(lesson => conversation.save()) + .then(conversation => flashCard.save()) + .then(flashCard => lesson); }); return { @@ -32,6 +38,46 @@ export default Ember.Route.extend({ } }, + async createConversation(lesson, position = 0) { + const conversations = await lesson.get("conversations"); + + const sortedConversations = conversations.sortBy("position"); + + const prevCard = sortedConversations[position - 1]; + const nextCard = sortedConversations[position]; + + const prev = Ember.isPresent(prevCard) ? prevCard.get("position") : undefined; + const next = Ember.isPresent(nextCard) ? nextCard.get("position") : undefined; + + let newPosition; + + if(prev === undefined && next !== undefined) { + newPosition = next/2; + } + + if(prev !== undefined && next === undefined) { + newPosition = prev + 1; + } + + if(prev !== undefined && next !== undefined) { + newPosition = (next - prev)/2 + prev; + } + + if(prev === undefined && next === undefined) { + newPosition = 1; + } + + const conversation = this.store + .createRecord('conversation', { lesson, position: newPosition }); + + const flashCard = this.store + .createRecord('flash-card', { conversation }); + + await conversation.save(); + await flashCard.save(); + await lesson.save(); + }, + actions: { onAudioCreated(model, blob) { const app = firebase.app(); @@ -40,9 +86,9 @@ export default Ember.Route.extend({ const path = `audio/${uuid()}.wav`; var audioRef = storageRef.child(path); - audioRef.put(blob).then(() => { + return audioRef.put(blob).then(() => { model.set("audioUrl", path); - model.save(); + return model.save(); }); }, @@ -54,32 +100,54 @@ export default Ember.Route.extend({ model.save(); }, - // @TODO: Not sure why this is failing. async destroyFlashCard(conversation, flashCard) { - await flashCard - .destroyRecord() - .catch(() => {}); + flashCard.deleteRecord(); if(conversation.get("isEmpty")) { conversation.deleteRecord(); } + await flashCard.save(); await conversation.save(); }, - async createConversation(lesson) { - await this.store - .createRecord('conversation', { lesson }) - .save(); - - await lesson.save(); + createConversation(lesson, position) { + this.createConversation(lesson, position); }, - async createFlashCard(conversation) { - await this.store - .createRecord('flash-card', { conversation }) - .save(); + async createFlashCard(conversation, position) { + const flashCards = await conversation.get("flashCards"); + + const sortedFlashCards = flashCards.sortBy("position"); + + const leftCard = sortedFlashCards[position - 1]; + const rightCard = sortedFlashCards[position]; + + const left = Ember.isPresent(leftCard) ? leftCard.get("position") : undefined; + const right = Ember.isPresent(rightCard) ? rightCard.get("position") : undefined; + + let newPosition; + + if(left === undefined && right !== undefined) { + newPosition = right/2; + } + + if(left !== undefined && right === undefined) { + newPosition = left + 1; + } + + if(left !== undefined && right !== undefined) { + newPosition = (right - left)/2 + left; + } + + if(left === undefined && right === undefined) { + newPosition = 1; + } + + const flashCard = this.store + .createRecord('flash-card', { conversation, position: newPosition }); + await flashCard.save(); await conversation.save(); } } diff --git a/app/styles/app.styl b/app/styles/app.styl index 093c11a..22d13f3 100644 --- a/app/styles/app.styl +++ b/app/styles/app.styl @@ -1,8 +1,10 @@ @lost flexbox flex @import "variables" +@import "color" @import "reset" @import "layout" @import "typography" +@import "material" @import "utils" @import "pod-styles" diff --git a/app/styles/color.styl b/app/styles/color.styl new file mode 100644 index 0000000..6e74a2a --- /dev/null +++ b/app/styles/color.styl @@ -0,0 +1,19 @@ +body-color = #F4F4F4 +dope-grey = #1E1E1E +dope-pink = #F94848 +dope-green = #00ae9c + +slate = #232323 +off-white = #F9F9F9 +light-grey = #C9C9C9 +medium-grey = #EBEDEC +dark-grey = #4C4C4C +sky-blue = #00B3DD +baby-blue = #BDEFFF +light-blue = #F3FDFF +light-green = #DEFFEE +dark-green = #4ACE86 +dark-orange = #FFB928 +hot-pink = #FF646C +dope-blue = #4DA6FF +light-orange = #F5E385 diff --git a/app/styles/layout.styl b/app/styles/layout.styl index c034fe1..cd07419 100644 --- a/app/styles/layout.styl +++ b/app/styles/layout.styl @@ -22,6 +22,7 @@ .stretch width: 100% + height: 100% .space-between justify-content: space-between @@ -39,10 +40,6 @@ for num in (1..9) flex: num // Refactor out into components -.flashCardContainer - margin-top: 4em - padding: 1em - .landingContainer padding: 5em max-width: 60em diff --git a/app/styles/material.styl b/app/styles/material.styl new file mode 100644 index 0000000..80c4744 --- /dev/null +++ b/app/styles/material.styl @@ -0,0 +1,26 @@ +.card + border-radius: 2px + transition: all 0.2s ease-in-out + +.card-1 + @extend .card + box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24) + +.card-2 + @extend .card + box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23) + + +.card-3 + @extend .card + box-shadow: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23) + + +.card-4 + @extend .card + box-shadow: 0 14px 28px rgba(0,0,0,0.25), 0 10px 10px rgba(0,0,0,0.22) + + +.card-5 + @extend .card + box-shadow: 0 19px 38px rgba(0,0,0,0.30), 0 15px 12px rgba(0,0,0,0.22) diff --git a/app/styles/reset.styl b/app/styles/reset.styl index 32b8e0e..e19c4a2 100644 --- a/app/styles/reset.styl +++ b/app/styles/reset.styl @@ -16,3 +16,30 @@ button margin: 0 padding: 0 border: 0 + +::-webkit-scrollbar + width: 11px + height: 11px + +::-webkit-scrollbar-button + width: 0px + height: 0px + +::-webkit-scrollbar-thumb + background: #e1e1e1 + border: 0px none white + border-radius: 50px + +::-webkit-scrollbar-thumb:hover + background: white + +::-webkit-scrollbar-thumb:active + background: rgba(white, 0.9) + +::-webkit-scrollbar-track + background: rgba(white, 0.5) + border: 0px none white + border-radius: 50px + +::-webkit-scrollbar-corner + background: transparent diff --git a/app/styles/variables.styl b/app/styles/variables.styl index a65d37f..2812e90 100644 --- a/app/styles/variables.styl +++ b/app/styles/variables.styl @@ -1,6 +1 @@ rupture.enable-em-breakpoints = true - -body-color = #F4F4F4 -dope-grey = #1E1E1E -dope-pink = #F94848 -dope-green = #00ae9c diff --git a/app/templates/lesson.hbs b/app/templates/lesson.hbs index c52c91c..1a58a81 100644 --- a/app/templates/lesson.hbs +++ b/app/templates/lesson.hbs @@ -1,13 +1,13 @@ {{navs/lesson-nav lessonId=lessonId - navigateHome=(route-action "navigateHome") - createConversation=(route-action "createConversation" lesson)}} + navigateHome=(route-action "navigateHome")}} {{conversation-group + createConversation=(route-action "createConversation" lesson) onAudioCreated=(route-action 'onAudioCreated') createFlashCard=(route-action 'createFlashCard') saveModel=(route-action 'saveModel') destroyFlashCard=(route-action 'destroyFlashCard') model=lesson.conversations}} -{{communication/video-chat twilioData=twilioData}} +