public async void Clone() { // This one has all the different widget types on var originalDashboard = await PortalClient.GetByNameAsync <Dashboard>("All Widgets").ConfigureAwait(false); var newDashboard = await PortalClient.CloneAsync(originalDashboard.Id, new DashboardCloneRequest { Name = "All widgets clone", Description = "I'm a clone and so if my wife.", DashboardGroupId = originalDashboard.DashboardGroupId, WidgetsConfig = originalDashboard.WidgetsConfig, WidgetsOrder = originalDashboard.WidgetsOrder }).ConfigureAwait(false); var newDashboardRefetch = await PortalClient. GetAsync <Dashboard>(newDashboard.Id) .ConfigureAwait(false); // Ensure that it is as expected Assert.NotNull(newDashboardRefetch); // Delete the clone await PortalClient .DeleteAsync(newDashboard) .ConfigureAwait(false); }
private static async Task ProcessStructureAsync <TGroup, TItem>( PortalClient portalClient, Mode mode, Structure <TGroup, TItem> structure, List <Property> variables, List <Property> properties, TGroup parentGroup, ILogger <Application> logger, CancellationToken cancellationToken) where TGroup : IdentifiedItem, IHasEndpoint, new() where TItem : IdentifiedItem, IHasEndpoint, new() { if (!structure.Enabled) { logger.LogInformation($"Not processing {typeof(TGroup)}, as they are disabled."); return; } // Structure is enabled logger.LogInformation($"Processing {typeof(TGroup)}..."); // Get any existing Groups // Filter on the group name var filterItems = new List <FilterItem <TGroup> > { new Eq <TGroup>(nameof(NamedEntity.Name), Substitute(structure.Name, variables)) }; // For hierarchical groups, also filter on the parent id switch (typeof(TGroup).Name) { case nameof(DashboardGroup): filterItems.Add(new Eq <TGroup>(nameof(DashboardGroup.ParentId), parentGroup?.Id ?? 1)); break; case nameof(DeviceGroup): filterItems.Add(new Eq <TGroup>(nameof(DeviceGroup.ParentId), parentGroup?.Id ?? 1)); break; case nameof(WebsiteGroup): filterItems.Add(new Eq <TGroup>(nameof(WebsiteGroup.ParentId), parentGroup?.Id ?? 1)); break; } var currentGroup = (await portalClient .GetAllAsync(new Filter <TGroup> { FilterItems = filterItems }, cancellationToken) .ConfigureAwait(false)).SingleOrDefault(); // existingGroup is now set to either the existing group, or null // What mode are we in? switch (mode) { case Mode.Delete: // Delete // Is there an existing group? if (currentGroup == null) { // No. There's nothing to do here. return; } // There's deletion to be done. // Recurse child groups first foreach (var childStructure in structure.Groups ?? Enumerable.Empty <Structure <TGroup, TItem> >()) { await ProcessStructureAsync( portalClient, mode, childStructure, variables, properties, currentGroup, logger, cancellationToken) .ConfigureAwait(false); } // Delete child nodes await DeleteChildNodesAsync <TGroup, TItem>(portalClient, currentGroup) .ConfigureAwait(false); // Try to delete this node await DeleteAsync <TGroup>(portalClient, currentGroup.Id) .ConfigureAwait(false); return; case Mode.Create: // Create. // Is there an existing group? if (currentGroup == null) { // No. We need to create one. currentGroup = await CreateGroupAsync <TGroup, TItem>( portalClient, parentGroup, structure, variables, properties) .ConfigureAwait(false); // Create individual items (e.g. Dashboards) foreach (var item in structure.Items ?? Enumerable.Empty <ItemSpec>()) { // Ensure that the name is set if (item.Name == null) { throw new ConfigurationException($"Creating items of type '{typeof(TItem).Name}' requires that the Name property is set."); } // Create any child items switch (typeof(TItem).Name) { case nameof(Dashboard): // Ensure that the name and id are set if (item.CloneFromId == null) { throw new ConfigurationException($"Creating items of type '{typeof(TItem).Name}' requires that the CloneFromId property is set."); } var originalDashboard = await portalClient .GetAsync <Dashboard>(item.CloneFromId.Value, cancellationToken) .ConfigureAwait(false); var newDashboard = await portalClient .CloneAsync(item.CloneFromId.Value, new DashboardCloneRequest { Name = Substitute(item.Name, variables), Description = Substitute(item.Description, variables), DashboardGroupId = currentGroup.Id, WidgetsConfig = originalDashboard.WidgetsConfig, WidgetsOrder = originalDashboard.WidgetsOrder }, cancellationToken) .ConfigureAwait(false); // All is well break; default: throw new NotSupportedException($"Creating items of type '{typeof(TItem).Name}' is not yet supported."); } } } // We now have a group. Process child structure foreach (var childStructure in structure.Groups ?? Enumerable.Empty <Structure <TGroup, TItem> >()) { await ProcessStructureAsync( portalClient, mode, childStructure, variables, properties, currentGroup, logger, cancellationToken) .ConfigureAwait(false); } return; default: // Unexpected mode var message = $"Unexpected mode: {mode}"; logger.LogError(message); throw new ConfigurationException(message); } }