Add updated projects UI

This commit is contained in:
Brian Federle 2011-11-03 15:13:07 -07:00
parent 0ad145cc94
commit 6152cdb36b
12 changed files with 1262 additions and 159 deletions

View File

@ -76,6 +76,7 @@ table thead th {
position: relative;
left: 0;
top: 0;
font-weight: normal;
}
table thead th.sorted {
@ -836,7 +837,7 @@ div.list-view div.toolbar div.section-switcher div.section-select label {
margin: 0 9px 0 0;
}
.detail-view .loading-overlay {
.loading-overlay {
position: absolute;
width: 100%;
height: 100%;
@ -1014,65 +1015,6 @@ div.detail-group.actions td {
width: 12px;
}
#header div.view-switcher {
width: 256px;
height: 39px;
background-position: 0px -5px;
/*+placement:shift 0px 1px;*/
position: relative;
left: 0px;
top: 1px;
}
#header div.view-switcher.alt {
background-position: 0px -41px;
}
#header div.view-switcher div {
float: left;
padding: 13px 12px 13px 24px;
/*[empty]display:;*/
}
#header div.view-switcher div:hover {
color: #64ACF7;
/*+text-shadow:0px 1px 1px #F5F5F5;*/
-moz-text-shadow: 0px 1px 1px #F5F5F5;
-webkit-text-shadow: 0px 1px 1px #F5F5F5;
-o-text-shadow: 0px 1px 1px #F5F5F5;
text-shadow: 0px 1px 1px #F5F5F5;
}
#header div.view-switcher div span.icon {
background: url(../images/icons.png) no-repeat;
padding: 4px 14px 0px 6px;
/*+placement:shift -8px 3px;*/
position: relative;
left: -8px;
top: 3px;
}
#header div.view-switcher div.default-view span.icon {
background-position: -23px 0px;
}
#header div.view-switcher div.select span.icon {
background-position: -47px 0px;
}
#header div.view-switcher.alt div.select span.icon {
background-position: -73px 0px;
}
#header div.view-switcher.alt div.select {
color: #FFFFFF;
/*+text-shadow:0px -1px 0px #787878;*/
-moz-text-shadow: 0px -1px 0px #787878;
-webkit-text-shadow: 0px -1px 0px #787878;
-o-text-shadow: 0px -1px 0px #787878;
text-shadow: 0px -1px 0px #787878;
}
#user {
height: 30px;
margin: 5px 6px 0 0;
@ -1131,18 +1073,6 @@ div.detail-group.actions td {
top: 13px;
}
/*Sample project view*/
.sample-project-view {
position: absolute;
background: url(../images/sample-project-view.png) no-repeat 0px 0px;
top: 25%;
left: 33%;
width: 421px;
height: 389px;
z-index: 200;
cursor: pointer;
}
/*Navigation*/
#navigation,
#browser {
@ -1322,6 +1252,10 @@ div.detail-group.actions td {
position: absolute;
}
.project-view div.toolbar {
background: #4991DA url(../images/bg-nav-item-active-project-view.png) 0px -210px;
}
div.toolbar div.filters {
margin: 5px 0px 0 12px;
}
@ -1340,6 +1274,15 @@ div.toolbar div.filters label {
padding: 5px 11px 0 0;
}
.project-view div.toolbar div.filters label {
color: #FFFFFF;
/*+text-shadow:0px 1px 1px #000000;*/
-moz-text-shadow: 0px 1px 1px #000000;
-webkit-text-shadow: 0px 1px 1px #000000;
-o-text-shadow: 0px 1px 1px #000000;
text-shadow: 0px 1px 1px #000000;
}
div.toolbar div.filters select {
width: 142px;
border: 1px solid #808080;
@ -1586,6 +1529,10 @@ div.list-view div.toolbar div.section-switcher div.section-select {
height: 26px;
}
.project-view div.list-view div.toolbar div.section-switcher div.section-select {
background: none;
}
div.list-view div.toolbar div.section-switcher div.section-select select {
width: 146px;
margin-right: 13px;
@ -1595,6 +1542,15 @@ div.list-view div.toolbar div.section-switcher div.section-select label {
margin: 0 9px 0 0;
}
.project-view div.list-view div.toolbar div.section-switcher div.section-select label {
color: #FFFFFF;
/*+text-shadow:0px 1px 1px #000000;*/
-moz-text-shadow: 0px 1px 1px #000000;
-webkit-text-shadow: 0px 1px 1px #000000;
-o-text-shadow: 0px 1px 1px #000000;
text-shadow: 0px 1px 1px #000000;
}
/*Breadcrumbs*/
div.toolbar div.filters {
margin: 5px 0px 0 12px;
@ -1629,7 +1585,7 @@ div.toolbar div.filters select {
#breadcrumbs {
height: 29px;
max-height: 29px;
background: transparent url(../images/bg-breadcrumbs.png) repeat-x;
background: url(../images/bg-breadcrumbs.png) repeat-x;
overflow: hidden;
width: 100%;
}
@ -1637,6 +1593,7 @@ div.toolbar div.filters select {
.project-view #breadcrumbs {
background-image: url(../images/bg-breadcrumbs-project-view.png);
background-position: 0px 1px;
background-color: #4991DA;
}
#breadcrumbs div.home {
@ -3798,14 +3755,14 @@ label.error {
width: 100%;
}
.tree-view > ul {
.tree-view>ul {
/*+placement:shift 3px 40px;*/
position: relative;
left: 3px;
top: 40px;
}
.tree-view > ul > li {
.tree-view>ul>li {
left: 5px;
}
@ -3840,7 +3797,7 @@ label.error {
position: absolute;
}
.tree-view ul li.expanded > .expand {
.tree-view ul li.expanded>.expand {
background-position: -631px -228px;
}
@ -4931,6 +4888,452 @@ div.panel.ui-dialog div.list-view div.fixed-header {
margin: 8px 0 0 9px;
}
/*Projects
** View switcher*/
#header .view-switcher {
font-size: 12px;
color: #55687B;
float: left;
margin: 11px 0 0 18px;
}
#header .view-switcher span {
padding: 0 13px 0 0;
}
#header .view-switcher select {
width: 144px;
margin: 0;
}
/*** Select project*/
.project-selector {
display: inline-block;
}
.project-selector-dialog .ui-widget-content {
padding: 0 !important;
}
.project-selector .toolbar {
width: 420px;
position: relative;
background: none;
border: none;
border-bottom: 1px solid #93A4B4;
/*+box-shadow:0px 2px 0px #FFFFFF;*/
-moz-box-shadow: 0px 2px 0px #FFFFFF;
-webkit-box-shadow: 0px 2px 0px #FFFFFF;
-o-box-shadow: 0px 2px 0px #FFFFFF;
box-shadow: 0px 2px 0px #FFFFFF;
}
.project-selector .search input[type=text] {
/*+border-radius:3px;*/
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
-khtml-border-radius: 3px;
border-radius: 3px 3px 3px 3px;
width: 192px;
height: 18px;
margin: 6px 0 0 105px;
/*+box-shadow:0px 1px 1px #FFFFFF;*/
-moz-box-shadow: 0px 1px 1px #FFFFFF;
-webkit-box-shadow: 0px 1px 1px #FFFFFF;
-o-box-shadow: 0px 1px 1px #FFFFFF;
box-shadow: 0px 1px 1px #FFFFFF;
border: 1px solid #9DADBB;
float: left;
}
.project-selector .search input[type=submit] {
display: block;
float: left;
border: none;
cursor: pointer;
margin: 6px 0 0;
background: url(../images/sprites.png) no-repeat -601px -328px;
width: 25px;
height: 22px;
border-left: 1px solid #283979;
/*+placement:shift -2px 0px;*/
position: relative;
left: -2px;
top: 0px;
cursor: pointer;
}
.project-selector .listing {
margin: 15px;
border: 1px solid #D0D0D0;
position: relative;
}
.project-selector .listing .data {
width: 100%;
height: 275px;
background: #F2F0F0;
overflow: auto;
margin: 18px 0 0;
}
.project-selector .listing .data ul {
text-align: left;
font-size: 11px;
}
.project-selector .listing .data ul li {
padding: 10px 0 10px 7px;
cursor: pointer;
}
.project-selector .listing .data ul li.odd {
background: #DFE1E3;
}
.project-selector .listing .data ul li:hover {
background: #CBDDF3;
border-top: 1px solid #FFFFFF;
border-bottom: 1px solid #BABFD9;
padding: 9px 0 9px 7px;
}
.project-selector .listing .header {
width: 379px;
background: url(../images/bg-gradients.png) repeat-x 0px -164px;
/*+text-shadow:0px 1px 1px #FFFFFF;*/
-moz-text-shadow: 0px 1px 1px #FFFFFF;
-webkit-text-shadow: 0px 1px 1px #FFFFFF;
-o-text-shadow: 0px 1px 1px #FFFFFF;
text-shadow: 0px 1px 1px #FFFFFF;
text-align: left;
color: #4F6171;
font-size: 12px;
padding: 2px 2px 3px 7px;
border-bottom: 1px solid #FFFFFF;
position: absolute;
}
/*** Dashboard*/
.project-dashboard .toolbar {
position: relative;
}
.project-dashboard .ui-tabs {
/*+placement:shift 10px -31px;*/
position: relative;
left: 10px;
top: -31px;
}
/*** New project form*/
.new-project {
display: inline-block;
margin: 0 0 20px 30px;
}
.new-project form {
margin: 0;
}
.ui-dialog .new-project {
text-align: left;
}
.new-project .title {
color: #3497E6;
font-size: 26px;
/*+text-shadow:0px 1px 2px #D6D6D6;*/
-moz-text-shadow: 0px 1px 2px #D6D6D6;
-webkit-text-shadow: 0px 1px 2px #D6D6D6;
-o-text-shadow: 0px 1px 2px #D6D6D6;
text-shadow: 0px 1px 2px #D6D6D6;
letter-spacing: 0px;
margin: 10px 0 32px;
}
.new-project .field {
/*+text-shadow:0px 1px 1px #FFFFFF;*/
-moz-text-shadow: 0px 1px 1px #FFFFFF;
-webkit-text-shadow: 0px 1px 1px #FFFFFF;
-o-text-shadow: 0px 1px 1px #FFFFFF;
text-shadow: 0px 1px 1px #FFFFFF;
width: 736px;
display: inline-block;
background: #DFDFDF;
margin: -2px 0 -1px -27px;
}
.new-project .field span.value {
color: #475765;
/*+placement:shift 21px 20px;*/
position: relative;
left: 21px;
top: 20px;
}
.new-project .field label {
display: block;
width: 150px;
height: 59px;
color: #5B5B5B;
float: left;
background: #D2D2D2;
text-align: right;
padding: 20px 24px 0 0;
}
.new-project .field label.error {
color: #FF0000;
font-size: 9px;
/*+placement:displace 204px 29px;*/
position: absolute;
margin-left: 204px;
margin-top: 29px;
background: none;
width: auto;
height: auto;
}
.new-project .field input[type=text] {
background: #FFFFFF 0px 7px;
/*+border-radius:5px;*/
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
-khtml-border-radius: 5px;
border-radius: 5px 5px 5px 5px;
font-size: 14px;
border: 1px solid #E2E1DF;
/*+box-shadow:inset 0px 1px 0px #A1A1A1;*/
-moz-box-shadow: inset 0px 1px 0px #A1A1A1;
-webkit-box-shadow: inset 0px 1px 0px #A1A1A1;
-o-box-shadow: inset 0px 1px 0px #A1A1A1;
box-shadow: inset 0px 1px 0px #A1A1A1;
width: 506px;
height: 21px;
margin: 17px 25px 0 0;
float: right;
border: 1px solid #C7C7C7;
}
.new-project .button.cancel {
color: #808080;
background: none;
font-size: 12px;
font-weight: bold;
float: left;
cursor: pointer;
color: #838181;
/*+placement:shift 488px 0px;*/
position: relative;
left: 488px;
top: 0px;
margin: 19px 0 0 40px;
}
.new-project .button.cancel:hover {
color: #3A3A3A;
}
.new-project input[type=submit],
.new-project .button.confirm {
display: inline-block;
height: 31px;
border: none;
/*+placement:float-right 63px 9px;*/
float: right;
position: relative;
left: 63px;
top: 9px;
color: #FFFFFF;
/*+text-shadow:0px -1px 1px #465259;*/
-moz-text-shadow: 0px -1px 1px #465259;
-webkit-text-shadow: 0px -1px 1px #465259;
-o-text-shadow: 0px -1px 1px #465259;
text-shadow: 0px -1px 1px #465259;
background: #0049FF url(../images/gradients.png) 0px -317px;
font-size: 13px;
font-weight: bold;
border: 1px solid #0069CF;
border-top: 1px solid #0070FC;
/*+border-radius:9px;*/
-moz-border-radius: 9px;
-webkit-border-radius: 9px;
-khtml-border-radius: 9px;
border-radius: 9px 9px 9px 9px;
margin: 0px 63px 0 0;
cursor: pointer;
}
.new-project input[type=submit]:hover,
.new-project .button.confirm:hover {
background-position: -3px -369px;
}
.new-project .button {
cursor: pointer;
}
.new-project .button.confirm {
display: block;
height: 27px;
padding: 13px 10px 0px 12px;
}
.new-project .button.confirm.next {
padding: 10px 34px 0px 29px;
}
.new-project .review .button.confirm.next {
/*+placement:shift 25px 11px;*/
position: relative;
left: 25px;
top: 11px;
}
.new-project .review .ui-tabs {
/*+placement:shift -29px -31px;*/
position: relative;
left: -29px;
top: -31px;
}
.new-project .review .ui-tabs .ui-widget-content {
width: 695px;
height: 185px;
}
.new-project .review .ui-tabs li {
}
.new-project .review .ui-tabs ul {
text-align: left;
/*+placement:shift -111px 1px;*/
position: relative;
left: -111px;
top: 1px;
}
.new-project .review .ui-tabs .list-view {
width: 688px;
height: 185px !important;
}
.new-project .review .ui-tabs .list-view .fixed-header {
position: absolute;
z-index: 1000;
height: 58px;
background: #FFFFFF;
top: -22px;
}
.new-project .review .ui-tabs .list-view .data-table table {
width: 669px;
margin: 31px 0 -1px;
}
.new-project .review .ui-tabs .list-view .data-table table .edit {
width: 132px;
background: #FFFFFF;
/*+placement:shift 14px 0px;*/
position: relative;
left: 14px;
top: 0px;
}
.new-project .review .ui-tabs .list-view .data-table table .edit select {
width: 95px;
height: 20px;
float: left;
background: #FFFFFF;
border: 1px solid #B2B2B2;
}
.new-project .review .ui-tabs .list-view .data-table table .edit .action {
float: left;
margin: 0;
padding: 0;
/*+placement:shift 14px 0px;*/
position: relative;
left: 14px;
top: 0px;
height: 20px;
}
.new-project .review .ui-tabs .list-view .toolbar {
display: none;
}
.new-project .review .ui-tabs .list-view .toolbar {
}
.new-project .review .project-data {
padding: 16px;
background: #F4F4F4;
margin: 0;
/*+placement:shift -19px -13px;*/
position: relative;
left: -19px;
top: -13px;
}
.new-project .review .project-data .field {
width: 677px;
margin: auto;
}
.new-project .button.later {
color: #808080;
background: url(../images/bg-gradients.png) 0px -261px;
border: 1px solid #B1B1B1;
/*+box-shadow:inset 0px 2px 2px #FFFFFF;*/
-moz-box-shadow: inset 0px 2px 2px #FFFFFF;
-webkit-box-shadow: inset 0px 2px 2px #FFFFFF;
-o-box-shadow: inset 0px 2px 2px #FFFFFF;
box-shadow: inset 0px 2px 2px #FFFFFF;
float: right;
font-size: 13px;
margin: 10px -40px 0 0;
padding: 13px 7px 14px 8px;
/*+border-radius:10px;*/
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
-khtml-border-radius: 10px;
border-radius: 10px 10px 10px 10px;
}
.new-project .button.later:hover {
color: #000000;
/*+box-shadow:inset 0px 1px 1px #A1A1A1;*/
-moz-box-shadow: inset 0px 1px 1px #A1A1A1;
-webkit-box-shadow: inset 0px 1px 1px #A1A1A1;
-o-box-shadow: inset 0px 1px 1px #A1A1A1;
box-shadow: inset 0px 1px 1px #A1A1A1;
background-position: 0px -86px;
}
.new-project input[type=submit]:hover {
background-position: -3px -369px;
}
.new-project .multi-edit {
width: 671px;
}
.new-project .multi-edit .data {
width: 700px;
}
.new-project .multi-edit .data .data-item {
margin: 0;
border: none;
border: 1px solid #D2D2D2;
}
.new-project .multi-edit .data .data-item.even td {
background: #DFE1E3;
}
/*Action icons*/
.action.edit .icon {
background-position: 1px -1px;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 96 KiB

View File

@ -1407,6 +1407,8 @@
<!-- CloudStack -->
<script src="scripts/ui-custom/login.js" type="text/javascript"></script>
<script src="scripts-test/cloudStack.js" type="text/javascript"></script>
<script src="scripts/ui-custom/projects.js" type="text/javascript"></script>
<script src="scripts-test/projects.js" type="text/javascript"></script>
<script src="scripts-test/dashboard.js" type="text/javascript"></script>
<script src="scripts/ui-custom/instanceWizard.js" type="text/javascript"></script>
<script src="scripts-test/instances.js" type="text/javascript"></script>

View File

@ -1413,6 +1413,8 @@
<script src="scripts/cloud.core.callbacks.js" type="text/javascript"></script>
<script src="scripts/sharedFunctions.js" type="text/javascript"></script>
<script src="scripts/ui-custom/login.js" type="text/javascript"></script>
<script src="scripts/ui-custom/projects.js" type="text/javascript"></script>
<script src="scripts-test/projects.js" type="text/javascript"></script>
<script src="scripts/cloudStack.js" type="text/javascript"></script>
<script src="scripts/dashboard.js" type="text/javascript"></script>
<script src="scripts/ui-custom/instanceWizard.js" type="text/javascript"></script>

View File

@ -28,6 +28,7 @@
$(function() {
var $container = $('#cloudStack3-container');
// Login
cloudStack.uiCustom.login({
$container: $container,

107
ui/scripts-test/projects.js Normal file
View File

@ -0,0 +1,107 @@
(function(cloudStack, testData) {
cloudStack.projects = {
add: function(args) {
setTimeout(function() {
args.response.success({
data: {
name: args.data['project-name'],
displayText: args.data['project-display-text'],
users: []
}
});
}, 1000);
},
addUserForm: {
noSelect: true,
fields: {
'username': { edit: true, label: 'Account' },
'role': {
label: 'Role',
select: function(args) {
args.response.success({
data: [
{ name: 'user', description: 'User' },
{ name: 'admin', description: 'Admin' }
]
});
}
},
'add-user': { addButton: true, label: '' }
},
add: {
label: 'Invite',
action: function(args) {
setTimeout(function() {
cloudStack.context.projects[0].users.push(args.data);
args.response.success({
notification: {
label: 'Added 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: {
destroy: {
label: 'Remove user from project',
action: function(args) {
setTimeout(function() {
args.response.success({
notification: {
label: 'Removed user from project',
poll: testData.notifications.testPoll
}
});
}, 500);
}
},
makeOwner: {
label: 'Make user project owner',
action: function(args) {
setTimeout(function() {
args.response.success({
notification: {
label: 'Assigned new owner to project',
poll: testData.notifications.testPoll
}
});
});
}
}
},
// Project users data provider
dataProvider: function(args) {
var data = cloudStack.context.projects ?
cloudStack.context.projects[0].users : [];
setTimeout(function() {
args.response.success({
data: data
});
}, 100);
}
},
// Project listing data provider
dataProvider: function(args) {
var user = args.context.users[0];
setTimeout(function() {
args.response.success({
data: user.username == 'bfederle' ? [] : testData.data.projects
});
}, 200);
}
};
} (cloudStack, testData));

View File

@ -5804,6 +5804,53 @@
"domain": "ROOT",
"timezone": "CET"
}
],
projects: [
{
name: 'prj1',
displayText: 'Project 1',
users: [
{
username: 'bfederle',
role: 'admin'
},
{
username: 'schhen',
role: 'admin'
},
{
username: 'jdoe',
role: 'user'
}
]
},
{
name: 'prj2',
displayText: 'Project 2',
users: [
{
username: 'someuserA',
role: 'user'
},
{
username: 'someuserB',
role: 'user'
},
{
username: 'someadmin',
role: 'admin'
}
]
},
{
name: 'prj3',
displayText: 'Project 3'
},
{
name: 'prj4',
displayText: 'Project 4'
}
]
}
};

107
ui/scripts/projects.js Normal file
View File

@ -0,0 +1,107 @@
(function(cloudStack, testData) {
cloudStack.projects = {
add: function(args) {
setTimeout(function() {
args.response.success({
data: {
name: args.data['project-name'],
displayText: args.data['project-display-text'],
users: []
}
});
}, 1000);
},
addUserForm: {
noSelect: true,
fields: {
'username': { edit: true, label: 'Account' },
'role': {
label: 'Role',
select: function(args) {
args.response.success({
data: [
{ name: 'user', description: 'User' },
{ name: 'admin', description: 'Admin' }
]
});
}
},
'add-user': { addButton: true, label: '' }
},
add: {
label: 'Invite',
action: function(args) {
setTimeout(function() {
cloudStack.context.projects[0].users.push(args.data);
args.response.success({
notification: {
label: 'Added 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: {
destroy: {
label: 'Remove user from project',
action: function(args) {
setTimeout(function() {
args.response.success({
notification: {
label: 'Removed user from project',
poll: testData.notifications.testPoll
}
});
}, 500);
}
},
makeOwner: {
label: 'Make user project owner',
action: function(args) {
setTimeout(function() {
args.response.success({
notification: {
label: 'Assigned new owner to project',
poll: testData.notifications.testPoll
}
});
});
}
}
},
// Project users data provider
dataProvider: function(args) {
var data = cloudStack.context.projects ?
cloudStack.context.projects[0].users : [];
setTimeout(function() {
args.response.success({
data: data
});
}, 100);
}
},
// Project listing data provider
dataProvider: function(args) {
var user = args.context.users[0];
setTimeout(function() {
args.response.success({
data: user.username == 'bfederle' ? [] : testData.data.projects
});
}, 200);
}
};
} (cloudStack, testData));

View File

@ -0,0 +1,451 @@
(function(cloudStack, $) {
var pageElems = {
/**
* User management multi-edit
*/
userManagement: function() {
var multiEdit = cloudStack.projects.addUserForm;
return $('<div>').multiEdit(multiEdit);
},
/**
* Projects dashboard
*/
dashboard: function() {
var tabs = {
Overview: function() {
return $('<img>').attr('src', 'images/screens/ProjectDashboard.png');
}
};
if (cloudStack.context.projects) {
tabs['Manage'] = function() {
return $('<div>').addClass('management');
};
}
var $tabs = $('<div>').addClass('tab-content').append($('<ul>'));
var $toolbar = $('<div>').addClass('toolbar')
.append(
$('<div>').addClass('button add')
.append($('<span>').html('New Project'))
.click(function() {
addProject();
})
);
// Make UI tabs
$.each(tabs, function(tabName, tab) {
var $tab = $('<li>').appendTo($tabs.find('ul'));
var $tabLink = $('<a>')
.attr({ href: '#project-view-dashboard-' + tabName })
.html(tabName)
.appendTo($tab);
var $content = $('<div>')
.appendTo($tabs)
.attr({ id: 'project-view-dashboard-' + tabName })
.append(tab());
});
$tabs.find('ul li:first').addClass('first');
$tabs.find('ul li:last').addClass('last');
$tabs.bind('tabsshow', function(event, ui) {
var $panel = $(ui.panel);
var $management = $panel.find('.management');
if ($management.size()) {
$management.children().remove();
$management.append(pageElems.userManagement());
}
});
return $('<div>').addClass('project-dashboard')
.append($.merge(
$toolbar,
$tabs.tabs()
));
},
/**
* Add new project flow
*/
newProjectForm: function() {
var $newProject = $('<div>').addClass('new-project');
$newProject.append($('<div>').addClass('title').html('Create a project'));
var $form = $('<form>');
var $formDesc = $('<div>').addClass('form-desc');
var $projectName = $('<div>').addClass('field name')
.append($('<label>').attr({ for: 'project-name' }).html('Project name'))
.append($('<input>').addClass('required').attr({
type: 'text',
name: 'project-name'
}));
var $projectDesc = $('<div>').addClass('field desc')
.append($('<label>').attr({ for: 'project-desc' }).html('Display text'))
.append($('<input>').attr({
type: 'text',
name: 'project-display-text'
}));
var $submit = $('<input>').attr({ type: 'submit' }).val('Create Project');
var $cancel = $('<div>').addClass('button cancel').html('Cancel');
var $loading = $('<div>').addClass('loading-overlay');
// Form events/validation
$form.validate();
$form.submit(function() {
if (!$form.valid()) return false;
$form.prepend($loading);
cloudStack.projects.add({
data: cloudStack.serializeForm($form),
response: {
success: function(args) {
// Add project data to context
cloudStack.context.projects = [args.data];
cloudStack.context.projects[0].isNew = true;
$loading.remove();
// Confirmation
$form.replaceWith(function() {
var $confirm = $('<div>').addClass('confirm');
// Update title with project name
$newProject.find('.title').html(args.data.name);
// Show field data
$confirm.append($projectName).find('input').replaceWith( // Name
$('<span>').addClass('value').html(
args.data.name
)
);
$confirm.append($projectDesc).find('input').replaceWith( // Display text
$('<span>').addClass('value').html(
args.data.displayText
)
);
var $buttons = $('<div>').addClass('buttons');
var $addAccountButton = $('<div>').addClass('button confirm').html('Add Accounts');
$addAccountButton.click(function() {
// Show add user form
$confirm.replaceWith(function() {
var $userManagement = pageElems.userManagement();
var $nextButton = $('<div>').addClass('button confirm next').html('Next');
$newProject.find('.title').html('Add Accounts to ' + args.data.name);
$nextButton.appendTo($userManagement).click(function() {
$newProject.find('.title').html('Review');
$userManagement.replaceWith(function() {
var $review = $('<div>').addClass('review');
var $projectData = $('<div>').addClass('project-data');
// Basic project data
$review.append($projectData);
$projectData.append($projectName).find('input').replaceWith( // Name
$('<span>').addClass('value').html(
args.data.name
)
);
$projectData.append($projectDesc).find('input').replaceWith( // Display text
$('<span>').addClass('value').html(
args.data.displayText
)
);
// User/resouce tabs
var $tabs = $('<div>').addClass('tabs resources').appendTo($review);
var $ul = $('<ul>').appendTo($tabs)
.append(
// Users tab
$('<li>').addClass('first').append(
$('<a>').attr({ href: '#new-project-review-tabs-users'}).html('Users')
)
)
.append(
// Resources tab
$('<li>').addClass('last').append(
$('<a>').attr({ href: '#new-project-review-tabs-resouces'}).html('Resources')
)
);
var $users = $('<div>').attr({ id: 'new-project-review-tabs-users' }).appendTo($tabs);
var $resouces = $('<div>').attr({ id: 'new-project-review-tabs-resouces' }).appendTo($tabs).html('(Resources go here)');
$tabs.tabs();
$users.listView({
listView: {
id: 'project-accounts',
disableInfiniteScrolling: true,
fields: {
username: { label: 'Account' },
role: { label: 'Role' }
},
actions: {
editRole: {
label: 'Edit account role',
action: {
custom: function(args) {
var $instanceRow = args.$instanceRow;
var $role = $instanceRow.find('td.role');
var role = $role.find('span').html();
var $select = $('<select>');
var $editButtons = $.merge(
$('<div>').addClass('action save'),
$('<div>').addClass('action cancel')
);
// Edit actions
$editButtons.click(function(event) {
var $target = $(event.target);
return false;
});
$role.addClass('editable');
$select.append(
$userManagement.find('option').clone()
);
$role.html('')
.append(
$('<div>').addClass('edit')
.append($select)
.append($editButtons)
);
$instanceRow.closest('.data-table').dataTable('refresh');
}
}
},
destroy: {
label: 'Remove account from project',
action: {
custom: function(args) {
}
}
}
},
dataProvider: function(args) {
setTimeout(function() {
args.response.success({
data: cloudStack.context.projects[0].users
});
}, 0);
}
}
});
// Save button
var $saveButton = $nextButton.clone().appendTo($review);
$saveButton.html('Save');
$saveButton.click(function() {
$('.ui-dialog, .overlay').remove();
showDashboard();
});
return $review;
});
});
return $userManagement;
});
});
var $laterButton = $('<div>').addClass('button later').html('Remind me later');
$laterButton.click(function() {
$(':ui-dialog, .overlay').remove();
showDashboard();
});
$buttons.appendTo($confirm).append($.merge(
$addAccountButton, $laterButton
));
return $confirm;
});
}
}
});
return false;
});
$cancel.click(function() {
$(':ui-dialog, .overlay').remove();
});
return $newProject
.append(
$form
.append($formDesc)
.append($projectName)
.append($projectDesc)
.append($cancel)
.append($submit)
);
},
/**
* Project selection list
*/
selector: function(dataProvider) {
// Get project data
var loadData = function(complete) {
cloudStack.projects.dataProvider({
context: cloudStack.context,
response: {
success: function(args) {
var data = args.data;
$(data).each(function() {
$('<li>')
.data('json-obj', this)
.html(this.displayText)
.appendTo($list.find('ul'));
});
cloudStack.evenOdd($list, 'li', {
even: function($elem) {
$elem.addClass('even');
},
odd: function($elem) {
$elem.addClass('odd');
}
});
if (complete) complete();
}
}
});
};
var $selector = $('<div>').addClass('project-selector');
var $toolbar = $('<div>').addClass('toolbar');
var $list = $('<div>').addClass('listing')
.append($('<div>').addClass('header').html('Name'))
.append($('<div>').addClass('data').append($('<ul>')));
var $searchForm = $('<form>');
var $search = $('<div>').appendTo($toolbar).addClass('search')
.append(
$searchForm
.append($('<input>').attr({ type: 'text' }))
.append($('<input>').attr({ type: 'submit' }).val(''))
);
// Search form
$searchForm.submit(function() {
$list.find('li').remove();
loadData();
return false;
});
// Initial load
loadData(function() {
if (!$list.find('li').size()) {
showDashboard();
$.merge($selector, $('.overlay')).remove();
return;
} else {
$selector.dialog({
title: 'Select Project',
dialogClass: 'project-selector-dialog',
width: 420
}).closest('.ui-dialog').overlay();
}
});
// Project item click event
$selector.click(function(event) {
var $target = $(event.target);
if ($target.is('li')) {
cloudStack.context.projects = [$target.data('json-obj')];
showDashboard();
$.merge($selector, $('.overlay')).remove();
}
});
return $selector
.append($toolbar)
.append($list);
}
};
/**
* Show project-mode appearance on CloudStack UI
*/
var applyProjectStyle = function() {
var $container = $('#cloudStack3-container');
$container.addClass('project-view');
};
/**
* Initiate new project flow
*/
var addProject = function() {
pageElems.newProjectForm().dialog({
title: 'New Project',
width: 760
}).closest('.ui-dialog').overlay();
};
/**
* Show the dashboard, in panel
*/
var showDashboard = function() {
var $browser = $('#browser .container');
applyProjectStyle($('html body'));
// Cleanup project context
if (cloudStack.context.projects)
cloudStack.context.projects[0].isNew = false;
$browser.cloudBrowser('removeAllPanels');
$browser.cloudBrowser('addPanel', {
title: 'Project Dashboard',
complete: function($newPanel) {
$('#navigation li.dashboard').addClass('active').siblings().removeClass('active');
$newPanel.append(pageElems.dashboard);
}
});
};
/**
* Projects entry point
*/
cloudStack.uiCustom.projects = function() {
var $dashboardNavItem = $('#navigation li.navigation-item.dashboard');
// Use project dashboard
var event = function() {
if (!$('#cloudStack3-container').hasClass('project-view')) {
// No longer in project view, go back to normal dashboard
$dashboardNavItem.unbind('click', event);
return true;
}
showDashboard();
$(this).addClass('active');
$(this).siblings().removeClass('active');
return false;
};
$dashboardNavItem.bind('click', event);
pageElems.selector();
};
})(cloudStack, jQuery);

View File

@ -1,10 +1,10 @@
(function($, window) {
window.cloudStack = {
(function($, cloudStack) {
$.extend(cloudStack, {
ui: {
widgets: {} // Defines API methods for UI widgets
},
uiCustom: {}
};
});
/**
* Generate navigation <li>s
@ -102,23 +102,34 @@
.notifications();
// Project switcher
var $viewSwitcher = $('<div>').addClass('button view-switcher')
var $viewSwitcher = $('<div>').addClass('view-switcher').append(
$.merge(
$('<span>').addClass('select-project').html('Select View:'),
$('<select>')
.append(
// Default View
$('<div>').addClass('default-view')
.html('Default View')
.prepend(
$('<span>').addClass('icon').html('&nbsp;')
)
$('<option>').val('default-view')
.html('All')
)
.append(
// Project View
$('<div>').addClass('select')
.html('Select View')
.prepend(
$('<span>').addClass('icon').html('&nbsp;')
)
);
$('<option>').val('select-project')
.html('Project View')
)
.change(function() {
var $projectSwitcher = $(this);
var $container = $('html body');
if ($projectSwitcher.val() == 'select-project') {
cloudStack.uiCustom.projects();
} else {
$('.project-view').removeClass('project-view');
}
return false;
})
)
);
// User status area
var $userInfo = $('<div>').attr({ id: 'user' }).addClass('button')
@ -223,6 +234,8 @@
return false;
}
else $('#user-options').hide();
return false;
});
$(document).bind('click', function(event) {
@ -255,49 +268,6 @@
return false;
}
// Project buttons
var $defaultSwitcher = $target.closest('div.controls div.button.view-switcher .default-view');
if ($defaultSwitcher.size()) {
$container.removeClass('project-view');
$defaultSwitcher.closest('.view-switcher').removeClass('alt');
$('#navigation li.dashboard').click();
return false;
}
var $projectSwitcher = $target.closest('div.controls div.button.view-switcher .select');
if ($projectSwitcher.size()) {
$projectSwitcher.html('<span class="icon"></span>Projects');
$projectSwitcher.closest('.view-switcher').addClass('alt');
$('<div>')
.addClass('sample-project-view')
.appendTo($container)
.overlay()
.click(function(event) {
$container.addClass('project-view');
$('#navigation li.dashboard')
.click();
$('div.overlay').remove();
$(this).remove();
$('div.panel:first').children().remove();
$('div.panel:first')
.append(
$('<img>')
.attr({ src: 'images/screens/ProjectDashboard.png' })
.css({ cursor: 'pointer' })
);
$('#breadcrumbs ul')
.addClass('project-view')
.prepend(
$('<li>').addClass('active').append($('<span>').html('Project Name'))
)
.append(
$('<div>').addClass('end')
);
});
return false;
}
// User options
if ($target.closest('#user div.icon.options').size()) {
$('#user-options').toggle();
@ -308,4 +278,4 @@
return true;
});
});
})(jQuery, window);
})(jQuery, window.cloudStack ? window.cloudStack : window.cloudStack = {});

View File

@ -18,7 +18,7 @@
// Setup columns
$.each(fields, function(fieldName, field) {
if (options.ignoreEmptyFields && !data[fieldName]) {
return true;
return true;
}
var $td = $('<td>').addClass(fieldName).appendTo($tr);
@ -95,8 +95,17 @@
$multi.find('th.multi-actions').width() + 4
);
// Action filter
var allowedActions = options.preFilter ? options.preFilter({
context: $.extend(true, {}, options.context, {
actions: $.map(actions, function(value, key) { return key; })
})
}) : null;
// Append actions
$.each(actions, function(actionID, action) {
if (allowedActions && $.inArray(actionID, allowedActions) == -1) return true;
$actions.append(
$('<div>')
.addClass('action')
@ -110,7 +119,7 @@
var isDestroy = $target.hasClass('destroy');
if (isDestroy) {
var $loading = _medit.loadingItem($multi, 'Removing rule...');
var $loading = _medit.loadingItem($multi, 'Removing...');
if ($expandable.is(':visible')) {
$expandable.slideToggle(function() {
@ -134,11 +143,11 @@
$('.notifications').notifications('add', {
section: 'network',
desc: notification.label,
interval: 1000,
interval: 500,
_custom: _custom,
poll: function(args) {
var complete = args.complete;
notification.poll({
_custom: args._custom,
complete: function(args) {
@ -223,7 +232,7 @@
},
details: function(data, $browser, options) {
if (!options) options = {};
var detailViewArgs, $detailView;
detailViewArgs = $.extend(true, {}, cloudStack.sections.instances.listView.detailView);
@ -316,6 +325,7 @@
var noSelect = args.noSelect;
var context = args.context;
var ignoreEmptyFields = args.ignoreEmptyFields;
var actionPreFilter = args.actionPreFilter;
var $thead = $('<tr>').appendTo(
$('<thead>').appendTo($inputTable)
@ -456,12 +466,12 @@
});
// Loading appearance
var $loading = _medit.loadingItem($multi, 'Adding rule...');
var $loading = _medit.loadingItem($multi, 'Adding...');
$dataBody.append($loading);
// Clear out fields
$multi.find('input').val('');
// Apply action
args.add.action({
context: context,
@ -474,11 +484,11 @@
$('.notifications').notifications('add', {
section: 'network',
desc: notification.label,
interval: 3000,
interval: 500,
_custom: successArgs._custom,
poll: function(pollArgs) {
var complete = pollArgs.complete;
notification.poll({
_custom: pollArgs._custom,
complete: function(completeArgs) {
@ -495,7 +505,8 @@
multipleAdd: multipleAdd,
noSelect: noSelect,
context: context,
ignoreEmptyFields: ignoreEmptyFields
ignoreEmptyFields: ignoreEmptyFields,
preFilter: actionPreFilter
}
).appendTo($dataBody);
}
@ -579,7 +590,8 @@
multipleAdd: multipleAdd,
noSelect: noSelect,
context: $.extend(true, {}, context, this._context),
ignoreEmptyFields: ignoreEmptyFields
ignoreEmptyFields: ignoreEmptyFields,
preFilter: actionPreFilter
}
).appendTo($dataBody);
});

View File

@ -69,7 +69,7 @@
if (args.data) $.extend(true, data, args.data);
if (listViewArgs) section = listViewArgs.section;
notification.desc = messages ?
notification.desc = messages ?
messages.notification(messageArgs) : null;
if (listViewArgs)
@ -226,7 +226,7 @@
}
}
};
if (action.custom && action.noAdd) {
action.custom({
data: data,
@ -236,7 +236,7 @@
complete: actionArgs.response.success
});
} else {
action(actionArgs);
action(actionArgs);
}
}
};
@ -494,7 +494,7 @@
})
.data('list-view-action-id', actionName)
);
return true;
} else if (action.type == 'checkbox') {
$td.append(
@ -513,10 +513,10 @@
})
.data('list-view-action-id', actionName)
);
return true;
}
$td.append(
$('<div></div>')
.addClass('action')
@ -579,7 +579,7 @@
$('<tr>').addClass('empty').append(
$('<td>').html('No data to show')
).appendTo($tbody)
];
];
}
return $tbody.find('tr:last').addClass('last');
@ -642,7 +642,7 @@
});
var $listView = $tr.closest('.list-view');
var isUICustom = $listView.data('view-args') ?
var isUICustom = $listView.data('view-args') ?
$tr.closest('.list-view').data('view-args').uiCustom : false;
if (options.actionFilter && !isUICustom) {
@ -651,7 +651,7 @@
actions: allowedActions,
item: dataItem
})
});
});
}
makeActionIcons(
@ -768,7 +768,7 @@
if (sectionPreFilter && $.inArray(key, sectionPreFilter) == -1) {
return true;
}
var $sectionButton;
if (!this.type || this.type == 'button') {
@ -921,9 +921,9 @@
return true;
loadBody(
$table,
listViewData.dataProvider,
listViewData.fields,
$table,
listViewData.dataProvider,
listViewData.fields,
false,
{
page: 1,
@ -946,6 +946,7 @@
// Infinite scrolling event
$listView.bind('scroll', function(event) {
if (args.listView.disableInfiniteScrolling) return false;
if ($listView.find('tr.last, td.loading:visible').size()) return false;
clearTimeout(infScrollTimer);