
From: Yu Xin Huo <huoyuxin@linux.vnet.ibm.com> Signed-off-by: Yu Xin Huo <huoyuxin@linux.vnet.ibm.com> --- ui/css/theme-default/guest-edit.css | 116 +++++++++++++++++++++++++++++++++++ ui/images/theme-default/group.png | Bin 0 -> 1703 bytes ui/images/theme-default/user.png | Bin 0 -> 1322 bytes ui/js/src/kimchi.api.js | 28 ++++++++ ui/js/src/kimchi.guest_edit_main.js | 112 ++++++++++++++++++++++++++++++++- ui/pages/guest-edit.html.tmpl | 37 +++++++++++ 6 files changed, 290 insertions(+), 3 deletions(-) create mode 100644 ui/images/theme-default/group.png create mode 100644 ui/images/theme-default/user.png diff --git a/ui/css/theme-default/guest-edit.css b/ui/css/theme-default/guest-edit.css index 3ce48be..8c2b26f 100644 --- a/ui/css/theme-default/guest-edit.css +++ b/ui/css/theme-default/guest-edit.css @@ -162,3 +162,119 @@ .guest-edit-interface .hide { display: none; } + +.guest-edit-permission { + height: 240px; + padding: 5px 10px!important; +} + +.guest-edit-permission .column { + display: inline-block; + vertical-align: top; + height: 100%; +} + +.guest-edit-permission .title { + margin-bottom: 3px; +} + +.guest-edit-permission input[type="text"] { + margin-bottom: 3px; + font-size: 12px; + width: 97%; +} + +.guest-edit-permission .body { + border: 1px solid #999999; + font-size: 12px; + padding: 1px; + overflow: auto; +} + +.guest-edit-permission .body .head { + margin-bottom: 3px; + font-weight: bold; + background: linear-gradient(to bottom, #E5E5E5 0%, #C4C4C4 100%) repeat scroll 0 0 transparent; +} + +.guest-edit-permission .body .item { + padding: 2px 3px; + margin-bottom: 1px; + cursor: pointer; +} + +.guest-edit-permission .body .item:hover { + background-color: #AAAAAA; +} + +.guest-edit-permission .body .item-picked { + background-color: #BBBBBB; +} + +.guest-edit-permission .body .item .icon { + display: inline-block; + height: 15px; + width: 15px; + vertical-align: bottom; +} + +.guest-edit-permission .body .item .user-icon { + background: url('/images/theme-default/user.png') no-repeat scroll; + background-size: 15px 15px; +} + +.guest-edit-permission .body .item .group-icon { + background: url('/images/theme-default/group.png') no-repeat scroll; + background-size: 15px 15px; +} + +.guest-edit-permission .avail { + width: 58%; +} + +.guest-edit-permission .avail .body { + height: 192px; +} + +.guest-edit-permission .avail .body .column-user { + width: 48%; +} +.guest-edit-permission .avail .body .column-group { + width: 50%; +} + +.guest-edit-permission .control { + width: 9%; +} + +.guest-edit-permission .control button { + width: 26px; + margin-left: 18px; +} + +.guest-edit-permission .control button:first-child { + margin-top: 110px; + margin-bottom: 2px; +} + +.guest-edit-permission .control .ui-button-text-only .ui-button-text { + padding: 2px 8px; +} + +.guest-edit-permission .selected { + width: 30%; + float: right; +} + +.guest-edit-permission .selected .title { + height: 43px; +} + +.guest-edit-permission .selected .body { + height: 192px; +} + +#form-guest-edit-permission-save { + float: right; + margin-right: 10px; +} diff --git a/ui/images/theme-default/group.png b/ui/images/theme-default/group.png new file mode 100644 index 0000000000000000000000000000000000000000..1160bd97178375f202c3c20fef689ddf4a6dcfae GIT binary patch literal 1703 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 literal 0 HcmV?d00001 diff --git a/ui/images/theme-default/user.png b/ui/images/theme-default/user.png new file mode 100644 index 0000000000000000000000000000000000000000..c57a81a92757ef31c424a4e6c741f71db62a1092 GIT binary patch literal 1322 zcmV+_1=aeAP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F80000PbVXQnQ*UN; zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU$%t=H+RCwCFS6xgTRTRGSvwt(QEW2!% zZEC<RY*%PmU|~TT(9l}brY~)zO*HkzHZ`VcV>GER{yyo84?Y{zXpHs6S4l9Y#$eJ` zmI9TeNz<hS;wC6n(*0#;*YAuwlVv;L6r^`@m^(Xj@A=NT=X~eDmCI%J$6w2=dc>kV zY@@+(9ODK4xF85;1zu=k91CHOq^hbvsYP|PR4&aWrYD(|;jiDtI5Pm<(b&U^nWnhO zZnuB!bUFte4hIuOQ3F&emDt+a8q4K!YCf0$1oO+2)4!@#0EkwQl5$ualok1!EXhHq z%gJmu8{>K206<bG6ogDB^F}6}*^Ol{S=pO6{k6PaIG$r3kLNqL+Z|Ng3M1<QNK>wD z0wClKm&?WQ4U=X0#ew+2^IHe7-h8rlfP@r~VhtmXu2yJ}XCzr-e!u_2cz2($B>?5B zi|2UO+S2;E!|Bj0HB)Q`0>S806y@n{9{~c7$%@p!ndP-YM`IIhEY=e{_Fn+RjXY4D zb{x;w(OtLDQsClyUxV+7?FS)7Fxa?e#qxE6tFbYV-gXdDdWFN`J9K{(0F)I&&kRj$ zI|#vW?8M0vpCb(|D<`nShlY!hry^t9K7x{3LJ-PdzWUnvKdl1r@A9)#r$@fP4l7&p zK#etB9o>b2g9B$ST)a@CRMeTzOi1}V@4bC5&=`2jO0Zg@ViXxFP-BUi$(LJN_Ksfp z=3D3WYuB~o(FYyT;UkCH$jA$KK}644v0lp-vto3ht%C^2h1~xbJa874jpHaz!TRjf zY@!{XyqnEtPcAMl+BGYX^P$j_DNIKpA3+{;9_VVv`tOm%b^yJ6^VZZ?maAd3z0;0@ z^8+}4h*+&yEHYHNtJz%k6}(OoDNW5J6wD))C57Iu_-s)vYB2+#M<hwQVt3em#0U9& zo&oSVtQoZgARg=c6uf^<=YBd{Y`}8a9F^U1Jl{ry%u<!a_#1N%?h2Ge@cpwW*%8Sl zF#ymAiApspWGS6aAB88zHwA!z8&qWFXDTRUy%7gEZ}J3fMsuAPv~1!2Wj+Ec3L+D2 zqQ(OhuzFCF7qC8cf8~C7W^Vd{X+O}>78M%&4WH3QB-PYQo53<|<J#h5P&Rc-l^#J? ztdGi32J7nTKEUIfrfCS5pT-%6Ny$cqM^~a*D~g8DbG5~0>&O6nb1AyN(`O36>+`;^ zE8i^Fw<;AciT(!v#fQ?cbAMMCx}7NsJl&F=7!*g?e<hVl1yaAKR6|o}Z|D*QkY09o zN@#y%ln=dSY#kHg^-=2m9;N1QW$4+`+|+aik2gd;`n?U_M)dhR4nPNiKf{Ix&_Fij z3wd5}JSG6RifhF^Mi%tOdm`1jyVF9%1!9s64=8STpq4mxa*!S{s%Us%UnHDGZax<4 zb!iSYtJOTviuu)rdkcFeCVpX4i3FROnWX~qzgZm!1kk2;v%da**4x{|>b>>js0Gj0 z79%RJ$03IxgUidyp5)ymo1dR&^T~O(w6w(16;L1%wz|4%C<yKjGVr{ij5;GUFVxVY zR|qke<XXV1A0cCv`|^h6xNTp%_8-x2w{KCTwpR&x%A<1^#8<T}S=9xRvL(nY<R)Z} gniR8!<R1YB09_*wa#VgYhyVZp07*qoM6N<$f^kM~^#A|> literal 0 HcmV?d00001 diff --git a/ui/js/src/kimchi.api.js b/ui/js/src/kimchi.api.js index 021be63..936e964 100644 --- a/ui/js/src/kimchi.api.js +++ b/ui/js/src/kimchi.api.js @@ -1056,5 +1056,33 @@ var kimchi = { kimchi.message.error(data.responseJSON.reason); } }); + }, + + getHostUsers : function(suc, err) { + kimchi.requestJSON({ + url : kimchi.url + 'host/users', + type : 'GET', + contentType : 'application/json', + dataType : 'json', + resend : true, + success : suc, + error : err ? err : function(data) { + kimchi.message.error(data.responseJSON.reason); + } + }); + }, + + getHostGroups : function(suc, err) { + kimchi.requestJSON({ + url : kimchi.url + 'host/groups', + type : 'GET', + contentType : 'application/json', + dataType : 'json', + resend : true, + success : suc, + error : err ? err : function(data) { + kimchi.message.error(data.responseJSON.reason); + } + }); } }; diff --git a/ui/js/src/kimchi.guest_edit_main.js b/ui/js/src/kimchi.guest_edit_main.js index 99dbe96..2e21e70 100644 --- a/ui/js/src/kimchi.guest_edit_main.js +++ b/ui/js/src/kimchi.guest_edit_main.js @@ -19,12 +19,13 @@ kimchi.guest_edit_main = function() { var buttonContainer = $('#action-button-container'); $('#guest-edit-tabs').tabs({ beforeActivate: function(event, ui) { + $(buttonContainer).addClass('hidden'); + $("#form-guest-edit-permission-save").addClass('hidden'); var deactivated = ui['newPanel']; if($(deactivated).attr('id') === 'form-guest-edit-general') { $(buttonContainer).removeClass('hidden'); - } - else { - $(buttonContainer).addClass('hidden'); + }else if($(deactivated).attr('id') === 'form-guest-edit-permission'){ + $("#form-guest-edit-permission-save").removeClass('hidden'); } } }); @@ -236,6 +237,110 @@ kimchi.guest_edit_main = function() { }); }; + var setupPermission = function() { + var userNodes = {}, groupNodes = {}; + kimchi.retrieveVM(kimchi.selectedGuest, function(vm){ + kimchi.getHostUsers(function(users){ + kimchi.getHostGroups(function(groups){ + var subArray = function(a1, a2){ //a1-a2 + for(var i=0; i<a2.length; i++){ + for(var j=0; j<a1.length; j++){ + if(a2[i] == a1[j]){ + a1.splice(j, 1); + break; + } + } + } + }; + subArray(users, vm.users); subArray(groups, vm.groups); + init(users, groups, vm.users, vm.groups); + }); + }); + }); + var sortNodes = function(container, isUser){ + nodes = container.children(); + var keys = []; + nodes.each(function(){ + keys.push($("label", this).text()); + }); + keys.sort(); + container.empty(); + for(var i=0; i<keys.length; i++){ + var itemNode = isUser ? userNodes[keys[i]] : groupNodes[keys[i]]; + $(itemNode).click(function(){ + $(this).toggleClass("item-picked"); + }); + container.append(itemNode); + } + }; + var init = function(availUsers, availGroups, selUsers, selGroups){ + var initNode = function(key, isUserNode){ + var nodeGroups = isUserNode ? userNodes : groupNodes; + nodeGroups[key] = $.parseHTML(kimchi.substitute($('#permission-item').html(), { + val: key, + class: isUserNode? "user-icon" : "group-icon" + })); + }; + for(var i=0; i<availUsers.length; i++){ + initNode(availUsers[i], true); + $("#permission-avail-users").append(userNodes[availUsers[i]]); + sortNodes($("#permission-avail-users"), true); + } + for(var i=0; i<selUsers.length; i++){ + initNode(selUsers[i], true); + $("#permission-sel-users").append(userNodes[selUsers[i]]); + sortNodes($("#permission-sel-users"), true); + } + for(var i=0; i<availGroups.length; i++){ + initNode(availGroups[i], false); + $("#permission-avail-groups").append(groupNodes[availGroups[i]]); + sortNodes($("#permission-avail-groups"), false); + } + for(var i=0; i<selGroups.length; i++){ + initNode(selGroups[i], false); + $("#permission-sel-groups").append(groupNodes[selGroups[i]]); + sortNodes($("#permission-sel-groups"), false); + } + }; + var filterNodes = function(key, container){ + container.children().each(function(){ + $(this).css("display", $("label", this).text().indexOf(key)==-1 ? "none" : ""); + }); + } + $("#permission-searchBox").on("keyup", function() { + var key = $(this).val(); + filterNodes(key, $("#permission-avail-users")); + filterNodes(key, $("#permission-avail-groups")); + }); + $('#permissionGo').button().click(function() { + $("#permission-avail-users").children(".item-picked").appendTo("#permission-sel-users").removeClass("item-picked"); + sortNodes($("#permission-sel-users"), true); + $("#permission-avail-groups").children(".item-picked").appendTo("#permission-sel-groups").removeClass("item-picked"); + sortNodes($("#permission-sel-groups"), false); + }); + $('#permissionBack').button().click(function() { + $("#permission-sel-users").children(".item-picked").appendTo("#permission-avail-users").removeClass("item-picked"); + sortNodes($("#permission-avail-users"), true); + $("#permission-sel-groups").children(".item-picked").appendTo("#permission-avail-groups").removeClass("item-picked"); + sortNodes($("#permission-avail-groups"), false); + $("#permission-searchBox").val(""); + filterNodes("", $("#permission-avail-users")); + filterNodes("", $("#permission-avail-groups")); + }); + $("#form-guest-edit-permission-save").on("click", function(){ + var content = { users: [], groups: [] }; + $("#permission-sel-users").children().each(function(){ + content.users.push($("label", this).text()); + }); + $("#permission-sel-groups").children().each(function(){ + content.groups.push($("label", this).text()); + }); + kimchi.updateVM(kimchi.selectedGuest, content, function(){ + kimchi.window.close(); + }); + }); + }; + var initContent = function(guest) { guest['icon'] = guest['icon'] || 'images/icon-vm.png'; $('#form-guest-edit-general').fillWithObject(guest); @@ -265,6 +370,7 @@ kimchi.guest_edit_main = function() { initStorageListeners(); setupInterface(); + setupPermission(); kimchi.topic('kimchi/vmCDROMAttached').subscribe(onAttached); kimchi.topic('kimchi/vmCDROMReplaced').subscribe(onReplaced); diff --git a/ui/pages/guest-edit.html.tmpl b/ui/pages/guest-edit.html.tmpl index ded892c..bb5f28d 100644 --- a/ui/pages/guest-edit.html.tmpl +++ b/ui/pages/guest-edit.html.tmpl @@ -38,6 +38,9 @@ <li> <a href="#form-guest-edit-interface">$_("Interface")</a> </li> + <li> + <a href="#form-guest-edit-permission">$_("Permission")</a> + </li> </ul> <form id="form-guest-edit-general"> <fieldset class="guest-edit-fieldset"> @@ -109,6 +112,31 @@ </div> <div class="body"></div> </form> + <form id="form-guest-edit-permission" class="guest-edit-permission"> + <div class="column avail"> + <div class="title">$_("Available system users and groups")</div> + <input type="text" id="permission-searchBox"> + <div class="body"> + <div class="head"> + <div class="column column-user"><div class="item">Users</div></div> + <div class="column column-group"><div class="item">Groups</div></div> + </div> + <div id="permission-avail-users" class="column column-user"></div> + <div id="permission-avail-groups" class="column column-group"></div> + </div> + </div> + <div class="column control"> + <button id="permissionGo"> > </button> + <button id="permissionBack"> < </button> + </div> + <div class="column selected"> + <div class="title">$_("Selected system users and groups")</div> + <div class="body"> + <div id="permission-sel-users"></div> + <div id="permission-sel-groups"></div> + </div> + </div> + </form> </div> </div> <footer> @@ -117,6 +145,9 @@ <span class="text">$_("Save")</span> </button> </div> + <button id="form-guest-edit-permission-save" class="btn-normal hidden"> + <span class="text">$_("Save")</span> + </button> </footer> </div> <script id="cdrom-row-tmpl" type="text/html"> @@ -186,6 +217,12 @@ </span> </div> </script> +<script id="permission-item" type="text/html"> +<div class="item"> + <span class="icon {class}"></span> + <label>{val}</label> +</div> +</script> <script type="text/javascript"> kimchi.guest_edit_main(); </script> -- 1.7.1