Changeset 15819


Ignore:
Timestamp:
02/27/18 23:20:14 (19 months ago)
Author:
jzenisek
Message:

#2839: implemented refreshing list of available (i.e. for non-admins assignable) resources depending on currently selected project

Location:
branches/2839_HiveProjectManagement
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • branches/2839_HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ProjectResourcesView.cs

    r15813 r15819  
    3737    private const int slaveImageIndex = 0;
    3838    private const int slaveGroupImageIndex = 1;
    39     public const string ungroupedGroupName = "UNGROUPED";
    40     public const string ungroupedGroupDescription = "Contains slaves that are not assigned to any group.";
     39    public const string UNGROUPED_GROUP_NAME = "UNGROUPED";
     40    public const string UNGROUPED_GROUP_DESCRIPTION = "Contains slaves that are not assigned to any group.";
     41    public const string IMMUTABLE_TAG = " [assigned, immutable]";
     42    public const string INCLUDED_TAG = " [included]";
     43    public const string ADDED_ASSIGNMENT_TAG = " [added assignment]";
     44    public const string REMOVED_ASSIGNMENT_TAG = " [removed assignment]";
     45    public const string ADDED_INCLUDE_TAG = " [added include]";
     46    public const string REMOVED_INCLUDE_TAG = " [removed include]";
    4147
    4248    private readonly HashSet<Resource> assignedResources = new HashSet<Resource>();
    4349    private readonly HashSet<Resource> newAssignedResources = new HashSet<Resource>();
    44     private readonly HashSet<Resource> inheritedResources = new HashSet<Resource>();
    45     private readonly HashSet<Resource> newInheritedResources = new HashSet<Resource>();
     50    private readonly HashSet<Resource> includedResources = new HashSet<Resource>();
     51    private readonly HashSet<Resource> newIncludedResources = new HashSet<Resource>();
    4652
    4753    private readonly Dictionary<Guid, HashSet<Project>> projectAncestors = new Dictionary<Guid, HashSet<Project>>();
     
    5460    private readonly Color addedIncludeColor = Color.FromArgb(25, 169, 221, 221); // #a9dddd
    5561    private readonly Color removedIncludeColor = Color.FromArgb(25, 249, 210, 145); // #f9d291
     62
     63    private HashSet<Resource> projectExclusiveResources = new HashSet<Resource>();
     64    private TreeNode ungroupedGroupNode;
    5665
    5766    public new Project Content {
     
    7382        assignedResources.Clear();
    7483        newAssignedResources.Clear();
    75         inheritedResources.Clear();
     84        includedResources.Clear();
    7685        resourceAncestors.Clear();
    7786        treeView.Nodes.Clear();
     
    132141    private void treeView_BeforeCheck(object sender, TreeViewCancelEventArgs e) {
    133142      var checkedResource = (Resource)e.Node.Tag;
    134       if (newInheritedResources.Contains(checkedResource) || checkedResource.Id == Guid.Empty) {
     143      if (newIncludedResources.Contains(checkedResource) || checkedResource.Id == Guid.Empty || e.Node == ungroupedGroupNode) {
    135144        e.Cancel = true;
    136145      } else if (!HiveRoles.CheckAdminUserPermissions()) {
    137           if (!projectAncestors[Content.Id].Any()) {
     146          if (!projectAncestors[Content.Id].Any() || projectExclusiveResources.Contains(checkedResource)) {
    138147            e.Cancel = true;
    139148          }
     
    164173    private void UpdateNewResourceTree() {
    165174      UpdateNewAssignedResources();
    166       UpdateNewInheritedResources();
     175      UpdateNewIncludedResources();
    167176      var top = BuildResourceTree(HiveAdminClient.Instance.Resources);
    168177      detailsViewHost.Content = top;
    169178    }
    170179
    171     private static IEnumerable<Resource> GetAssignedResourcesForProject(Guid projectId) {
     180    private IEnumerable<Resource> GetAvailableResourcesForProjectAdministration(Guid projectId) {
     181      projectExclusiveResources.Clear();
    172182      if (projectId == Guid.Empty) return Enumerable.Empty<Resource>();
    173       var assignedProjectResources = HiveServiceLocator.Instance.CallHiveService(s => s.GetAssignedResourcesForProjectAdministration(projectId));
    174       return HiveAdminClient.Instance.Resources.Where(x => assignedProjectResources.Select(y => y.ResourceId).Contains(x.Id));
     183      var resources = HiveAdminClient.Instance.Resources.Where(x => x.Id != Guid.Empty);
     184      if (!resources.Any()) return resources;
     185      if (IsAdmin()) return resources;
     186
     187      // get project specific assigned resources
     188      var projectResources = resources.Where(x =>
     189        HiveAdminClient.Instance.ProjectResourceAssignments
     190          .Where(a => a.ProjectId == projectId)
     191          .Select(a => a.ResourceId)
     192        .Contains(x.Id));
     193
     194      // look up for assignments of ancestor projects
     195      var projectIds = new HashSet<Guid>();
     196      if(projectAncestors.ContainsKey(projectId)) {
     197        projectAncestors[projectId].ToList().ForEach(x => projectIds.Add(x.Id));
     198      }
     199      var ancestorProjectResources = resources.Where(x =>
     200        HiveAdminClient.Instance.ProjectResourceAssignments
     201          .Where(a => projectIds.Contains(a.ProjectId))
     202          .Select(a => a.ResourceId)
     203        .Contains(x.Id));
     204
     205      // look down for included resources of ancestor projects
     206      HashSet<Resource> availableResources = new HashSet<Resource>(ancestorProjectResources);
     207      foreach (var r in ancestorProjectResources) {
     208        if(resourceDescendants.ContainsKey(r.Id)) {
     209          foreach(var d in resourceDescendants[r.Id]) {
     210            availableResources.Add(d);
     211          }
     212        }
     213      }
     214
     215      // determine resources, which are exclusively assigned to the currently selected project
     216      projectResources
     217        .Except(availableResources)
     218        .ToList()
     219        .ForEach(x => projectExclusiveResources.Add(x));
     220
     221      // look down for included resources of currently selected project
     222      if (projectExclusiveResources.Any()) {
     223        foreach (var r in projectExclusiveResources.ToArray()) {
     224          if (resourceDescendants.ContainsKey(r.Id)) {
     225            foreach (var d in resourceDescendants[r.Id]) {
     226              projectExclusiveResources.Add(d);
     227            }
     228          }
     229        }
     230      }
     231
     232      return availableResources.Union(projectExclusiveResources);
     233    }
     234
     235    private IEnumerable<Resource> GetAssignedResourcesForProject(Guid projectId) {
     236      if (projectId == Guid.Empty) return Enumerable.Empty<Resource>();
     237      return HiveAdminClient.Instance.Resources.Where(x =>
     238        HiveAdminClient.Instance.ProjectResourceAssignments
     239          .Where(a => a.ProjectId == projectId)
     240          .Select(a => a.ResourceId)
     241        .Contains(x.Id));
    175242    }
    176243
     
    199266    }
    200267
    201     private void UpdateNewInheritedResources() {
    202       newInheritedResources.Clear();
     268    private void UpdateNewIncludedResources() {
     269      newIncludedResources.Clear();
    203270      foreach (var a in newAssignedResources) {
    204271        if (resourceDescendants.ContainsKey(a.Id)) {
    205272          foreach (var r in resourceDescendants[a.Id]) {
    206             newInheritedResources.Add(r);
    207           }
    208         }
    209       }
    210     }
    211 
    212     private void UpdateResourceGenealogy() {
    213       resourceAncestors.Clear();
    214       resourceDescendants.Clear();
    215       var resources = HiveAdminClient.Instance.Resources;
    216 
    217       foreach(var r in resources.Where(x => x.Id != Guid.Empty)) {
    218         resourceAncestors.Add(r.Id, new HashSet<Resource>());
    219         resourceDescendants.Add(r.Id, new HashSet<Resource>());
    220       }
    221 
    222       foreach(var r in resources.Where(x => x.Id != Guid.Empty)) {
    223         var parentResourceId = r.ParentResourceId;
    224         while(parentResourceId != null) {
    225           var parent = resources.SingleOrDefault(x => x.Id == parentResourceId);
    226           if(parent != null) {
    227             resourceAncestors[r.Id].Add(parent);
    228             resourceDescendants[parent.Id].Add(r);
    229             parentResourceId = parent.ParentResourceId;
    230           } else {
    231             parentResourceId = null;
    232           }
    233         }
    234       }
    235 
    236       inheritedResources.Clear();
    237       newInheritedResources.Clear();
    238       foreach(var a in assignedResources) {
    239         if (resourceDescendants.ContainsKey(a.Id)) {
    240           foreach(var r in resourceDescendants[a.Id]) {
    241             inheritedResources.Add(r);
    242             newInheritedResources.Add(r);
    243           }
    244         }
    245       }
    246 
    247       //foreach(var r in resources) {
    248       //  if (resourceAncestors.ContainsKey(r.Id)
    249       //    && resourceAncestors[r.Id].Intersect(assignedResources.Select(x => x.Id)).Any()) {
    250       //    inheritedResources.Add(r);
    251       //  }
    252       //}
     273            newIncludedResources.Add(r);
     274          }
     275        }
     276      }
    253277    }
    254278
     
    260284      treeView.AfterCheck -= treeView_AfterCheck;
    261285
    262       resources = resources.Where(x => x.Id != Guid.Empty);
     286      resources = GetAvailableResourcesForProjectAdministration(Content.Id);
     287
    263288      var mainResources = new HashSet<Resource>(resources.OfType<SlaveGroup>().Where(x => x.ParentResourceId == null));
    264289      var parentedMainResources = new HashSet<Resource>(resources.OfType<SlaveGroup>()
     
    273298      Resource currentResource = null;
    274299
    275 
    276300      var addedAssignments = newAssignedResources.Except(assignedResources);
    277301      var removedAssignments = assignedResources.Except(newAssignedResources);
    278       var addedIncludes = newInheritedResources.Except(inheritedResources);
    279       var removedIncludes = inheritedResources.Except(newInheritedResources);
    280 
    281       //var assignmentDiff = new HashSet<Resource>(newAssignedResources);
    282       //assignmentDiff.SymmetricExceptWith(assignedResources);
    283       //var inheritanceDiff = new HashSet<Resource>(newInheritedResources);
    284       //inheritanceDiff.SymmetricExceptWith(inheritedResources);
     302      var addedIncludes = newIncludedResources.Except(includedResources);
     303      var removedIncludes = includedResources.Except(newIncludedResources);
    285304
    286305      while (stack.Any()) {
     
    306325          newNode.Checked = true;
    307326          if(!HiveRoles.CheckAdminUserPermissions()) {
    308             if(!projectAncestors[Content.Id].Any()) {
     327            if(!projectAncestors[Content.Id].Any() || projectExclusiveResources.Contains(newResource)) {
    309328              newNode.ForeColor = SystemColors.GrayText;
    310               newNode.Text += " [immutable]";
     329              newNode.Text += IMMUTABLE_TAG;
    311330            }
    312331          }
    313332
    314         } else if (newInheritedResources.Contains(newResource)) {
     333        } else if (newIncludedResources.Contains(newResource)) {
    315334          newNode.Checked = true;
    316335          newNode.ForeColor = SystemColors.GrayText;
    317336        }
    318337
    319           if (inheritedResources.Contains(newResource) && newInheritedResources.Contains(newResource)) {
    320           newNode.Text += " [included]";
     338          if (includedResources.Contains(newResource) && newIncludedResources.Contains(newResource)) {
     339          newNode.Text += INCLUDED_TAG;
    321340        } else if (addedIncludes.Contains(newResource)) {
    322341          newNode.BackColor = addedIncludeColor;
    323342          newNode.ForeColor = SystemColors.GrayText;
    324           newNode.Text += " [added include]";
     343          newNode.Text += ADDED_INCLUDE_TAG;
    325344        } else if (removedIncludes.Contains(newResource)) {
    326345          newNode.BackColor = removedIncludeColor;
    327           newNode.Text += " [removed include]";
     346          newNode.Text += REMOVED_INCLUDE_TAG;
    328347        }
    329348
     
    331350          newNode.BackColor = addedAssignmentColor;
    332351          newNode.ForeColor = SystemColors.ControlText;
    333           newNode.Text += " [added assignment]";
     352          newNode.Text += ADDED_ASSIGNMENT_TAG;
    334353        } else if (removedAssignments.Contains(newResource)) {
    335354          newNode.BackColor = removedAssignmentColor;
    336355          newNode.ForeColor = SystemColors.ControlText;
    337           newNode.Text += " [removed assignment]";
     356          newNode.Text += REMOVED_ASSIGNMENT_TAG;
    338357        }
    339358
     
    354373        }
    355374        newNode.SelectedImageIndex = newNode.ImageIndex;
    356         //if (newResource.OwnerUserId == UserInformation.Instance.User.Id)
    357         //  newNode.BackColor = ownedResourceColor;
    358375      }
    359376
    360377      var ungroupedSlaves = subResources.OfType<Slave>().OrderBy(x => x.Name);
    361378      if(ungroupedSlaves.Any()) {
    362         var ungroupedNode = new TreeNode(ungroupedGroupName) {
     379        ungroupedGroupNode = new TreeNode(UNGROUPED_GROUP_NAME) {
    363380          ForeColor = SystemColors.GrayText,
    364381          Tag = new SlaveGroup() {
    365             Name = ungroupedGroupName,
    366             Description = ungroupedGroupDescription
     382            Name = UNGROUPED_GROUP_NAME,
     383            Description = UNGROUPED_GROUP_DESCRIPTION
    367384          }
    368385        };
     
    370387        foreach (var slave in ungroupedSlaves) {
    371388          var slaveNode = new TreeNode(slave.Name) { Tag = slave };
    372           ungroupedNode.Nodes.Add(slaveNode);
    373         }
    374         treeView.Nodes.Add(ungroupedNode);
     389          ungroupedGroupNode.Nodes.Add(slaveNode);
     390        }
     391        treeView.Nodes.Add(ungroupedGroupNode);
     392      } else {
     393        ungroupedGroupNode?.Nodes.Clear();
    375394      }
    376395
     
    407426    }
    408427
     428    private void UpdateResourceGenealogy() {
     429      resourceAncestors.Clear();
     430      resourceDescendants.Clear();
     431      var resources = HiveAdminClient.Instance.Resources;
     432
     433      foreach (var r in resources.Where(x => x.Id != Guid.Empty)) {
     434        resourceAncestors.Add(r.Id, new HashSet<Resource>());
     435        resourceDescendants.Add(r.Id, new HashSet<Resource>());
     436      }
     437
     438      foreach (var r in resources.Where(x => x.Id != Guid.Empty)) {
     439        var parentResourceId = r.ParentResourceId;
     440        while (parentResourceId != null) {
     441          var parent = resources.SingleOrDefault(x => x.Id == parentResourceId);
     442          if (parent != null) {
     443            resourceAncestors[r.Id].Add(parent);
     444            resourceDescendants[parent.Id].Add(r);
     445            parentResourceId = parent.ParentResourceId;
     446          } else {
     447            parentResourceId = null;
     448          }
     449        }
     450      }
     451
     452      includedResources.Clear();
     453      newIncludedResources.Clear();
     454      foreach (var a in assignedResources) {
     455        if (resourceDescendants.ContainsKey(a.Id)) {
     456          foreach (var r in resourceDescendants[a.Id]) {
     457            includedResources.Add(r);
     458            newIncludedResources.Add(r);
     459          }
     460        }
     461      }
     462    }
     463
     464    private bool IsAdmin() {
     465      return HiveRoles.CheckAdminUserPermissions();
     466    }
     467
    409468    #endregion
    410469  }
  • branches/2839_HiveProjectManagement/HeuristicLab.Clients.Hive.Administrator/3.3/Views/ResourcesView.cs

    r15813 r15819  
    298298    private void treeSlaveGroup_MouseDown(object sender, MouseEventArgs e) {
    299299      var node = treeView.GetNodeAt(e.Location);
    300       if(node != null && node != ungroupedGroupNode /*!node.Text.StartsWith(UNGROUPED_GROUP_NAME)*/) ChangeSelectedResourceNode(node);
     300      if(node != null && node != ungroupedGroupNode) ChangeSelectedResourceNode(node);
    301301    }
    302302
  • branches/2839_HiveProjectManagement/HeuristicLab.Clients.Hive/3.3/HiveAdminClient.cs

    r15813 r15819  
    6565    }
    6666
     67    private IItemList<AssignedProjectResource> projectResourceAssignments;
     68    public IItemList<AssignedProjectResource> ProjectResourceAssignments {
     69      get { return projectResourceAssignments; }
     70    }
     71
    6772    private Dictionary<Guid, HashSet<Project>> projectAncestors;
    6873    public Dictionary<Guid, HashSet<Project>> ProjectAncestors {
     
    110115        resources = new ItemList<Resource>();
    111116        projects = new ItemList<Project>();
     117        projectResourceAssignments = new ItemList<AssignedProjectResource>();
    112118
    113119        projectAncestors = new Dictionary<Guid, HashSet<Project>>();
     
    120126          service.GetSlavesForAdministration().ForEach(s => resources.Add(s));
    121127          service.GetProjectsForAdministration().ForEach(p => projects.Add(p));
     128          var projectIds = projects.Select(p => p.Id).ToList();
     129          if(projectIds.Any())
     130            service.GetAssignedResourcesForProjectsAdministration(projectIds)
     131            .ForEach(a => projectResourceAssignments.Add(a));
    122132        });
    123133
  • branches/2839_HiveProjectManagement/HeuristicLab.Clients.Hive/3.3/ServiceClients/HiveServiceClient.cs

    r15658 r15819  
    24522452        void SaveProjectPermissions(System.Guid projectId, System.Collections.Generic.List<System.Guid> grantedUserIds, bool reassign, bool cascading, bool reassignCascading);
    24532453       
    2454         [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GrantProjectPermissions", ReplyAction="http://tempuri.org/IHiveService/GrantProjectPermissionsResponse")]
    2455         void GrantProjectPermissions(System.Guid projectId, System.Collections.Generic.List<System.Guid> grantedUserIds, bool cascading);
    2456        
    2457         [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/RevokeProjectPermissions", ReplyAction="http://tempuri.org/IHiveService/RevokeProjectPermissionsResponse")]
    2458         void RevokeProjectPermissions(System.Guid projectId, System.Collections.Generic.List<System.Guid> grantedUserIds, bool cascading);
    2459        
    24602454        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GetProjectPermissions", ReplyAction="http://tempuri.org/IHiveService/GetProjectPermissionsResponse")]
    24612455        System.Collections.Generic.List<HeuristicLab.Clients.Hive.ProjectPermission> GetProjectPermissions(System.Guid projectId);
     
    24632457        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/SaveProjectResourceAssignments", ReplyAction="http://tempuri.org/IHiveService/SaveProjectResourceAssignmentsResponse")]
    24642458        void SaveProjectResourceAssignments(System.Guid projectId, System.Collections.Generic.List<System.Guid> resourceIds, bool reassign, bool cascading, bool reassignCascading);
    2465        
    2466         [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/AssignProjectResources", ReplyAction="http://tempuri.org/IHiveService/AssignProjectResourcesResponse")]
    2467         void AssignProjectResources(System.Guid projectId, System.Collections.Generic.List<System.Guid> resourceIds, bool cascading);
    2468        
    2469         [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/UnassignProjectResources", ReplyAction="http://tempuri.org/IHiveService/UnassignProjectResourcesResponse")]
    2470         void UnassignProjectResources(System.Guid projectId, System.Collections.Generic.List<System.Guid> resourceIds, bool cascading);
    24712459       
    24722460        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GetAssignedResourcesForProject", ReplyAction="http://tempuri.org/IHiveService/GetAssignedResourcesForProjectResponse")]
     
    24772465        System.Collections.Generic.List<HeuristicLab.Clients.Hive.AssignedProjectResource> GetAssignedResourcesForProjectAdministration(System.Guid projectId);
    24782466       
     2467        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/GetAssignedResourcesForProjectsAdministration", ReplyAction="http://tempuri.org/IHiveService/GetAssignedResourcesForProjectsAdministrationResp" +
     2468            "onse")]
     2469        System.Collections.Generic.List<HeuristicLab.Clients.Hive.AssignedProjectResource> GetAssignedResourcesForProjectsAdministration(System.Collections.Generic.List<System.Guid> projectIds);
     2470       
    24792471        [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IHiveService/AddSlave", ReplyAction="http://tempuri.org/IHiveService/AddSlaveResponse")]
    24802472        System.Guid AddSlave(HeuristicLab.Clients.Hive.Slave slave);
     
    27672759        }
    27682760       
    2769         public void GrantProjectPermissions(System.Guid projectId, System.Collections.Generic.List<System.Guid> grantedUserIds, bool cascading)
    2770         {
    2771             base.Channel.GrantProjectPermissions(projectId, grantedUserIds, cascading);
    2772         }
    2773        
    2774         public void RevokeProjectPermissions(System.Guid projectId, System.Collections.Generic.List<System.Guid> grantedUserIds, bool cascading)
    2775         {
    2776             base.Channel.RevokeProjectPermissions(projectId, grantedUserIds, cascading);
    2777         }
    2778        
    27792761        public System.Collections.Generic.List<HeuristicLab.Clients.Hive.ProjectPermission> GetProjectPermissions(System.Guid projectId)
    27802762        {
     
    27872769        }
    27882770       
    2789         public void AssignProjectResources(System.Guid projectId, System.Collections.Generic.List<System.Guid> resourceIds, bool cascading)
    2790         {
    2791             base.Channel.AssignProjectResources(projectId, resourceIds, cascading);
    2792         }
    2793        
    2794         public void UnassignProjectResources(System.Guid projectId, System.Collections.Generic.List<System.Guid> resourceIds, bool cascading)
    2795         {
    2796             base.Channel.UnassignProjectResources(projectId, resourceIds, cascading);
    2797         }
    2798        
    27992771        public System.Collections.Generic.List<HeuristicLab.Clients.Hive.AssignedProjectResource> GetAssignedResourcesForProject(System.Guid projectId)
    28002772        {
     
    28072779        }
    28082780       
     2781        public System.Collections.Generic.List<HeuristicLab.Clients.Hive.AssignedProjectResource> GetAssignedResourcesForProjectsAdministration(System.Collections.Generic.List<System.Guid> projectIds)
     2782        {
     2783            return base.Channel.GetAssignedResourcesForProjectsAdministration(projectIds);
     2784        }
     2785       
    28092786        public System.Guid AddSlave(HeuristicLab.Clients.Hive.Slave slave)
    28102787        {
  • branches/2839_HiveProjectManagement/HeuristicLab.Services.Hive/3.3/HiveService.cs

    r15760 r15819  
    10531053    }
    10541054
     1055    public IEnumerable<DT.AssignedProjectResource> GetAssignedResourcesForProjectsAdministration(IEnumerable<Guid> projectIds) {
     1056      RoleVerifier.AuthenticateForAnyRole(HiveRoles.Administrator, HiveRoles.Client);
     1057      foreach(var id in projectIds)
     1058        AuthorizationManager.AuthorizeForProjectAdministration(id, false);
     1059
     1060      var pm = PersistenceManager;
     1061      using (new PerformanceLogger("GetAssignedResourcesForProject")) {
     1062        var assignedProjectResourceDao = pm.AssignedProjectResourceDao;
     1063        var assignments = new List<DT.AssignedProjectResource>();
     1064        pm.UseTransaction(() => {
     1065          foreach (var id in projectIds) {
     1066            assignments.AddRange(assignedProjectResourceDao.GetByProjectId(id)
     1067              .Select(x => x.ToDto()));
     1068          }
     1069        });
     1070        return assignments.Distinct();
     1071      }
     1072    }
     1073
    10551074    #endregion
    10561075
  • branches/2839_HiveProjectManagement/HeuristicLab.Services.Hive/3.3/ServiceContracts/IHiveService.cs

    r15715 r15819  
    185185    [OperationContract]
    186186    IEnumerable<AssignedProjectResource> GetAssignedResourcesForProjectAdministration(Guid projectId);
     187
     188    [OperationContract]
     189    IEnumerable<AssignedProjectResource> GetAssignedResourcesForProjectsAdministration(IEnumerable<Guid> projectIds);
    187190    #endregion
    188191
Note: See TracChangeset for help on using the changeset viewer.