Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectsView.cs @ 15401

Last change on this file since 15401 was 15401, checked in by jkarder, 7 years ago

#2839:

  • worked on hive administrator view
  • updated service clients
File size: 15.0 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2017 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
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;
23using System.Collections.Generic;
24using System.ComponentModel;
25using System.Drawing;
26using System.Linq;
27using System.Windows.Forms;
28using HeuristicLab.Clients.Access;
29using HeuristicLab.Clients.Hive.Views;
30using HeuristicLab.Collections;
31using HeuristicLab.Common.Resources;
32using HeuristicLab.Core;
33using HeuristicLab.Core.Views;
34using HeuristicLab.MainForm;
35
36namespace HeuristicLab.Clients.Hive.Administrator.Views {
37  [View("Projects View")]
38  [Content(typeof(IItemList<Project>), false)]
39  public partial class ProjectsView : ItemView, IDisposable {
40    private const int greenFlagImageIndex = 0;
41    private const int redFlagImageIndex = 1;
42
43    private readonly object locker = new object();
44    private bool updatingProjects = false;
45    private bool removingProjects = false;
46    private bool savingProjects = false;
47
48    public new IItemList<Project> Content {
49      get { return (IItemList<Project>)base.Content; }
50      set { base.Content = value; }
51    }
52
53    public ProjectsView() {
54      InitializeComponent();
55
56      projectsTreeView.ImageList.Images.Add(VSImageLibrary.FlagGreen);
57      projectsTreeView.ImageList.Images.Add(VSImageLibrary.FlagRed);
58
59      HiveAdminClient.Instance.Refreshing += HiveAdminClient_Instance_Refreshing;
60      HiveAdminClient.Instance.Refreshed += HiveAdminClient_Instance_Refreshed;
61      AccessClient.Instance.Refreshing += AccessClient_Instance_Refreshing;
62      AccessClient.Instance.Refreshed += AccessClient_Instance_Refreshed;
63    }
64
65    #region Overrides
66    protected override void OnClosing(FormClosingEventArgs e) {
67      AccessClient.Instance.Refreshed -= AccessClient_Instance_Refreshed;
68      AccessClient.Instance.Refreshing -= AccessClient_Instance_Refreshing;
69      HiveAdminClient.Instance.Refreshed -= HiveAdminClient_Instance_Refreshed;
70      HiveAdminClient.Instance.Refreshing -= HiveAdminClient_Instance_Refreshing;
71      base.OnClosing(e);
72    }
73
74    protected override void RegisterContentEvents() {
75      base.RegisterContentEvents();
76      Content.ItemsAdded += Content_ItemsAdded;
77      Content.ItemsRemoved += Content_ItemsRemoved;
78    }
79
80    protected override void DeregisterContentEvents() {
81      Content.ItemsRemoved -= Content_ItemsRemoved;
82      Content.ItemsAdded -= Content_ItemsAdded;
83      base.DeregisterContentEvents();
84    }
85
86    protected override void OnContentChanged() {
87      base.OnContentChanged();
88      if (Content == null) {
89        projectsTreeView.Nodes.Clear();
90        projectView.Content = null;
91        permissionsView.Content = null;
92        permissionsView.FetchSelectedUsers = null;
93      } else {
94        var top = BuildProjectTree(Content);
95        projectView.Content = top;
96        permissionsView.Content = AccessClient.Instance;
97      }
98    }
99
100    protected override void SetEnabledStateOfControls() {
101      base.SetEnabledStateOfControls();
102      bool enabled = Content != null;
103      addButton.Enabled = enabled;
104      removeButton.Enabled = enabled;
105      saveProjectButton.Enabled = enabled;
106      savePermissionsButton.Enabled = enabled && permissionsView.FetchSelectedUsers != null;
107      permissionsView.Enabled = enabled && permissionsView.FetchSelectedUsers != null;
108    }
109    #endregion
110
111    #region Event Handlers
112    private void Content_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<Project>> e) {
113      OnContentChanged();
114    }
115
116    private void Content_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<Project>> e) {
117      OnContentChanged();
118    }
119
120    private void ProjectViewContent_PropertyChanged(object sender, PropertyChangedEventArgs e) {
121      OnContentChanged();
122    }
123
124    private void HiveAdminClient_Instance_Refreshing(object sender, EventArgs e) {
125      if (InvokeRequired) Invoke((Action<object, EventArgs>)HiveAdminClient_Instance_Refreshing, sender, e);
126      else {
127        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
128        mainForm.AddOperationProgressToView(this, "Refreshing ...");
129        SetEnabledStateOfControls();
130      }
131    }
132
133    private void HiveAdminClient_Instance_Refreshed(object sender, EventArgs e) {
134      if (InvokeRequired) Invoke((Action<object, EventArgs>)HiveAdminClient_Instance_Refreshed, sender, e);
135      else {
136        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
137        mainForm.RemoveOperationProgressFromView(this);
138        SetEnabledStateOfControls();
139      }
140    }
141
142    private void AccessClient_Instance_Refreshing(object sender, EventArgs e) {
143      if (InvokeRequired) Invoke((Action<object, EventArgs>)AccessClient_Instance_Refreshing, sender, e);
144      else {
145        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
146        mainForm.AddOperationProgressToView(this, "Refreshing ...");
147        SetEnabledStateOfControls();
148      }
149    }
150
151    private void AccessClient_Instance_Refreshed(object sender, EventArgs e) {
152      if (InvokeRequired) Invoke((Action<object, EventArgs>)AccessClient_Instance_Refreshed, sender, e);
153      else {
154        var mainForm = MainFormManager.GetMainForm<MainForm.WindowsForms.MainForm>();
155        mainForm.RemoveOperationProgressFromView(this);
156        SetEnabledStateOfControls();
157      }
158    }
159
160    private async void ProjectsView_Load(object sender, EventArgs e) {
161      lock (locker) {
162        if (updatingProjects) return;
163        updatingProjects = true;
164      }
165
166      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
167        action: () => UpdateProjects(),
168        finallyCallback: () => updatingProjects = false);
169    }
170
171    private async void refreshButton_Click(object sender, EventArgs e) {
172      lock (locker) {
173        if (updatingProjects) return;
174        updatingProjects = true;
175      }
176
177      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
178        action: () => UpdateProjects(),
179        finallyCallback: () => updatingProjects = false);
180    }
181
182    private void addButton_Click(object sender, EventArgs e) {
183      var project = new Project {
184        Name = "New Project",
185        OwnerUserId = UserInformation.Instance.User.Id
186      };
187      Content.Add(project);
188    }
189
190    private async void removeButton_Click(object sender, EventArgs e) {
191      lock (locker) {
192        if (removingProjects) return;
193        removingProjects = true;
194      }
195
196      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
197        action: () => RemoveProject(),
198        finallyCallback: () => removingProjects = false);
199    }
200
201    private async void saveProjectButton_Click(object sender, EventArgs e) {
202      lock (locker) {
203        if (savingProjects) return;
204        savingProjects = true;
205      }
206
207      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
208        action: () => {
209          var projectsToSave = Content.Where(x => x.Id == Guid.Empty || x.Modified);
210          foreach (var project in projectsToSave)
211            project.Store();
212        },
213        finallyCallback: () => savingProjects = false);
214    }
215
216    private async void projectsTreeView_AfterSelect(object sender, TreeViewEventArgs e) {
217      var selectedProject = (Project)e.Node.Tag;
218
219      if (projectView.Content != null)
220        projectView.Content.PropertyChanged -= ProjectViewContent_PropertyChanged;
221
222      projectView.Content = selectedProject;
223
224      selectedProject.PropertyChanged += ProjectViewContent_PropertyChanged;
225
226      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
227        action: () => UpdatePermissions());
228    }
229
230    private void projectsTreeView_DragDrop(object sender, DragEventArgs e) {
231      var sourceNode = (TreeNode)e.Data.GetData(typeof(TreeNode));
232      if (sourceNode == null) return;
233
234      var treeView = (TreeView)sender;
235      if (sourceNode.TreeView != treeView) return;
236
237      var targetPoint = treeView.PointToClient(new Point(e.X, e.Y));
238      var targetNode = treeView.GetNodeAt(targetPoint);
239
240      if (sourceNode == targetNode) return;
241
242      if (sourceNode.Parent == null)
243        treeView.Nodes.Remove(sourceNode);
244      else {
245        sourceNode.Parent.Nodes.Remove(sourceNode);
246        ((Project)sourceNode.Tag).ParentProjectId = null;
247      }
248
249      if (targetNode == null) {
250        treeView.Nodes.Add(sourceNode);
251      } else {
252        targetNode.Nodes.Add(sourceNode);
253        ((Project)sourceNode.Tag).ParentProjectId = ((Project)targetNode.Tag).Id;
254      }
255    }
256
257    private void projectsTreeView_ItemDrag(object sender, ItemDragEventArgs e) {
258      var sourceNode = (TreeNode)e.Item;
259      if (IsAuthorized((Project)sourceNode.Tag))
260        DoDragDrop(sourceNode, DragDropEffects.All);
261    }
262
263    private void projectsTreeView_DragEnter(object sender, DragEventArgs e) {
264      e.Effect = DragDropEffects.Move;
265    }
266
267    private void projectsTreeView_DragOver(object sender, DragEventArgs e) {
268      e.Effect = DragDropEffects.Move;
269    }
270
271    private void projectsTreeView_QueryContinueDrag(object sender, QueryContinueDragEventArgs e) {
272      e.Action = DragAction.Continue;
273    }
274
275    private void tabControl_SelectedIndexChanged(object sender, EventArgs e) {
276      if (tabControl.SelectedIndex == 1) {
277        UpdatePermissions();
278      }
279    }
280
281    private async void savePermissionsButton_Click(object sender, EventArgs e) {
282      var project = (Project)projectsTreeView.SelectedNode.Tag;
283
284      await SecurityExceptionUtil.TryAsyncAndReportSecurityExceptions(
285        action: () => HiveServiceLocator.Instance.CallHiveService(s => {
286          s.GrantProjectPermissions(project.Id, permissionsView.GetAddedUsers().Select(x => x.Id).ToList());
287          s.RevokeProjectPermissions(project.Id, permissionsView.GetDeletedUsers().Select(x => x.Id).ToList());
288        }));
289    }
290    #endregion
291
292    #region Helpers
293    private Project BuildProjectTree(IEnumerable<Project> projects) {
294      projectsTreeView.Nodes.Clear();
295      if (!projects.Any()) return null;
296
297      var mainProjects = new HashSet<Project>(projects.Where(x => x.ParentProjectId == null));
298      var subProbjects = new HashSet<Project>(projects.Except(mainProjects));
299
300      var stack = new Stack<Project>(mainProjects.OrderByDescending(x => x.Name));
301      var top = stack.Peek();
302
303      TreeNode currentNode = null;
304      Project currentProject = null;
305
306      while (stack.Any()) {
307        var newProject = stack.Pop();
308        var newNode = new TreeNode(newProject.Name) { Tag = newProject };
309
310        while (currentNode != null && newProject.ParentProjectId != currentProject.Id) {
311          currentNode = currentNode.Parent;
312          currentProject = currentNode == null ? null : (Project)currentNode.Tag;
313        }
314
315        if (currentNode == null) {
316          projectsTreeView.Nodes.Add(newNode);
317          newNode.ImageIndex = greenFlagImageIndex;
318        } else {
319          currentNode.Nodes.Add(newNode);
320          newNode.ImageIndex = redFlagImageIndex;
321        }
322
323        newNode.SelectedImageIndex = newNode.ImageIndex;
324
325        var childProjects = subProbjects.Where(x => x.ParentProjectId == newProject.Id);
326        if (childProjects.Any()) {
327          foreach (var project in childProjects.OrderByDescending(x => x.Name)) {
328            subProbjects.Remove(project);
329            stack.Push(project);
330          }
331          currentNode = newNode;
332          currentProject = newProject;
333        }
334      }
335
336      projectsTreeView.ExpandAll();
337
338      return top;
339    }
340
341    private void UpdateProjects() {
342      try {
343
344      } catch (AnonymousUserException) {
345        ShowHiveInformationDialog();
346      }
347      HiveAdminClient.Instance.Refresh();
348      Content = HiveAdminClient.Instance.Projects;
349    }
350
351    private void RemoveProject() {
352      var selectedNode = projectsTreeView.SelectedNode;
353      if (selectedNode == null || selectedNode.Tag == null) return;
354
355      var project = (Project)selectedNode.Tag;
356      var result = MessageBox.Show(
357        "Do you really want to delete " + project.Name + "?",
358        "HeuristicLab Hive Administrator",
359        MessageBoxButtons.YesNo,
360        MessageBoxIcon.Question);
361
362      if (result == DialogResult.Yes) {
363        if (Content.Any(x => x.ParentProjectId == project.Id)) {
364          MessageBox.Show(
365            "Only empty projects can be deleted.",
366            "HeuristicLab Hive Administrator",
367            MessageBoxButtons.OK,
368            MessageBoxIcon.Error);
369        } else {
370          Content.Remove(project);
371          HiveAdminClient.Delete(project);
372        }
373      }
374    }
375
376    private void UpdatePermissions() {
377      var selectedNode = projectsTreeView.SelectedNode;
378      var project = (Project)selectedNode?.Tag;
379
380      if (IsAuthorized(project)) {
381        permissionsView.FetchSelectedUsers = () =>
382          HiveServiceLocator.Instance.CallHiveService(s => s.GetProjectPermissions(project.Id))
383                                            .Select(x => x.GrantedUserId)
384                                            .ToList();
385
386        savePermissionsButton.Enabled = true;
387
388        if (!tabControl.TabPages.Contains(permissionsTabPage))
389          tabControl.TabPages.Add(permissionsTabPage);
390
391        if (tabControl.SelectedIndex == 1 && permissionsView.Content != null && permissionsView.FetchSelectedUsers != null)
392          permissionsView.ManualRefresh();
393      } else {
394        permissionsView.FetchSelectedUsers = null;
395        savePermissionsButton.Enabled = false;
396
397        if (tabControl.TabPages.Contains(permissionsTabPage))
398          tabControl.TabPages.Remove(permissionsTabPage);
399      }
400    }
401
402    private bool IsAuthorized(Project project) {
403      return project != null
404          && UserInformation.Instance.UserExists
405          && (project.OwnerUserId == UserInformation.Instance.User.Id || HiveRoles.CheckAdminUserPermissions());
406    }
407
408    private void ShowHiveInformationDialog() {
409      if (InvokeRequired) Invoke((Action)ShowHiveInformationDialog);
410      else {
411        using (HiveInformationDialog dialog = new HiveInformationDialog()) {
412          dialog.ShowDialog(this);
413        }
414      }
415    }
416    #endregion
417  }
418}
Note: See TracBrowser for help on using the repository browser.