Merge branch 'groups-ui' of github.com:AlexanderOtavka/hifi into groups

This commit is contained in:
Seth Alves 2016-07-29 08:15:35 -07:00
commit 954c88188c
3 changed files with 316 additions and 82 deletions

View file

@ -455,12 +455,16 @@
"name": "group_permissions", "name": "group_permissions",
"type": "table", "type": "table",
"caption": "Permissions for Users in Groups", "caption": "Permissions for Users in Groups",
"can_add_new_rows": true, "categorize_by_key": "permissions_id",
"can_add_new_categories": true,
"can_add_new_rows": false,
"new_category_placeholder": "Add Group",
"new_category_message": "Reload to see ranks",
"groups": [ "groups": [
{ {
"label": "Group", "label": "Rank",
"span": 2 "span": 1
}, },
{ {
"label": "Permissions <a data-toggle='tooltip' data-html='true' title='<p><strong>Domain-Wide User Permissions</strong></p><ul><li><strong>Connect</strong><br />Sets whether users in specific groups can connect to the domain.</li><li><strong>Lock / Unlock</strong><br />Sets whether users in specific groups can change the &ldquo;locked&rdquo; property of an entity (either from on to off or off to on).</li><li><strong>Rez</strong><br />Sets whether users in specific groups can create new entities.</li><li><strong>Rez Temporary</strong><br />Sets whether users in specific groups can create new entities with a finite lifetime.</li><li><strong>Write Assets</strong><br />Sets whether users in specific groups can make changes to the domain&rsquo;s asset-server assets.</li><li><strong>Ignore Max Capacity</strong><br />Sets whether user in specific groups can connect even if the domain has reached or exceeded its maximum allowed agents.</li></ul><p>Permissions granted to a specific user will be a union of the permissions granted to the groups they are in, as well as permissions from the previous section. Group permissions are only granted if the user doesn&rsquo;t have their own row in the per-account section, below.</p>'>?</a>", "label": "Permissions <a data-toggle='tooltip' data-html='true' title='<p><strong>Domain-Wide User Permissions</strong></p><ul><li><strong>Connect</strong><br />Sets whether users in specific groups can connect to the domain.</li><li><strong>Lock / Unlock</strong><br />Sets whether users in specific groups can change the &ldquo;locked&rdquo; property of an entity (either from on to off or off to on).</li><li><strong>Rez</strong><br />Sets whether users in specific groups can create new entities.</li><li><strong>Rez Temporary</strong><br />Sets whether users in specific groups can create new entities with a finite lifetime.</li><li><strong>Write Assets</strong><br />Sets whether users in specific groups can make changes to the domain&rsquo;s asset-server assets.</li><li><strong>Ignore Max Capacity</strong><br />Sets whether user in specific groups can connect even if the domain has reached or exceeded its maximum allowed agents.</li></ul><p>Permissions granted to a specific user will be a union of the permissions granted to the groups they are in, as well as permissions from the previous section. Group permissions are only granted if the user doesn&rsquo;t have their own row in the per-account section, below.</p>'>?</a>",
@ -471,7 +475,9 @@
"columns": [ "columns": [
{ {
"name": "permissions_id", "name": "permissions_id",
"label": "Group Name" "label": "Group Name",
"readonly": true,
"hidden": true
}, },
{ {
"name": "rank_id", "name": "rank_id",
@ -487,7 +493,7 @@
}, },
{ {
"name": "rank_name", "name": "rank_name",
"label": "Rank Name", "label": "",
"readonly": true "readonly": true
}, },
{ {
@ -543,13 +549,17 @@
{ {
"name": "group_forbiddens", "name": "group_forbiddens",
"type": "table", "type": "table",
"caption": "Permissions denied to Users in Groups", "caption": "Permissions Denied to Users in Groups",
"can_add_new_rows": true, "categorize_by_key": "permissions_id",
"can_add_new_categories": true,
"can_add_new_rows": false,
"new_category_placeholder": "Add Blacklist Group",
"new_category_message": "Reload to see ranks",
"groups": [ "groups": [
{ {
"label": "Group", "label": "Rank",
"span": 2 "span": 1
}, },
{ {
"label": "Permissions <a data-toggle='tooltip' data-html='true' title='<p><strong>Domain-Wide User Permissions</strong></p><ul><li><strong>Connect</strong><br />Sets whether users in specific groups can connect to the domain.</li><li><strong>Lock / Unlock</strong><br />Sets whether users in specific groups can change the &ldquo;locked&rdquo; property of an entity (either from on to off or off to on).</li><li><strong>Rez</strong><br />Sets whether users in specific groups can create new entities.</li><li><strong>Rez Temporary</strong><br />Sets whether users in specific groups can create new entities with a finite lifetime.</li><li><strong>Write Assets</strong><br />Sets whether users in specific groups can make changes to the domain&rsquo;s asset-server assets.</li><li><strong>Ignore Max Capacity</strong><br />Sets whether user in specific groups can connect even if the domain has reached or exceeded its maximum allowed agents.</li></ul><p>Permissions granted to a specific user will be a union of the permissions granted to the groups they are in. Group permissions are only granted if the user doesn&rsquo;t have their own row in the per-account section, below.</p>'>?</a>", "label": "Permissions <a data-toggle='tooltip' data-html='true' title='<p><strong>Domain-Wide User Permissions</strong></p><ul><li><strong>Connect</strong><br />Sets whether users in specific groups can connect to the domain.</li><li><strong>Lock / Unlock</strong><br />Sets whether users in specific groups can change the &ldquo;locked&rdquo; property of an entity (either from on to off or off to on).</li><li><strong>Rez</strong><br />Sets whether users in specific groups can create new entities.</li><li><strong>Rez Temporary</strong><br />Sets whether users in specific groups can create new entities with a finite lifetime.</li><li><strong>Write Assets</strong><br />Sets whether users in specific groups can make changes to the domain&rsquo;s asset-server assets.</li><li><strong>Ignore Max Capacity</strong><br />Sets whether user in specific groups can connect even if the domain has reached or exceeded its maximum allowed agents.</li></ul><p>Permissions granted to a specific user will be a union of the permissions granted to the groups they are in. Group permissions are only granted if the user doesn&rsquo;t have their own row in the per-account section, below.</p>'>?</a>",
@ -560,7 +570,8 @@
"columns": [ "columns": [
{ {
"name": "permissions_id", "name": "permissions_id",
"label": "Group Name" "label": "Group Name",
"hidden": true
}, },
{ {
"name": "rank_id", "name": "rank_id",
@ -574,7 +585,7 @@
}, },
{ {
"name": "rank_name", "name": "rank_name",
"label": "Rank Name", "label": "",
"readonly": true "readonly": true
}, },
{ {

View file

@ -3,6 +3,10 @@ body {
padding-bottom: 30px; padding-bottom: 30px;
} }
[hidden] {
display: none !important;
}
.table-lead .lead-line { .table-lead .lead-line {
background-color: black; background-color: black;
} }
@ -20,7 +24,9 @@ body {
top: 40px; top: 40px;
} }
.table .value-row td, .table .inputs td { .table .value-row td,
.table .value-category td,
.table .inputs td {
vertical-align: middle; vertical-align: middle;
} }
@ -31,6 +37,31 @@ body {
margin-right: auto; margin-right: auto;
} }
.value-category:not(.inputs) {
font-weight: bold;
background: #f5f5f5;
}
.table .value-category [message]::after {
content: attr(message);
font-style: italic;
font-weight: normal;
}
.table .value-row.contracted,
.table .inputs.contracted {
display: none;
}
.toggle-category {
cursor: pointer;
}
.toggle-category-icon {
padding: 4px;
margin-right: 8px;
}
.glyphicon-remove { .glyphicon-remove {
font-size: 24px; font-size: 24px;
} }

View file

@ -7,10 +7,20 @@ var Settings = {
TRIGGER_CHANGE_CLASS: 'trigger-change', TRIGGER_CHANGE_CLASS: 'trigger-change',
DATA_ROW_CLASS: 'value-row', DATA_ROW_CLASS: 'value-row',
DATA_COL_CLASS: 'value-col', DATA_COL_CLASS: 'value-col',
DATA_CATEGORY_CLASS: 'value-category',
ADD_ROW_BUTTON_CLASS: 'add-row', ADD_ROW_BUTTON_CLASS: 'add-row',
ADD_ROW_SPAN_CLASSES: 'glyphicon glyphicon-plus add-row', ADD_ROW_SPAN_CLASSES: 'glyphicon glyphicon-plus add-row',
DEL_ROW_BUTTON_CLASS: 'del-row', DEL_ROW_BUTTON_CLASS: 'del-row',
DEL_ROW_SPAN_CLASSES: 'glyphicon glyphicon-remove del-row', DEL_ROW_SPAN_CLASSES: 'glyphicon glyphicon-remove del-row',
ADD_CATEGORY_BUTTON_CLASS: 'add-category',
ADD_CATEGORY_SPAN_CLASSES: 'glyphicon glyphicon-plus add-category',
TOGGLE_CATEGORY_COLUMN_CLASS: 'toggle-category',
TOGGLE_CATEGORY_SPAN_CLASS: 'toggle-category-icon',
TOGGLE_CATEGORY_SPAN_CLASSES: 'glyphicon toggle-category-icon',
TOGGLE_CATEGORY_EXPANDED_CLASS: 'glyphicon-triangle-bottom',
TOGGLE_CATEGORY_CONTRACTED_CLASS: 'glyphicon-triangle-right',
DEL_CATEGORY_BUTTON_CLASS: 'del-category',
DEL_CATEGORY_SPAN_CLASSES: 'glyphicon glyphicon-remove del-category',
MOVE_UP_BUTTON_CLASS: 'move-up', MOVE_UP_BUTTON_CLASS: 'move-up',
MOVE_UP_SPAN_CLASSES: 'glyphicon glyphicon-chevron-up move-up', MOVE_UP_SPAN_CLASSES: 'glyphicon glyphicon-chevron-up move-up',
MOVE_DOWN_BUTTON_CLASS: 'move-down', MOVE_DOWN_BUTTON_CLASS: 'move-down',
@ -37,7 +47,7 @@ var viewHelpers = {
form_group = "<div class='form-group " + (isAdvanced ? Settings.ADVANCED_CLASS : "") + "' data-keypath='" + keypath + "'>"; form_group = "<div class='form-group " + (isAdvanced ? Settings.ADVANCED_CLASS : "") + "' data-keypath='" + keypath + "'>";
setting_value = _(values).valueForKeyPath(keypath); setting_value = _(values).valueForKeyPath(keypath);
if (typeof setting_value == 'undefined' || setting_value === null) { if (_.isUndefined(setting_value) || _.isNull(setting_value)) {
if (_.has(setting, 'default')) { if (_.has(setting, 'default')) {
setting_value = setting.default; setting_value = setting.default;
} else { } else {
@ -51,11 +61,11 @@ var viewHelpers = {
} }
function common_attrs(extra_classes) { function common_attrs(extra_classes) {
extra_classes = (typeof extra_classes !== 'undefined' ? extra_classes : ""); extra_classes = (!_.isUndefined(extra_classes) ? extra_classes : "");
return " class='" + (setting.type !== 'checkbox' ? 'form-control' : '') return " class='" + (setting.type !== 'checkbox' ? 'form-control' : '')
+ " " + Settings.TRIGGER_CHANGE_CLASS + " " + extra_classes + "' data-short-name='" + " " + Settings.TRIGGER_CHANGE_CLASS + " " + extra_classes + "' data-short-name='"
+ setting.name + "' name='" + keypath + "' " + setting.name + "' name='" + keypath + "' "
+ "id='" + (typeof setting.html_id !== 'undefined' ? setting.html_id : keypath) + "'"; + "id='" + (!_.isUndefined(setting.html_id) ? setting.html_id : keypath) + "'";
} }
if (setting.type === 'checkbox') { if (setting.type === 'checkbox') {
@ -164,19 +174,31 @@ $(document).ready(function(){
}); });
$('#' + Settings.FORM_ID).on('click', '.' + Settings.ADD_ROW_BUTTON_CLASS, function(){ $('#' + Settings.FORM_ID).on('click', '.' + Settings.ADD_ROW_BUTTON_CLASS, function(){
addTableRow(this); addTableRow($(this).closest('tr'));
}); });
$('#' + Settings.FORM_ID).on('click', '.' + Settings.DEL_ROW_BUTTON_CLASS, function(){ $('#' + Settings.FORM_ID).on('click', '.' + Settings.DEL_ROW_BUTTON_CLASS, function(){
deleteTableRow(this); deleteTableRow($(this).closest('tr'));
});
$('#' + Settings.FORM_ID).on('click', '.' + Settings.ADD_CATEGORY_BUTTON_CLASS, function(){
addTableCategory($(this).closest('tr'));
});
$('#' + Settings.FORM_ID).on('click', '.' + Settings.DEL_CATEGORY_BUTTON_CLASS, function(){
deleteTableCategory($(this).closest('tr'));
});
$('#' + Settings.FORM_ID).on('click', '.' + Settings.TOGGLE_CATEGORY_COLUMN_CLASS, function(){
toggleTableCategory($(this).closest('tr'));
}); });
$('#' + Settings.FORM_ID).on('click', '.' + Settings.MOVE_UP_BUTTON_CLASS, function(){ $('#' + Settings.FORM_ID).on('click', '.' + Settings.MOVE_UP_BUTTON_CLASS, function(){
moveTableRow(this, true); moveTableRow($(this).closest('tr'), true);
}); });
$('#' + Settings.FORM_ID).on('click', '.' + Settings.MOVE_DOWN_BUTTON_CLASS, function(){ $('#' + Settings.FORM_ID).on('click', '.' + Settings.MOVE_DOWN_BUTTON_CLASS, function(){
moveTableRow(this, false); moveTableRow($(this).closest('tr'), false);
}); });
$('#' + Settings.FORM_ID).on('keyup', function(e){ $('#' + Settings.FORM_ID).on('keyup', function(e){
@ -198,10 +220,11 @@ $(document).ready(function(){
} }
if (sibling.hasClass(Settings.ADD_DEL_BUTTONS_CLASS)) { if (sibling.hasClass(Settings.ADD_DEL_BUTTONS_CLASS)) {
sibling.find('.' + Settings.ADD_ROW_BUTTON_CLASS).click() sibling.find('.' + Settings.ADD_ROW_BUTTON_CLASS).click();
sibling.find("." + Settings.ADD_CATEGORY_BUTTON_CLASS).click();
// set focus to the first input in the new row // set focus to the first input in the new row
$target.closest('table').find('tr.inputs input:first').focus() $target.closest('table').find('tr.inputs input:first').focus();
} }
} }
@ -924,8 +947,9 @@ $('body').on('click', '.save-button', function(e){
function makeTable(setting, keypath, setting_value, isLocked) { function makeTable(setting, keypath, setting_value, isLocked) {
var isArray = !_.has(setting, 'key'); var isArray = !_.has(setting, 'key');
var isHash = !isArray; var categoryKey = setting.categorize_by_key;
var isCategorized = !!categoryKey && isArray;
if (!isArray && setting.can_order) { if (!isArray && setting.can_order) {
setting.can_order = false; setting.can_order = false;
} }
@ -939,9 +963,10 @@ function makeTable(setting, keypath, setting_value, isLocked) {
var nonDeletableRowKey = setting["non-deletable-row-key"]; var nonDeletableRowKey = setting["non-deletable-row-key"];
var nonDeletableRowValues = setting["non-deletable-row-values"]; var nonDeletableRowValues = setting["non-deletable-row-values"];
html += "<table class='table table-bordered " + (isLocked ? "locked-table" : "") + "' data-short-name='" + setting.name html += "<table class='table table-bordered " + (isLocked ? "locked-table" : "") + "' " +
+ "' name='" + keypath + "' id='" + (typeof setting.html_id !== 'undefined' ? setting.html_id : keypath) "data-short-name='" + setting.name + "' name='" + keypath + "' " +
+ "' data-setting-type='" + (isArray ? 'array' : 'hash') + "'>"; "id='" + (!_.isUndefined(setting.html_id) ? setting.html_id : keypath) + "' " +
"data-setting-type='" + (isArray ? 'array' : 'hash') + "'>";
if (setting.caption) { if (setting.caption) {
html += "<caption>" + setting.caption + "</caption>" html += "<caption>" + setting.caption + "</caption>"
@ -974,25 +999,43 @@ function makeTable(setting, keypath, setting_value, isLocked) {
html += "<td class='key'><strong>" + setting.key.label + "</strong></td>" // Key html += "<td class='key'><strong>" + setting.key.label + "</strong></td>" // Key
} }
var numVisibleColumns = 0;
_.each(setting.columns, function(col) { _.each(setting.columns, function(col) {
if (!col.hidden) numVisibleColumns++;
html += "<td " + (col.hidden ? "style='display: none;'" : "") + "class='data " + html += "<td " + (col.hidden ? "style='display: none;'" : "") + "class='data " +
(col.class ? col.class : '') + "'><strong>" + col.label + "</strong></td>" // Data (col.class ? col.class : '') + "'><strong>" + col.label + "</strong></td>" // Data
}) })
if (!isLocked && !setting.read_only) { if (!isLocked && !setting.read_only) {
if (setting.can_order) { if (setting.can_order) {
numVisibleColumns++;
html += "<td class='" + Settings.REORDER_BUTTONS_CLASSES + html += "<td class='" + Settings.REORDER_BUTTONS_CLASSES +
"'><a href='javascript:void(0);' class='glyphicon glyphicon-sort'></a></td>"; "'><a href='javascript:void(0);' class='glyphicon glyphicon-sort'></a></td>";
} }
html += "<td class='" + Settings.ADD_DEL_BUTTONS_CLASSES + "'></td></tr>" numVisibleColumns++;
html += "<td class='" + Settings.ADD_DEL_BUTTONS_CLASSES + "'></td></tr>";
} }
// populate rows in the table from existing values // populate rows in the table from existing values
var row_num = 1; var row_num = 1;
if (keypath.length > 0 && _.size(setting_value) > 0) { if (keypath.length > 0 && _.size(setting_value) > 0) {
var rowIsObject = setting.columns.length > 1;
_.each(setting_value, function(row, rowIndexOrName) { _.each(setting_value, function(row, rowIndexOrName) {
html += "<tr class='" + Settings.DATA_ROW_CLASS + "'" + (isArray ? "" : "name='" + keypath + "." + rowIndexOrName + "'") + ">" var categoryPair = {};
var categoryValue = "";
if (isCategorized) {
categoryValue = rowIsObject ? row[categoryKey] : row;
categoryPair[categoryKey] = categoryValue;
if (_.findIndex(setting_value, categoryPair) === rowIndexOrName) {
html += makeTableCategoryHeader(categoryKey, categoryValue, numVisibleColumns, setting.can_add_new_categories, "");
}
}
html += "<tr class='" + Settings.DATA_ROW_CLASS + "' " +
(isCategorized ? ("data-category='" + categoryValue + "'") : "") + " " +
(isArray ? "" : "name='" + keypath + "." + rowIndexOrName + "'") + ">";
if (setting.numbered === true) { if (setting.numbered === true) {
html += "<td class='numbered'>" + row_num + "</td>" html += "<td class='numbered'>" + row_num + "</td>"
@ -1006,8 +1049,8 @@ function makeTable(setting, keypath, setting_value, isLocked) {
_.each(setting.columns, function(col) { _.each(setting.columns, function(col) {
var colValue, colName;
if (isArray) { if (isArray) {
rowIsObject = setting.columns.length > 1;
colValue = rowIsObject ? row[col.name] : row; colValue = rowIsObject ? row[col.name] : row;
colName = keypath + "[" + rowIndexOrName + "]" + (rowIsObject ? "." + col.name : ""); colName = keypath + "[" + rowIndexOrName + "]" + (rowIsObject ? "." + col.name : "");
} else { } else {
@ -1019,21 +1062,28 @@ function makeTable(setting, keypath, setting_value, isLocked) {
|| (nonDeletableRowKey === col.name && nonDeletableRowValues.indexOf(colValue) !== -1); || (nonDeletableRowKey === col.name && nonDeletableRowValues.indexOf(colValue) !== -1);
if (isArray && col.type === "checkbox" && col.editable) { if (isArray && col.type === "checkbox" && col.editable) {
html += "<td class='" + Settings.DATA_COL_CLASS + "'name='" + col.name + "'>" html +=
+ "<input type='checkbox' class='form-control table-checkbox' " "<td class='" + Settings.DATA_COL_CLASS + "'name='" + col.name + "'>" +
+ "name='" + colName + "'" + (colValue ? " checked" : "") + " /></td>"; "<input type='checkbox' class='form-control table-checkbox' " +
"name='" + colName + "'" + (colValue ? " checked" : "") + "/>" +
"</td>";
} else if (isArray && col.type === "time" && col.editable) { } else if (isArray && col.type === "time" && col.editable) {
html += "<td class='" + Settings.DATA_COL_CLASS + "'name='" + col.name + "'>" html +=
+ "<input type='time' class='form-control table-time' " "<td class='" + Settings.DATA_COL_CLASS + "'name='" + col.name + "'>" +
+ "name='" + colName + "' value='" + (colValue || col.default || "00:00") + "' /></td>"; "<input type='time' class='form-control table-time' name='" + colName + "' " +
"value='" + (colValue || col.default || "00:00") + "'/>" +
"</td>";
} else { } else {
// Use a hidden input so that the values are posted. // Use a hidden input so that the values are posted.
html += "<td " + (col.hidden ? "style='display: none;'" : "") + "class='" + Settings.DATA_COL_CLASS + html +=
"' name='" + colName + "'>" + colValue + "<input type='hidden' name='" + colName + "<td class='" + Settings.DATA_COL_CLASS + "' " + (col.hidden ? "style='display: none;'" : "") +
"' value='" + colValue + "'/></td>"; "name='" + colName + "'>" +
colValue +
"<input type='hidden' name='" + colName + "' value='" + colValue + "'/>" +
"</td>";
} }
}) });
if (!isLocked && !setting.read_only) { if (!isLocked && !setting.read_only) {
if (setting.can_order) { if (setting.can_order) {
@ -1051,24 +1101,53 @@ function makeTable(setting, keypath, setting_value, isLocked) {
html += "</tr>" html += "</tr>"
if (isCategorized && setting.can_add_new_rows && _.findLastIndex(setting_value, categoryPair) === rowIndexOrName) {
html += makeTableInputs(setting, categoryPair, categoryValue);
}
row_num++ row_num++
}); });
} }
// populate inputs in the table for new values // populate inputs in the table for new values
if (!isLocked && !setting.read_only && setting.can_add_new_rows) { if (!isLocked && !setting.read_only) {
html += makeTableInputs(setting) if (setting.can_add_new_categories) {
html += makeTableCategoryInput(setting, numVisibleColumns);
}
if (setting.can_add_new_rows || setting.can_add_new_categories) {
html += makeTableInputs(setting, {}, "");
}
} }
html += "</table>" html += "</table>"
return html; return html;
} }
function makeTableInputs(setting) { function makeTableCategoryHeader(categoryKey, categoryValue, numVisibleColumns, canRemove, message) {
var html = "<tr class='inputs'>" var html =
"<tr class='" + Settings.DATA_CATEGORY_CLASS + "' data-key='" + categoryKey + "' data-category='" + categoryValue + "'>" +
"<td colspan='" + (numVisibleColumns - 1) + "' class='" + Settings.TOGGLE_CATEGORY_COLUMN_CLASS + "'>" +
"<span class='" + Settings.TOGGLE_CATEGORY_SPAN_CLASSES + " " + Settings.TOGGLE_CATEGORY_EXPANDED_CLASS + "'></span>" +
"<span message='" + message + "'>" + categoryValue + "</span>" +
"</td>" +
((canRemove) ? (
"<td class='" + Settings.ADD_DEL_BUTTONS_CLASSES + "'>" +
"<a href='javascript:void(0);' class='" + Settings.DEL_CATEGORY_SPAN_CLASSES + "'></a>" +
"</td>"
) : (
"<td></td>"
)) +
"</tr>";
return html;
}
function makeTableInputs(setting, initialValues, categoryValue) {
var html = "<tr class='inputs'" + (setting.can_add_new_categories && !categoryValue ? " hidden" : "") + " " +
(categoryValue ? ("data-category='" + categoryValue + "'") : "") + " " +
(setting.categorize_by_key ? ("data-keep-field='" + setting.categorize_by_key + "'") : "") + ">";
if (setting.numbered === true) { if (setting.numbered === true) {
html += "<td class='numbered'></td>" html += "<td class='numbered'></td>";
} }
if (setting.key) { if (setting.key) {
@ -1078,15 +1157,21 @@ function makeTableInputs(setting) {
} }
_.each(setting.columns, function(col) { _.each(setting.columns, function(col) {
var defaultValue = _.has(initialValues, col.name) ? initialValues[col.name] : col.default;
if (col.type === "checkbox") { if (col.type === "checkbox") {
html += "<td class='" + Settings.DATA_COL_CLASS + "'name='" + col.name + "'>" html +=
+ "<input type='checkbox' class='form-control table-checkbox' " "<td class='" + Settings.DATA_COL_CLASS + "'name='" + col.name + "'>" +
+ "name='" + col.name + "'" + (col.default ? " checked" : "") + "/></td>"; "<input type='checkbox' class='form-control table-checkbox' " +
"name='" + col.name + "'" + (defaultValue ? " checked" : "") + "/>" +
"</td>";
} else { } else {
html += "<td " + (col.hidden ? "style='display: none;'" : "") + "class='" + Settings.DATA_COL_CLASS + "'name='" + col.name + "'>\ html +=
<input type='text' class='form-control' placeholder='" + (col.placeholder ? col.placeholder : "") + "'\ "<td " + (col.hidden ? "style='display: none;'" : "") + " class='" + Settings.DATA_COL_CLASS + "' " +
value='" + (col.default ? col.default : "") + "' data-default='" + (col.default ? col.default : "") + "'" + (col.readonly ? " readonly" : "") + ">\ "name='" + col.name + "'>" +
</td>" "<input type='text' class='form-control' placeholder='" + (col.placeholder ? col.placeholder : "") + "' " +
"value='" + (defaultValue || "") + "' data-default='" + (defaultValue || "") + "'" +
(col.readonly ? " readonly" : "") + ">" +
"</td>";
} }
}) })
@ -1094,12 +1179,30 @@ function makeTableInputs(setting) {
html += "<td class='" + Settings.REORDER_BUTTONS_CLASSES + "'></td>" html += "<td class='" + Settings.REORDER_BUTTONS_CLASSES + "'></td>"
} }
html += "<td class='" + Settings.ADD_DEL_BUTTONS_CLASSES + html += "<td class='" + Settings.ADD_DEL_BUTTONS_CLASSES +
"'><a href='javascript:void(0);' class='glyphicon glyphicon-plus " + Settings.ADD_ROW_BUTTON_CLASS + "'></a></td>" "'><a href='javascript:void(0);' class='" + Settings.ADD_ROW_SPAN_CLASSES + "'></a></td>"
html += "</tr>" html += "</tr>"
return html return html
} }
function makeTableCategoryInput(setting, numVisibleColumns) {
var canAddRows = setting.can_add_new_rows;
var categoryKey = setting.categorize_by_key;
var placeholder = setting.new_category_placeholder || "";
var message = setting.new_category_message || "";
var html =
"<tr class='" + Settings.DATA_CATEGORY_CLASS + " inputs' data-can-add-rows='" + canAddRows + "' " +
"data-key='" + categoryKey + "' data-message='" + message + "'>" +
"<td colspan='" + (numVisibleColumns - 1) + "'>" +
"<input type='text' class='form-control' placeholder='" + placeholder + "'/>" +
"</td>" +
"<td class='" + Settings.ADD_DEL_BUTTONS_CLASSES + "'>" +
"<a href='javascript:void(0);' class='" + Settings.ADD_CATEGORY_SPAN_CLASSES + "'></a>" +
"</td>" +
"</tr>";
return html;
}
function badgeSidebarForDifferences(changedElement) { function badgeSidebarForDifferences(changedElement) {
// figure out which group this input is in // figure out which group this input is in
var panelParentID = changedElement.closest('.panel').attr('id'); var panelParentID = changedElement.closest('.panel').attr('id');
@ -1138,13 +1241,12 @@ function badgeSidebarForDifferences(changedElement) {
$("a[href='#" + panelParentID + "'] .badge").html(badgeValue); $("a[href='#" + panelParentID + "'] .badge").html(badgeValue);
} }
function addTableRow(add_glyphicon) { function addTableRow(row) {
var row = $(add_glyphicon).closest('tr') var table = row.parents('table');
var isArray = table.data('setting-type') === 'array';
var keepField = row.data("keep-field");
var table = row.parents('table') var columns = row.parent().children('.' + Settings.DATA_ROW_CLASS);
var isArray = table.data('setting-type') === 'array'
var columns = row.parent().children('.' + Settings.DATA_ROW_CLASS)
if (!isArray) { if (!isArray) {
// Check key spaces // Check key spaces
@ -1261,10 +1363,12 @@ function addTableRow(add_glyphicon) {
} else { } else {
console.log("Unknown table element") console.log("Unknown table element")
} }
}) });
input_clone.find('input').each(function(){ input_clone.children('td').each(function () {
$(this).val($(this).attr('data-default')); if ($(this).attr("name") !== keepField) {
$(this).find("input").val($(this).attr('data-default'));
}
}); });
if (isArray) { if (isArray) {
@ -1276,44 +1380,132 @@ function addTableRow(add_glyphicon) {
badgeSidebarForDifferences($(table)) badgeSidebarForDifferences($(table))
row.parent().append(input_clone) row.after(input_clone)
} }
function deleteTableRow(delete_glyphicon) { function deleteTableRow($row) {
var row = $(delete_glyphicon).closest('tr') var $table = $row.closest('table');
var categoryName = $row.data("category");
var isArray = $table.data('setting-type') === 'array';
var table = $(row).closest('table') $row.empty();
var isArray = table.data('setting-type') === 'array'
row.empty();
if (!isArray) { if (!isArray) {
row.html("<input type='hidden' class='form-control' name='" $row.html("<input type='hidden' class='form-control' name='" + $row.attr('name') + "' data-changed='true' value=''>");
+ row.attr('name') + "' data-changed='true' value=''>");
} else { } else {
if (table.find('.' + Settings.DATA_ROW_CLASS).length > 1) { if ($table.find('.' + Settings.DATA_ROW_CLASS + "[data-category='" + categoryName + "']").length <= 1) {
updateDataChangedForSiblingRows(row) // This is the last row of the category, so delete the header
$table.find('.' + Settings.DATA_CATEGORY_CLASS + "[data-category='" + categoryName + "']").remove();
}
if ($table.find('.' + Settings.DATA_ROW_CLASS).length > 1) {
updateDataChangedForSiblingRows($row);
// this isn't the last row - we can just remove it // this isn't the last row - we can just remove it
row.remove() $row.remove();
} else { } else {
// this is the last row, we can't remove it completely since we need to post an empty array // this is the last row, we can't remove it completely since we need to post an empty array
$row
row.removeClass(Settings.DATA_ROW_CLASS).removeClass(Settings.NEW_ROW_CLASS) .removeClass(Settings.DATA_ROW_CLASS)
row.addClass('empty-array-row') .removeClass(Settings.NEW_ROW_CLASS)
.removeAttr("data-category")
row.html("<input type='hidden' class='form-control' name='" + table.attr("name").replace('[]', '') .addClass('empty-array-row')
+ "' data-changed='true' value=''>"); .html("<input type='hidden' class='form-control' name='" + $table.attr("name").replace('[]', '') + "' " +
"data-changed='true' value=''>");
} }
} }
// we need to fire a change event on one of the remaining inputs so that the sidebar badge is updated // we need to fire a change event on one of the remaining inputs so that the sidebar badge is updated
badgeSidebarForDifferences($(table)) badgeSidebarForDifferences($table);
} }
function moveTableRow(move_glyphicon, move_up) { function addTableCategory($categoryInputRow) {
var row = $(move_glyphicon).closest('tr') var $input = $categoryInputRow.find("input").first();
var categoryValue = $input.prop("value");
if (!categoryValue || $categoryInputRow.closest("table").find("tr[data-category='" + categoryValue + "']").length !== 0) {
$categoryInputRow.addClass("has-warning");
setTimeout(function () {
$categoryInputRow.removeClass("has-warning");
}, 400);
return;
}
var $rowInput = $categoryInputRow.next(".inputs").clone();
if (!$rowInput) {
console.error("Error cloning inputs");
}
var canAddRows = $categoryInputRow.data("can-add-rows");
var message = $categoryInputRow.data("message");
var categoryKey = $categoryInputRow.data("key");
var width = 0;
$categoryInputRow
.children("td")
.each(function () {
width += $(this).prop("colSpan") || 1;
});
$input
.prop("value", "")
.focus();
$rowInput.find("td[name='" + categoryKey + "'] > input").first()
.prop("value", categoryValue);
$rowInput
.attr("data-category", categoryValue)
.addClass(Settings.NEW_ROW_CLASS);
var $newCategoryRow = $(makeTableCategoryHeader(categoryKey, categoryValue, width, true, " - " + message));
$newCategoryRow.addClass(Settings.NEW_ROW_CLASS);
$categoryInputRow
.before($newCategoryRow)
.before($rowInput);
if (canAddRows) {
$rowInput.removeAttr("hidden");
} else {
addTableRow($rowInput);
}
}
function deleteTableCategory($categoryHeaderRow) {
var categoryName = $categoryHeaderRow.data("category");
$categoryHeaderRow
.closest("table")
.find("tr[data-category='" + categoryName + "']")
.each(function () {
if ($(this).hasClass(Settings.DATA_ROW_CLASS)) {
deleteTableRow($(this));
} else {
$(this).remove();
}
});
}
function toggleTableCategory($categoryHeaderRow) {
var $icon = $categoryHeaderRow.find("." + Settings.TOGGLE_CATEGORY_SPAN_CLASS).first();
var categoryName = $categoryHeaderRow.data("category");
var wasExpanded = $icon.hasClass(Settings.TOGGLE_CATEGORY_EXPANDED_CLASS);
if (wasExpanded) {
$icon
.addClass(Settings.TOGGLE_CATEGORY_CONTRACTED_CLASS)
.removeClass(Settings.TOGGLE_CATEGORY_EXPANDED_CLASS);
} else {
$icon
.addClass(Settings.TOGGLE_CATEGORY_EXPANDED_CLASS)
.removeClass(Settings.TOGGLE_CATEGORY_CONTRACTED_CLASS);
}
$categoryHeaderRow
.closest("table")
.find("tr[data-category='" + categoryName + "']")
.toggleClass("contracted", wasExpanded);
}
function moveTableRow(row, move_up) {
var table = $(row).closest('table') var table = $(row).closest('table')
var isArray = table.data('setting-type') === 'array' var isArray = table.data('setting-type') === 'array'
if (!isArray) { if (!isArray) {