Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ResourcesView.cs @ 8078

Last change on this file since 8078 was 8075, checked in by ascheibe, 12 years ago

#1859 some improvements for the resource permission management ui

File size: 20.5 KB
RevLine 
[6976]1#region License Information
2/* HeuristicLab
[7259]3 * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
[6976]4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
[8051]23using System.Collections.Generic;
[6976]24using System.Drawing;
25using System.Linq;
26using System.ServiceModel.Security;
27using System.Threading;
28using System.Threading.Tasks;
29using System.Windows.Forms;
[8051]30using HeuristicLab.Clients.Access;
[6976]31using HeuristicLab.Clients.Hive.Views;
32using HeuristicLab.Core;
33using HeuristicLab.Core.Views;
34using HeuristicLab.MainForm;
35using TS = System.Threading.Tasks;
36
37namespace HeuristicLab.Clients.Hive.Administrator.Views {
38  [View("Resources View")]
[7928]39  [Content(typeof(IItemList<Resource>), false)]
[6976]40  public partial class ResourcesView : ItemView, IDisposable {
41    public new IItemList<Resource> Content {
42      get { return (IItemList<Resource>)base.Content; }
43      set { base.Content = value; }
44    }
45
46    public const string UngroupedGroupName = "UNGROUPED";
47    private const int slaveImageIndex = 0;
48    private const int slaveGroupImageIndex = 1;
[8051]49    private readonly Color ownedResourceColor = Color.LightGreen;
[6976]50    private TS.Task progressTask;
51    private bool stopProgressTask;
[8051]52    private bool currentlyAuthorized;
[6976]53
54
55    public ResourcesView() {
56      InitializeComponent();
[7256]57      treeSlaveGroup.ImageList.Images.Add(HeuristicLab.Common.Resources.VSImageLibrary.MonitorLarge);
58      treeSlaveGroup.ImageList.Images.Add(HeuristicLab.Common.Resources.VSImageLibrary.NetworkCenterLarge);
[6976]59
60      HiveAdminClient.Instance.Refreshing += new EventHandler(Instance_Refreshing);
61      HiveAdminClient.Instance.Refreshed += new EventHandler(Instance_Refreshed);
[8051]62
[8075]63      Access.AccessClient.Instance.Refreshing += new EventHandler(AccessClient_Refreshing);
64      Access.AccessClient.Instance.Refreshed += new EventHandler(AccessClient_Refreshed);
[6976]65    }
66
67    private void UpdateProgress() {
68      while (!stopProgressTask) {
69        int diff = (progressBar.Maximum - progressBar.Minimum) / 10;
70
71        if (progressBar.InvokeRequired) {
72          progressBar.Invoke(new Action(delegate() { progressBar.Value = (progressBar.Value + diff) % progressBar.Maximum; }));
73        } else {
74          progressBar.Value = (progressBar.Value + diff) % progressBar.Maximum;
75        }
76
77        //ok, this is not very clever...
78        Thread.Sleep(500);
79      }
80      if (progressBar.InvokeRequired) {
81        progressBar.Invoke(new Action(delegate() { progressBar.Value = progressBar.Minimum; }));
82      } else {
83        progressBar.Value = progressBar.Minimum;
84      }
85    }
86
87    void Instance_Refreshing(object sender, EventArgs e) {
88      stopProgressTask = false;
89      progressTask = new TS.Task(UpdateProgress);
90      progressTask.Start();
[8075]91      SetEnabledStateOfControls();
[6976]92    }
93
94    void Instance_Refreshed(object sender, EventArgs e) {
95      stopProgressTask = true;
[8075]96      SetEnabledStateOfControls();
[6976]97    }
98
[8075]99    void AccessClient_Refreshing(object sender, EventArgs e) {
[8051]100      stopProgressTask = false;
101      progressTask = new TS.Task(UpdateProgress);
102      progressTask.Start();
[8075]103      SetEnabledStateOfControls();
[8051]104    }
105
[8075]106    void AccessClient_Refreshed(object sender, EventArgs e) {
[8051]107      stopProgressTask = true;
[8075]108      SetEnabledStateOfControls();
[8051]109    }
110
[6976]111    #region Register Content Events
112    protected override void DeregisterContentEvents() {
113      Content.ItemsAdded -= new Collections.CollectionItemsChangedEventHandler<Collections.IndexedItem<Resource>>(Content_ItemsAdded);
114      Content.ItemsRemoved -= new Collections.CollectionItemsChangedEventHandler<Collections.IndexedItem<Resource>>(Content_ItemsRemoved);
115      base.DeregisterContentEvents();
116    }
117    protected override void RegisterContentEvents() {
118      base.RegisterContentEvents();
119      Content.ItemsAdded += new Collections.CollectionItemsChangedEventHandler<Collections.IndexedItem<Resource>>(Content_ItemsAdded);
120      Content.ItemsRemoved += new Collections.CollectionItemsChangedEventHandler<Collections.IndexedItem<Resource>>(Content_ItemsRemoved);
121    }
122    #endregion
123
124    protected override void OnContentChanged() {
125      base.OnContentChanged();
126      if (Content == null) {
127        slaveView.Content = null;
[8051]128        scheduleView.Content = null;
129        permissionView.Content = null;
130        permissionView.FetchSelectedUsers = null;
[6976]131        treeSlaveGroup.Nodes.Clear();
132      } else {
[8051]133        permissionView.Content = Access.AccessClient.Instance;
[6976]134        treeSlaveGroup.Nodes.Clear();
135
136        //rebuild
137        TreeNode ungrp = new TreeNode(UngroupedGroupName);
138        ungrp.ImageIndex = slaveGroupImageIndex;
139        ungrp.SelectedImageIndex = ungrp.ImageIndex;
140        var newGroup = new SlaveGroup();
141        newGroup.Name = UngroupedGroupName;
142        newGroup.Id = Guid.NewGuid();
143        newGroup.Description = "Contains slaves which are in no group";
144        ungrp.Tag = newGroup;
145
146        foreach (Resource g in Content) {
147          if (g.GetType() == typeof(SlaveGroup)) {
148            //root node
149            if (g.ParentResourceId == null) {
150              TreeNode tn = new TreeNode();
151              tn.ImageIndex = slaveGroupImageIndex;
152              tn.SelectedImageIndex = tn.ImageIndex;
153
154              tn.Tag = g;
155              tn.Text = g.Name;
[8051]156              if (g.OwnerUserId == Access.UserInformation.Instance.User.Id) tn.BackColor = ownedResourceColor;
[6976]157
158              BuildSlaveGroupTree(g, tn);
159              treeSlaveGroup.Nodes.Add(tn);
160            }
161          } else if (g.GetType() == typeof(Slave)) {
162            if (g.ParentResourceId == null) {
163              var stn = new TreeNode(g.Name);
164              stn.ImageIndex = slaveImageIndex;
165              stn.SelectedImageIndex = stn.ImageIndex;
166              stn.Tag = g;
[8051]167              if (g.OwnerUserId == Access.UserInformation.Instance.User.Id) stn.BackColor = ownedResourceColor;
[6976]168              ungrp.Nodes.Add(stn);
169            }
170          }
171        }
172        treeSlaveGroup.Nodes.Add(ungrp);
173      }
174    }
175
176    private void BuildSlaveGroupTree(Resource g, TreeNode tn) {
177      foreach (Resource r in Content.Where(s => s.ParentResourceId != null && s.ParentResourceId == g.Id)) {
178        TreeNode stn = new TreeNode(r.Name);
179        if (r is Slave) {
180          stn.ImageIndex = slaveImageIndex;
181        } else if (r is SlaveGroup) {
182          stn.ImageIndex = slaveGroupImageIndex;
183        }
184        stn.SelectedImageIndex = stn.ImageIndex;
185        stn.Tag = r;
[8051]186        if (r.OwnerUserId == Access.UserInformation.Instance.User.Id) stn.BackColor = ownedResourceColor;
[6976]187        tn.Nodes.Add(stn);
188
189        BuildSlaveGroupTree(r, stn);
190      }
191    }
192
193    protected override void SetEnabledStateOfControls() {
194      base.SetEnabledStateOfControls();
[7250]195      if (Content == null) {
196        btnAddGroup.Enabled = false;
197        btnRemoveGroup.Enabled = false;
198        btnSave.Enabled = false;
[8051]199        btnPermissionsSave.Enabled = false;
200        permissionView.Enabled = false;
[8075]201        scheduleView.SetEnabledStateOfSchedule(false);
202        btnPermissionsSave.Enabled = false;
203        permissionView.Enabled = false;
[7250]204      } else {
205        btnAddGroup.Enabled = true;
206        btnRemoveGroup.Enabled = true;
207        btnSave.Enabled = true;
[8075]208        scheduleView.SetEnabledStateOfSchedule(IsAuthorized(slaveView.Content));
209        btnPermissionsSave.Enabled = permissionView.FetchSelectedUsers != null;
210        permissionView.Enabled = permissionView.FetchSelectedUsers != null;
[7250]211      }
[6976]212    }
213
[8051]214    private bool IsAuthorized(Resource resource) {
215      return resource != null
216          && resource.Name != UngroupedGroupName
217          && resource.Id != Guid.Empty
[8071]218          && UserInformation.Instance.UserExists
219          && (resource.OwnerUserId == UserInformation.Instance.User.Id || HiveRoles.CheckAdminUserPermissions());
[8051]220    }
[6976]221
[8051]222    private void treeSlaveGroup_AfterSelect(object sender, TreeViewEventArgs e) {
223      if (e.Action != TreeViewAction.Unknown) {
224        Resource selectedResource = ((Resource)e.Node.Tag);
225        currentlyAuthorized = IsAuthorized(selectedResource);
226        if (currentlyAuthorized) {
227          permissionView.FetchSelectedUsers = new Func<List<Guid>>(() => {
228            return HiveServiceLocator.Instance.CallHiveService<List<ResourcePermission>>(service => {
229              return service.GetResourcePermissions(selectedResource.Id);
230            }).Select(x => x.GrantedUserId).ToList();
231          });
232          if (!tabSlaveGroup.TabPages.Contains(tabPermissions)) tabSlaveGroup.TabPages.Add(tabPermissions);
233        } else {
234          permissionView.FetchSelectedUsers = null;
235          btnPermissionsSave.Enabled = false;
236          if (selectedResource.Id == Guid.Empty) {
237            if (!tabSlaveGroup.TabPages.Contains(tabPermissions)) tabSlaveGroup.TabPages.Add(tabPermissions);
238          } else tabSlaveGroup.TabPages.Remove(tabPermissions);
239        }
[6976]240
[8051]241        if (slaveView.Content != null && slaveView.Content is SlaveGroup) {
242          slaveView.Content.PropertyChanged -= new System.ComponentModel.PropertyChangedEventHandler(SlaveViewContent_PropertyChanged);
243        }
244
245        slaveView.Content = selectedResource;
246        HiveAdminClient.Instance.DowntimeForResourceId = selectedResource.Id;
247
248        if (selectedResource is SlaveGroup) {
249          slaveView.Content.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(SlaveViewContent_PropertyChanged);
250        }
251
252        if (tabSlaveGroup.SelectedIndex == 1) {
253          UpdateScheduleAsync();
254        } else if (tabSlaveGroup.SelectedIndex == 2) {
255          UpdatePermissionsAsync();
256        }
[6976]257      }
258    }
259
260    void SlaveViewContent_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) {
261      OnContentChanged();
262      if (e.PropertyName == "HbInterval") {
263        UpdateChildHbIntervall(slaveView.Content);
264      }
265    }
266
267    private void UpdateChildHbIntervall(Resource resource) {
268      foreach (Resource r in Content.Where(x => x.ParentResourceId == resource.Id)) {
269        r.HbInterval = resource.HbInterval;
270        if (r is SlaveGroup) {
271          UpdateChildHbIntervall(r);
272        }
273      }
274    }
275
276    private void btnAddGroup_Click(object sender, EventArgs e) {
277      SlaveGroup newGroup = new SlaveGroup();
278      newGroup.Name = "New Group";
[8051]279      newGroup.OwnerUserId = UserInformation.Instance.User.Id;
[6976]280      Content.Add(newGroup);
281    }
282
283    void Content_ItemsRemoved(object sender, Collections.CollectionItemsChangedEventArgs<Collections.IndexedItem<Resource>> e) {
284      OnContentChanged();
285    }
286
287    void Content_ItemsAdded(object sender, Collections.CollectionItemsChangedEventArgs<Collections.IndexedItem<Resource>> e) {
288      OnContentChanged();
289    }
290
291    private void btnRemoveGroup_Click(object sender, EventArgs e) {
292      if (treeSlaveGroup.SelectedNode != null && treeSlaveGroup.SelectedNode.Tag != null) {
293        Resource res = (Resource)treeSlaveGroup.SelectedNode.Tag;
294
295        DialogResult diagRes = MessageBox.Show("Do you really want to delete " + res.Name + "?", "HeuristicLab Hive Administrator", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
296        if (diagRes == DialogResult.Yes) {
297          if (res is Slave) {
298            Content.Remove(res);
299            HiveAdminClient.Delete(res);
300          } else if (res is SlaveGroup) {
301            //only delete empty groups
302            if (Content.Where(s => s.ParentResourceId == res.Id).Count() < 1) {
303              Content.Remove(res);
304              HiveAdminClient.Delete(res);
305            } else {
306              MessageBox.Show("Only empty groups can be deleted.", "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Error);
307            }
308          }
309        }
310      }
311    }
312
313    private void btnSave_Click(object sender, EventArgs e) {
314      foreach (Resource res in Content) {
315        if (res is SlaveGroup && res.Id == Guid.Empty) {
316          SlaveGroup slaveGroup = (SlaveGroup)res;
317          slaveGroup.Store();
318        } else if (res.Id != Guid.Empty && res.Modified) {
319          res.Store();
320        }
321      }
322    }
323
324    private void treeSlaveGroup_DragDrop(object sender, DragEventArgs e) {
325      if (e.Data.GetDataPresent("System.Windows.Forms.TreeNode", false)) {
326        Point pt = ((TreeView)sender).PointToClient(new Point(e.X, e.Y));
327        TreeNode destNode = ((TreeView)sender).GetNodeAt(pt);
328        TreeNode newNode = (TreeNode)e.Data.GetData("System.Windows.Forms.TreeNode");
329
330        if (destNode.TreeView == newNode.TreeView) {
331          if (destNode.Text == UngroupedGroupName || (destNode.Parent != null && destNode.Parent.Text == UngroupedGroupName)) {
[8051]332            MessageBox.Show(string.Format("You can't drag items to the group \"{0}\".{1}This group only contains slaves which haven't yet been assigned to a real group.",
[6976]333              UngroupedGroupName, Environment.NewLine), "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Information);
334            return;
335          }
336
337          SlaveGroup sgrp = null;
338          TreeNode parentNode = null;
339          if (destNode.Tag != null && destNode.Tag is SlaveGroup) {
340            sgrp = (SlaveGroup)destNode.Tag;
341            parentNode = destNode;
342          } else if (destNode.Parent != null && destNode.Parent.Tag is SlaveGroup) {
343            sgrp = (SlaveGroup)destNode.Parent.Tag;
344            parentNode = destNode.Parent;
345          }
346
347          if (newNode.Tag is SlaveGroup && CheckParentsEqualsMovedNode(parentNode, newNode)) {
348            return;
349          }
350
[8051]351          SlaveGroup parent = (SlaveGroup)parentNode.Tag;
352
353          if (parent.OwnerUserId != null && !IsAuthorized(parent)) {
354            MessageBox.Show(string.Format("You don't have the permissions to drag items to the group \"{0}\".", ((Resource)parentNode.Tag).Name),
355              "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Error);
356            return;
357          }
358
[6976]359          if (sgrp != null && newNode.Tag != null) {
360            //save parent group to get an id
361            if (sgrp.Id == Guid.Empty) {
362              sgrp.Store();
363            }
364
365            if (newNode.Tag is Slave) {
366              Slave slave = (Slave)newNode.Tag;
367              if (slave.ParentResourceId == null || (slave.ParentResourceId != null && slave.ParentResourceId != sgrp.Id)) {
368                slave.ParentResourceId = sgrp.Id;
369                newNode.Remove();
370                parentNode.Nodes.Clear();
371                BuildSlaveGroupTree(sgrp, parentNode);
372              }
373            } else if (newNode.Tag is SlaveGroup) {
374              SlaveGroup slaveGroup = (SlaveGroup)newNode.Tag;
375              if (slaveGroup.ParentResourceId == null || (slaveGroup.ParentResourceId != null && slaveGroup.ParentResourceId != sgrp.Id)) {
376                slaveGroup.ParentResourceId = sgrp.Id;
377                newNode.Remove();
378                parentNode.Nodes.Clear();
379                BuildSlaveGroupTree(sgrp, parentNode);
380              }
381            }
382          }
383        }
384      }
385    }
386
387    private bool CheckParentsEqualsMovedNode(TreeNode dest, TreeNode movedNode) {
388      TreeNode tmp = dest;
389
390      while (tmp != null) {
391        if (tmp == movedNode) {
392          return true;
393        }
394        tmp = tmp.Parent;
395      }
396      return false;
397    }
398
399    private void treeSlaveGroup_ItemDrag(object sender, ItemDragEventArgs e) {
400      TreeNode sourceNode = (TreeNode)e.Item;
[8051]401      if (IsAuthorized((Resource)sourceNode.Tag))
402        DoDragDrop(sourceNode, DragDropEffects.All);
[6976]403    }
404
405    private void treeSlaveGroup_DragEnter(object sender, DragEventArgs e) {
406      e.Effect = DragDropEffects.Move;
407    }
408
409    private void treeSlaveGroup_DragOver(object sender, DragEventArgs e) {
410      e.Effect = DragDropEffects.Move;
411    }
412
413    private void treeSlaveGroup_QueryContinueDrag(object sender, QueryContinueDragEventArgs e) {
414      e.Action = DragAction.Continue;
415    }
416
417    void ResetView() {
[7256]418      if (this.InvokeRequired) {
419        Invoke(new Action(ResetView));
420      } else {
421        treeSlaveGroup.Nodes.Clear();
[6976]422
[7256]423        if (slaveView.Content != null && slaveView.Content is SlaveGroup) {
424          slaveView.Content.PropertyChanged -= new System.ComponentModel.PropertyChangedEventHandler(SlaveViewContent_PropertyChanged);
425        }
426        slaveView.Content = null;
427        if (scheduleView.Content != null) {
428          scheduleView.Content.Clear();
429        }
430        HiveAdminClient.Instance.ResetDowntime();
[6976]431      }
432    }
433
434    private void UpdateResources() {
[7256]435      ResetView();
[6976]436
437      try {
438        HiveAdminClient.Instance.Refresh();
439        Content = HiveAdminClient.Instance.Resources;
440      }
441      catch (MessageSecurityException) {
[7256]442        ShowMessageSecurityException();
[6976]443      }
[7249]444      catch (AnonymousUserException) {
[7256]445        ShowHiveInformationDialog();
[7249]446      }
[6976]447    }
448
[7256]449    private void ShowMessageSecurityException() {
450      if (this.InvokeRequired) {
451        Invoke(new Action(ShowMessageSecurityException));
452      } else {
453        MessageBox.Show("A Message Security error has occured. This normally means that your user name or password is wrong.", "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Error);
454      }
455    }
456
457    private void ShowHiveInformationDialog() {
458      if (this.InvokeRequired) {
459        Invoke(new Action(ShowHiveInformationDialog));
460      } else {
461        using (HiveInformationDialog dialog = new HiveInformationDialog()) {
462          dialog.ShowDialog(this);
463        }
464      }
465    }
466
[6976]467    private void UpdateResourcesAsync() {
468      TS.Task.Factory.StartNew(UpdateResources).ContinueWith((t) => {
469        DisplayError(t.Exception);
470      }, TaskContinuationOptions.OnlyOnFaulted);
471    }
472
473    private void UpdateSchedule() {
474      HiveAdminClient.Instance.RefreshCalendar();
[8051]475      scheduleView.Invoke(new Action(() => {
476        scheduleView.Content = HiveAdminClient.Instance.Downtimes;
[8075]477        SetEnabledStateOfControls();
[8051]478      }));
[6976]479    }
480
481    private void UpdateScheduleAsync() {
482      TS.Task.Factory.StartNew(UpdateSchedule).ContinueWith((t) => {
483        DisplayError(t.Exception);
484      }, TaskContinuationOptions.OnlyOnFaulted);
485    }
486
[8051]487    private void UpdatePermissions() {
488      if (permissionView.Content != null && permissionView.FetchSelectedUsers != null)
489        permissionView.Invoke(new Action(() => permissionView.ManualRefresh()));
490    }
491
492    private void UpdatePermissionsAsync() {
493      TS.Task.Factory.StartNew(UpdatePermissions).ContinueWith((t) => {
494        DisplayError(t.Exception);
495      }, TaskContinuationOptions.OnlyOnFaulted);
496    }
497
498
[6976]499    private void DisplayError(Exception ex) {
500      MessageBox.Show(string.Format("An error occured while updating: {0} {1}", Environment.NewLine, ex.Message), "HeuristicLab Hive Administrator", MessageBoxButtons.OK, MessageBoxIcon.Error);
501    }
502
503    private void tabSlaveGroup_SelectedIndexChanged(object sender, EventArgs e) {
504      if (tabSlaveGroup.SelectedIndex == 1) {
505        UpdateScheduleAsync();
[8051]506      } else if (tabSlaveGroup.SelectedIndex == 2) {
507        UpdatePermissionsAsync();
[6976]508      }
509    }
510
511    private void btnRefresh_Click(object sender, EventArgs e) {
512      UpdateResourcesAsync();
513    }
[6994]514
515    private void ResourcesView_Load(object sender, EventArgs e) {
516      UpdateResourcesAsync();
517    }
[8051]518
519    private void btnPermissionsSave_Click(object sender, EventArgs e) {
[8075]520      SetEnabledStateOfControls();
[8051]521      HiveServiceLocator.Instance.CallHiveService(service => {
522        service.GrantResourcePermissions(((Resource)treeSlaveGroup.SelectedNode.Tag).Id, permissionView.GetAddedUsers().Select(x => x.Id).ToList());
523        service.RevokeResourcePermissions(((Resource)treeSlaveGroup.SelectedNode.Tag).Id, permissionView.GetDeletedUsers().Select(x => x.Id).ToList());
524      });
[8075]525      SetEnabledStateOfControls();
[8051]526    }
[6976]527  }
528}
Note: See TracBrowser for help on using the repository browser.