mirror of https://github.com/apache/cloudstack.git
-Add example network section
-Move example VPN section to detail view -Support reordering of list view items -Example reorder actions for service offerings
This commit is contained in:
parent
25fd6701b5
commit
a7c8c618a3
|
|
@ -6835,3 +6835,50 @@ div.panel.ui-dialog div.list-view div.fixed-header {
|
|||
background-position: -229px -586px;
|
||||
}
|
||||
|
||||
.moveTop .icon {
|
||||
background-position: -24px -161px;
|
||||
}
|
||||
|
||||
.moveTop:hover .icon {
|
||||
background-position: -24px -734px;
|
||||
}
|
||||
|
||||
.moveBottom .icon {
|
||||
background-position: -98px -161px;
|
||||
}
|
||||
|
||||
.moveBottom:hover .icon {
|
||||
background-position: -98px -734px;
|
||||
}
|
||||
|
||||
.moveUp .icon {
|
||||
background-position: -2px -161px;
|
||||
}
|
||||
|
||||
.moveUp:hover .icon {
|
||||
background-position: -2px -734px;
|
||||
}
|
||||
|
||||
.moveDown .icon {
|
||||
background-position: -55px -161px;
|
||||
}
|
||||
|
||||
.moveDown:hover .icon {
|
||||
background-position: -55px -734px;
|
||||
}
|
||||
|
||||
.moveDrag .icon {
|
||||
cursor: move;
|
||||
/*+border-radius:10px;*/
|
||||
-moz-border-radius: 10px;
|
||||
-webkit-border-radius: 10px;
|
||||
-khtml-border-radius: 10px;
|
||||
border-radius: 10px 10px 10px 10px;
|
||||
background-position: -74px -162px;
|
||||
}
|
||||
|
||||
.moveDrag:hover .icon {
|
||||
background-color: #FFFFFF;
|
||||
cursor: move !important;
|
||||
}
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 95 KiB |
|
|
@ -68,6 +68,45 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
|
||||
reorder: {
|
||||
moveTop: {
|
||||
action: function(args) {
|
||||
setTimeout(function() {
|
||||
args.response.success();
|
||||
}, 500);
|
||||
}
|
||||
},
|
||||
moveBottom: {
|
||||
action: function(args) {
|
||||
setTimeout(function() {
|
||||
args.response.success();
|
||||
}, 500);
|
||||
}
|
||||
},
|
||||
moveUp: {
|
||||
action: function(args) {
|
||||
setTimeout(function() {
|
||||
args.response.success();
|
||||
}, 500);
|
||||
}
|
||||
},
|
||||
moveDown: {
|
||||
action: function(args) {
|
||||
setTimeout(function() {
|
||||
args.response.success();
|
||||
}, 500);
|
||||
}
|
||||
},
|
||||
moveDrag: {
|
||||
action: function(args) {
|
||||
setTimeout(function() {
|
||||
args.response.success();
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
dataProvider: function(args) {
|
||||
setTimeout(function() {
|
||||
args.response.success({
|
||||
|
|
@ -90,6 +129,45 @@
|
|||
memory: { label: 'Memory' },
|
||||
domain: { label: 'Domain'}
|
||||
},
|
||||
|
||||
reorder: {
|
||||
moveTop: {
|
||||
action: function(args) {
|
||||
setTimeout(function() {
|
||||
args.response.success();
|
||||
}, 500);
|
||||
}
|
||||
},
|
||||
moveBottom: {
|
||||
action: function(args) {
|
||||
setTimeout(function() {
|
||||
args.response.success();
|
||||
}, 500);
|
||||
}
|
||||
},
|
||||
moveUp: {
|
||||
action: function(args) {
|
||||
setTimeout(function() {
|
||||
args.response.success();
|
||||
}, 500);
|
||||
}
|
||||
},
|
||||
moveDown: {
|
||||
action: function(args) {
|
||||
setTimeout(function() {
|
||||
args.response.success();
|
||||
}, 500);
|
||||
}
|
||||
},
|
||||
moveDrag: {
|
||||
action: function(args) {
|
||||
setTimeout(function() {
|
||||
args.response.success();
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
add: {
|
||||
label: 'Add system service offering',
|
||||
|
|
@ -168,6 +246,44 @@
|
|||
});
|
||||
},
|
||||
|
||||
reorder: {
|
||||
moveTop: {
|
||||
action: function(args) {
|
||||
setTimeout(function() {
|
||||
args.response.success();
|
||||
}, 500);
|
||||
}
|
||||
},
|
||||
moveBottom: {
|
||||
action: function(args) {
|
||||
setTimeout(function() {
|
||||
args.response.success();
|
||||
}, 500);
|
||||
}
|
||||
},
|
||||
moveUp: {
|
||||
action: function(args) {
|
||||
setTimeout(function() {
|
||||
args.response.success();
|
||||
}, 500);
|
||||
}
|
||||
},
|
||||
moveDown: {
|
||||
action: function(args) {
|
||||
setTimeout(function() {
|
||||
args.response.success();
|
||||
}, 500);
|
||||
}
|
||||
},
|
||||
moveDrag: {
|
||||
action: function(args) {
|
||||
setTimeout(function() {
|
||||
args.response.success();
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
add: {
|
||||
label: 'Add disk offering',
|
||||
|
|
@ -251,6 +367,44 @@
|
|||
traffictype: { label: 'Traffic Type'}
|
||||
},
|
||||
|
||||
reorder: {
|
||||
moveTop: {
|
||||
action: function(args) {
|
||||
setTimeout(function() {
|
||||
args.response.success();
|
||||
}, 500);
|
||||
}
|
||||
},
|
||||
moveBottom: {
|
||||
action: function(args) {
|
||||
setTimeout(function() {
|
||||
args.response.success();
|
||||
}, 500);
|
||||
}
|
||||
},
|
||||
moveUp: {
|
||||
action: function(args) {
|
||||
setTimeout(function() {
|
||||
args.response.success();
|
||||
}, 500);
|
||||
}
|
||||
},
|
||||
moveDown: {
|
||||
action: function(args) {
|
||||
setTimeout(function() {
|
||||
args.response.success();
|
||||
}, 500);
|
||||
}
|
||||
},
|
||||
moveDrag: {
|
||||
action: function(args) {
|
||||
setTimeout(function() {
|
||||
args.response.success();
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
add: {
|
||||
label: 'Add network offering',
|
||||
|
|
@ -327,7 +481,7 @@
|
|||
|
||||
vlanId: { label: 'VLAN ID', isHidden: true, dependsOn: 'specifyVlan'},
|
||||
|
||||
supportedServices: {
|
||||
supportedServices: {
|
||||
label: 'Supported Services',
|
||||
|
||||
dynamic: function(args) {
|
||||
|
|
@ -343,7 +497,7 @@
|
|||
};
|
||||
|
||||
fields[id.isEnabled] = { label: this, isBoolean: true };
|
||||
fields[id.provider] = {
|
||||
fields[id.provider] = {
|
||||
label: this + ' Provider',
|
||||
isHidden: true,
|
||||
dependsOn: id.isEnabled,
|
||||
|
|
@ -368,7 +522,7 @@
|
|||
tags: { label: 'Tags' }
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
notification: {
|
||||
poll: testData.notifications.testPoll
|
||||
},
|
||||
|
|
|
|||
|
|
@ -6,6 +6,49 @@
|
|||
label: 'Select view'
|
||||
},
|
||||
sections: {
|
||||
networks: {
|
||||
type: 'select',
|
||||
title: 'Networks',
|
||||
listView: {
|
||||
filters: {
|
||||
all: { label: 'All' },
|
||||
mine: { label: 'My network' }
|
||||
},
|
||||
fields: {
|
||||
displaytext: { label: 'Name' },
|
||||
traffictype: { label: 'Traffic Type' },
|
||||
gateway: { label: 'Gateway' },
|
||||
vlan: { label: 'VLAN' }
|
||||
},
|
||||
dataProvider: testData.dataProvider.listView('networks'),
|
||||
|
||||
detailView: {
|
||||
name: 'Network details',
|
||||
viewAll: { path: 'network.ipAddresses', label: 'IP Addresses' },
|
||||
tabs: {
|
||||
details: {
|
||||
title: 'Details',
|
||||
fields: [
|
||||
{
|
||||
displaytext: { label: 'Name' }
|
||||
},
|
||||
{
|
||||
name: { label: 'Short name' },
|
||||
traffictype: { label: 'Traffic Type' },
|
||||
gateway: { label: 'Gateway' },
|
||||
vlan: { label: 'VLAN' }
|
||||
},
|
||||
{
|
||||
startip: { label: 'Start IP' },
|
||||
endip: { label: 'End IP' }
|
||||
}
|
||||
],
|
||||
dataProvider: testData.dataProvider.detailView('networks')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
ipAddresses: {
|
||||
type: 'select',
|
||||
title: 'IP Addresses',
|
||||
|
|
@ -86,9 +129,6 @@
|
|||
})
|
||||
},
|
||||
messages: {
|
||||
confirm: function(args) {
|
||||
return 'Are you sure you want to enable static NAT?';
|
||||
},
|
||||
notification: function(args) {
|
||||
return 'Enabled Static NAT';
|
||||
}
|
||||
|
|
@ -113,48 +153,6 @@
|
|||
notification: {
|
||||
poll: testData.notifications.customPoll({ isstaticnat: false })
|
||||
}
|
||||
},
|
||||
enableVPN: {
|
||||
label: 'Enable VPN',
|
||||
action: function(args) {
|
||||
args.response.success();
|
||||
},
|
||||
messages: {
|
||||
confirm: function(args) {
|
||||
return 'Please confirm that you want VPN enabled for this IP address.';
|
||||
},
|
||||
notification: function(args) {
|
||||
return 'Enabled VPN';
|
||||
},
|
||||
complete: function(args) {
|
||||
return 'VPN is now enabled for IP ' + args.publicip + '.'
|
||||
+ '<br/>Your IPsec pre-shared key is:<br/>' + args.presharedkey;
|
||||
}
|
||||
},
|
||||
notification: {
|
||||
poll: testData.notifications.customPoll({
|
||||
publicip: '10.2.2.1',
|
||||
presharedkey: '23fudh881ssx88199488PP!#Dwdw',
|
||||
vpnenabled: true
|
||||
})
|
||||
}
|
||||
},
|
||||
disableVPN: {
|
||||
label: 'Disable VPN',
|
||||
action: function(args) {
|
||||
args.response.success();
|
||||
},
|
||||
messages: {
|
||||
confirm: function(args) {
|
||||
return 'Are you sure you want to disable VPN?';
|
||||
},
|
||||
notification: function(args) {
|
||||
return 'Disabled VPN';
|
||||
}
|
||||
},
|
||||
notification: {
|
||||
poll: testData.notifications.customPoll({ vpnenabled: false })
|
||||
}
|
||||
}
|
||||
},
|
||||
dataProvider: testData.dataProvider.listView('network'),
|
||||
|
|
@ -174,6 +172,87 @@
|
|||
|
||||
return disabledTabs;
|
||||
},
|
||||
actions: {
|
||||
enableStaticNAT: {
|
||||
label: 'Enable static NAT',
|
||||
action: {
|
||||
noAdd: true,
|
||||
custom: cloudStack.uiCustom.enableStaticNAT({
|
||||
listView: cloudStack.sections.instances,
|
||||
action: function(args) {
|
||||
args.response.success();
|
||||
}
|
||||
})
|
||||
},
|
||||
messages: {
|
||||
notification: function(args) {
|
||||
return 'Enabled Static NAT';
|
||||
}
|
||||
},
|
||||
notification: {
|
||||
poll: testData.notifications.customPoll({ isstaticnat: true })
|
||||
}
|
||||
},
|
||||
disableStaticNAT: {
|
||||
label: 'Disable static NAT',
|
||||
action: function(args) {
|
||||
args.response.success();
|
||||
},
|
||||
messages: {
|
||||
confirm: function(args) {
|
||||
return 'Are you sure you want to disable static NAT?';
|
||||
},
|
||||
notification: function(args) {
|
||||
return 'Disabled Static NAT';
|
||||
}
|
||||
},
|
||||
notification: {
|
||||
poll: testData.notifications.customPoll({ isstaticnat: false })
|
||||
}
|
||||
},
|
||||
enableVPN: {
|
||||
label: 'Enable VPN',
|
||||
action: function(args) {
|
||||
args.response.success();
|
||||
},
|
||||
messages: {
|
||||
confirm: function(args) {
|
||||
return 'Please confirm that you want VPN enabled for this IP address.';
|
||||
},
|
||||
notification: function(args) {
|
||||
return 'Enabled VPN';
|
||||
},
|
||||
complete: function(args) {
|
||||
return 'VPN is now enabled for IP ' + args.publicip + '.'
|
||||
+ '<br/>Your IPsec pre-shared key is:<br/>' + args.presharedkey;
|
||||
}
|
||||
},
|
||||
notification: {
|
||||
poll: testData.notifications.customPoll({
|
||||
publicip: '10.2.2.1',
|
||||
presharedkey: '23fudh881ssx88199488PP!#Dwdw',
|
||||
vpnenabled: true
|
||||
})
|
||||
}
|
||||
},
|
||||
disableVPN: {
|
||||
label: 'Disable VPN',
|
||||
action: function(args) {
|
||||
args.response.success();
|
||||
},
|
||||
messages: {
|
||||
confirm: function(args) {
|
||||
return 'Are you sure you want to disable VPN?';
|
||||
},
|
||||
notification: function(args) {
|
||||
return 'Disabled VPN';
|
||||
}
|
||||
},
|
||||
notification: {
|
||||
poll: testData.notifications.customPoll({ vpnenabled: false })
|
||||
}
|
||||
}
|
||||
},
|
||||
tabs: {
|
||||
details: {
|
||||
title: 'Details',
|
||||
|
|
|
|||
|
|
@ -111,31 +111,15 @@
|
|||
detailView: function(section) {
|
||||
return function(args) {
|
||||
setTimeout(function() {
|
||||
var item = $.grep(testData.data[section], function(elem) {
|
||||
var pulledData = $.grep(testData.data[section], function(elem) {
|
||||
return elem.id == args.id;
|
||||
});
|
||||
})[0];
|
||||
|
||||
var item = $.extend(true, {}, pulledData, args.jsonObj);
|
||||
|
||||
args.response.success({
|
||||
actionFilter: function(args) {
|
||||
var allowedActions = args.context.actions;
|
||||
var disallowedActions = [];
|
||||
var item = args.context.item;
|
||||
var status = item.state;
|
||||
|
||||
if (status == 'Running' || status == 'Starting') {
|
||||
disallowedActions.push('start');
|
||||
} else if (status == 'Stopped' || status == 'Stopping') {
|
||||
disallowedActions.push('stop');
|
||||
disallowedActions.push('restart');
|
||||
}
|
||||
|
||||
allowedActions = $.grep(allowedActions, function(item) {
|
||||
return $.inArray(item, disallowedActions) == -1;
|
||||
});
|
||||
|
||||
return allowedActions;
|
||||
},
|
||||
data: item[0]
|
||||
actionFilter: testData.actionFilter,
|
||||
data: item
|
||||
});
|
||||
}, 300);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
*/
|
||||
var withinResizeBounds = function($elem, posX) {
|
||||
var leftBound = $elem.offset().left + $elem.width() / 1.2;
|
||||
|
||||
|
||||
return posX > leftBound;
|
||||
};
|
||||
|
||||
|
|
@ -165,7 +165,7 @@
|
|||
|
||||
computeEvenOddRows();
|
||||
};
|
||||
|
||||
|
||||
var resizeHeaders = function() {
|
||||
var $thead = $table.closest('div.data-table').find('thead');
|
||||
var $tbody = $table.find('tbody');
|
||||
|
|
@ -209,6 +209,13 @@
|
|||
refresh: function() {
|
||||
resizeHeaders();
|
||||
computeEvenOddRows();
|
||||
},
|
||||
|
||||
selectRow: function(rowIndex) {
|
||||
var $row = $($table.find('tbody tr')[rowIndex]);
|
||||
|
||||
$row.siblings().removeClass('selected');
|
||||
$row.addClass('selected');
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -67,6 +67,116 @@
|
|||
var id = args.id;
|
||||
var context = $detailView.data('view-args').context;
|
||||
var _custom = $detailView.data('_custom');
|
||||
var customAction = action.action.custom;
|
||||
var noAdd = action.noAdd;
|
||||
|
||||
var updateTabContent = function(newData) {
|
||||
var $detailViewElems = $detailView.find('ul.ui-tabs-nav, .detail-group').remove();
|
||||
$detailView.tabs('destroy');
|
||||
$detailView.data('view-args').jsonObj = newData;
|
||||
|
||||
makeTabs(
|
||||
$detailView,
|
||||
$detailView.data('view-args').tabs,
|
||||
{
|
||||
context: context,
|
||||
tabFilter: $detailView.data('view-args').tabFilter,
|
||||
newData: newData
|
||||
}
|
||||
).appendTo($detailView);
|
||||
|
||||
$detailView.tabs();
|
||||
};
|
||||
|
||||
var performAction = function(data, options) {
|
||||
if (!options) options = {};
|
||||
|
||||
var $form = options.$form;
|
||||
|
||||
if (customAction && !noAdd) {
|
||||
customAction({
|
||||
context: context,
|
||||
complete: function(args) {
|
||||
// Set loading appearance
|
||||
var $loading = $('<div>').addClass('loading-overlay');
|
||||
$detailView.prepend($loading);
|
||||
|
||||
args = args ? args : {};
|
||||
|
||||
var $item = args.$item;
|
||||
|
||||
notification.desc = messages.notification(args.messageArgs);
|
||||
notification._custom = args._custom;
|
||||
|
||||
addNotification(
|
||||
notification,
|
||||
|
||||
// Success
|
||||
function(args) {
|
||||
$loading.remove();
|
||||
updateTabContent(args.data);
|
||||
},
|
||||
|
||||
{},
|
||||
|
||||
// Error
|
||||
function(args) {}
|
||||
);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// Set loading appearance
|
||||
var $loading = $('<div>').addClass('loading-overlay');
|
||||
$detailView.prepend($loading);
|
||||
|
||||
action.action({
|
||||
data: data,
|
||||
_custom: _custom,
|
||||
ref: options.ref,
|
||||
context: $detailView.data('view-args').context,
|
||||
$form: $form,
|
||||
response: {
|
||||
success: function(args) {
|
||||
args = args ? args : {};
|
||||
notification._custom = args._custom;
|
||||
|
||||
if (additional && additional.success) additional.success(args);
|
||||
|
||||
// Setup notification
|
||||
addNotification(
|
||||
notification,
|
||||
function(args) {
|
||||
if ($detailView.is(':visible')) {
|
||||
$loading.remove();
|
||||
updateTabContent(args.data);
|
||||
}
|
||||
|
||||
if (messages.complete) {
|
||||
cloudStack.dialog.notice({
|
||||
message: messages.complete(args.data)
|
||||
});
|
||||
}
|
||||
if (additional && additional.complete) additional.complete($.extend(true, args, {
|
||||
$detailView: $detailView
|
||||
}));
|
||||
},
|
||||
|
||||
{},
|
||||
|
||||
// Error
|
||||
function(args) {
|
||||
|
||||
}
|
||||
);
|
||||
},
|
||||
error: function(args) {
|
||||
if (args.message)
|
||||
cloudStack.dialog.notice({ message: args.message });
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var externalLinkAction = action.action.externalLink;
|
||||
if (externalLinkAction) {
|
||||
|
|
@ -87,102 +197,39 @@
|
|||
+ 'width=' + externalLinkAction.width + ','
|
||||
+ 'height=' + externalLinkAction.height
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
notification.desc = messages.notification(messageArgs);
|
||||
notification.section = 'instances';
|
||||
|
||||
notification.desc = messages.notification(messageArgs);
|
||||
notification.section = 'instances';
|
||||
|
||||
var performAction = function(data, options) {
|
||||
if (!options) options = {};
|
||||
|
||||
var $form = options.$form;
|
||||
|
||||
// Set loading appearance
|
||||
var $loading = $('<div>').addClass('loading-overlay');
|
||||
$detailView.prepend($loading);
|
||||
|
||||
action.action({
|
||||
data: data,
|
||||
_custom: _custom,
|
||||
ref: options.ref,
|
||||
context: $detailView.data('view-args').context,
|
||||
$form: $form,
|
||||
response: {
|
||||
success: function(args) {
|
||||
args = args ? args : {};
|
||||
notification._custom = args._custom;
|
||||
|
||||
if (additional && additional.success) additional.success(args);
|
||||
|
||||
// Setup notification
|
||||
addNotification(
|
||||
notification,
|
||||
function(args) {
|
||||
if ($detailView.is(':visible')) {
|
||||
$loading.remove();
|
||||
|
||||
// Refresh actions
|
||||
loadTabContent(
|
||||
$detailView.find('.detail-group:visible'),
|
||||
$detailView.data('view-args'),
|
||||
{
|
||||
newData: args.data
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (messages.complete) {
|
||||
cloudStack.dialog.notice({
|
||||
message: messages.complete(args.data)
|
||||
});
|
||||
}
|
||||
if (additional && additional.complete) additional.complete($.extend(true, args, {
|
||||
$detailView: $detailView
|
||||
}));
|
||||
},
|
||||
|
||||
{},
|
||||
|
||||
// Error
|
||||
function(args) {
|
||||
|
||||
}
|
||||
);
|
||||
if (!action.createForm) {
|
||||
if (messages && messages.confirm) {
|
||||
cloudStack.dialog.confirm({
|
||||
message: messages.confirm(messageArgs),
|
||||
action: function() {
|
||||
performAction({
|
||||
id: id
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
performAction({ id: id });
|
||||
}
|
||||
} else {
|
||||
cloudStack.dialog.createForm({
|
||||
form: action.createForm,
|
||||
after: function(args) {
|
||||
performAction(args.data, {
|
||||
ref: args.ref,
|
||||
context: $detailView.data('view-args').context,
|
||||
$form: args.$form
|
||||
});
|
||||
},
|
||||
error: function(args) {
|
||||
if (args.message)
|
||||
cloudStack.dialog.notice({ message: args.message });
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
if (!action.createForm)
|
||||
cloudStack.dialog.confirm({
|
||||
message: messages.confirm(messageArgs),
|
||||
action: function() {
|
||||
performAction({
|
||||
ref: {
|
||||
id: id
|
||||
});
|
||||
}
|
||||
});
|
||||
else {
|
||||
cloudStack.dialog.createForm({
|
||||
form: action.createForm,
|
||||
after: function(args) {
|
||||
performAction(args.data, {
|
||||
ref: args.ref,
|
||||
context: $detailView.data('view-args').context,
|
||||
$form: args.$form
|
||||
});
|
||||
},
|
||||
ref: {
|
||||
id: id
|
||||
},
|
||||
context: $detailView.data('view-args').context
|
||||
});
|
||||
},
|
||||
context: $detailView.data('view-args').context
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -207,7 +254,7 @@
|
|||
*/
|
||||
edit: function($detailView, args) {
|
||||
if ($detailView.find('.button.done').size()) return false;
|
||||
|
||||
|
||||
// Convert value TDs
|
||||
var $inputs = $detailView.find('input[type=text], select');
|
||||
var action = args.actions[args.actionName];
|
||||
|
|
@ -235,7 +282,7 @@
|
|||
);
|
||||
$value.data('detail-view-selected-option', $input.find('option:selected').val());
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
var applyEdits = function($inputs, $editButton) {
|
||||
|
|
@ -269,7 +316,7 @@
|
|||
convertInputs($inputs);
|
||||
addNotification(
|
||||
notificationArgs, function(data) {}, []
|
||||
);
|
||||
);
|
||||
} else {
|
||||
$loading.appendTo($detailView);
|
||||
addNotification(
|
||||
|
|
@ -505,8 +552,8 @@
|
|||
if (tabData.preFilter) {
|
||||
hiddenFields = tabData.preFilter({
|
||||
context: context,
|
||||
fields: $.map(fields, function(fieldGroup) {
|
||||
return $.map(fieldGroup, function(value, key) { return key; });
|
||||
fields: $.map(fields, function(fieldGroup) {
|
||||
return $.map(fieldGroup, function(value, key) { return key; });
|
||||
})
|
||||
});
|
||||
}
|
||||
|
|
@ -634,6 +681,7 @@
|
|||
var isMultiple = tabs.multiple || tabs.isMultiple;
|
||||
var viewAll = args.viewAll;
|
||||
var $detailView = $tabContent.closest('.detail-view');
|
||||
var jsonObj = $detailView.data('view-args').jsonObj;
|
||||
|
||||
if (tabs.custom) {
|
||||
return tabs.custom({
|
||||
|
|
@ -659,14 +707,14 @@
|
|||
return dataProvider({
|
||||
tab: targetTabID,
|
||||
id: args.id,
|
||||
jsonObj: options.newData ? $.extend(true, {}, args.jsonObj, options.newData) : args.jsonObj,
|
||||
jsonObj: jsonObj,
|
||||
context: args.context,
|
||||
response: {
|
||||
success: function(args) {
|
||||
if (options.newData) {
|
||||
$.extend(args.data, options.newData);
|
||||
}
|
||||
|
||||
|
||||
if (args._custom) {
|
||||
$detailView.data('_custom', args._custom);
|
||||
}
|
||||
|
|
@ -708,6 +756,78 @@
|
|||
});
|
||||
};
|
||||
|
||||
var makeTabs = function($detailView, tabs, options) {
|
||||
if (!options) options = {};
|
||||
|
||||
var $tabs = $('<ul>');
|
||||
var $tabContentGroup = $('<div>');
|
||||
var removedTabs = [];
|
||||
var tabFilter = options.tabFilter;
|
||||
var context = options.context ? options.context : {};
|
||||
|
||||
if (options.newData) {
|
||||
$.extend(
|
||||
context[$detailView.data('view-args').section][0],
|
||||
options.newData
|
||||
);
|
||||
}
|
||||
|
||||
if (tabFilter) {
|
||||
removedTabs = tabFilter({
|
||||
context: context
|
||||
});
|
||||
}
|
||||
|
||||
$.each(tabs, function(key, value) {
|
||||
// Don't render tab, if filtered out
|
||||
if ($.inArray(key, removedTabs) > -1) return true;
|
||||
|
||||
var propGroup = key;
|
||||
var prop = value;
|
||||
var title = prop.title;
|
||||
var $tab = $('<li>').attr('detail-view-tab', true).appendTo($tabs);
|
||||
|
||||
var $tabLink = $('<a></a>').attr({
|
||||
href: '#details-tab-' + propGroup
|
||||
}).html(title).appendTo($tab);
|
||||
|
||||
var $tabContent = $('<div>').attr({
|
||||
id: 'details-tab-' + propGroup
|
||||
}).addClass('detail-group').appendTo($tabContentGroup);
|
||||
|
||||
$tabContent.data('detail-view-tab-id', key);
|
||||
$tabContent.data('detail-view-tab-data', value);
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
$tabs.find('li:first').addClass('first');
|
||||
$tabs.find('li:last').addClass('last');
|
||||
|
||||
return $.merge(
|
||||
$tabs, $tabContentGroup.children()
|
||||
);
|
||||
};
|
||||
|
||||
var replaceTabs = function($detailView, $newTabs, tabs, options) {
|
||||
var $detailViewElems = $detailView.find('ul.ui-tabs-nav, .detail-group');
|
||||
$detailView.tabs('destroy');
|
||||
$detailViewElems.remove();
|
||||
|
||||
makeTabs($detailView, tabs, options).appendTo($detailView);
|
||||
};
|
||||
|
||||
var makeToolbar = function() {
|
||||
return $('<div class="toolbar">')
|
||||
.append(
|
||||
$('<div>')
|
||||
.addClass('button refresh')
|
||||
.append(
|
||||
$('<span>').html('Refresh')
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
$.fn.detailView = function(args) {
|
||||
var $detailView = this;
|
||||
|
||||
|
|
@ -715,49 +835,13 @@
|
|||
$detailView.data('view-args', args);
|
||||
|
||||
// Create toolbar
|
||||
var $toolbar = $('<div class="toolbar">')
|
||||
.append(
|
||||
$('<div>')
|
||||
.addClass('button refresh')
|
||||
.append(
|
||||
$('<span>').html('Refresh')
|
||||
)
|
||||
)
|
||||
.appendTo($detailView);
|
||||
var $tabs = $('<ul></ul>').appendTo($detailView);
|
||||
var $toolbar = makeToolbar().appendTo($detailView);
|
||||
|
||||
// Get tab filter, if present
|
||||
var removedTabs = [];
|
||||
if (args.tabFilter) {
|
||||
removedTabs = args.tabFilter({
|
||||
context: args.context
|
||||
});
|
||||
}
|
||||
|
||||
// Make tabs
|
||||
$.each(args.tabs, function(key, value) {
|
||||
// Don't render tab, if filtered out
|
||||
if ($.inArray(key, removedTabs) > -1) return true;
|
||||
|
||||
var propGroup = key;
|
||||
var prop = value;
|
||||
var title = prop.title;
|
||||
var $tab = $('<li></li>').attr('detail-view-tab', true).appendTo($tabs);
|
||||
|
||||
var $tabLink = $('<a></a>').attr({
|
||||
href: '#details-tab-' + propGroup
|
||||
}).html(title).appendTo($tab);
|
||||
|
||||
var $tabContent = $('<div></div>').attr({
|
||||
id: 'details-tab-' + propGroup
|
||||
}).addClass('detail-group').appendTo($detailView);
|
||||
|
||||
$tabContent.data('detail-view-tab-id', key);
|
||||
$tabContent.data('detail-view-tab-data', value);
|
||||
});
|
||||
|
||||
$tabs.find('li:first').addClass('first');
|
||||
$tabs.find('li:last').addClass('last');
|
||||
// Create tabs
|
||||
var $tabs = makeTabs($detailView, args.tabs, {
|
||||
context: args.context,
|
||||
tabFilter: args.tabFilter
|
||||
}).appendTo($detailView);
|
||||
|
||||
$detailView.tabs();
|
||||
|
||||
|
|
|
|||
|
|
@ -314,7 +314,7 @@
|
|||
// Hide edit field, validate and save changes
|
||||
var showLabel = function(val, options) {
|
||||
if (!options) options = {};
|
||||
|
||||
|
||||
var oldVal = $label.html();
|
||||
$label.html(val);
|
||||
|
||||
|
|
@ -376,7 +376,7 @@
|
|||
'Unset value for ' + $instanceRow.find('td.name span').html()
|
||||
},
|
||||
function(args) {
|
||||
|
||||
|
||||
},
|
||||
[{ name: newName }]
|
||||
);
|
||||
|
|
@ -390,6 +390,62 @@
|
|||
}
|
||||
};
|
||||
|
||||
var rowActions = {
|
||||
_std: function($tr, action) {
|
||||
action();
|
||||
|
||||
$tr.closest('.data-table').dataTable('refresh');
|
||||
|
||||
setTimeout(function() {
|
||||
$tr.closest('.data-table').dataTable('selectRow', $tr.index());
|
||||
}, 0);
|
||||
},
|
||||
|
||||
moveTop: function($tr) {
|
||||
rowActions._std($tr, function() {
|
||||
$tr.closest('tbody').prepend($tr);
|
||||
$tr.closest('.list-view').animate({ scrollTop: 0 });
|
||||
});
|
||||
},
|
||||
|
||||
moveBottom: function($tr) {
|
||||
rowActions._std($tr, function() {
|
||||
$tr.closest('tbody').append($tr);
|
||||
$tr.closest('.list-view').animate({ scrollTop: 0 });
|
||||
});
|
||||
},
|
||||
|
||||
moveUp: function($tr) {
|
||||
rowActions._std($tr, function() {
|
||||
$tr.prev().before($tr);
|
||||
});
|
||||
},
|
||||
|
||||
moveDown: function($tr) {
|
||||
rowActions._std($tr, function() {
|
||||
$tr.next().after($tr);
|
||||
});
|
||||
},
|
||||
|
||||
moveTo: function($tr, index, after) {
|
||||
rowActions._std($tr, function() {
|
||||
var $target = $tr.closest('tbody').find('tr').filter(function() {
|
||||
return $(this).index() == index;
|
||||
});
|
||||
|
||||
if ($target.index() > $tr.index()) $target.after($tr);
|
||||
else $target.before($tr);
|
||||
|
||||
$tr.closest('.list-view').scrollTop($tr.position().top - $tr.height() * 2);
|
||||
|
||||
if (after)
|
||||
setTimeout(function() {
|
||||
after();
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Edit field text
|
||||
*
|
||||
|
|
@ -422,8 +478,20 @@
|
|||
return $editArea.hide();
|
||||
};
|
||||
|
||||
var createHeader = function(fields, $table, actions) {
|
||||
var renderActionCol = function(actions) {
|
||||
return $.grep(
|
||||
$.map(actions, function(value, key) {
|
||||
return key;
|
||||
}),
|
||||
function(elem) { return elem != 'add'; }
|
||||
).length;
|
||||
};
|
||||
|
||||
var createHeader = function(fields, $table, actions, options) {
|
||||
if (!options) options = {};
|
||||
|
||||
var $thead = $('<thead>').appendTo($table);
|
||||
var reorder = options.reorder;
|
||||
|
||||
$.each(fields, function(key) {
|
||||
var field = this;
|
||||
|
|
@ -434,7 +502,7 @@
|
|||
$th.html(field.label);
|
||||
});
|
||||
|
||||
if (actions) {
|
||||
if (actions && renderActionCol(actions)) {
|
||||
$thead.append(
|
||||
$('<th></th>')
|
||||
.html('Actions')
|
||||
|
|
@ -442,6 +510,12 @@
|
|||
);
|
||||
}
|
||||
|
||||
if (reorder) {
|
||||
$thead.append(
|
||||
$('<th>').html('Order').addClass('reorder-actions reduced-hide')
|
||||
);
|
||||
}
|
||||
|
||||
return $thead;
|
||||
};
|
||||
|
||||
|
|
@ -452,7 +526,7 @@
|
|||
$filters.append('<label>Filter By: </label>');
|
||||
|
||||
var $filterSelect = $('<select id="filterBy"></select>').appendTo($filters);
|
||||
|
||||
|
||||
if (filters)
|
||||
$.each(filters, function(key) {
|
||||
var $option = $('<option>').attr({
|
||||
|
|
@ -560,6 +634,7 @@
|
|||
section: args.section,
|
||||
context: args.context
|
||||
});
|
||||
|
||||
var $detailView, $detailsPanel;
|
||||
var panelArgs = {
|
||||
title: title,
|
||||
|
|
@ -585,6 +660,7 @@
|
|||
var addTableRows = function(fields, data, $tbody, actions, options) {
|
||||
if (!options) options = {};
|
||||
var rows = [];
|
||||
var reorder = options.reorder;
|
||||
|
||||
if (!data || ($.isArray(data) && !data.length)) {
|
||||
if (!$tbody.find('tr').size()) {
|
||||
|
|
@ -613,6 +689,7 @@
|
|||
$tr.appendTo($tbody);
|
||||
}
|
||||
|
||||
// Add field data
|
||||
$.each(fields, function(key) {
|
||||
var field = this;
|
||||
var $td = $('<td>')
|
||||
|
|
@ -645,11 +722,88 @@
|
|||
}
|
||||
});
|
||||
|
||||
// Add reorder actions
|
||||
if (reorder) {
|
||||
$('<td>').addClass('actions reorder').appendTo($tr).append(function() {
|
||||
var $td = $(this);
|
||||
|
||||
$.each(reorder, function(actionName, action) {
|
||||
var fnLabel = {
|
||||
moveTop: 'Move to top',
|
||||
moveUp: 'Move up one row',
|
||||
moveDown: 'Move down one row',
|
||||
moveDrag: 'Drag to new position'
|
||||
};
|
||||
|
||||
$('<div>')
|
||||
.addClass('action reorder')
|
||||
.addClass(actionName)
|
||||
.append(
|
||||
$('<span>').addClass('icon').html(' ')
|
||||
)
|
||||
.attr({
|
||||
title: fnLabel[actionName]
|
||||
})
|
||||
.appendTo($td)
|
||||
.click(function() {
|
||||
if (actionName == 'moveDrag') return false;
|
||||
|
||||
var rowIndex = $tr.index();
|
||||
rowActions[actionName]($tr);
|
||||
|
||||
action.action({
|
||||
response: {
|
||||
success: function(args) {
|
||||
$tr.closest('.data-table').dataTable('selectRow', $tr.index());
|
||||
},
|
||||
error: function(args) {
|
||||
// Move back to previous position
|
||||
rowActions.moveTo($tr, rowIndex);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Draggable action
|
||||
var initDraggable = function($tr) {
|
||||
var originalIndex;
|
||||
|
||||
return $tr.closest('tbody').sortable({
|
||||
handle: '.action.moveDrag',
|
||||
start: function(event, ui) {
|
||||
originalIndex = ui.item.index();
|
||||
},
|
||||
stop: function(event, ui) {
|
||||
rowActions._std($tr, function() {});
|
||||
|
||||
reorder.moveDrag.action({
|
||||
response: {
|
||||
success: function(args) {},
|
||||
error: function(args) {
|
||||
$tr.closest('tbody').sortable('cancel');
|
||||
rowActions._std($tr, function() {});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
if (reorder && reorder.moveDrag) {
|
||||
initDraggable($tr);
|
||||
}
|
||||
}
|
||||
|
||||
// Add action data
|
||||
$tr.data('list-view-item-id', id);
|
||||
$tr.data('jsonObj', dataItem);
|
||||
$tr.data('list-view-action-filter', options.actionFilter);
|
||||
|
||||
if (actions) {
|
||||
if (actions && renderActionCol(actions)) {
|
||||
var allowedActions = $.map(actions, function(value, key) {
|
||||
return key;
|
||||
});
|
||||
|
|
@ -705,6 +859,7 @@
|
|||
var loadBody = function($table, dataProvider, fields, append, loadArgs, actions, options) {
|
||||
if (!options) options = {};
|
||||
var context = options.context;
|
||||
var reorder = options.reorder;
|
||||
|
||||
var $tbody = $table.find('tbody');
|
||||
if (!loadArgs) loadArgs = {
|
||||
|
|
@ -733,7 +888,8 @@
|
|||
|
||||
addTableRows(fields, args.data, $tbody, actions, {
|
||||
actionFilter: args.actionFilter,
|
||||
context: context
|
||||
context: context,
|
||||
reorder: reorder
|
||||
});
|
||||
$table.dataTable(null, { noSelect: uiCustom });
|
||||
},
|
||||
|
|
@ -849,6 +1005,7 @@
|
|||
var infScrollTimer;
|
||||
var page = 1;
|
||||
var actions = listViewData.actions;
|
||||
var reorder = listViewData.reorder;
|
||||
|
||||
// Add panel controls
|
||||
$('<div class="panel-controls">').append($('<div class="control expand">').attr({
|
||||
|
|
@ -869,7 +1026,7 @@
|
|||
|
||||
$('<tbody>').appendTo($table);
|
||||
|
||||
createHeader(listViewData.fields, $table, actions);
|
||||
createHeader(listViewData.fields, $table, actions, { reorder: reorder });
|
||||
|
||||
var $switcher;
|
||||
if (args.sections) {
|
||||
|
|
@ -884,26 +1041,27 @@
|
|||
|
||||
createFilters($toolbar, listViewData.filters);
|
||||
createSearchBar($toolbar);
|
||||
|
||||
|
||||
loadBody(
|
||||
$table,
|
||||
listViewData.dataProvider,
|
||||
listViewData.fields,
|
||||
false,
|
||||
{
|
||||
page: page,
|
||||
page: page,
|
||||
filterBy: {
|
||||
kind: $listView.find('select[id=filterBy]').val(),
|
||||
search: {
|
||||
value: $listView.find('input[type=text]').val(),
|
||||
by: 'name'
|
||||
}
|
||||
},
|
||||
},
|
||||
ref: args.ref
|
||||
},
|
||||
actions,
|
||||
{
|
||||
context: args.context
|
||||
context: args.context,
|
||||
reorder: reorder
|
||||
}
|
||||
);
|
||||
|
||||
|
|
@ -949,7 +1107,7 @@
|
|||
{
|
||||
page: 1,
|
||||
filterBy: {
|
||||
kind: $listView.find('select[id=filterBy]').val(),
|
||||
kind: $listView.find('select[id=filterBy]').val(),
|
||||
search: {
|
||||
value: $listView.find('input[type=text]').val(),
|
||||
by: 'name'
|
||||
|
|
@ -967,7 +1125,7 @@
|
|||
|
||||
// Infinite scrolling event
|
||||
$listView.bind('scroll', function(event) {
|
||||
if (args.listView.disableInfiniteScrolling) return false;
|
||||
if (args.listView && args.listView.disableInfiniteScrolling) return false;
|
||||
if ($listView.find('tr.last, td.loading:visible').size()) return false;
|
||||
|
||||
clearTimeout(infScrollTimer);
|
||||
|
|
@ -983,7 +1141,9 @@
|
|||
search: {},
|
||||
kind: 'all'
|
||||
}
|
||||
}, actions);
|
||||
}, actions, {
|
||||
reorder: listViewData.reorder
|
||||
});
|
||||
}
|
||||
}, 500);
|
||||
|
||||
|
|
@ -1028,20 +1188,19 @@
|
|||
|
||||
// Populate context object w/ instance data
|
||||
var listViewActiveSection = $listView.data('view-args').activeSection;
|
||||
|
||||
|
||||
// Create custom-generated detail view
|
||||
if (listViewData.detailView.pageGenerator) {
|
||||
detailViewArgs.pageGenerator = listViewData.detailView.pageGenerator;
|
||||
}
|
||||
|
||||
var listViewArgs = $listView.data('view-args');
|
||||
if (listViewArgs.listView)
|
||||
detailViewArgs.section = listViewArgs.listView.section;
|
||||
else
|
||||
detailViewArgs.section = listViewArgs.activeSection ? listViewArgs.activeSection : listViewArgs.id;
|
||||
|
||||
detailViewArgs.section = listViewArgs.activeSection ?
|
||||
listViewArgs.activeSection : listViewArgs.id;
|
||||
|
||||
detailViewArgs.context[
|
||||
listViewActiveSection != '_zone' ?
|
||||
listViewActiveSection != '_zone' ?
|
||||
listViewActiveSection : detailViewArgs.section
|
||||
] = [jsonObj];
|
||||
|
||||
|
|
@ -1053,7 +1212,9 @@
|
|||
}
|
||||
|
||||
// Action icons
|
||||
if ($target.closest('td.actions').size() || $target.closest('.action.add').size()) {
|
||||
if (!$target.closest('td.actions').hasClass('reorder') &&
|
||||
($target.closest('td.actions').size() ||
|
||||
$target.closest('.action.add').size())) {
|
||||
var actionID = $target.closest('.action').data('list-view-action-id');
|
||||
var $tr;
|
||||
|
||||
|
|
@ -1115,6 +1276,7 @@
|
|||
var targetArgs = listViewArgs.activeSection ? listViewArgs.sections[
|
||||
listViewArgs.activeSection
|
||||
].listView : listViewArgs;
|
||||
var reorder = targetArgs.reorder;
|
||||
|
||||
var $tr = addTableRows(
|
||||
targetArgs.fields,
|
||||
|
|
@ -1123,7 +1285,8 @@
|
|||
targetArgs.actions,
|
||||
{
|
||||
prepend: true,
|
||||
actionFilter: actionFilter
|
||||
actionFilter: actionFilter,
|
||||
reorder: reorder
|
||||
}
|
||||
)[0];
|
||||
listView.find('table').dataTable('refresh');
|
||||
|
|
@ -1142,6 +1305,7 @@
|
|||
var targetArgs = listViewArgs.activeSection ? listViewArgs.sections[
|
||||
listViewArgs.activeSection
|
||||
].listView : listViewArgs;
|
||||
var reorder = targetArgs.reorder;
|
||||
var $table = $row.closest('table');
|
||||
|
||||
$newRow = addTableRows(
|
||||
|
|
@ -1150,7 +1314,8 @@
|
|||
$listView.find('table tbody'),
|
||||
targetArgs.actions,
|
||||
{
|
||||
actionFilter: actionFilter
|
||||
actionFilter: actionFilter,
|
||||
reorder: reorder
|
||||
}
|
||||
)[0];
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue