Commit 6398af71 by Frances Botsford Committed by Andy Armstrong

Make group config styles generic

parent 39acbdcb
......@@ -24,7 +24,7 @@ define([
groupsAllocation: '.group-allocation',
errorMessage: '.group-configuration-edit-error',
inputGroupName: '.group-name',
inputName: '.group-configuration-name-input',
inputName: '.collection-name-input',
inputDescription: '.group-configuration-description-input',
usageCount: '.group-configuration-usage-count',
usage: '.group-configuration-usage',
......@@ -635,15 +635,15 @@ define([
describe('Content groups list view', function() {
var newGroupCss = '.new-button',
addGroupCss = '.action-add',
inputCss = '.group-configuration-name-input',
inputCss = '.collection-name-input',
saveButtonCss = '.action-primary',
cancelButtonCss = '.action-cancel',
validationErrorCss = '.group-configuration-edit-error',
validationErrorCss = '.content-group-edit-error',
scopedGroupSelector, createGroups, renderView, saveOrCancel, editNewGroup, editExistingGroup,
verifyEditingGroup, respondToSave, expectGroupsVisible, correctValidationError;
scopedGroupSelector = function(groupIndex, additionalSelectors) {
var groupSelector = '.group-configurations-list-item-' + groupIndex;
var groupSelector = '.content-groups-list-item-' + groupIndex;
if (additionalSelectors) {
return groupSelector + ' ' + additionalSelectors;
} else {
......@@ -704,11 +704,11 @@ define([
// editing a group.
index = index || 0;
if (expectEditing) {
expect(view.$(scopedGroupSelector(index, '.group-configuration-edit'))).toExist();
expect(view.$(scopedGroupSelector(index, '.content-group-edit'))).toExist();
expect(view.$(newGroupCss)).not.toExist();
expect(view.$(addGroupCss)).toHaveClass('is-hidden');
} else {
expect(view.$('.group-configuration-edit')).not.toExist();
expect(view.$('.content-group-edit')).not.toExist();
if (view.collection.length === 0) {
expect(view.$(newGroupCss)).toExist();
expect(view.$(addGroupCss)).not.toExist();
......@@ -742,7 +742,7 @@ define([
expectGroupsVisible = function(view, groupNames) {
_.each(groupNames, function(groupName) {
expect(view.$('.group-configurations-list-item')).toContainText(groupName);
expect(view.$('.content-groups-list-item')).toContainText(groupName);
});
};
......@@ -753,13 +753,13 @@ define([
});
it('shows a message when no groups are present', function() {
expect(renderView().$('.no-group-configurations-content'))
expect(renderView().$('.no-content'))
.toContainText('You have not created any content groups yet.');
});
it('can render groups', function() {
var groupNames = ['Group 1', 'Group 2', 'Group 3'];
renderView(groupNames).$('.group-configuration-details').each(function(index) {
renderView(groupNames).$('.content-group-details').each(function(index) {
expect($(this)).toContainText(groupNames[index]);
});
});
......
......@@ -52,7 +52,7 @@ define([
expect(view.$('.ui-loading')).toBeVisible();
view.render();
expect(view.$(groupConfigItemClassName)).toExist();
expect(view.$('.content-groups .no-group-configurations-content')).toExist();
expect(view.$('.content-groups .no-content')).toExist();
expect(view.$('.ui-loading')).toHaveClass('is-hidden');
});
});
......
......@@ -9,7 +9,7 @@ define([
var ContentGroupDetailsView = BaseView.extend({
tagName: 'div',
className: 'group-configuration-details',
className: 'content-group-details collection',
events: {
'click .edit': 'editGroup'
......
......@@ -10,7 +10,7 @@ function(ListItemEditorView, _) {
var ContentGroupEditorView = ListItemEditorView.extend({
tagName: 'div',
className: 'group-configuration-edit',
className: 'content-group-edit collection-edit',
events: {
'submit': 'setAndClose',
'click .action-cancel': 'cancel'
......
......@@ -12,6 +12,8 @@ define([
var ContentGroupItemView = ListItemView.extend({
tagName: 'section',
baseClassName: 'content-group',
createEditView: function() {
return new ContentGroupEditorView({model: this.model});
},
......
......@@ -15,6 +15,8 @@ define([
// Translators: This refers to a content group that can be linked to a student cohort.
itemCategoryDisplayName: gettext('content group'),
emptyMessage: gettext('You have not created any content groups yet.'),
createItemView: function(options) {
return new ContentGroupItemView(options);
}
......
......@@ -19,6 +19,7 @@ function(BaseView, _, gettext, str) {
var index = this.model.collection.indexOf(this.model);
return [
'collection',
'group-configuration-details',
'group-configuration-details-' + index
].join(' ');
......
......@@ -11,7 +11,7 @@ function(ListItemEditorView, _, $, gettext, ExperimentGroupEditView) {
var GroupConfigurationEditorView = ListItemEditorView.extend({
tagName: 'div',
events: {
'change .group-configuration-name-input': 'setName',
'change .collection-name-input': 'setName',
'change .group-configuration-description-input': 'setDescription',
'click .action-add-group': 'createGroup',
'focus .input-text': 'onFocus',
......@@ -24,6 +24,7 @@ function(ListItemEditorView, _, $, gettext, ExperimentGroupEditView) {
var index = this.model.collection.indexOf(this.model);
return [
'collection-edit',
'group-configuration-edit',
'group-configuration-edit-' + index
].join(' ');
......@@ -84,7 +85,7 @@ function(ListItemEditorView, _, $, gettext, ExperimentGroupEditView) {
setName: function(event) {
if (event && event.preventDefault) { event.preventDefault(); }
this.model.set(
'name', this.$('.group-configuration-name-input').val(),
'name', this.$('.collection-name-input').val(),
{ silent: true }
);
},
......
......@@ -18,6 +18,13 @@ define([
tagName: 'section',
baseClassName: 'group-configuration',
canDelete: true,
// Translators: this refers to a collection of groups.
itemDisplayName: gettext('group configuration'),
attributes: function () {
return {
'id': this.model.get('id'),
......@@ -25,11 +32,6 @@ define([
};
},
// Translators: this refers to a collection of groups.
itemDisplayName: gettext('group configuration'),
canDelete: true,
createEditView: function() {
return new GroupConfigurationEditorView({model: this.model});
},
......
......@@ -17,6 +17,8 @@ define([
// Translators: this refers to a collection of groups.
itemCategoryDisplayName: gettext('group configuration'),
emptyMessage: gettext('You have not created any group configurations yet.'),
createItemView: function(options) {
return new GroupConfigurationItemView(options);
}
......
......@@ -10,6 +10,7 @@
* - itemCategoryDisplayName (string): Display name for the category
* of items this list contains. For example, 'Group Configuration'.
* Note that it must be translated.
* - emptyMessage (string): Text to render when the list is empty.
*/
define([
'js/views/baseview'
......@@ -21,6 +22,8 @@ define([
'click .new-button': 'onAddItem'
},
listContainerCss: '.list-items',
initialize: function() {
this.listenTo(this.collection, 'add', this.addNewItemView);
this.listenTo(this.collection, 'remove', this.onRemoveItem);
......@@ -35,12 +38,13 @@ define([
render: function(model) {
this.$el.html(this.template({
itemCategoryDisplayName: this.itemCategoryDisplayName,
emptyMessage: this.emptyMessage,
length: this.collection.length,
isEditing: model && model.get('editing')
}));
this.collection.each(function(model) {
this.$('.content-groups').append(this.createItemView({model: model}).render().el);
this.$(this.listContainerCss).append(this.createItemView({model: model}).render().el);
}, this);
return this;
......@@ -71,7 +75,7 @@ define([
// If items already exist, just append one new.
// Otherwise re-render the empty list HTML.
if (this.collection.length > 1) {
this.$('.content-groups').append(view.render().el);
this.$(this.listContainerCss).append(view.render().el);
} else {
this.render();
}
......
......@@ -5,6 +5,7 @@
* Subclasses must implement:
* - itemDisplayName (string): Display name for the list item.
* Must be translated.
* - baseClassName (string): CSS class name representing the item.
* - createEditView (function): Render and append the edit view to the
* DOM.
* - createDetailsView (function): Render and append the details view
......@@ -29,9 +30,11 @@ define([
var index = this.model.collection.indexOf(this.model);
return [
'group-configuration',
'group-configurations-list-item',
'group-configurations-list-item-' + index
'wrapper-collection',
'wrapper-collection-' + index,
this.baseClassName,
this.baseClassName + 's-list-item',
this.baseClassName + 's-list-item-' + index
].join(' ');
},
......
......@@ -63,8 +63,8 @@
% endif
</article>
<aside class="content-supplementary" role="complementary">
<div class="content-groups-doc">
<div class="bit">
<div class="bit">
<div class="content-groups-doc">
<h3 class="title-3">${_("Content Groups")}</h3>
<p>${_("Use content groups to give groups of students access to a specific set of course content. In addition to course content that is intended for all students, each content group sees content that you specifically designate as visible to it. By associating a content group with one or more cohorts, you can customize the content that a particular cohort or cohorts sees in your course.")}</p>
<p>${_("Click {em_start}New content group{em_end} to add a new content group. To edit the name of a content group, hover over its box and click {em_start}Edit{em_end}. Content groups cannot be deleted.").format(em_start="<strong>", em_end="</strong>")}</p>
......@@ -72,8 +72,8 @@
</div>
</div>
% if should_show_experiment_groups:
<div class="experiment-groups-doc">
<div class="bit">
<div class="bit">
<div class="experiment-groups-doc">
<h3 class="title-3">${_("Experiment Group Configurations")}</h3>
<p>${_("Use experiment group configurations to define how many groups of students are in a content experiment. When you create a content experiment for a course, you select the group configuration to use.")}</p>
<p>${_("Click {em_start}New Group Configuration{em_end} to add a new configuration. To edit a configuration, hover over its box and click {em_start}Edit{em_end}.").format(em_start="<strong>", em_end="</strong>")}</p>
......
<div class="wrapper-group-configuration">
<header class="group-configuration-header">
<h3 class="group-configuration-title">
<div class="collection-details">
<header class="collection-header">
<h3 class="title">
<%- name %>
</h3>
</header>
<ul class="actions group-configuration-actions">
<ul class="actions">
<li class="action action-edit">
<button class="edit"><i class="icon fa fa-pencil"></i> <%= gettext("Edit") %></button>
</li>
......
<form class="group-configuration-edit-form">
<div class="wrapper-form">
<form class="collection-edit-form">
<% if (error && error.message) { %>
<div class="group-configuration-edit-error message message-status message-status error is-shown" name="group-configuration-edit-error">
<div class="content-group-edit-error message message-status message-status error is-shown">
<%= gettext(error.message) %>
</div>
<% } %>
<fieldset class="groups-fields">
<div class="input-wrap field text required add-group-configuration-name <% if(error && error.attributes && error.attributes.name) { print('error'); } %>">
<div class="wrapper-form">
<fieldset class="collection-fields">
<div class="input-wrap field text required add-collection-name <% if(error && error.attributes && error.attributes.name) { print('error'); } %>">
<label for="group-cohort-name-<%= uniqueId %>"><%= gettext("Content Group Name") %></label>
<input name="group-cohort-name" id="group-cohort-name-<%= uniqueId %>" class="group-configuration-name-input input-text" value="<%- name %>" type="text" placeholder="<%= gettext("This is the name of the group") %>">
<input name="group-cohort-name" id="group-cohort-name-<%= uniqueId %>" class="collection-name-input input-text" value="<%- name %>" type="text" placeholder="<%= gettext("This is the name of the group") %>">
</div>
</fieldset>
</div>
......
<div class="wrapper-group-configuration">
<header class="group-configuration-header">
<h3 class="group-configuration-title">
<a href="#" class="group-toggle <% if(showGroups){ print('hide'); } else { print('show'); } %>-groups">
<div class="collection-details wrapper-group-configuration">
<header class="collection-header group-configuration-header">
<h3 class="title group-configuration-title">
<a href="#" class="toggle group-toggle <% if(showGroups){ print('hide'); } else { print('show'); } %>-groups">
<i class="ui-toggle-expansion icon fa fa-caret-<% if(showGroups){ print('down'); } else { print('right'); } %>"></i>
<%= name %>
</a>
</h3>
</header>
<ol class="group-configuration-info group-configuration-info-<% if(showGroups){ print('block'); } else { print('inline'); } %>">
<ol class="collection-info group-configuration-info group-configuration-info-<% if(showGroups){ print('block'); } else { print('inline'); } %>">
<% if (!_.isUndefined(id)) { %>
<li class="group-configuration-id"
><span class="group-configuration-label"><%= gettext('ID') %>: </span
......@@ -16,7 +16,7 @@
></li>
<% } %>
<% if (showGroups) { %>
<li class="group-configuration-description">
<li class="collection-description group-configuration-description">
<%= description %>
</li>
<% } else { %>
......@@ -31,11 +31,11 @@
<% if(showGroups) { %>
<% allocation = Math.floor(100 / groups.length) %>
<ol class="groups groups-<%= index %>">
<ol class="collection-items groups groups-<%= index %>">
<% groups.each(function(group, groupIndex) { %>
<li class="group group-<%= groupIndex %>">
<span class="group-name"><%= group.get('name') %></span>
<span class="group-allocation"><%= allocation %>%</span>
<li class="item group group-<%= groupIndex %>">
<span class="name group-name"><%= group.get('name') %></span>
<span class="meta group-allocation"><%= allocation %>%</span>
</li>
<% }) %>
</ol>
......@@ -56,12 +56,12 @@
</ul>
</div>
<% if(showGroups) { %>
<div class="wrapper-group-configuration-usages">
<div class="collection-references wrapper-group-configuration-usages">
<% if (!_.isEmpty(usage)) { %>
<h4 class="group-configuration-usage-text"><%= gettext('This Group Configuration is used in:') %></h4>
<ol class="group-configuration-usage">
<h4 class="intro group-configuration-usage-text"><%= gettext('This Group Configuration is used in:') %></h4>
<ol class="usage group-configuration-usage">
<% _.each(usage, function(unit) { %>
<li class="group-configuration-usage-unit">
<li class="usage-unit group-configuration-usage-unit">
<p><a href=<%= unit.url %> ><%= unit.label %></a></p>
<% if (unit.validation) { %>
<p>
......@@ -70,7 +70,7 @@
<% } else if (unit.validation.type === 'error') { %>
<i class="icon fa fa-exclamation-circle"></i>
<% } %>
<span class="group-configuration-validation-message">
<span class="usage-validation-message group-configuration-validation-message">
<%= unit.validation.text %>
</span>
</p>
......
<form class="group-configuration-edit-form">
<div class="wrapper-form">
<form class="collection-edit-form group-configuration-edit-form">
<% if (error && error.message) { %>
<div class="group-configuration-edit-error message message-status message-status error is-shown" name="group-configuration-edit-error">
<%= gettext(error.message) %>
</div>
<% } %>
<fieldset class="group-configuration-fields">
<div class="wrapper-form">
<fieldset class="collection-fields group-configuration-fields">
<legend class="sr"><%= gettext("Group Configuration information") %></legend>
<div class="input-wrap field text required add-group-configuration-name <% if(error && error.attributes && error.attributes.name) { print('error'); } %>">
<div class="input-wrap field text required add-collection-name add-group-configuration-name <% if(error && error.attributes && error.attributes.name) { print('error'); } %>">
<label for="group-configuration-name-<%= uniqueId %>"><%= gettext("Group Configuration Name") %></label><%
if (!_.isUndefined(id)) {
%><span class="group-configuration-id">
......@@ -16,7 +16,7 @@
</span><%
}
%>
<input id="group-configuration-name-<%= uniqueId %>" class="group-configuration-name-input input-text" name="group-configuration-name" type="text" placeholder="<%= gettext("This is the Name of the Group Configuration") %>" value="<%= name %>">
<input id="group-configuration-name-<%= uniqueId %>" class="collection-name-input input-text" name="group-configuration-name" type="text" placeholder="<%= gettext("This is the Name of the Group Configuration") %>" value="<%= name %>">
<span class="tip tip-stacked"><%= gettext("Name or short description of the configuration") %></span>
</div>
<div class="input-wrap field text add-group-configuration-description">
......@@ -30,10 +30,10 @@
<label class="groups-fields-label required"><%= gettext("Groups") %></label>
<span class="tip tip-stacked"><%= gettext("Name of the groups that students will be assigned to, for example, Control, Video, Problems. You must have two or more groups.") %></span>
<ol class="groups list-input enum"></ol>
<button class="action action-add-group"><i class="icon fa fa-plus"></i> <%= gettext("Add another group") %></button>
<button class="action action-add-group action-add-item"><i class="icon fa fa-plus"></i> <%= gettext("Add another group") %></button>
</fieldset>
<% if (!_.isEmpty(usage)) { %>
<div class="wrapper-group-configuration-validation">
<div class="wrapper-group-configuration-validation usage-validation">
<i class="icon fa fa-warning"></i>
<p class="group-configuration-validation-text">
<%= gettext('This configuration is currently used in content experiments. If you make changes to the groups, you may need to edit those experiments.') %>
......
<% if (length === 0) { %>
<div class="no-group-configurations-content">
<p><%- interpolate(gettext("You have not created any %(item_type)ss yet."), {item_type: itemCategoryDisplayName}, true) %><a href="#" class="button new-button"><i class="icon fa fa-plus"></i> <%= gettext("Add your first content group") %></a></p>
<div class="no-content">
<p>
<%- emptyMessage %>
<a href="#" class="button new-button"><i class="icon fa fa-plus"></i> <%= interpolate(gettext("Add your first %(item_type)s"), {item_type: itemCategoryDisplayName}, true) %></a>
</p>
</div>
<% } else { %>
<div class="content-groups"></div>
<div class="list-items"></div>
<% if (!isEditing) { %>
<button class="action action-add">
<i class="icon fa fa-plus"></i><%- interpolate(gettext('New %(item_type)s'), {item_type: itemCategoryDisplayName}, true) %>
......
......@@ -49,7 +49,7 @@ class GroupConfigurationsPage(CoursePage):
"""
Return list of the group-configurations-list-item's of specified type for the course.
"""
css = prefix + ' .group-configurations-list-item'
css = prefix + ' .wrapper-collection'
return [GroupConfiguration(self, prefix, index) for index in xrange(len(self.q(css=css)))]
def create_experiment_group_configuration(self):
......@@ -90,7 +90,7 @@ class GroupConfigurationsPage(CoursePage):
"""
Returns the message about "no content" for the specified type.
"""
return self.q(css='.wrapper-content ' + prefix + ' .no-group-configurations-content')
return self.q(css='.wrapper-content ' + prefix + ' .no-content')
@property
def experiment_group_sections_present(self):
......@@ -107,7 +107,7 @@ class GroupConfiguration(object):
def __init__(self, page, prefix, index):
self.page = page
self.SELECTOR = prefix + ' .group-configurations-list-item-{}'.format(index)
self.SELECTOR = prefix + ' .wrapper-collection-{}'.format(index)
self.index = index
def get_selector(self, css=''):
......@@ -195,9 +195,9 @@ class GroupConfiguration(object):
"""
Return group configuration mode.
"""
if self.find_css('.group-configuration-edit').present:
if self.find_css('.collection-edit').present:
return 'edit'
elif self.find_css('.group-configuration-details').present:
elif self.find_css('.collection').present:
return 'details'
@property
......@@ -227,14 +227,14 @@ class GroupConfiguration(object):
"""
Return group configuration name.
"""
return self.get_text('.group-configuration-title')
return self.get_text('.title')
@name.setter
def name(self, value):
"""
Set group configuration name.
"""
self.find_css('.group-configuration-name-input').first.fill(value)
self.find_css('.collection-name-input').first.fill(value)
@property
def description(self):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment