BLD-1117: Add read-only list of Group Configurations.
This commit is contained in:
20
cms/static/js/collections/group.js
Normal file
20
cms/static/js/collections/group.js
Normal file
@@ -0,0 +1,20 @@
|
||||
define([
|
||||
'backbone', 'js/models/group'
|
||||
],
|
||||
function (Backbone, GroupModel) {
|
||||
'use strict';
|
||||
var GroupCollection = Backbone.Collection.extend({
|
||||
model: GroupModel,
|
||||
/**
|
||||
* Indicates if the collection is empty when all the models are empty
|
||||
* or the collection does not include any models.
|
||||
**/
|
||||
isEmpty: function() {
|
||||
return this.length === 0 || this.every(function(m) {
|
||||
return m.isEmpty();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return GroupCollection;
|
||||
});
|
||||
11
cms/static/js/collections/group_configuration.js
Normal file
11
cms/static/js/collections/group_configuration.js
Normal file
@@ -0,0 +1,11 @@
|
||||
define([
|
||||
'backbone', 'js/models/group_configuration'
|
||||
],
|
||||
function(Backbone, GroupConfigurationModel) {
|
||||
'use strict';
|
||||
var GroupConfigurationCollection = Backbone.Collection.extend({
|
||||
model: GroupConfigurationModel
|
||||
});
|
||||
|
||||
return GroupConfigurationCollection;
|
||||
});
|
||||
29
cms/static/js/models/group.js
Normal file
29
cms/static/js/models/group.js
Normal file
@@ -0,0 +1,29 @@
|
||||
define([
|
||||
'backbone', 'gettext', 'backbone.associations'
|
||||
], function(Backbone, gettext) {
|
||||
'use strict';
|
||||
var Group = Backbone.AssociatedModel.extend({
|
||||
defaults: function() {
|
||||
return { name: '' };
|
||||
},
|
||||
|
||||
isEmpty: function() {
|
||||
return !this.get('name');
|
||||
},
|
||||
|
||||
toJSON: function() {
|
||||
return { name: this.get('name') };
|
||||
},
|
||||
|
||||
validate: function(attrs) {
|
||||
if (!attrs.name) {
|
||||
return {
|
||||
message: gettext('Group name is required'),
|
||||
attributes: { name: true }
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return Group;
|
||||
});
|
||||
87
cms/static/js/models/group_configuration.js
Normal file
87
cms/static/js/models/group_configuration.js
Normal file
@@ -0,0 +1,87 @@
|
||||
define([
|
||||
'backbone', 'underscore', 'gettext', 'js/models/group',
|
||||
'js/collections/group', 'backbone.associations', 'coffee/src/main'
|
||||
],
|
||||
function(Backbone, _, gettext, GroupModel, GroupCollection) {
|
||||
'use strict';
|
||||
var GroupConfiguration = Backbone.AssociatedModel.extend({
|
||||
defaults: function() {
|
||||
return {
|
||||
id: null,
|
||||
name: '',
|
||||
description: '',
|
||||
groups: new GroupCollection([{}, {}]),
|
||||
showGroups: false
|
||||
};
|
||||
},
|
||||
|
||||
relations: [{
|
||||
type: Backbone.Many,
|
||||
key: 'groups',
|
||||
relatedModel: GroupModel,
|
||||
collectionType: GroupCollection
|
||||
}],
|
||||
|
||||
initialize: function() {
|
||||
this.setOriginalAttributes();
|
||||
return this;
|
||||
},
|
||||
|
||||
setOriginalAttributes: function() {
|
||||
this._originalAttributes = this.toJSON();
|
||||
},
|
||||
|
||||
reset: function() {
|
||||
this.set(this._originalAttributes);
|
||||
},
|
||||
|
||||
isDirty: function() {
|
||||
return !_.isEqual(
|
||||
this._originalAttributes, this.toJSON()
|
||||
);
|
||||
},
|
||||
|
||||
isEmpty: function() {
|
||||
return !this.get('name') && this.get('groups').isEmpty();
|
||||
},
|
||||
|
||||
toJSON: function() {
|
||||
return {
|
||||
id: this.get('id'),
|
||||
name: this.get('name'),
|
||||
description: this.get('description'),
|
||||
groups: this.get('groups').toJSON()
|
||||
};
|
||||
},
|
||||
|
||||
validate: function(attrs) {
|
||||
if (!attrs.name) {
|
||||
return {
|
||||
message: gettext('Group Configuration name is required'),
|
||||
attributes: {name: true}
|
||||
};
|
||||
}
|
||||
if (attrs.groups.length === 0) {
|
||||
return {
|
||||
message: gettext('Please add at least one group'),
|
||||
attributes: {groups: true}
|
||||
};
|
||||
} else {
|
||||
// validate all groups
|
||||
var invalidGroups = [];
|
||||
attrs.groups.each(function(group) {
|
||||
if(!group.isValid()) {
|
||||
invalidGroups.push(group);
|
||||
}
|
||||
});
|
||||
if (!_.isEmpty(invalidGroups)) {
|
||||
return {
|
||||
message: gettext('All groups must have a name'),
|
||||
attributes: {groups: invalidGroups}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return GroupConfiguration;
|
||||
});
|
||||
228
cms/static/js/spec/models/group_configuration_spec.js
Normal file
228
cms/static/js/spec/models/group_configuration_spec.js
Normal file
@@ -0,0 +1,228 @@
|
||||
define([
|
||||
'backbone', 'js/models/group_configuration',
|
||||
'js/collections/group_configuration', 'js/models/group',
|
||||
'js/collections/group', 'coffee/src/main'
|
||||
], function(
|
||||
Backbone, GroupConfiguration, GroupConfigurationSet, Group, GroupSet, main
|
||||
) {
|
||||
'use strict';
|
||||
beforeEach(function() {
|
||||
this.addMatchers({
|
||||
toBeInstanceOf: function(expected) {
|
||||
return this.actual instanceof expected;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('GroupConfiguration model', function() {
|
||||
beforeEach(function() {
|
||||
main();
|
||||
this.model = new GroupConfiguration();
|
||||
});
|
||||
|
||||
describe('Basic', function() {
|
||||
it('should have an empty name by default', function() {
|
||||
expect(this.model.get('name')).toEqual('');
|
||||
});
|
||||
|
||||
it('should have an empty description by default', function() {
|
||||
expect(this.model.get('description')).toEqual('');
|
||||
});
|
||||
|
||||
it('should not show groups by default', function() {
|
||||
expect(this.model.get('showGroups')).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should have a GroupSet with two groups by default', function() {
|
||||
var groups = this.model.get('groups');
|
||||
|
||||
expect(groups).toBeInstanceOf(GroupSet);
|
||||
expect(groups.length).toEqual(2);
|
||||
expect(groups.at(0).isEmpty()).toBeTruthy();
|
||||
expect(groups.at(1).isEmpty()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should be empty by default', function() {
|
||||
expect(this.model.isEmpty()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should be able to reset itself', function() {
|
||||
this.model.set('name', 'foobar');
|
||||
this.model.reset();
|
||||
|
||||
expect(this.model.get('name')).toEqual('');
|
||||
});
|
||||
|
||||
it('should not be dirty by default', function() {
|
||||
expect(this.model.isDirty()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should be dirty after it\'s been changed', function() {
|
||||
this.model.set('name', 'foobar');
|
||||
|
||||
expect(this.model.isDirty()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should not be dirty after calling setOriginalAttributes', function() {
|
||||
this.model.set('name', 'foobar');
|
||||
this.model.setOriginalAttributes();
|
||||
|
||||
expect(this.model.isDirty()).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Input/Output', function() {
|
||||
var deepAttributes = function(obj) {
|
||||
if (obj instanceof Backbone.Model) {
|
||||
return deepAttributes(obj.attributes);
|
||||
} else if (obj instanceof Backbone.Collection) {
|
||||
return obj.map(deepAttributes);
|
||||
} else if (_.isArray(obj)) {
|
||||
return _.map(obj, deepAttributes);
|
||||
} else if (_.isObject(obj)) {
|
||||
var attributes = {};
|
||||
|
||||
for (var prop in obj) {
|
||||
if (obj.hasOwnProperty(prop)) {
|
||||
attributes[prop] = deepAttributes(obj[prop]);
|
||||
}
|
||||
}
|
||||
return attributes;
|
||||
} else {
|
||||
return obj;
|
||||
}
|
||||
};
|
||||
|
||||
it('should match server model to client model', function() {
|
||||
var serverModelSpec = {
|
||||
'id': 10,
|
||||
'name': 'My GroupConfiguration',
|
||||
'description': 'Some description',
|
||||
'groups': [
|
||||
{
|
||||
'name': 'Group 1'
|
||||
}, {
|
||||
'name': 'Group 2'
|
||||
}
|
||||
]
|
||||
},
|
||||
clientModelSpec = {
|
||||
'id': 10,
|
||||
'name': 'My GroupConfiguration',
|
||||
'description': 'Some description',
|
||||
'showGroups': false,
|
||||
'groups': [
|
||||
{
|
||||
'name': 'Group 1'
|
||||
}, {
|
||||
'name': 'Group 2'
|
||||
}
|
||||
]
|
||||
},
|
||||
model = new GroupConfiguration(serverModelSpec);
|
||||
|
||||
expect(deepAttributes(model)).toEqual(clientModelSpec);
|
||||
expect(model.toJSON()).toEqual(serverModelSpec);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Validation', function() {
|
||||
it('requires a name', function() {
|
||||
var model = new GroupConfiguration({ name: '' });
|
||||
|
||||
expect(model.isValid()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('requires at least one group', function() {
|
||||
var model = new GroupConfiguration({ name: 'foo' });
|
||||
model.get('groups').reset();
|
||||
|
||||
expect(model.isValid()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('requires a valid group', function() {
|
||||
var group = new Group(),
|
||||
model = new GroupConfiguration({ name: 'foo' });
|
||||
|
||||
group.isValid = function() { return false; };
|
||||
model.get('groups').reset([group]);
|
||||
|
||||
expect(model.isValid()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('requires all groups to be valid', function() {
|
||||
var group1 = new Group(),
|
||||
group2 = new Group(),
|
||||
model = new GroupConfiguration({ name: 'foo' });
|
||||
|
||||
group1.isValid = function() { return true; };
|
||||
group2.isValid = function() { return false; };
|
||||
model.get('groups').reset([group1, group2]);
|
||||
|
||||
expect(model.isValid()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('can pass validation', function() {
|
||||
var group = new Group(),
|
||||
model = new GroupConfiguration({ name: 'foo' });
|
||||
|
||||
group.isValid = function() { return true; };
|
||||
model.get('groups').reset([group]);
|
||||
|
||||
expect(model.isValid()).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Group model', function() {
|
||||
beforeEach(function() {
|
||||
this.model = new Group();
|
||||
});
|
||||
|
||||
describe('Basic', function() {
|
||||
it('should have a name by default', function() {
|
||||
expect(this.model.get('name')).toEqual('');
|
||||
});
|
||||
|
||||
it('should be empty by default', function() {
|
||||
expect(this.model.isEmpty()).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Validation', function() {
|
||||
it('requires a name', function() {
|
||||
var model = new Group({ name: '' });
|
||||
|
||||
expect(model.isValid()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('can pass validation', function() {
|
||||
var model = new Group({ name: 'a' });
|
||||
|
||||
expect(model.isValid()).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Group collection', function() {
|
||||
beforeEach(function() {
|
||||
this.collection = new GroupSet();
|
||||
});
|
||||
|
||||
it('is empty by default', function() {
|
||||
expect(this.collection.isEmpty()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('is empty if all groups are empty', function() {
|
||||
this.collection.add([{}, {}, {}]);
|
||||
|
||||
expect(this.collection.isEmpty()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('is not empty if a group is not empty', function() {
|
||||
this.collection.add([{}, { name: 'full' }, {} ]);
|
||||
|
||||
expect(this.collection.isEmpty()).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
145
cms/static/js/spec/views/group_configuration_spec.js
Normal file
145
cms/static/js/spec/views/group_configuration_spec.js
Normal file
@@ -0,0 +1,145 @@
|
||||
define([
|
||||
'js/models/group_configuration', 'js/models/course',
|
||||
'js/collections/group_configuration', 'js/views/group_configuration_details',
|
||||
'js/views/group_configurations_list', 'jasmine-stealth'
|
||||
], function(
|
||||
GroupConfigurationModel, Course, GroupConfigurationSet,
|
||||
GroupConfigurationDetails, GroupConfigurationsList
|
||||
) {
|
||||
'use strict';
|
||||
beforeEach(function() {
|
||||
window.course = new Course({
|
||||
id: '5',
|
||||
name: 'Course Name',
|
||||
url_name: 'course_name',
|
||||
org: 'course_org',
|
||||
num: 'course_num',
|
||||
revision: 'course_rev'
|
||||
});
|
||||
|
||||
this.addMatchers({
|
||||
toContainText: function(text) {
|
||||
var trimmedText = $.trim(this.actual.text());
|
||||
|
||||
if (text && $.isFunction(text.test)) {
|
||||
return text.test(trimmedText);
|
||||
} else {
|
||||
return trimmedText.indexOf(text) !== -1;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
delete window.course;
|
||||
});
|
||||
|
||||
describe('GroupConfigurationDetails', function() {
|
||||
var tpl = readFixtures('group-configuration-details.underscore');
|
||||
|
||||
beforeEach(function() {
|
||||
setFixtures($('<script>', {
|
||||
id: 'group-configuration-details-tpl',
|
||||
type: 'text/template'
|
||||
}).text(tpl));
|
||||
|
||||
this.model = new GroupConfigurationModel({
|
||||
name: 'Configuration',
|
||||
description: 'Configuration Description',
|
||||
id: 0
|
||||
});
|
||||
|
||||
spyOn(this.model, 'destroy').andCallThrough();
|
||||
this.collection = new GroupConfigurationSet([ this.model ]);
|
||||
this.view = new GroupConfigurationDetails({
|
||||
model: this.model
|
||||
});
|
||||
});
|
||||
|
||||
describe('Basic', function() {
|
||||
it('should render properly', function() {
|
||||
this.view.render();
|
||||
|
||||
expect(this.view.$el).toContainText('Configuration');
|
||||
expect(this.view.$el).toContainText('ID: 0');
|
||||
});
|
||||
|
||||
it('should show groups appropriately', function() {
|
||||
this.model.get('groups').add([{}, {}, {}]);
|
||||
this.model.set('showGroups', false);
|
||||
this.view.render().$('.show-groups').click();
|
||||
|
||||
expect(this.model.get('showGroups')).toBeTruthy();
|
||||
expect(this.view.$el.find('.group').length).toBe(5);
|
||||
expect(this.view.$el.find('.group-configuration-groups-count'))
|
||||
.not.toExist();
|
||||
expect(this.view.$el.find('.group-configuration-description'))
|
||||
.toContainText('Configuration Description');
|
||||
expect(this.view.$el.find('.group-allocation'))
|
||||
.toContainText('20%');
|
||||
});
|
||||
|
||||
it('should hide groups appropriately', function() {
|
||||
this.model.get('groups').add([{}, {}, {}]);
|
||||
this.model.set('showGroups', true);
|
||||
this.view.render().$('.hide-groups').click();
|
||||
|
||||
expect(this.model.get('showGroups')).toBeFalsy();
|
||||
expect(this.view.$el.find('.group').length).toBe(0);
|
||||
expect(this.view.$el.find('.group-configuration-groups-count'))
|
||||
.toContainText('Contains 5 groups');
|
||||
expect(this.view.$el.find('.group-configuration-description'))
|
||||
.not.toExist();
|
||||
expect(this.view.$el.find('.group-allocation'))
|
||||
.not.toExist();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('GroupConfigurationsList', function() {
|
||||
var noGroupConfigurationsTpl = readFixtures(
|
||||
'no-group-configurations.underscore'
|
||||
);
|
||||
|
||||
beforeEach(function() {
|
||||
var showEl = $('<li>');
|
||||
|
||||
setFixtures($('<script>', {
|
||||
id: 'no-group-configurations-tpl',
|
||||
type: 'text/template'
|
||||
}).text(noGroupConfigurationsTpl));
|
||||
|
||||
this.showSpies = spyOnConstructor(
|
||||
window, 'GroupConfigurationDetails', [ 'render' ]
|
||||
);
|
||||
this.showSpies.render.andReturn(this.showSpies);
|
||||
this.showSpies.$el = showEl;
|
||||
this.showSpies.el = showEl.get(0);
|
||||
this.collection = new GroupConfigurationSet();
|
||||
this.view = new GroupConfigurationsList({
|
||||
collection: this.collection
|
||||
});
|
||||
this.view.render();
|
||||
});
|
||||
|
||||
var message = 'should render the empty template if there are no group ' +
|
||||
'configurations';
|
||||
it(message, function() {
|
||||
expect(this.view.$el).toContainText(
|
||||
'You haven\'t created any group configurations yet.'
|
||||
);
|
||||
expect(this.view.$el).not.toContain('.new-button');
|
||||
expect(this.showSpies.constructor).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should render GroupConfigurationDetails views by default', function() {
|
||||
this.collection.add([{}, {}, {}]);
|
||||
this.view.render();
|
||||
|
||||
expect(this.view.$el).not.toContainText(
|
||||
'You haven\'t created any group configurations yet.'
|
||||
);
|
||||
expect(this.view.$el.find('.group-configuration').length).toBe(3);
|
||||
});
|
||||
});
|
||||
});
|
||||
71
cms/static/js/spec/views/pages/group_configurations_spec.js
Normal file
71
cms/static/js/spec/views/pages/group_configurations_spec.js
Normal file
@@ -0,0 +1,71 @@
|
||||
define([
|
||||
'jquery', 'underscore', 'js/views/pages/group_configurations',
|
||||
'js/collections/group_configuration'
|
||||
], function ($, _, GroupConfigurationsPage, GroupConfigurationCollection) {
|
||||
'use strict';
|
||||
describe('GroupConfigurationsPage', function() {
|
||||
var mockGroupConfigurationsPage = readFixtures(
|
||||
'mock/mock-group-configuration-page.underscore'
|
||||
),
|
||||
noGroupConfigurationsTpl = readFixtures(
|
||||
'no-group-configurations.underscore'
|
||||
), view;
|
||||
|
||||
var initializePage = function (disableSpy) {
|
||||
view = new GroupConfigurationsPage({
|
||||
el: $('.content-primary'),
|
||||
collection: new GroupConfigurationCollection({
|
||||
name: 'Configuration 1'
|
||||
})
|
||||
});
|
||||
|
||||
if (!disableSpy) {
|
||||
spyOn(view, 'addGlobalActions');
|
||||
}
|
||||
};
|
||||
|
||||
beforeEach(function () {
|
||||
setFixtures($('<script>', {
|
||||
id: 'no-group-configurations-tpl',
|
||||
type: 'text/template'
|
||||
}).text(noGroupConfigurationsTpl));
|
||||
appendSetFixtures(mockGroupConfigurationsPage);
|
||||
});
|
||||
|
||||
describe('Initial display', function() {
|
||||
it('can render itself', function() {
|
||||
initializePage();
|
||||
expect(view.$('.ui-loading')).toBeVisible();
|
||||
view.render();
|
||||
expect(view.$('.no-group-configurations-content')).toBeTruthy();
|
||||
expect(view.$('.ui-loading')).toBeHidden();
|
||||
});
|
||||
});
|
||||
|
||||
describe('on page close/change', function() {
|
||||
it('I see notification message if the model is changed',
|
||||
function() {
|
||||
var message;
|
||||
|
||||
initializePage(true);
|
||||
view.render();
|
||||
message = view.onBeforeUnload();
|
||||
expect(message).toBeUndefined();
|
||||
});
|
||||
|
||||
it('I do not see notification message if the model is not changed',
|
||||
function() {
|
||||
var expectedMessage = [
|
||||
'You have unsaved changes. Do you really want to ',
|
||||
'leave this page?'
|
||||
].join(''), message;
|
||||
|
||||
initializePage();
|
||||
view.render();
|
||||
view.collection.at(0).set('name', 'Configuration 2');
|
||||
message = view.onBeforeUnload();
|
||||
expect(message).toBe(expectedMessage);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
54
cms/static/js/views/group_configuration_details.js
Normal file
54
cms/static/js/views/group_configuration_details.js
Normal file
@@ -0,0 +1,54 @@
|
||||
define([
|
||||
'js/views/baseview', 'underscore', 'gettext'
|
||||
],
|
||||
function(BaseView, _, gettext) {
|
||||
'use strict';
|
||||
var GroupConfigurationDetails = BaseView.extend({
|
||||
tagName: 'section',
|
||||
className: 'group-configuration',
|
||||
events: {
|
||||
'click .show-groups': 'showGroups',
|
||||
'click .hide-groups': 'hideGroups'
|
||||
},
|
||||
|
||||
initialize: function() {
|
||||
this.template = _.template(
|
||||
$('#group-configuration-details-tpl').text()
|
||||
);
|
||||
this.listenTo(this.model, 'change', this.render);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var attrs = $.extend({}, this.model.attributes, {
|
||||
groupsCountMessage: this.getGroupsCountTitle(),
|
||||
index: this.model.collection.indexOf(this.model)
|
||||
});
|
||||
|
||||
this.$el.html(this.template(attrs));
|
||||
return this;
|
||||
},
|
||||
|
||||
showGroups: function(e) {
|
||||
if(e && e.preventDefault) { e.preventDefault(); }
|
||||
this.model.set('showGroups', true);
|
||||
},
|
||||
|
||||
hideGroups: function(e) {
|
||||
if(e && e.preventDefault) { e.preventDefault(); }
|
||||
this.model.set('showGroups', false);
|
||||
},
|
||||
|
||||
getGroupsCountTitle: function () {
|
||||
var count = this.model.get('groups').length,
|
||||
message = ngettext(
|
||||
// Translators: 'count' is number of groups that the group configuration contains.
|
||||
'Contains %(count)s group', 'Contains %(count)s groups',
|
||||
count
|
||||
);
|
||||
|
||||
return interpolate(message, { count: count }, true);
|
||||
}
|
||||
});
|
||||
|
||||
return GroupConfigurationDetails;
|
||||
});
|
||||
36
cms/static/js/views/group_configurations_list.js
Normal file
36
cms/static/js/views/group_configurations_list.js
Normal file
@@ -0,0 +1,36 @@
|
||||
define(['js/views/baseview', 'jquery', 'js/views/group_configuration_details'],
|
||||
function(BaseView, $, GroupConfigurationDetailsView) {
|
||||
'use strict';
|
||||
var GroupConfigurationsList = BaseView.extend({
|
||||
tagName: 'div',
|
||||
className: 'group-configurations-list',
|
||||
events: { },
|
||||
|
||||
initialize: function() {
|
||||
this.emptyTemplate = this.loadTemplate('no-group-configurations');
|
||||
this.listenTo(this.collection, 'all', this.render);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var configurations = this.collection;
|
||||
if(configurations.length === 0) {
|
||||
this.$el.html(this.emptyTemplate());
|
||||
} else {
|
||||
var frag = document.createDocumentFragment();
|
||||
|
||||
configurations.each(function(configuration) {
|
||||
var view = new GroupConfigurationDetailsView({
|
||||
model: configuration
|
||||
});
|
||||
|
||||
frag.appendChild(view.render().el);
|
||||
});
|
||||
|
||||
this.$el.html([frag]);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
return GroupConfigurationsList;
|
||||
});
|
||||
40
cms/static/js/views/pages/group_configurations.js
Normal file
40
cms/static/js/views/pages/group_configurations.js
Normal file
@@ -0,0 +1,40 @@
|
||||
define([
|
||||
'jquery', 'underscore', 'gettext', 'js/views/baseview',
|
||||
'js/views/group_configurations_list'
|
||||
],
|
||||
function ($, _, gettext, BaseView, ConfigurationsListView) {
|
||||
'use strict';
|
||||
var GroupConfigurationsPage = BaseView.extend({
|
||||
initialize: function() {
|
||||
BaseView.prototype.initialize.call(this);
|
||||
this.listView = new ConfigurationsListView({
|
||||
collection: this.collection
|
||||
});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
this.hideLoadingIndicator();
|
||||
this.$el.append(this.listView.render().el);
|
||||
this.addGlobalActions();
|
||||
},
|
||||
|
||||
addGlobalActions: function () {
|
||||
$(window).on('beforeunload', this.onBeforeUnload.bind(this));
|
||||
},
|
||||
|
||||
onBeforeUnload: function () {
|
||||
var dirty = this.collection.find(function(configuration) {
|
||||
return configuration.isDirty();
|
||||
});
|
||||
|
||||
if(dirty) {
|
||||
return gettext(
|
||||
'You have unsaved changes. Do you really want to ' +
|
||||
'leave this page?'
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return GroupConfigurationsPage;
|
||||
}); // end define();
|
||||
Reference in New Issue
Block a user