diff --git a/ui/scripts-test/cloudStack.js b/ui/scripts-test/cloudStack.js index 22540c481ab..7567393800c 100644 --- a/ui/scripts-test/cloudStack.js +++ b/ui/scripts-test/cloudStack.js @@ -8,7 +8,7 @@ if (user.role == 'admin') return args.context.sections; - return ['dashboard', 'instances', 'storage', 'templates', 'events']; + return ['dashboard', 'instances', 'storage', 'templates', 'events', 'projects']; }, sections: { dashboard: {}, @@ -20,9 +20,9 @@ domains: {}, events: {}, system: {}, + projects: {}, 'global-settings': {}, - configuration: {}, - projects: {} + configuration: {} } }); diff --git a/ui/scripts-test/projects.js b/ui/scripts-test/projects.js index bea0020c0fd..b2dd62459ca 100644 --- a/ui/scripts-test/projects.js +++ b/ui/scripts-test/projects.js @@ -1,5 +1,9 @@ (function($, cloudStack, testData) { cloudStack.projects = { + requireInvitation: function(args) { + return cloudStack.context.users[0].username == 'jdoe'; + }, + add: function(args) { setTimeout(function() { args.response.success({ @@ -11,6 +15,54 @@ }); }, 1000); }, + inviteForm: { + noSelect: true, + fields: { + 'email': { edit: true, label: 'E-mail' }, + 'add-user': { addButton: true, label: '' } + }, + add: { + label: 'Invite', + action: function(args) { + setTimeout(function() { + args.response.success({ + data: args.data, + notification: { + label: 'Invited user to project', + poll: testData.notifications.testPoll + } + }); + }, 100); + } + }, + actionPreFilter: function(args) { + if (cloudStack.context.projects && + cloudStack.context.projects[0] && + !cloudStack.context.projects[0].isNew) { + return args.context.actions; + } + + return ['destroy']; + }, + + actions: {}, + + // Project users data provider + dataProvider: function(args) { + var data = cloudStack.context.projects ? + [ + { email: 'brian.federle@citrix.com' }, + { email: 'john.doe@aol.com' }, + { email: 'some.user@gmail.com' } + ] : []; + + setTimeout(function() { + args.response.success({ + data: data + }); + }, 100); + } + }, addUserForm: { noSelect: true, fields: { @@ -18,7 +70,7 @@ 'add-user': { addButton: true, label: '' } }, add: { - label: 'Invite', + label: 'Add user', action: function(args) { setTimeout(function() { args.response.success({ diff --git a/ui/scripts/projects.js b/ui/scripts/projects.js index 490c606f44c..4f241a7d482 100644 --- a/ui/scripts/projects.js +++ b/ui/scripts/projects.js @@ -1,9 +1,13 @@ (function(cloudStack, testData) { cloudStack.projects = { + requireInvitation: function(args) { + return false; + }, + add: function(args) { setTimeout(function() { $.ajax({ - url: createURL('createProject'), + url: createURL('createProject', { ignoreProject: true }), data: { account: args.context.users[0].account, domainId: args.context.users[0].domainid, @@ -25,6 +29,73 @@ }); }, 100); }, + inviteForm: { + noSelect: true, + fields: { + 'email': { edit: true, label: 'E-mail' }, + 'add-user': { addButton: true, label: '' } + }, + add: { + label: 'Invite', + action: function(args) { + $.ajax({ + url: createURL('addAccountToProject', { ignoreProject: true }), + data: { + projectId: args.context.projects[0].id, + email: args.data.email + }, + dataType: 'json', + async: true, + success: function(data) { + data: args.data, + args.response.success({ + _custom: { + jobId: data.addaccounttoprojectresponse.jobid + }, + notification: { + label: 'Invited user to project', + poll: pollAsyncJobResult + } + }); + } + }); + } + }, + actionPreFilter: function(args) { + if (cloudStack.context.projects && + cloudStack.context.projects[0] && + !cloudStack.context.projects[0].isNew) { + return args.context.actions; + } + + return ['destroy']; + }, + + actions: {}, + + // Project users data provider + dataProvider: function(args) { + $.ajax({ + url: createURL('listProjectInvitations', { ignoreProject: true }), + data: { + projectId: args.context.projects[0].id + }, + dataType: 'json', + async: true, + success: function(data) { + var invites = data.listprojectinvitationsresponse.projectinvitation; + args.response.success({ + data: $.map(invites, function(elem) { + return { + id: elem.id, + email: elem.email ? elem.email : elem.account + }; + }) + }); + } + }); + } + }, addUserForm: { noSelect: true, fields: { @@ -32,10 +103,10 @@ 'add-user': { addButton: true, label: '' } }, add: { - label: 'Invite', + label: 'Add user', action: function(args) { $.ajax({ - url: createURL('addAccountToProject'), + url: createURL('addAccountToProject', { ignoreProject: true }), data: { projectId: args.context.projects[0].id, account: args.data.username @@ -79,7 +150,7 @@ label: 'Remove user from project', action: function(args) { $.ajax({ - url: createURL('deleteAccountFromProject'), + url: createURL('deleteAccountFromProject', { ignoreProject: true }), data: { projectId: args.context.projects[0].id, account: args.context.multiRule[0].username @@ -105,7 +176,7 @@ label: 'Make user project owner', action: function(args) { $.ajax({ - url: createURL('updateProject'), + url: createURL('updateProject', { ignoreProject: true }), data: { id: cloudStack.context.projects[0].id, account: args.context.multiRule[0].username @@ -131,7 +202,7 @@ // Project users data provider dataProvider: function(args) { $.ajax({ - url: createURL('listProjectAccounts'), + url: createURL('listProjectAccounts', { ignoreProject: true }), data: { projectId: args.context.projects[0].id }, @@ -157,7 +228,7 @@ var user = args.context.users[0]; $.ajax({ - url: createURL('listProjects'), + url: createURL('listProjects', { ignoreProject: true }), data: { accountId: user.userid }, @@ -192,7 +263,7 @@ dataProvider: function(args) { $.ajax({ - url: createURL('listProjects'), + url: createURL('listProjects', { ignoreProject: true }), dataType: 'json', async: true, success: function(data) { @@ -230,7 +301,7 @@ label: 'Remove project', action: function(args) { $.ajax({ - url: createURL('deleteProject'), + url: createURL('deleteProject', { ignoreProject: true }), data: { id: args.data.id }, diff --git a/ui/scripts/sharedFunctions.js b/ui/scripts/sharedFunctions.js index babe6f7b6da..5798c0b46cc 100644 --- a/ui/scripts/sharedFunctions.js +++ b/ui/scripts/sharedFunctions.js @@ -62,10 +62,11 @@ var pollAsyncJobResult = function(args) { } //API calls -function createURL(apiName) { +function createURL(apiName, options) { + if (!options) options = {}; var urlString = clientApiUrl + "?" + "command=" + apiName +"&response=json&sessionkey=" + g_sessionKey; - if (cloudStack.context && cloudStack.context.projects) { + if (cloudStack.context && cloudStack.context.projects && !options.ignoreProject) { urlString = urlString + '&projectid=' + cloudStack.context.projects[0].id; } diff --git a/ui/scripts/ui-custom/projects.js b/ui/scripts/ui-custom/projects.js index ee710b95c7e..0dfa9c38ec0 100644 --- a/ui/scripts/ui-custom/projects.js +++ b/ui/scripts/ui-custom/projects.js @@ -4,7 +4,9 @@ * User management multi-edit */ userManagement: function(args) { - var multiEdit = cloudStack.projects.addUserForm; + var multiEdit = !args.useInvites ? + cloudStack.projects.addUserForm : + cloudStack.projects.inviteForm; return $('
').multiEdit($.extend(true, {}, multiEdit, { context: args.context @@ -22,9 +24,13 @@ }; if (cloudStack.context.projects) { - tabs['Manage'] = function() { + tabs['Users'] = function() { return $('
').addClass('management'); }; + + tabs['Invitations'] = function() { + return $('
').addClass('management-invite'); + }; } var $tabs = $('
').addClass('tab-content').append($('
    ')); @@ -49,13 +55,26 @@ $tabs.bind('tabsshow', function(event, ui) { var $panel = $(ui.panel); var $management = $panel.find('.management'); + var $managementInvite = $panel.find('.management-invite'); if ($management.size()) { $management.children().remove(); $management.append(pageElems.userManagement({ context: cloudStack.context })); + + return true; } + + if ($managementInvite.size()) { + $managementInvite.children().remove(); + $managementInvite.append(pageElems.userManagement({ + context: cloudStack.context, + useInvites: true + })); + } + + return true; }); return $('
    ').addClass('project-dashboard') @@ -136,7 +155,8 @@ var $userManagement = pageElems.userManagement({ context: $.extend(true, {}, cloudStack.context, { projects: [project] - }) + }), + useInvites: cloudStack.projects.requireInvitation() }); var $nextButton = $('
    ').addClass('button confirm next').html('Next'); @@ -185,11 +205,12 @@ listView: { id: 'project-accounts', disableInfiniteScrolling: true, - - fields: { + fields: !cloudStack.projects.requireInvitation() ? { username: { label: 'Account' } + } : { + email: { label: 'E-mail invite'} }, - actions: { + actions: !cloudStack.projects.requireInvitation() ? { destroy: { label: 'Remove account from project', action: { @@ -214,14 +235,16 @@ } } } - }, + } : {}, dataProvider: function(args) { setTimeout(function() { args.response.success({ data: $.map($userManagement.find('.data-item tr'), function(elem) { // Store previous user data in list table - return { + return !cloudStack.projects.requireInvitation() ? { username: $(elem).find('td.username span').html() + } : { + email: $(elem).find('td.email span').html() }; }) }); @@ -351,16 +374,19 @@ // Initial load loadData(function() { if (!$list.find('li').size()) { - showDashboard(); + cloudStack.dialog.notice({ + message: 'You do not have any projects. ' + + 'Please create a new project from the projects section.' + }).closest('.ui-dialog'); $.merge($selector, $('.overlay')).remove(); - - return; + $('.select.default-view').click(); } else { $selector.dialog({ title: 'Select Project', dialogClass: 'project-selector-dialog', width: 420 }).closest('.ui-dialog').overlay(); + showDashboard(); } }); @@ -444,7 +470,6 @@ return true; } - showDashboard(); $(this).addClass('active'); $(this).siblings().removeClass('active');