66
77<section >
88 <article id =" stage" >
9+
10+ <div class =" message" style =" display : none " data-bind =" text: message, visible: message" ></div >
11+
912 <h2 >User Security Policies</h2 >
1013
1114 <form >
1215 <textarea placeholder =" Search for usernames (comma-separated)" autocomplete =" off" autofocus style =" width : 100% ;" rows =" 5" data-bind =" value: searchQuery" ></textarea ><br />
13- <input type =" button" value =" Search" data-bind =" click: search" />
16+ <input type =" button" value =" Search" title = " Search " data-bind =" click: search" />
1417 </form ><br />
1518
16- @using (Html .BeginForm (" Update" , " SecurityPolicy" , new { area = " Admin" }, FormMethod .Post , new { id = " delete-form" }))
17- {
1819 <div data-bind =" visible: searchResults().length > 0" >
19- <input type =" hidden" name =" UsersQuery" data-bind =" value: searchQuery" />
20-
20+
2121 <div class =" message warning" style =" display : none ;" data-bind =" visible: searchNotFoundResults().length > 0" >
2222 <strong >The following users were not found:</strong ><br />
2323 <span data-bind =" text: searchNotFoundResults().join(',')" ></span >
2424 </div >
25+
26+ @using (Html .BeginForm ())
27+ {
28+ <div >
29+ <table id =" searchResults" class =" sexy-table" >
30+ <thead >
31+ <tr >
32+ <th >Username </th >
33+ @foreach ( var subscription in Model .SubscriptionNames )
34+ {
35+ <th ><input type =" checkbox" data-bind =" click: toggleSelectAll, checked: selectAllState.@subscription" />@subscription </th >
36+ }
37+ </tr >
38+ </thead >
39+ <tbody id =" policies" data-bind =" foreach: searchResults" >
40+ <tr >
41+ <td ><a href =" #" data-bind =" text: Username, attr: { href: $parent.generateUserUrl($data) }" ></a ></td >
42+ @foreach ( var subscription in Model .SubscriptionNames )
43+ {
44+ <td ><input type =" checkbox" data-bind =" checked: $data.Selected.@subscription, value: $parent.generateValue($data, '@subscription')" /></td >
45+ }
46+ </tr >
47+ </tbody >
48+ </table >
49+ </div >
2550
26- <div >
27- <table id =" searchResults" class =" sexy-table" >
28- <thead >
29- <tr >
30- <th >Username </th >
31- @foreach ( var subscription in Model .SubscriptionNames )
32- {
33- <th ><input type =" checkbox" data-bind =" click: toggleSelectAll, checked: selectAllState.@subscription" />@subscription </th >
34- }
35- </tr >
36- </thead >
37- <tbody data-bind =" foreach: searchResults" >
38- <tr >
39- <td ><a href =" #" data-bind =" text: Username, attr: { href: $parent.generateUserUrl($data) }" ></a ></td >
40- @foreach ( var subscription in Model .SubscriptionNames )
41- {
42- <td ><input type =" checkbox" name =" UserSubscriptions[]" data-bind =" checked: $data.Selected.@subscription, value: $parent.generateValue($data, '@subscription')" /></td >
43- }
44- </tr >
45- </tbody >
46- </table >
47- </div >
48-
49- <div class =" danger-zone" style =" display : none ;" data-bind =" visible: changeTracker" >
51+ <div class =" danger-zone" style =" display : none ;" data-bind =" visible: changeTracker" >
5052
51- <fieldset id =" unlist-form" class =" form" >
52- @Html.AntiForgeryToken()
53-
54- <p >
55- Onboarding users to security policy subscriptions could result in changes which <strong >CANNOT </strong > be undone .
56- </p >
57-
58- <input type =" submit" value =" I understand, update security policies." title =" I understand, update security policies." />
59- <a class =" cancel" href =" @Url.Action(" Index " , " Home " )" title =" Cancel changes" >Cancel </a >
60- </fieldset >
61- </div >
53+ <fieldset id =" update-form" class =" form" >
54+ <p >
55+ Onboarding users to security policy subscriptions could result in changes which <strong >CANNOT </strong > be undone .
56+ </p >
57+
58+ <input type =" submit" value =" I understand, update policies." title =" I understand, update policies." data-bind =" click: update" />
59+ <a class =" cancel" href =" @Url.Action(" Index " , " Home " )" title =" Cancel changes" >Cancel </a >
60+ </fieldset >
61+ </div >
62+ }
6263
6364 </div >
64- }
6565</article >
6666</section >
6767
7272 var viewModel = function () {
7373 var $self = this ;
7474
75- this .subscriptions = @Html .Raw (Json .Encode (@Model .SubscriptionNames ));
75+ this .message = ko .observable (' ' );
76+
77+ this .currentSubscription ;
78+ this .subscriptionNames = @Html .Raw (Json .Encode (@Model .SubscriptionNames ));
7679 this .searchQuery = ko .observable (' ' );
7780
81+ this .update = function () {
82+ var subscriptions = [];
83+ $ (' #policies input:checkbox' ).each (function (i , checkbox ) {
84+ subscriptions .push (checkbox .value );
85+ });
86+
87+ $ .ajax ({
88+ url: ' @Url.Action("Update", "SecurityPolicy", new { area = "Admin" })' ,
89+ cache: false ,
90+ dataType: ' json' ,
91+ type: ' POST' ,
92+ data: JSON .stringify (subscriptions),
93+ contentType: ' application/json; charset=utf-8' ,
94+ success : function (data ) {
95+ $self .changeTracker (false );
96+ $self .message (" Security policies updated!" );
97+ }
98+ })
99+ .error (function (jqXhr , textStatus , errorThrown ) {
100+ alert (" Error: " + errorThrown);
101+ });
102+ },
103+
78104 this .search = function () {
105+ $self .message (" " );
79106 $ .ajax ({
80107 url: ' @Url.Action("Search", "SecurityPolicy", new {area = "Admin"})?query=' + encodeURIComponent ($self .searchQuery ()),
81- cache: false ,
82- dataType: ' json' ,
83- success : function (data ) {
84- $self .changeTracker (false );
85- $self .resetSelectAllState ();
86- $self .searchResults .removeAll ();
87- $self .searchNotFoundResults .removeAll ();
88-
89- for (var i = 0 ; i < data .Users .length ; i++ ) {
90- var user = data .Users [i];
91- user .Selected = {};
92- for (var key in user .Subscriptions ) {
93- user .Selected [key] = ko .observable (user .Subscriptions [key]);
94- user .Selected [key].subscribe ($self .markDirty );
95- }
108+ cache: false ,
109+ dataType: ' json' ,
110+ success : function (data ) {
111+ $self .changeTracker (false );
112+ $self .resetSelectAllState ();
113+ $self .searchResults .removeAll ();
114+ $self .searchNotFoundResults .removeAll ();
115+
116+ for (var i = 0 ; i < data .Users .length ; i++ ) {
117+ var user = data .Users [i];
118+ user .Selected = {};
119+ for (var key in user .Subscriptions ) {
120+ user .Selected [key] = ko .observable (user .Subscriptions [key]);
121+ user .Selected [key].subscribe ($self .markDirty );
96122 }
97-
98- $self .searchResults (data .Users );
99- $self .searchNotFoundResults (data .UsersNotFound );
100- },
101- error : function (data ) {
102- alert (" Error: " + errorThrown);
103123 }
104- })
105- .error (function (jqXhr , textStatus , errorThrown ) {
106- alert (" Error: " + errorThrown);
107- });
124+
125+ $self .searchResults (data .Users );
126+ $self .searchNotFoundResults (data .UsersNotFound );
127+ }
128+ })
129+ .error (function (jqXhr , textStatus , errorThrown ) {
130+ alert (" Error: " + errorThrown);
131+ });
108132 };
109-
133+
110134 this .selectAllState = {};
111- for (var i = 0 ; i < this .subscriptions .length ; i++ )
135+ for (var i = 0 ; i < this .subscriptionNames .length ; i++ )
112136 {
113- var subscription = this .subscriptions [i];
137+ var subscription = this .subscriptionNames [i];
114138 this .selectAllState [subscription] = ko .observable (false );
115139 }
116140
117141 this .resetSelectAllState = function () {
118- for (var i = 0 ; i < $self .subscriptions .length ; i++ )
142+ for (var i = 0 ; i < $self .subscriptionNames .length ; i++ )
119143 {
120- $self .selectAllState [$self .subscriptions [i]](false );
144+ var subscription = $self .subscriptionNames [i];
145+ $self .selectAllState [subscription](false );
121146 }
122147 }
123-
148+
124149 this .toggleSelectAll = function (data , e ) {
125- var subscription = e .currentTarget .nextSibling .data ;
126- $self .selectAllState [subscription ](! $self .selectAllState [subscription ]());
150+ $self . currentSubscription = e .currentTarget .nextSibling .data ;
151+ $self .selectAllState [$self . currentSubscription ](! $self .selectAllState [$self . currentSubscription ]());
127152 return true ;
128153 };
129154
130155 this .generateValue = function (user , subscription ) {
131- return JSON .stringify ({ " u" : user .Username , " g" : subscription })
156+ return JSON .stringify ({ " u" : user .Username , " g" : subscription, " v " : user . Selected [subscription]() })
132157 };
133158
134159 this .generateUserUrl = function (user ) {
145170 $self .changeTracker (true );
146171 };
147172
148- for (var i = 0 ; i < this .subscriptions .length ; i++ ) {
173+ for (var i = 0 ; i < this .subscriptionNames .length ; i++ ) {
174+ var subscription = this .subscriptionNames [i];
149175 this .selectAllState [subscription].subscribe (function () {
150- var state = $self .selectAllState [subscription ]();
176+ var state = $self .selectAllState [$self . currentSubscription ]();
151177
152178 ko .utils .arrayForEach ($self .searchResults (), function (result ) {
153- result .Selected [subscription ](state);
179+ result .Selected [$self . currentSubscription ](state);
154180 });
155181 });
156182 }
157183 };
158184
159185 ko .applyBindings (new viewModel (), $ (' #stage' ).get (0 ));
160-
161- $ (' #delete-form' ).submit (function (e ) {
162- if (! confirm (' Are you sure you want to continue?' )) {
163- e .preventDefault ();
164- }
165- });
166186 });
167187 </script >
168188}
0 commit comments