edx-modulestore
Advanced tools
Comparing version 0.0.8 to 0.0.9
@@ -5,4 +5,6 @@ var Q = require('q'); | ||
var utils = require('./utils'); | ||
var Module = require('./models/module'); | ||
var Organization = require('./organization'); | ||
var About = require('./about'); | ||
@@ -14,7 +16,3 @@ | ||
var Course = function (modulestore, model, organization) { | ||
if (!modulestore) { | ||
throw new Error('course: modulestore is required'); | ||
} | ||
var Course = function (modulestore, model) { | ||
if (!model) { | ||
@@ -24,4 +22,2 @@ throw new Error('course: model cannot be null'); | ||
this.organization = organization; | ||
this._modulestore = modulestore; | ||
@@ -33,3 +29,70 @@ this._model = model; | ||
/* | ||
** Static methods | ||
*/ | ||
Course.find = function (modulestore, filter) { | ||
if (!modulestore) { | ||
throw new Error('course: modulestore is required'); | ||
} | ||
var deferred = Q.defer(); | ||
Module(modulestore.connection).find(_.merge(filter || {}, { | ||
'_id.category': 'course' | ||
}), function (err, models) { | ||
if (err) { | ||
deferred.reject(new Error(err)); | ||
} | ||
else { | ||
var courses = _.map(models, function (model) { | ||
return new Course(modulestore, model); | ||
}); | ||
Q.allSettled( | ||
_.map(courses, function (course) { | ||
return course._fetchAboutFields(); | ||
}) | ||
).then(function () { | ||
deferred.resolve(courses); | ||
}); | ||
} | ||
}); | ||
return deferred.promise; | ||
} | ||
Course.findById = function (modulestore, id) { | ||
if (!modulestore) { | ||
throw new Error('course: modulestore is required'); | ||
} | ||
var deferred = Q.defer(); | ||
var elements = id.split('/'); | ||
if (elements.length !== 3) { | ||
deferred.reject(new Error('Invalid course ID')); | ||
} | ||
else { | ||
Module(modulestore.connection).findOne({ | ||
'_id.org': elements[0], | ||
'_id.course': elements[1], | ||
'_id.name': elements[2] | ||
}, function (err, model) { | ||
if (err) { | ||
deferred.reject(new Error(err)); | ||
} | ||
else { | ||
var course = new Course(modulestore, model); | ||
course._fetchAboutFields().done(function () { | ||
deferred.resolve(course); | ||
}); | ||
} | ||
}); | ||
} | ||
return deferred.promise; | ||
} | ||
/* | ||
@@ -46,11 +109,25 @@ ** Private methods | ||
if (!this.organization) { | ||
this.organization = new Organization( | ||
this._modulestore, | ||
this.get('metadata.display_organization') || this.get('_id.org') | ||
); | ||
} | ||
this.organization = Organization.fromCourse(this._modulestore, this._model); | ||
}; | ||
Course.prototype._fetchAboutFields = function (modulestore) { | ||
var self = this; | ||
var promises = _.map([ | ||
'short_description' | ||
], function (field) { | ||
return About.fetch(self._modulestore, self, field); | ||
}); | ||
return Q.allSettled(promises).then(function (fields) { | ||
self._about = _.reduce(fields, function (result, field) { | ||
if (field.state === 'fulfilled') { | ||
result[field.value.name] = field.value; | ||
} | ||
return result; | ||
}, {}); | ||
}); | ||
}; | ||
/* | ||
@@ -70,6 +147,10 @@ ** Public attributes | ||
Course.prototype.__defineGetter__('shortId', function () { | ||
Course.prototype.__defineGetter__('number', function () { | ||
return this.get('_id.course'); | ||
}); | ||
Course.prototype.__defineGetter__('session', function () { | ||
return this.get('_id.name'); | ||
}); | ||
Course.prototype.__defineGetter__('name', function () { | ||
@@ -80,7 +161,5 @@ return this.get('metadata.display_name'); | ||
Course.prototype.__defineGetter__('description', function () { | ||
var item = _.find(this._about, function (item) { | ||
return item._id.name === 'short_description'; | ||
}); | ||
var about = this._about['short_description']; | ||
return item ? item.get('definition.data.data') : null; | ||
return about ? about.value : null; | ||
}); | ||
@@ -110,7 +189,8 @@ | ||
return this._modulestore.studioBase + '/settings/details/slashes:' + [ | ||
return this._modulestore.studioBase + [ | ||
'/course', | ||
_id.org, | ||
_id.course, | ||
_id.name | ||
].join('+'); | ||
].join('/'); | ||
} | ||
@@ -172,26 +252,2 @@ | ||
Course.prototype.fetchAboutData = function () { | ||
var self = this; | ||
var deferred = Q.defer(); | ||
var _id = this.get('_id'); | ||
Module(this._modulestore.connection).find({ | ||
'_id.tag': _id.tag, | ||
'_id.org': _id.org, | ||
'_id.course': _id.course, | ||
'_id.category': 'about' | ||
}, function (err, values) { | ||
if (err) { | ||
deferred.reject(new Error(err)); | ||
} | ||
else { | ||
self._about = values; | ||
deferred.resolve(); | ||
} | ||
}) | ||
return deferred.promise; | ||
}; | ||
Course.prototype.get = function (key) { | ||
@@ -204,3 +260,4 @@ return this._model.get(key); | ||
id: this.id, | ||
shortId: this.shortId, | ||
number: this.number, | ||
session: this.session, | ||
state: this.state, | ||
@@ -207,0 +264,0 @@ name: this.name, |
@@ -79,37 +79,4 @@ var Q = require('q'); | ||
modulestore.findCourses = function (organization) { | ||
var self = this; | ||
var filter = {}; | ||
var deferred = Q.defer(); | ||
if (organization) { | ||
filter = { | ||
'$or': [ | ||
{ '_id.org': organization.name }, | ||
{ 'metadata.display_organization': organization.name } | ||
] | ||
}; | ||
} | ||
Module(this.connection).find(_.merge(filter, { | ||
'_id.category': 'course' | ||
}), function (err, courses) { | ||
if (err) { | ||
deferred.reject(new Error(err)); | ||
} | ||
else { | ||
var courses = _.map(courses, function (model) { | ||
return new Course(self, model, organization); | ||
}); | ||
var promises = _.map(courses, function (course) { | ||
return course.fetchAboutData(); | ||
}) | ||
Q.all(promises).then(function () { | ||
deferred.resolve(courses); | ||
}); | ||
} | ||
}); | ||
return deferred.promise; | ||
modulestore.findCourses = function (filter) { | ||
return Course.find(this, filter); | ||
}; | ||
@@ -119,28 +86,3 @@ | ||
modulestore.findCourse = function (id) { | ||
var self = this; | ||
var deferred = Q.defer(); | ||
var elements = id.split('/'); | ||
if (elements.length !== 3) { | ||
deferred.reject(new Error('Invalid course ID')); | ||
} | ||
else { | ||
Module(this.connection).findOne({ | ||
'_id.org': elements[0], | ||
'_id.course': elements[1], | ||
'_id.name': elements[2] | ||
}, function (err, course) { | ||
if (err) { | ||
deferred.reject(new Error(err)); | ||
} | ||
else { | ||
var c = new Course(self, course); | ||
c.fetchAboutData().then(function () { | ||
deferred.resolve(c); | ||
}); | ||
} | ||
}); | ||
} | ||
return deferred.promise; | ||
return Course.findById(this, id); | ||
}; | ||
@@ -150,28 +92,3 @@ | ||
modulestore.findOrganizations = function (filter) { | ||
var self = this; | ||
var deferred = Q.defer(); | ||
Module(this.connection).mapReduce({ | ||
query: _.merge(filter || {}, { | ||
'_id.category': 'course' | ||
}), | ||
map: function () { | ||
emit(this.metadata.display_organization || this._id.org, 1); | ||
}, | ||
reduce: function (k, v) { | ||
return v.length; | ||
} | ||
}, function (err, organizations) { | ||
if (err) { | ||
deferred.reject(new Error(err)); | ||
} | ||
else { | ||
deferred.resolve(_.map(organizations, function (organization) { | ||
var o = new Organization(self, organization._id); | ||
o.coursesCount = organization.value; | ||
return o; | ||
})); | ||
} | ||
}); | ||
return deferred.promise; | ||
return Organization.find(this, filter); | ||
}; | ||
@@ -178,0 +95,0 @@ |
@@ -0,4 +1,6 @@ | ||
var Q = require('q'); | ||
var _ = require('lodash'); | ||
var util = require('util'); | ||
var Module = require('./models/module'); | ||
@@ -9,3 +11,3 @@ /* | ||
var Organization = function (modulestore, name) { | ||
var Organization = function (modulestore, model) { | ||
if (!modulestore) { | ||
@@ -15,9 +17,51 @@ throw new Error('organization: modulestore is required'); | ||
if (!name) { | ||
throw new Error('organization: name cannot be null'); | ||
if (!model) { | ||
throw new Error('organization: model cannot be null'); | ||
} | ||
model.names = _.filter(model.names, function (name) { | ||
return !!name; | ||
}); | ||
this._modulestore = modulestore; | ||
this._model = model; | ||
} | ||
this.name = name; | ||
/* | ||
** Static methods | ||
*/ | ||
Organization.find = function (modulestore, filter) { | ||
if (!modulestore) { | ||
throw new Error('organization: modulestore is required'); | ||
} | ||
var deferred = Q.defer(); | ||
Module(modulestore.connection).aggregate([ | ||
{ $match: _.merge(filter || {}, { '_id.category':'course' }) }, | ||
{ $project: { '_id': true, 'name': '$metadata.display_organization' } }, | ||
{ $group: { '_id': '$_id.org', names: { $addToSet: '$name' } } } | ||
], function (err, models) { | ||
if (err) { | ||
deferred.reject(new Error(err)); | ||
} | ||
else { | ||
deferred.resolve(_.map(models, function (model) { | ||
return new Organization(modulestore, model); | ||
})); | ||
} | ||
}); | ||
return deferred.promise; | ||
}; | ||
Organization.fromCourse = function (modulestore, course) { | ||
return new Organization(modulestore, { | ||
_id: course.get('_id.org'), | ||
names: [ | ||
course.get('metadata.display_organization') | ||
] | ||
}); | ||
} | ||
@@ -30,4 +74,11 @@ | ||
Organization.prototype.__defineGetter__('id', function () { | ||
return this._model._id; | ||
}); | ||
Organization.prototype.__defineGetter__('name', function () { | ||
return this._model.names.length ? this._model.names[0] : null; | ||
}); | ||
/* | ||
@@ -37,4 +88,10 @@ ** Public methods | ||
Organization.prototype.get = function (key) { | ||
return this._model[key]; | ||
}; | ||
Organization.prototype.findCourses = function (filter) { | ||
return this._modulestore.findCourses(this); | ||
return this._modulestore.findCourses({ | ||
'_id.org': this.id | ||
}); | ||
}; | ||
@@ -44,4 +101,4 @@ | ||
return { | ||
name: this.name, | ||
coursesCount: this.coursesCount | ||
id: this.id, | ||
name: this.name | ||
}; | ||
@@ -57,7 +114,6 @@ } | ||
Organization.prototype.toString = function () { | ||
return this.name; | ||
return this.name || this.id; | ||
} | ||
/* | ||
@@ -64,0 +120,0 @@ ** Exports |
{ | ||
"name": "edx-modulestore", | ||
"version": "0.0.8", | ||
"version": "0.0.9", | ||
"description": "Easy browsing of Open edX modulestores", | ||
@@ -5,0 +5,0 @@ "author": "Bertrand Marron", |
15949
12
502