diff --git a/assets_helper.py b/assets_helper.py
index 681362cc0..dec694f1d 100644
--- a/assets_helper.py
+++ b/assets_helper.py
@@ -28,7 +28,7 @@ def is_active(asset, at_time=None):
if asset['is_enabled'] and asset['start_date'] and asset['end_date']:
at = at_time or get_time()
- return asset['start_date'] < at and asset['end_date'] > at
+ return asset['start_date'] <= at <= asset['end_date']
return False
diff --git a/static/coffee/specs/screenly-spec.coffee b/static/coffee/specs/screenly-spec.coffee
index f2f0efcb1..a37e7dc43 100644
--- a/static/coffee/specs/screenly-spec.coffee
+++ b/static/coffee/specs/screenly-spec.coffee
@@ -1,76 +1,113 @@
describe "Screenly Open Source", ->
- it "should have a screenly object at its root", ->
- expect(screenly).toBeDefined()
-
- it "should have an instance of Assets on the screenly object", ->
- expect(screenly.Assets).toBeDefined()
- expect(screenly.Assets).toEqual jasmine.any(screenly.collections.Assets)
- expect(screenly.ActiveAssets).toEqual jasmine.any(screenly.collections.ActiveAssets)
- expect(screenly.InactiveAssets).toEqual jasmine.any(screenly.collections.InactiveAssets)
-
- describe "Models", ->
-
- it "should exist", ->
- expect(screenly.models).toBeDefined()
+ it "should have a Screenly object at its root", ->
+ expect(Screenly).toBeDefined()
- describe "Asset model", ->
- it "should exist", ->
- expect(screenly.models.Asset).toBeDefined()
- describe "Collections", ->
+ describe "date_to", ->
- it "should exist", ->
- expect(screenly.collections).toBeDefined()
+ test_date = new Date(2014, 5, 6, 14, 20, 0, 0);
+ a_date = Screenly.date_to(test_date);
- describe "Assets", ->
- it "should exist", ->
- expect(screenly.collections.Assets).toBeDefined()
- expect(screenly.collections.ActiveAssets).toBeDefined()
- expect(screenly.collections.InactiveAssets).toBeDefined()
+ it "should format date and time as 'MM/DD/YYYY hh:mm:ss A'", ->
+ expect(a_date.string()).toBe '06/06/2014 02:20:00 PM'
+
+ it "should format date as 'MM/a_date/YYYY'", ->
+ expect(a_date.date()).toBe '06/06/2014'
+
+ it "should format date as 'hh:mm:ss A'", ->
+ expect(a_date.time()).toBe '02:20 PM'
- it "should use the Asset model", ->
- assets = new screenly.collections.Assets()
- expect(assets.model).toBe screenly.models.Asset
- it "should populate ActiveAssets and InactiveAssets when fetched", ->
- screenly.Assets.reset [
- {name: "zacharytamas.com", mimetype:"webpage", is_active: true},
- ]
+ describe "Models", ->
- # ActiveAssets should have one model now
- expect(screenly.ActiveAssets.models.length).toEqual 1
+ describe "Asset model", ->
+ it "should exist", ->
+ expect(Screenly.Asset).toBeDefined()
+
+ start_date = new Date(2014, 4, 6, 14, 20, 0, 0);
+ end_date = new Date();
+ end_date.setMonth(end_date.getMonth() + 2)
+ asset = new Screenly.Asset({
+ asset_id: 2
+ duration: "8"
+ end_date: end_date
+ is_enabled: true
+ mimetype: 'webpage'
+ name: 'Test'
+ start_date: start_date
+ uri: 'http://www.screenlyapp.com'
+ })
+
+ it "should be active if enabled and date is in range", ->
+ expect(asset.active()).toBe true
+
+ it "should be inactive if disabled and date is in range", ->
+ asset.set 'is_enabled', false
+ expect(asset.active()).toBe false
+
+ it "should be inactive if enabled and date is out of range", ->
+ asset.set 'is_enabled', true
+ asset.set 'start_date', asset.get 'end_date'
+ expect(asset.active()).toBe false
+
+ it "should rollback to backup data if it exists", ->
+
+ asset.set 'start_date', start_date
+ asset.set 'end_date', end_date
+ asset.backup()
+
+ asset.set({
+ is_enabled: false
+ name: "Test 2"
+ start_date: new Date(2011, 4, 6, 14, 20, 0, 0)
+ end_date: new Date(2011, 4, 6, 14, 20, 0, 0)
+ uri: "http://www.wireload.net"
+ })
+
+ asset.rollback()
+
+ expect(asset.get 'is_enabled').toBe true
+ expect(asset.get 'name').toBe 'Test'
+ expect(asset.get 'start_date').toBe start_date
+ expect(asset.get 'uri').toBe "http://www.screenlyapp.com"
+
+ it "should erase backup date after rollback", ->
+ asset.set({
+ is_enabled: false
+ name: "Test 2"
+ start_date: new Date(2011, 4, 6, 14, 20, 0, 0)
+ end_date: new Date(2011, 4, 6, 14, 20, 0, 0)
+ uri: "http://www.wireload.net"
+ })
+
+ asset.rollback()
+
+ expect(asset.get 'is_enabled').toBe false
+ expect(asset.get 'name').toBe 'Test 2'
+ expect(asset.get('start_date').toISOString()).toBe (new Date(2011, 4, 6, 14, 20, 0, 0)).toISOString()
+ expect(asset.get 'uri').toBe "http://www.wireload.net"
- # InactiveAssets should still be empty
- expect(screenly.InactiveAssets.models.length).toEqual 0
- # Now make the page inactive and confirm that ActiveAssets
- # is empty (the previous information is wiped away on a
- # new data load) and the InactiveAssets collection contains
- # the new asset.
+ describe "Collections", ->
- screenly.Assets.reset [
- {name: "zacharytamas.com", mimetype:"webpage", is_active: false},
- ]
+ describe "Assets", ->
+ it "should exist", ->
+ expect(Screenly.Assets).toBeDefined()
- # ActiveAssets should be empty now
- expect(screenly.ActiveAssets.models.length).toEqual 0
+ it "should use the Asset model", ->
+ assets = new Screenly.Assets()
+ expect(assets.model).toBe Screenly.Asset
- # InactiveAssets should have a model
- expect(screenly.InactiveAssets.models.length).toEqual 1
- screenly.Assets.reset [
- {name: "zacharytamas.com", mimetype:"webpage", is_active: false},
- {name: "Hacker News", mimetype: "webpage", is_active: true}
- ]
+ describe "Views", ->
- # They should both have a model now
- expect(screenly.ActiveAssets.models.length).toEqual 1
- expect(screenly.InactiveAssets.models.length).toEqual 1
- expect(screenly.Assets.models.length).toEqual 2
+ it "should have EditAssetView", ->
+ expect(Screenly.View.EditAssetView).toBeDefined()
- describe "Views", ->
+ it "should have AssetRowView", ->
+ expect(Screenly.View.AssetRowView).toBeDefined()
- it "should exist", ->
- expect(screenly.views).toBeDefined()
+ it "should have AssetsView", ->
+ expect(Screenly.View.AssetsView).toBeDefined()
\ No newline at end of file
diff --git a/static/js/main.js b/static/js/main.js
new file mode 100644
index 000000000..fd5dbaedf
--- /dev/null
+++ b/static/js/main.js
@@ -0,0 +1,5 @@
+jQuery(function() {
+ Screenly.app = new Screenly.App({
+ el: $('body')
+ });
+});
diff --git a/static/js/screenly-ose.coffee b/static/js/screenly-ose.coffee
index ccee8244e..a8115da1c 100644
--- a/static/js/screenly-ose.coffee
+++ b/static/js/screenly-ose.coffee
@@ -34,11 +34,29 @@ API.Asset = class Asset extends Backbone.Model
name: ''
mimetype: 'webpage'
uri: ''
+ is_active: false
start_date: now()
end_date: (moment().add 'days', 7).toDate()
duration: default_duration
is_enabled: 0
nocache: 0
+ active: =>
+ if @get('is_enabled') and @get('start_date') and @get('end_date')
+ at = now()
+ start_date = new Date(@get('start_date'));
+ end_date = new Date(@get('end_date'));
+ return start_date <= at <= end_date
+ else
+ return false
+
+ backup: =>
+ @backup_attributes = @toJSON()
+
+ rollback: =>
+ if @backup_attributes
+ @set @backup_attributes
+ @backup_attributes = undefined
+
API.Assets = class Assets extends Backbone.Collection
url: "/api/assets"
@@ -46,7 +64,8 @@ API.Assets = class Assets extends Backbone.Collection
# Views
-class EditAssetView extends Backbone.View
+API.View = {};
+API.View.EditAssetView = class EditAssetView extends Backbone.View
$f: (field) => @$ "[name='#{field}']" # get field element
$fv: (field, val...) => (@$f field).val val... # get or set filed value
@@ -59,7 +78,11 @@ class EditAssetView extends Backbone.View
(@$ 'input[name="nocache"]').prop 'checked', @model.get 'nocache'
(@$ '.modal-header .close').remove()
(@$el.children ":first").modal()
+
+ @model.backup()
+
@model.bind 'change', @render
+
@render()
@validate()
_.delay (=> (@$f 'uri').focus()), 300
@@ -179,7 +202,7 @@ class EditAssetView extends Backbone.View
cancel: (e) =>
- @model.set @model.previousAttributes()
+ @model.rollback()
unless @edit then @model.destroy()
(@$el.children ":first").modal 'hide'
@@ -224,7 +247,7 @@ class EditAssetView extends Backbone.View
(@$ '.advanced-accordion').toggle has_nocache is on
-class AssetRowView extends Backbone.View
+API.View.AssetRowView = class AssetRowView extends Backbone.View
tagName: "tr"
initialize: (options) =>
@@ -296,7 +319,7 @@ class AssetRowView extends Backbone.View
no
-class AssetsView extends Backbone.View
+API.View.AssetsView = class AssetsView extends Backbone.View
initialize: (options) =>
@collection.bind event, @render for event in ('reset add remove sync'.split ' ')
@sorted = (@$ '#active-assets').sortable
@@ -312,7 +335,7 @@ class AssetsView extends Backbone.View
(@$ "##{which}-assets").html '' for which in ['active', 'inactive']
@collection.each (model) =>
- which = if model.get 'is_active' then 'active' else 'inactive'
+ which = if model.active() then 'active' else 'inactive'
(@$ "##{which}-assets").append (new AssetRowView model: model).render()
for which in ['inactive', 'active']
@@ -347,6 +370,3 @@ API.App = class App extends Backbone.View
new Asset {}, {collection: API.assets}
no
-
-jQuery -> API.app = new App el: $ 'body'
-
diff --git a/static/js/screenly-ose.js b/static/js/screenly-ose.js
index 8320ce930..7df11ff15 100644
--- a/static/js/screenly-ose.js
+++ b/static/js/screenly-ose.js
@@ -1,14 +1,11 @@
-//@ sourceMappingURL=screenly-ose.map
-// Generated by CoffeeScript 1.6.1
-
-/* screenly-ose ui
-*/
+// Generated by CoffeeScript 1.7.1
+/* screenly-ose ui */
(function() {
var API, App, Asset, AssetRowView, Assets, AssetsView, EditAssetView, date_to, delay, get_filename, get_mimetype, get_template, insertWbr, mimetypes, now, url_test,
- _this = this,
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
+ __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
__slice = [].slice;
@@ -45,18 +42,20 @@
mimetypes = [['jpg jpeg png pnm gif bmp'.split(' '), 'image'], ['avi mkv mov mpg mpeg mp4 ts flv'.split(' '), 'video']];
- get_mimetype = function(filename) {
- var ext, mt;
- ext = (_.last(filename.split('.'))).toLowerCase();
- mt = _.find(mimetypes, function(mt) {
- return __indexOf.call(mt[0], ext) >= 0;
- });
- if (mt) {
- return mt[1];
- } else {
- return null;
- }
- };
+ get_mimetype = (function(_this) {
+ return function(filename) {
+ var ext, mt;
+ ext = (_.last(filename.split('.'))).toLowerCase();
+ mt = _.find(mimetypes, function(mt) {
+ return __indexOf.call(mt[0], ext) >= 0;
+ });
+ if (mt) {
+ return mt[1];
+ } else {
+ return null;
+ }
+ };
+ })(this);
url_test = function(v) {
return /(http|https):\/\/[\w-]+(\.?[\w-]+)+([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])?/.test(v);
@@ -73,14 +72,13 @@
Backbone.emulateJSON = true;
API.Asset = Asset = (function(_super) {
-
__extends(Asset, _super);
function Asset() {
- var _this = this;
- this.defaults = function() {
- return Asset.prototype.defaults.apply(_this, arguments);
- };
+ this.rollback = __bind(this.rollback, this);
+ this.backup = __bind(this.backup, this);
+ this.active = __bind(this.active, this);
+ this.defaults = __bind(this.defaults, this);
return Asset.__super__.constructor.apply(this, arguments);
}
@@ -93,6 +91,7 @@
name: '',
mimetype: 'webpage',
uri: '',
+ is_active: false,
start_date: now(),
end_date: (moment().add('days', 7)).toDate(),
duration: default_duration,
@@ -101,12 +100,34 @@
};
};
+ Asset.prototype.active = function() {
+ var at, end_date, start_date;
+ if (this.get('is_enabled') && this.get('start_date') && this.get('end_date')) {
+ at = now();
+ start_date = new Date(this.get('start_date'));
+ end_date = new Date(this.get('end_date'));
+ return (start_date <= at && at <= end_date);
+ } else {
+ return false;
+ }
+ };
+
+ Asset.prototype.backup = function() {
+ return this.backup_attributes = this.toJSON();
+ };
+
+ Asset.prototype.rollback = function() {
+ if (this.backup_attributes) {
+ this.set(this.backup_attributes);
+ return this.backup_attributes = void 0;
+ }
+ };
+
return Asset;
})(Backbone.Model);
API.Assets = Assets = (function(_super) {
-
__extends(Assets, _super);
function Assets() {
@@ -121,62 +142,28 @@
})(Backbone.Collection);
- EditAssetView = (function(_super) {
+ API.View = {};
+ API.View.EditAssetView = EditAssetView = (function(_super) {
__extends(EditAssetView, _super);
function EditAssetView() {
- var _this = this;
- this.displayAdvanced = function() {
- return EditAssetView.prototype.displayAdvanced.apply(_this, arguments);
- };
- this.toggleAdvanced = function() {
- return EditAssetView.prototype.toggleAdvanced.apply(_this, arguments);
- };
- this.updateMimetype = function(filename) {
- return EditAssetView.prototype.updateMimetype.apply(_this, arguments);
- };
- this.updateFileUploadMimetype = function() {
- return EditAssetView.prototype.updateFileUploadMimetype.apply(_this, arguments);
- };
- this.updateUriMimetype = function() {
- return EditAssetView.prototype.updateUriMimetype.apply(_this, arguments);
- };
- this.clickTabNavUpload = function(e) {
- return EditAssetView.prototype.clickTabNavUpload.apply(_this, arguments);
- };
- this.clickTabNavUri = function(e) {
- return EditAssetView.prototype.clickTabNavUri.apply(_this, arguments);
- };
- this.cancel = function(e) {
- return EditAssetView.prototype.cancel.apply(_this, arguments);
- };
- this.validate = function(e) {
- return EditAssetView.prototype.validate.apply(_this, arguments);
- };
- this.change = function(e) {
- return EditAssetView.prototype.change.apply(_this, arguments);
- };
- this.save = function(e) {
- return EditAssetView.prototype.save.apply(_this, arguments);
- };
- this.viewmodel = function() {
- return EditAssetView.prototype.viewmodel.apply(_this, arguments);
- };
- this.render = function() {
- return EditAssetView.prototype.render.apply(_this, arguments);
- };
- this.initialize = function(options) {
- return EditAssetView.prototype.initialize.apply(_this, arguments);
- };
- this.$fv = function() {
- var field, val;
- field = arguments[0], val = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
- return EditAssetView.prototype.$fv.apply(_this, arguments);
- };
- this.$f = function(field) {
- return EditAssetView.prototype.$f.apply(_this, arguments);
- };
+ this.displayAdvanced = __bind(this.displayAdvanced, this);
+ this.toggleAdvanced = __bind(this.toggleAdvanced, this);
+ this.updateMimetype = __bind(this.updateMimetype, this);
+ this.updateFileUploadMimetype = __bind(this.updateFileUploadMimetype, this);
+ this.updateUriMimetype = __bind(this.updateUriMimetype, this);
+ this.clickTabNavUpload = __bind(this.clickTabNavUpload, this);
+ this.clickTabNavUri = __bind(this.clickTabNavUri, this);
+ this.cancel = __bind(this.cancel, this);
+ this.validate = __bind(this.validate, this);
+ this.change = __bind(this.change, this);
+ this.save = __bind(this.save, this);
+ this.viewmodel = __bind(this.viewmodel, this);
+ this.render = __bind(this.render, this);
+ this.initialize = __bind(this.initialize, this);
+ this.$fv = __bind(this.$fv, this);
+ this.$f = __bind(this.$f, this);
return EditAssetView.__super__.constructor.apply(this, arguments);
}
@@ -191,7 +178,6 @@
};
EditAssetView.prototype.initialize = function(options) {
- var _this = this;
this.edit = options.edit;
($('body')).append(this.$el.html(get_template('asset-modal')));
(this.$('input.time')).timepicker({
@@ -203,12 +189,15 @@
(this.$('input[name="nocache"]')).prop('checked', this.model.get('nocache'));
(this.$('.modal-header .close')).remove();
(this.$el.children(":first")).modal();
+ this.model.backup();
this.model.bind('change', this.render);
this.render();
this.validate();
- _.delay((function() {
- return (_this.$f('uri')).focus();
- }), 300);
+ _.delay(((function(_this) {
+ return function() {
+ return (_this.$f('uri')).focus();
+ };
+ })(this)), 300);
return false;
};
@@ -287,8 +276,7 @@
};
EditAssetView.prototype.save = function(e) {
- var save,
- _this = this;
+ var save;
e.preventDefault();
this.viewmodel();
save = null;
@@ -300,11 +288,13 @@
(this.$('.progress')).show();
this.$el.fileupload({
url: this.model.url(),
- progressall: function(e, data) {
- if (data.loaded && data.total) {
- return (_this.$('.progress .bar')).css('width', "" + (data.loaded / data.total * 100) + "%");
- }
- }
+ progressall: (function(_this) {
+ return function(e, data) {
+ if (data.loaded && data.total) {
+ return (_this.$('.progress .bar')).css('width', "" + (data.loaded / data.total * 100) + "%");
+ }
+ };
+ })(this)
});
save = this.$el.fileupload('send', {
fileInput: this.$f('file_upload')
@@ -328,60 +318,72 @@
save = this.model.save();
}
(this.$('input, select')).prop('disabled', true);
- save.done(function(data) {
- _this.model.id = data.asset_id;
- if (!_this.model.collection) {
- _this.collection.add(_this.model);
- }
- (_this.$el.children(":first")).modal('hide');
- _.extend(_this.model.attributes, data);
- if (!_this.edit) {
- return _this.model.collection.add(_this.model);
- }
- });
- save.fail(function() {
- (_this.$('.progress')).hide();
- return (_this.$('input, select')).prop('disabled', false);
- });
+ save.done((function(_this) {
+ return function(data) {
+ _this.model.id = data.asset_id;
+ if (!_this.model.collection) {
+ _this.collection.add(_this.model);
+ }
+ (_this.$el.children(":first")).modal('hide');
+ _.extend(_this.model.attributes, data);
+ if (!_this.edit) {
+ return _this.model.collection.add(_this.model);
+ }
+ };
+ })(this));
+ save.fail((function(_this) {
+ return function() {
+ (_this.$('.progress')).hide();
+ return (_this.$('input, select')).prop('disabled', false);
+ };
+ })(this));
return false;
};
EditAssetView.prototype.change = function(e) {
- var _this = this;
- this._change || (this._change = _.throttle((function() {
- _this.viewmodel();
- _this.model.trigger('change');
- _this.validate();
- return true;
- }), 500));
+ this._change || (this._change = _.throttle(((function(_this) {
+ return function() {
+ _this.viewmodel();
+ _this.model.trigger('change');
+ _this.validate();
+ return true;
+ };
+ })(this)), 500));
return this._change.apply(this, arguments);
};
EditAssetView.prototype.validate = function(e) {
- var errors, field, fn, that, v, validators, _i, _len, _ref, _results,
- _this = this;
+ var errors, field, fn, that, v, validators, _i, _len, _ref, _results;
that = this;
validators = {
- duration: function(v) {
- if (('video' !== _this.model.get('mimetype')) && (!(_.isNumber(v * 1)) || v * 1 < 1)) {
- return 'please enter a valid number';
- }
- },
- uri: function(v) {
- if (_this.model.isNew() && ((that.$('#tab-uri')).hasClass('active')) && !url_test(v)) {
- return 'please enter a valid URL';
- }
- },
- file_upload: function(v) {
- if (_this.model.isNew() && !v && !(that.$('#tab-uri')).hasClass('active')) {
- return 'please select a file';
- }
- },
- end_date: function(v) {
- if (!((new Date(_this.$fv('start_date'))) < (new Date(_this.$fv('end_date'))))) {
- return 'end date should be after start date';
- }
- }
+ duration: (function(_this) {
+ return function(v) {
+ if (('video' !== _this.model.get('mimetype')) && (!(_.isNumber(v * 1)) || v * 1 < 1)) {
+ return 'please enter a valid number';
+ }
+ };
+ })(this),
+ uri: (function(_this) {
+ return function(v) {
+ if (_this.model.isNew() && ((that.$('#tab-uri')).hasClass('active')) && !url_test(v)) {
+ return 'please enter a valid URL';
+ }
+ };
+ })(this),
+ file_upload: (function(_this) {
+ return function(v) {
+ if (_this.model.isNew() && !v && !(that.$('#tab-uri')).hasClass('active')) {
+ return 'please select a file';
+ }
+ };
+ })(this),
+ end_date: (function(_this) {
+ return function(v) {
+ if (!((new Date(_this.$fv('start_date'))) < (new Date(_this.$fv('end_date'))))) {
+ return 'end date should be after start date';
+ }
+ };
+ })(this)
};
errors = (function() {
var _results;
@@ -408,7 +410,7 @@
};
EditAssetView.prototype.cancel = function(e) {
- this.model.set(this.model.previousAttributes());
+ this.model.rollback();
if (!this.edit) {
this.model.destroy();
}
@@ -442,17 +444,19 @@
};
EditAssetView.prototype.updateUriMimetype = function() {
- var _this = this;
- return _.defer(function() {
- return _this.updateMimetype(_this.$fv('uri'));
- });
+ return _.defer((function(_this) {
+ return function() {
+ return _this.updateMimetype(_this.$fv('uri'));
+ };
+ })(this));
};
EditAssetView.prototype.updateFileUploadMimetype = function() {
- var _this = this;
- return _.defer(function() {
- return _this.updateMimetype(_this.$fv('file_upload'));
- });
+ return _.defer((function(_this) {
+ return function() {
+ return _this.updateMimetype(_this.$fv('file_upload'));
+ };
+ })(this));
};
EditAssetView.prototype.updateMimetype = function(filename) {
@@ -483,36 +487,18 @@
})(Backbone.View);
- AssetRowView = (function(_super) {
-
+ API.View.AssetRowView = AssetRowView = (function(_super) {
__extends(AssetRowView, _super);
function AssetRowView() {
- var _this = this;
- this.hidePopover = function() {
- return AssetRowView.prototype.hidePopover.apply(_this, arguments);
- };
- this.showPopover = function() {
- return AssetRowView.prototype.showPopover.apply(_this, arguments);
- };
- this["delete"] = function(e) {
- return AssetRowView.prototype.delete.apply(_this, arguments);
- };
- this.edit = function(e) {
- return AssetRowView.prototype.edit.apply(_this, arguments);
- };
- this.setEnabled = function(enabled) {
- return AssetRowView.prototype.setEnabled.apply(_this, arguments);
- };
- this.toggleIsEnabled = function(e) {
- return AssetRowView.prototype.toggleIsEnabled.apply(_this, arguments);
- };
- this.render = function() {
- return AssetRowView.prototype.render.apply(_this, arguments);
- };
- this.initialize = function(options) {
- return AssetRowView.prototype.initialize.apply(_this, arguments);
- };
+ this.hidePopover = __bind(this.hidePopover, this);
+ this.showPopover = __bind(this.showPopover, this);
+ this["delete"] = __bind(this["delete"], this);
+ this.edit = __bind(this.edit, this);
+ this.setEnabled = __bind(this.setEnabled, this);
+ this.toggleIsEnabled = __bind(this.toggleIsEnabled, this);
+ this.render = __bind(this.render, this);
+ this.initialize = __bind(this.initialize, this);
return AssetRowView.__super__.constructor.apply(this, arguments);
}
@@ -556,24 +542,27 @@
};
AssetRowView.prototype.toggleIsEnabled = function(e) {
- var save, val,
- _this = this;
+ var save, val;
val = (1 + this.model.get('is_enabled')) % 2;
this.model.set({
is_enabled: val
});
this.setEnabled(false);
save = this.model.save();
- save.done(function() {
- return _this.setEnabled(true);
- });
- save.fail(function() {
- _this.model.set(_this.model.previousAttributes(), {
- silent: true
- });
- _this.setEnabled(true);
- return _this.render();
- });
+ save.done((function(_this) {
+ return function() {
+ return _this.setEnabled(true);
+ };
+ })(this));
+ save.fail((function(_this) {
+ return function() {
+ _this.model.set(_this.model.previousAttributes(), {
+ silent: true
+ });
+ _this.setEnabled(true);
+ return _this.render();
+ };
+ })(this));
return true;
};
@@ -599,13 +588,14 @@
};
AssetRowView.prototype["delete"] = function(e) {
- var xhr,
- _this = this;
+ var xhr;
this.hidePopover();
if ((xhr = this.model.destroy()) === !false) {
- xhr.done(function() {
- return _this.remove();
- });
+ xhr.done((function(_this) {
+ return function() {
+ return _this.remove();
+ };
+ })(this));
} else {
this.remove();
}
@@ -630,21 +620,13 @@
})(Backbone.View);
- AssetsView = (function(_super) {
-
+ API.View.AssetsView = AssetsView = (function(_super) {
__extends(AssetsView, _super);
function AssetsView() {
- var _this = this;
- this.render = function() {
- return AssetsView.prototype.render.apply(_this, arguments);
- };
- this.update_order = function() {
- return AssetsView.prototype.update_order.apply(_this, arguments);
- };
- this.initialize = function(options) {
- return AssetsView.prototype.initialize.apply(_this, arguments);
- };
+ this.render = __bind(this.render, this);
+ this.update_order = __bind(this.update_order, this);
+ this.initialize = __bind(this.initialize, this);
return AssetsView.__super__.constructor.apply(this, arguments);
}
@@ -670,19 +652,20 @@
};
AssetsView.prototype.render = function() {
- var which, _i, _j, _len, _len1, _ref, _ref1,
- _this = this;
+ var which, _i, _j, _len, _len1, _ref, _ref1;
_ref = ['active', 'inactive'];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
which = _ref[_i];
(this.$("#" + which + "-assets")).html('');
}
- this.collection.each(function(model) {
- which = model.get('is_active') ? 'active' : 'inactive';
- return (_this.$("#" + which + "-assets")).append((new AssetRowView({
- model: model
- })).render());
- });
+ this.collection.each((function(_this) {
+ return function(model) {
+ which = model.active() ? 'active' : 'inactive';
+ return (_this.$("#" + which + "-assets")).append((new AssetRowView({
+ model: model
+ })).render());
+ };
+ })(this));
_ref1 = ['inactive', 'active'];
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
which = _ref1[_j];
@@ -702,32 +685,29 @@
})(Backbone.View);
API.App = App = (function(_super) {
-
__extends(App, _super);
function App() {
- var _this = this;
- this.add = function(e) {
- return App.prototype.add.apply(_this, arguments);
- };
- this.initialize = function() {
- return App.prototype.initialize.apply(_this, arguments);
- };
+ this.add = __bind(this.add, this);
+ this.initialize = __bind(this.initialize, this);
return App.__super__.constructor.apply(this, arguments);
}
App.prototype.initialize = function() {
- var _this = this;
- ($(window)).ajaxError(function(e, r) {
- var err, j;
- ($('#request-error')).html((get_template('request-error'))());
- if ((j = $.parseJSON(r.responseText)) && (err = j.error)) {
- return ($('#request-error .msg')).text('Server Error: ' + err);
- }
- });
- ($(window)).ajaxSuccess(function(data) {
- return ($('#request-error')).html('');
- });
+ ($(window)).ajaxError((function(_this) {
+ return function(e, r) {
+ var err, j;
+ ($('#request-error')).html((get_template('request-error'))());
+ if ((j = $.parseJSON(r.responseText)) && (err = j.error)) {
+ return ($('#request-error .msg')).text('Server Error: ' + err);
+ }
+ };
+ })(this));
+ ($(window)).ajaxSuccess((function(_this) {
+ return function(data) {
+ return ($('#request-error')).html('');
+ };
+ })(this));
(API.assets = new Assets()).fetch();
return API.assetsView = new AssetsView({
collection: API.assets,
@@ -752,10 +732,4 @@
})(Backbone.View);
- jQuery(function() {
- return API.app = new App({
- el: $('body')
- });
- });
-
}).call(this);
diff --git a/static/spec/runner.html b/static/spec/runner.html
index 6384f6f9d..fd24f13e0 100644
--- a/static/spec/runner.html
+++ b/static/spec/runner.html
@@ -8,9 +8,18 @@
+
+
-
+
+
+
+
+
+
diff --git a/static/spec/screenly-spec.js b/static/spec/screenly-spec.js
index 65ec9eed8..ef3c9956f 100644
--- a/static/spec/screenly-spec.js
+++ b/static/spec/screenly-spec.js
@@ -1,2 +1,110 @@
-// Generated by CoffeeScript 1.4.0
-(function(){describe("Screenly Open Source",function(){it("should have a screenly object at its root",function(){return expect(screenly).toBeDefined()});it("should have an instance of Assets on the screenly object",function(){expect(screenly.Assets).toBeDefined();expect(screenly.Assets).toEqual(jasmine.any(screenly.collections.Assets));expect(screenly.ActiveAssets).toEqual(jasmine.any(screenly.collections.ActiveAssets));return expect(screenly.InactiveAssets).toEqual(jasmine.any(screenly.collections.InactiveAssets))});describe("Models",function(){it("should exist",function(){return expect(screenly.models).toBeDefined()});return describe("Asset model",function(){return it("should exist",function(){return expect(screenly.models.Asset).toBeDefined()})})});describe("Collections",function(){it("should exist",function(){return expect(screenly.collections).toBeDefined()});return describe("Assets",function(){it("should exist",function(){expect(screenly.collections.Assets).toBeDefined();expect(screenly.collections.ActiveAssets).toBeDefined();return expect(screenly.collections.InactiveAssets).toBeDefined()});it("should use the Asset model",function(){var e;e=new screenly.collections.Assets;return expect(e.model).toBe(screenly.models.Asset)});return it("should populate ActiveAssets and InactiveAssets when fetched",function(){screenly.Assets.reset([{name:"zacharytamas.com",mimetype:"webpage",is_active:!0}]);expect(screenly.ActiveAssets.models.length).toEqual(1);expect(screenly.InactiveAssets.models.length).toEqual(0);screenly.Assets.reset([{name:"zacharytamas.com",mimetype:"webpage",is_active:!1}]);expect(screenly.ActiveAssets.models.length).toEqual(0);expect(screenly.InactiveAssets.models.length).toEqual(1);screenly.Assets.reset([{name:"zacharytamas.com",mimetype:"webpage",is_active:!1},{name:"Hacker News",mimetype:"webpage",is_active:!0}]);expect(screenly.ActiveAssets.models.length).toEqual(1);expect(screenly.InactiveAssets.models.length).toEqual(1);return expect(screenly.Assets.models.length).toEqual(2)})})});return describe("Views",function(){return it("should exist",function(){return expect(screenly.views).toBeDefined()})})})}).call(this);
\ No newline at end of file
+// Generated by CoffeeScript 1.7.1
+(function() {
+ describe("Screenly Open Source", function() {
+ it("should have a Screenly object at its root", function() {
+ return expect(Screenly).toBeDefined();
+ });
+ describe("date_to", function() {
+ var a_date, test_date;
+ test_date = new Date(2014, 5, 6, 14, 20, 0, 0);
+ a_date = Screenly.date_to(test_date);
+ it("should format date and time as 'MM/DD/YYYY hh:mm:ss A'", function() {
+ return expect(a_date.string()).toBe('06/06/2014 02:20:00 PM');
+ });
+ it("should format date as 'MM/a_date/YYYY'", function() {
+ return expect(a_date.date()).toBe('06/06/2014');
+ });
+ return it("should format date as 'hh:mm:ss A'", function() {
+ return expect(a_date.time()).toBe('02:20 PM');
+ });
+ });
+ describe("Models", function() {
+ return describe("Asset model", function() {
+ var asset, end_date, start_date;
+ it("should exist", function() {
+ return expect(Screenly.Asset).toBeDefined();
+ });
+ start_date = new Date(2014, 4, 6, 14, 20, 0, 0);
+ end_date = new Date();
+ end_date.setMonth(end_date.getMonth() + 2);
+ asset = new Screenly.Asset({
+ asset_id: 2,
+ duration: "8",
+ end_date: end_date,
+ is_enabled: true,
+ mimetype: 'webpage',
+ name: 'Test',
+ start_date: start_date,
+ uri: 'http://www.screenlyapp.com'
+ });
+ it("should be active if enabled and date is in range", function() {
+ return expect(asset.active()).toBe(true);
+ });
+ it("should be inactive if disabled and date is in range", function() {
+ asset.set('is_enabled', false);
+ return expect(asset.active()).toBe(false);
+ });
+ it("should be inactive if enabled and date is out of range", function() {
+ asset.set('is_enabled', true);
+ asset.set('start_date', asset.get('end_date'));
+ return expect(asset.active()).toBe(false);
+ });
+ it("should rollback to backup data if it exists", function() {
+ asset.set('start_date', start_date);
+ asset.set('end_date', end_date);
+ asset.backup();
+ asset.set({
+ is_enabled: false,
+ name: "Test 2",
+ start_date: new Date(2011, 4, 6, 14, 20, 0, 0),
+ end_date: new Date(2011, 4, 6, 14, 20, 0, 0),
+ uri: "http://www.wireload.net"
+ });
+ asset.rollback();
+ expect(asset.get('is_enabled')).toBe(true);
+ expect(asset.get('name')).toBe('Test');
+ expect(asset.get('start_date')).toBe(start_date);
+ return expect(asset.get('uri')).toBe("http://www.screenlyapp.com");
+ });
+ return it("should erase backup date after rollback", function() {
+ asset.set({
+ is_enabled: false,
+ name: "Test 2",
+ start_date: new Date(2011, 4, 6, 14, 20, 0, 0),
+ end_date: new Date(2011, 4, 6, 14, 20, 0, 0),
+ uri: "http://www.wireload.net"
+ });
+ asset.rollback();
+ expect(asset.get('is_enabled')).toBe(false);
+ expect(asset.get('name')).toBe('Test 2');
+ expect(asset.get('start_date').toISOString()).toBe((new Date(2011, 4, 6, 14, 20, 0, 0)).toISOString());
+ return expect(asset.get('uri')).toBe("http://www.wireload.net");
+ });
+ });
+ });
+ describe("Collections", function() {
+ return describe("Assets", function() {
+ it("should exist", function() {
+ return expect(Screenly.Assets).toBeDefined();
+ });
+ return it("should use the Asset model", function() {
+ var assets;
+ assets = new Screenly.Assets();
+ return expect(assets.model).toBe(Screenly.Asset);
+ });
+ });
+ });
+ return describe("Views", function() {
+ it("should have EditAssetView", function() {
+ return expect(Screenly.View.EditAssetView).toBeDefined();
+ });
+ it("should have AssetRowView", function() {
+ return expect(Screenly.View.AssetRowView).toBeDefined();
+ });
+ return it("should have AssetsView", function() {
+ return expect(Screenly.View.AssetsView).toBeDefined();
+ });
+ });
+ });
+
+}).call(this);
diff --git a/views/index.haml b/views/index.haml
index 967b9afc7..8182eb459 100644
--- a/views/index.haml
+++ b/views/index.haml
@@ -30,6 +30,7 @@
%script(src="/static/js/moment.js")
%script(src="/static/js/screenly-ose.js")
+ %script(src="/static/js/main.js")
%script(type="text/template", id="asset-row-template")
%td.asset_row_name