Skip to content

Commit

Permalink
Merge pull request #912 from jrjohnson/389-lmsearch
Browse files Browse the repository at this point in the history
Add search to add course / session learning material
  • Loading branch information
thecoolestguy committed Oct 23, 2015
2 parents bc4aeeb + 0980494 commit 0e353c5
Show file tree
Hide file tree
Showing 13 changed files with 358 additions and 35 deletions.
99 changes: 72 additions & 27 deletions app/components/detail-learning-materials.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,49 +2,71 @@ import Ember from 'ember';
import DS from 'ember-data';
import { translationMacro as t } from "ember-i18n";

const {computed, inject, RSVP} = Ember;
const {notEmpty, or, not} = computed;
const {service} = inject;
const {PromiseArray} = DS;

export default Ember.Component.extend({
currentUser: Ember.inject.service(),
store: Ember.inject.service(),
i18n: Ember.inject.service(),
currentUser: service(),
store: service(),
i18n: service(),
subject: null,
isCourse: false,
isManaging: Ember.computed.or('isManagingMaterial', 'isManagingMesh'),
isManagingMaterial: Ember.computed.notEmpty('managingMaterial'),
isManagingMesh: Ember.computed.notEmpty('meshMaterial'),
isManaging: or('isManagingMaterial', 'isManagingMesh'),
isManagingMaterial: notEmpty('managingMaterial'),
isManagingMesh: notEmpty('meshMaterial'),
managingMaterial: null,
meshMaterial: null,
isSession: Ember.computed.not('isCourse'),
materials: Ember.computed.alias('subject.learningMaterials'),
isSession: not('isCourse'),
newLearningMaterials: [],
classNames: ['detail-learning-materials'],
newButtonTitle: t('general.add'),
bufferMaterial: null,
bufferTerms: [],
learningMaterialStatuses: function(){
var self = this;
return DS.PromiseArray.create({
return PromiseArray.create({
promise: self.get('store').findAll('learning-material-status')
});
}.property(),
learningMaterialUserRoles: function(){
learningMaterialUserRoles: computed(function(){
var self = this;
return DS.PromiseArray.create({
return PromiseArray.create({
promise: self.get('store').findAll('learning-material-user-role')
});
}.property(),
proxyMaterials: Ember.computed('materials.@each', function(){
}),
proxyMaterials: computed('subject.learningMaterials.[]', function(){
let materialProxy = Ember.ObjectProxy.extend({
sortTerms: ['name'],
sortedDescriptors: Ember.computed.sort('content.meshDescriptors', 'sortTerms')
});
return this.get('materials').map(material => {
return this.get('subject.learningMaterials').map(material => {
return materialProxy.create({
content: material
});
});
}),
parentMaterials: computed('subject.learningMaterials.[]', function(){
let defer = RSVP.defer();
this.get('subject.learningMaterials').then(subLms => {
let promises = [];
let learningMaterials = [];
subLms.forEach(lm => {
promises.pushObject(lm.get('learningMaterial').then(learningMaterial => {
learningMaterials.pushObject(learningMaterial);
}));
});
RSVP.all(promises).then(()=>{
defer.resolve(learningMaterials);
});
});
return PromiseArray.create({
promise: defer.promise
});
}),
actions: {
manageMaterial: function(learningMaterial){
manageMaterial(learningMaterial){
var buffer = Ember.Object.create();
buffer.set('publicNotes', learningMaterial.get('publicNotes'));
buffer.set('required', learningMaterial.get('required'));
Expand All @@ -57,13 +79,13 @@ export default Ember.Component.extend({
});
});
},
manageDescriptors: function(learningMaterial){
manageDescriptors(learningMaterial){
learningMaterial.get('meshDescriptors').then(descriptors => {
this.set('bufferTerms', descriptors.toArray());
this.set('meshMaterial', learningMaterial);
});
},
save: function(){
save(){
if(this.get('isManagingMaterial')){
let buffer = this.get('bufferMaterial');
let learningMaterial = this.get('managingMaterial');
Expand Down Expand Up @@ -116,14 +138,14 @@ export default Ember.Component.extend({
});
}
},
cancel: function(){
cancel(){
this.set('bufferMaterial', null);
this.set('managingMaterial', null);
this.set('bufferTerms', []);
this.set('meshMaterial', null);

},
addNewLearningMaterial: function(type){
addNewLearningMaterial(type){
var self = this;
if(type === 'file' || type === 'citation' || type === 'link'){
self.get('learningMaterialStatuses').then(function(statuses){
Expand All @@ -146,7 +168,7 @@ export default Ember.Component.extend({
});
}
},
saveNewLearningMaterial: function(lm){
saveNewLearningMaterial(lm){
var self = this;
var subjectLm;
var lmCollectionType;
Expand Down Expand Up @@ -176,26 +198,49 @@ export default Ember.Component.extend({
});
});
},
removeNewLearningMaterial: function(lm){
removeNewLearningMaterial(lm){
this.get('newLearningMaterials').removeObject(lm);
},
addTermToBuffer: function(term){
addTermToBuffer(term){
this.get('bufferTerms').addObject(term);
},
removeTermFromBuffer: function(term){
removeTermFromBuffer(term){
this.get('bufferTerms').removeObject(term);
},
changeStatus: function(newStatus){
changeStatus(newStatus){
this.get('bufferMaterial').set('status', newStatus);
},
changeRequired: function(value){
changeRequired(value){
this.get('bufferMaterial').set('required', value);
},
changePublicNotes: function(value){
changePublicNotes(value){
this.get('bufferMaterial').set('publicNotes', value);
},
changeNotes: function(value){
changeNotes(value){
this.get('bufferMaterial').set('notes', value);
},
addLearningMaterial(parentLearningMaterial){
let newLearningMaterial;
let lmCollectionType;
if(this.get('isCourse')){
newLearningMaterial = this.get('store').createRecord('course-learning-material', {
course: this.get('subject'),
learningMaterial: parentLearningMaterial
});
lmCollectionType = 'courseLearningMaterials';
}
if(this.get('isSession')){
newLearningMaterial = this.get('store').createRecord('session-learning-material', {
session: this.get('subject'),
learningMaterial: parentLearningMaterial
});
lmCollectionType = 'sessionLearningMaterials';
}
newLearningMaterial.save().then(savedLearningMaterial => {
parentLearningMaterial.get(lmCollectionType).then(children => {
children.pushObject(savedLearningMaterial);
});
});
}
},
});
78 changes: 78 additions & 0 deletions app/components/learningmaterial-search.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import Ember from 'ember';

const {inject, run, computed} = Ember;
const {service} = inject;
const {debounce} = run;
const {or, notEmpty} = computed;

export default Ember.Component.extend({
store: service(),
i18n: service(),
classNames: ['learningmaterial-search'],
results: [],
currentMaterials: [],
searching: false,
showMoreInputPrompt: false,
showNoResultsMessage: false,
currentlySearchingForTerm: false,
hasResults: notEmpty('results'),
showList: or('searching', 'showMoreInputPrompt', 'showNoResultsMessage', 'hasResults'),
actions: {
clear() {
let input = this.$('input')[0];
input.value = '';
this.setProperties({
searchTerms: '',
showMoreInputPrompt: false,
showNoResultsMessage: false,
searching: false,
results: [],
showClearButton: false,
});
},
inputValueChanged(){
let input = this.$('input')[0];
let searchTerms = input.value;
if(this.get('currentlySearchingForTerm') === searchTerms){
return;
}
this.setProperties({
currentlySearchingForTerm: searchTerms,
showMoreInputPrompt: false,
showNoResultsMessage: false,
searching: false,
});
let noWhiteSpaceTerm = searchTerms.replace(/ /g,'');
if(noWhiteSpaceTerm.length === 0){
this.send('clear');
return;
} else if(noWhiteSpaceTerm.length < 3){
this.setProperties({
results: [],
showMoreInputPrompt: true,
});
return;
}
this.set('searching', true);
debounce(this, function(){
this.send('search', searchTerms);
}, 1000);
},
search(searchTerms){
this.set('searching', true);
this.get('store').query('learningMaterial', {q: searchTerms}).then(learningMaterials => {
let results = learningMaterials.filter(learningMaterial => {
return !this.get('currentMaterials').contains(learningMaterial);
});
this.set('searching', false);
if(results.get('length') === 0){
this.set('showNoResultsMessage', true);
}
this.set('results', results.sortBy('title'));
});
},
add(lm){
this.sendAction('add', lm);
},
}
});
2 changes: 1 addition & 1 deletion app/locales/en/translations.js
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ export default {
'copyrightPermission': 'Copyright Permission',
'copyrightAgreement': "The file I am attempting to upload is my own or I have express permission to reproduce and/or distribute this item and does not contain any protected health information. My use of this file is in compliance with Government and University policies on copyright and information security and my educational program's guidelines for professional conduct. This file also adheres to the Terms and Conditions for this application.",
'copyrightRationale':'Copyright Rationale',

'searchPlaceholder': 'Find Learning Material',
},
'groupMembers': {
'filterPlaceholder': 'Filter by name or email',
Expand Down
2 changes: 1 addition & 1 deletion app/locales/es/translations.js
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ export default {
'copyrightPermission': 'Permisos de Derechos de Autor',
'copyrightAgreement': "El archivo yo estoy tratando a subir es mi pripio o yo la tengo la autorización expresa a reproducir y/o distribuir esta información y que no contiene ninguna información de la salud protegida. Mi uso de este archivo conforme a Políticas del gobierno y a la Universidad según a la seguridad de copyright e información y las reglas de mi program de estudio a cerca de conducto profesional. Este archivo también adhiere a los Terminos y Condiciones para esta aplicación.",
'copyrightRationale':'Justificación para Derechos de Autor',

'searchPlaceholder': 'encontrar material de aprendizaje',
},
'groupMembers': {
'filterPlaceholder': 'Aplicar un Filtro por nombre o email',
Expand Down
2 changes: 1 addition & 1 deletion app/locales/fr/translations.js
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ export default {
'copyrightPermission': "Droit d'auteur",
'copyrightAgreement': "Le fichier que je tente de télécharger est ma propre ou je avoir la permission expresse à reproduire et / ou distribuer cet article et ne contient pas d'informations de santé protégées . Mon utilisation de ce fichier est en conformité avec les politiques gouvernementales et universitaires sur le droit d'auteur et de la sécurité de l'information et les directives de mon programme d'enseignement de conduite professionnelle . Ce fichier respecte également les Termes et Conditions pour cette application .",
'copyrightRationale': "Raison du droit d'auteur",

'searchPlaceholder': "Trouver matières d'étude",
},
'groupMembers': {
'filterPlaceholder': "Filtre par nom ou email",
Expand Down
26 changes: 24 additions & 2 deletions app/mirage/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,17 @@ export default function() {
this.get('/api/courselearningmaterials/:id', 'courseLearningMaterial');
this.put('/api/courselearningmaterials/:id', 'courseLearningMaterial');
this.delete('/api/courselearningmaterials/:id', 'courseLearningMaterial');
this.post('/api/courselearningmaterials', 'courseLearningMaterial');
this.post('/api/courselearningmaterials', function(db, request) {
let attrs = JSON.parse(request.requestBody);
let record = db.courseLearningMaterials.insert(attrs);
let lm = db.learningMaterials.find(record.learningMaterial);
if(lm){
lm.courseLearningMaterials.pushObject(record);
}
return {
courseLearningMaterial: record
};
});

this.get('/api/courses', getAll);
this.get('/api/courses/:id', 'course');
Expand Down Expand Up @@ -232,7 +242,19 @@ export default function() {
this.get('/api/sessionlearningmaterials/:id', 'sessionLearningMaterial');
this.put('/api/sessionlearningmaterials/:id', 'sessionLearningMaterial');
this.delete('/api/sessionlearningmaterials/:id', 'sessionLearningMaterial');
this.post('/api/sessionlearningmaterials', 'sessionLearningMaterial');

this.post('/api/sessionlearningmaterials', function(db, request) {
let attrs = JSON.parse(request.requestBody);
let record = db.sessionLearningMaterial.insert(attrs);
let lm = db.learningMaterials.find(record.learningMaterial);

if(lm){
lm.sessionLearningMaterials.pushObject(record);
}
return {
sessionLearningMaterial: record
};
});

this.get('/api/sessiontypes', getAll);
this.get('/api/sessiontypes/:id', 'sessionType');
Expand Down
3 changes: 3 additions & 0 deletions app/mirage/helpers/get-all.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ export default function getAll(db, request){
case 'meshDescriptors':
comparisonString = (obj.name + obj.annotation).toLowerCase();
break;
case 'learningMaterials':
comparisonString = (obj.title).toLowerCase();
break;
default:
console.log('No Q comparison defined for ' + modelName);
return false;
Expand Down
54 changes: 54 additions & 0 deletions app/styles/components/_detailview.scss
Original file line number Diff line number Diff line change
Expand Up @@ -347,3 +347,57 @@ $collapse-control-shadow-grey: #e2e2e2;
list-style-type: disc;
}
}

.learningmaterial-search {
display: inline-block;
float: right;
margin-top: 1em;
position: relative;

input {
height: 2em;
width: 200px;
}

.results {
@include transition (all .2s ease-in-out);
background: $white;
border: 1px solid $background-grey;
border-radius: $base-border-radius;
box-shadow: 0 2px 2px transparentize($black, .8);
color: $base-font-color;
cursor: pointer;
left: 0;
max-height: 400px;
overflow-x: visible;
overflow-y: auto;
//this should be absolute, but first we have to move the .global-search
//out of the grid.
position: relative;
top: 0;
width: 300px;
z-index: 100;

li {
border-bottom: 1px solid $base-border-color;
padding: $base-font-size * .6;
padding-left: 1em;

&.active:hover {
background-color: $background-grey;
cursor: pointer;
}

&.inactive {
color: darken($header-grey, 20);
font-style: italic;
}
}
}

.livesearch-user-email {
color: $medium-grey;
font-style: italic;
padding-right: .2em;
}
}
Loading

0 comments on commit 0e353c5

Please sign in to comment.