Esempio n. 1
0
        // ----------

        async Task <ICommandResultBase> InstallLabelsAsync(IShellFeature feature)
        {
            // Validate

            if (feature == null)
            {
                throw new ArgumentNullException(nameof(feature));
            }

            if (string.IsNullOrEmpty(feature.ModuleId))
            {
                throw new ArgumentNullException(nameof(feature.ModuleId));
            }

            // Our result
            var result = new CommandResultBase();

            for (var i = 0; i < 10; i++)
            {
                var categoryResult = await InstallLabelAsync(feature, i);

                if (!categoryResult.Succeeded)
                {
                    return(result.Failed(categoryResult.Errors.ToArray()));
                }
            }

            return(result.Success());
        }
Esempio n. 2
0
        /* General Idea...
         *
         *  public static IEnumerable<T> Traverse<T>(T item, Func<T, IEnumerable<T>> childSelector)
         *  {
         *      var stack = new Stack<T>();
         *      stack.Push(item);
         *      while (stack.Any())
         *      {
         *          var next = stack.Pop();
         *          yield return next;
         *          foreach (var child in childSelector(next))
         *              stack.Push(child);
         *      }
         *  }
         *
         */

        IEnumerable <IShellFeature> QueryDependencies(
            IShellFeature feature,
            IShellFeature[] features,
            Func <IShellFeature, IShellFeature[], IShellFeature[]> query)
        {
            var dependencies = new HashSet <IShellFeature>()
            {
                feature
            };

            var stack = new Stack <IShellFeature[]>();

            stack.Push(query(feature, features));

            while (stack.Count > 0)
            {
                var next = stack.Pop();
                foreach (var dependency in next.Where(dependency => !dependencies.Contains(dependency)))
                {
                    dependencies.Add(dependency);
                    stack.Push(query(dependency, features));
                }
            }

            return(_features
                   .Where(f => dependencies.Any(d => d.ModuleId == f.Value.ModuleId))
                   .Select(f => f.Value));
        }
Esempio n. 3
0
        // ----------

        async Task <ICommandResultBase> InstallCategoriesAsync(IShellFeature feature)
        {
            // Validate

            if (feature == null)
            {
                throw new ArgumentNullException(nameof(feature));
            }

            if (string.IsNullOrEmpty(feature.ModuleId))
            {
                throw new ArgumentNullException(nameof(feature.ModuleId));
            }

            // Our result
            var result = new CommandResultBase();

            foreach (var tag in ExampleTags)
            {
                var categoryResult = await InstallInternalAsync(feature, tag);

                if (!categoryResult.Succeeded)
                {
                    return(result.Failed(categoryResult.Errors.ToArray()));
                }
            }

            return(result.Success());
        }
Esempio n. 4
0
        async Task <ICommandResultBase> InstallInternalAsync(IShellFeature feature, string tag)
        {
            // Validate

            if (feature == null)
            {
                throw new ArgumentNullException(nameof(feature));
            }

            if (string.IsNullOrEmpty(feature.ModuleId))
            {
                throw new ArgumentNullException(nameof(feature.ModuleId));
            }

            var user = await _contextFacade.GetAuthenticatedUserAsync();

            // Our result
            var result = new CommandResultBase();

            var categoryResult = await _tagManager.CreateAsync(new TagBase()
            {
                FeatureId     = feature.Id,
                Name          = tag,
                Description   = $"An example desccription for the '{tag}' tag within '{feature.ModuleId}'.",
                CreatedUserId = user?.Id ?? 0,
                CreatedDate   = DateTimeOffset.UtcNow
            });

            if (!categoryResult.Succeeded)
            {
                return(result.Failed(result.Errors.ToArray()));
            }

            return(result.Success());
        }
        async Task <ICommandResultBase> UninstallInternalAsync(IShellFeature feature)
        {
            // Validate

            if (feature == null)
            {
                throw new ArgumentNullException(nameof(feature));
            }

            if (string.IsNullOrEmpty(feature.ModuleId))
            {
                throw new ArgumentNullException(nameof(feature.ModuleId));
            }

            // Our result
            var result = new CommandResultBase();

            // Get entities feature for categories feature
            var entityFeature = await GetEntityFeatureAsync(feature);

            if (entityFeature == null)
            {
                return(result.Failed($"A feature named {feature.ModuleId.Replace(".Categories", "")} is not enabled!"));
            }

            // Replacements for SQL script
            var replacements = new Dictionary <string, string>()
            {
                ["{featureId}"]       = feature.Id.ToString(),
                ["{entityFeatureId}"] = entityFeature.Id.ToString()
            };

            // Sql to execute
            var sql = @"
                DELETE FROM {prefix}_EntityCategories WHERE CategoryId IN (
                    SELECT Id FROM {prefix}_Categories WHERE FeatureId = {featureId}
                );
                DELETE FROM {prefix}_CategoryData WHERE CategoryId IN (
                    SELECT Id FROM {prefix}_Categories WHERE FeatureId = {featureId}
                );
                UPDATE {prefix}_Entities SET CategoryId = 0 WHERE FeatureId = {entityFeatureId}
            ";

            // Execute and return result
            var error = string.Empty;

            try
            {
                await _dbHelper.ExecuteScalarAsync <int>(sql, replacements);
            }
            catch (Exception e)
            {
                error = e.Message;
            }

            return(!string.IsNullOrEmpty(error)
                ? result.Failed(error)
                : result.Success());
        }
Esempio n. 6
0
        async Task <CommandResultBase> UpdateShellFeatureVersionAsync(IShellFeature feature, string newVersion)
        {
            var result = new CommandResultBase();

            // Ensure the version is valid
            if (newVersion.ToVersion() == null)
            {
                return(result.Failed(
                           $"The version '{newVersion}' for feature '{feature.ModuleId}' is not a valid version. Versions must contain major, minor & build numbers. For example 1.0.0, 2.4.0 or 3.2.1"));
            }

            // Update version
            feature.Version = newVersion;

            // Update shell features
            var shellFeature = await _shellFeatureStore.UpdateAsync((ShellFeature)feature);

            // Ensure the update was successful before updating shell descriptor
            if (shellFeature == null)
            {
                return(result.Failed(
                           $"Could not update shell feature. An error occurred whilst updating the version for feature {feature.ModuleId} to version {newVersion}."));
            }

            // First get all existing enabled features
            var enabledFeatures = await _shellDescriptorManager.GetEnabledFeaturesAsync();

            // Update version for enabled feature
            var descriptor = new ShellDescriptor();

            foreach (var enabledFeature in enabledFeatures)
            {
                if (enabledFeature.ModuleId.Equals(feature.ModuleId, StringComparison.OrdinalIgnoreCase))
                {
                    enabledFeature.Version = newVersion;
                }
                descriptor.Modules.Add(new ShellModule(enabledFeature));
            }

            // Ensure we have a descriptor
            if (descriptor.Modules?.Count == 0)
            {
                return(result.Failed("A valid shell descriptor could not be constructed."));
            }

            // Update shell descriptor
            var updatedDescriptor = await _shellDescriptorStore.SaveAsync(descriptor);

            if (updatedDescriptor == null)
            {
                return(result.Failed(
                           $"Could not update shell descriptor. An error occurred whilst updating the version for feature {feature.ModuleId} to version {newVersion}."));
            }

            return(result.Success());
        }
Esempio n. 7
0
        async Task <ICommandResultBase> UninstallCategoriesAsync(IShellFeature feature)
        {
            // Validate

            if (feature == null)
            {
                throw new ArgumentNullException(nameof(feature));
            }

            if (string.IsNullOrEmpty(feature.ModuleId))
            {
                throw new ArgumentNullException(nameof(feature.ModuleId));
            }

            // Our result
            var result = new CommandResultBase();

            // Replacements for SQL script
            var replacements = new Dictionary <string, string>()
            {
                ["{featureId}"] = feature.Id.ToString()
            };

            // Sql to execute
            var sql = @"
                DELETE FROM {prefix}_CategoryData WHERE CategoryId IN (
                    SELECT Id FROM {prefix}_Categories WHERE FeatureId = {featureId}
                );
                DELETE FROM {prefix}_CategoryRoles WHERE CategoryId IN (
                    SELECT Id FROM {prefix}_Categories WHERE FeatureId = {featureId}
                );
                DELETE FROM {prefix}_Categories WHERE FeatureId = {featureId};
            ";

            // Execute and return result
            var error = string.Empty;

            try
            {
                await _dbHelper.ExecuteScalarAsync <int>(sql, replacements);
            }
            catch (Exception e)
            {
                error = e.Message;
            }

            return(!string.IsNullOrEmpty(error)
                ? result.Failed(error)
                : result.Success());
        }
Esempio n. 8
0
        async Task <IShellFeature> FeatureInstalled(IShellFeature feature)
        {
            if (feature == null)
            {
                return(feature);
            }

            TourStep stepToUpdate = null;

            if (ShellDescriptors.CoreModules.Contains(feature.Descriptor.Id))
            {
                stepToUpdate = DefaultSteps.EnablleCoreFeature;
            }

            if (ShellDescriptors.OptionalModules.Contains(feature.Descriptor.Id))
            {
                stepToUpdate = DefaultSteps.EnablleOptionalFeature;
            }

            if (ShellDescriptors.SearchModules.Contains(feature.Descriptor.Id))
            {
                stepToUpdate = DefaultSteps.EnableSearch;
            }

            // We need a step to update
            if (stepToUpdate == null)
            {
                return(feature);
            }

            // Update step
            var step = await _tourDescriptorStore.GetStepAsync(stepToUpdate.Id);

            if (step != null)
            {
                if (!step.CompletedDate.HasValue)
                {
                    step.CompletedDate = DateTimeOffset.Now;
                    await _tourDescriptorStore.UpdateStepAsync(step);
                }
            }

            // Return
            return(feature);
        }
Esempio n. 9
0
        async Task <ICommandResultBase> InstallCategoryAsync(IShellFeature feature, int sortOrder = 0)
        {
            // Validate

            if (feature == null)
            {
                throw new ArgumentNullException(nameof(feature));
            }

            if (string.IsNullOrEmpty(feature.ModuleId))
            {
                throw new ArgumentNullException(nameof(feature.ModuleId));
            }

            // Our result
            var result = new CommandResultBase();

            var icons = new DefaultIcons();

            var foreColor = "#ffffff";
            var backColor = $"#{_colorProvider.GetColor()}";
            var iconCss   = $"fal fa-{icons.GetIcon()}";

            var categoryResult = await _categoryManager.CreateAsync(new CategoryBase()
            {
                FeatureId   = feature.Id,
                ParentId    = 0,
                Name        = $"Example Category {_random.Next(0, 2000).ToString()}",
                Description = $"This is just an example category desccription.",
                ForeColor   = foreColor,
                BackColor   = backColor,
                IconCss     = iconCss,
                SortOrder   = sortOrder
            });

            if (!categoryResult.Succeeded)
            {
                return(result.Failed(result.Errors.ToArray()));
            }

            return(result.Success());
        }
Esempio n. 10
0
        async Task <ICommandResultBase> InstallLabelAsync(IShellFeature feature, int sortOrder = 0)
        {
            // Validate

            if (feature == null)
            {
                throw new ArgumentNullException(nameof(feature));
            }

            if (string.IsNullOrEmpty(feature.ModuleId))
            {
                throw new ArgumentNullException(nameof(feature.ModuleId));
            }

            var user = await _contextFacade.GetAuthenticatedUserAsync();

            // Our result
            var result = new CommandResultBase();

            var foreColor = "#ffffff";
            var backColor = $"#{_colorProvider.GetColor()}";

            var categoryResult = await _labelManager.CreateAsync(new LabelBase()
            {
                FeatureId     = feature.Id,
                ParentId      = 0,
                Name          = $"Example Label {_random.Next(0, 2000).ToString()}",
                Description   = $"This is an example label description.",
                ForeColor     = foreColor,
                BackColor     = backColor,
                SortOrder     = sortOrder,
                CreatedUserId = user?.Id ?? 0,
                CreatedDate   = DateTimeOffset.UtcNow
            });

            if (!categoryResult.Succeeded)
            {
                return(result.Failed(result.Errors.ToArray()));
            }

            return(result.Success());
        }
Esempio n. 11
0
        // ----------

        async Task <ICommandResultBase> InstallInternalAsync(IShellFeature feature)
        {
            // Validate

            if (feature == null)
            {
                throw new ArgumentNullException(nameof(feature));
            }

            if (string.IsNullOrEmpty(feature.ModuleId))
            {
                throw new ArgumentNullException(nameof(feature.ModuleId));
            }

            var user = await _contextFacade.GetAuthenticatedUserAsync();

            // Get all feature tags
            var labels = await _labelStore.QueryAsync()
                         .Select <LabelQueryParams>(Q =>
            {
                Q.FeatureId.Equals(feature.Id);
            })
                         .ToList();

            // Associate every tag with at least 1 entity

            var output = new CommandResultBase();

            if (labels != null)
            {
                var entities = await _entityStore.QueryAsync()
                               .Select <EntityQueryParams>(q =>
                {
                    q.FeatureId.Equals(feature.Id);
                })
                               .ToList();

                var alreadyAdded = new Dictionary <int, Entity>();
                foreach (var label in labels?.Data)
                {
                    var randomEntities = GetRandomEntities(entities?.Data, alreadyAdded);
                    if (randomEntities == null)
                    {
                        return(output.Success());
                    }
                    foreach (var entity in randomEntities)
                    {
                        var result = await _entityLabelManager.CreateAsync(new EntityLabel()
                        {
                            EntityId      = entity.Id,
                            LabelId       = label.Id,
                            CreatedUserId = user?.Id ?? 0,
                            CreatedDate   = DateTime.UtcNow
                        });

                        if (!result.Succeeded)
                        {
                            return(output.Failed(result.Errors.ToArray()));
                        }
                    }
                }
            }

            return(output.Success());
        }
Esempio n. 12
0
 public FeatureEventContext(IShellFeature feature)
 {
     this.Feature = feature;
 }
        // ----------

        async Task <ICommandResultBase> InstallInternalAsync(IShellFeature feature)
        {
            // Validate

            if (feature == null)
            {
                throw new ArgumentNullException(nameof(feature));
            }

            if (string.IsNullOrEmpty(feature.ModuleId))
            {
                throw new ArgumentNullException(nameof(feature.ModuleId));
            }

            var user = await _contextFacade.GetAuthenticatedUserAsync();

            // Get all feature tags
            var categories = await _categoryStore.QueryAsync()
                             .Select <CategoryQueryParams>(Q =>
            {
                Q.FeatureId.Equals(feature.Id);
            })
                             .ToList();

            // Associate every category with at least 1 entity

            var output = new CommandResultBase();

            if (categories != null)
            {
                var entityFeature = await GetEntityFeatureAsync(feature);

                if (entityFeature == null)
                {
                    return(output.Failed($"A feature named {feature.ModuleId.Replace(".Categories", "")} is not enabled!"));
                }

                // Get entities for feature
                var entities = await _entityStore.QueryAsync()
                               .Select <EntityQueryParams>(q =>
                {
                    q.FeatureId.Equals(entityFeature.Id);
                    q.CategoryId.Equals(0);
                })
                               .ToList();

                // Keeps track of entities already added to categories
                var alreadyAdded = new Dictionary <int, Entity>();

                // Interate categories building random entities
                // not already added to a category and adding
                // those random entities to the current category
                foreach (var category in categories?.Data)
                {
                    // Get random entities
                    var randomEntities = GetRandomEntities(entities?.Data, alreadyAdded);

                    // Ensure we have some random entities, they may have already al been added
                    if (randomEntities == null)
                    {
                        return(output.Success());
                    }

                    // Add random entities to category
                    foreach (var randomEntity in randomEntities)
                    {
                        // Get the full entity
                        var entity = await _entityStore.GetByIdAsync(randomEntity.Id);

                        // Update
                        entity.CategoryId     = category.Id;
                        entity.ModifiedUserId = user?.Id ?? 0;
                        entity.ModifiedDate   = DateTime.UtcNow;

                        // Persist
                        var entityResult = await _entityManager.UpdateAsync(entity);

                        if (entityResult.Succeeded)
                        {
                            // Add entity / category relationship
                            var result = await _entityCategoryManager.CreateAsync(new EntityCategory()
                            {
                                EntityId      = entityResult.Response.Id,
                                CategoryId    = category.Id,
                                CreatedUserId = user?.Id ?? 0,
                                CreatedDate   = DateTime.UtcNow
                            });

                            if (!result.Succeeded)
                            {
                                return(output.Failed(result.Errors.ToArray()));
                            }
                        }
                        else
                        {
                            return(output.Failed(entityResult.Errors.ToArray()));
                        }
                    }
                }
            }

            return(output.Success());
        }
Esempio n. 14
0
        // ------------------------

        async Task <IDictionary <string, IFeatureEventContext> > InvokeFeatureEventHandlersAsync(
            IShellFeature feature,
            Func <IFeatureEventContext, Task <CommandResultBase> > configure)
        {
            var output = new CommandResultBase();

            // Get available module
            var module = await _shellDescriptorManager.GetFeatureAsync(feature.ModuleId);

            // Raise updating & updated event handlers for features
            return(await InvokeFeatureEvents(new[] { feature },
                                             async (context, handler) =>
            {
                var contexts = new ConcurrentDictionary <string, IFeatureEventContext>();

                try
                {
                    // Ensure we only invoke handlers for the feature we are updating
                    if (context.Feature.ModuleId.Equals(feature.ModuleId, StringComparison.OrdinalIgnoreCase))
                    {
                        await handler.UpdatingAsync(context);
                    }
                    contexts.AddOrUpdate(context.Feature.ModuleId, context, (k, v) =>
                    {
                        foreach (var error in context.Errors)
                        {
                            v.Errors.Add(error.Key, error.Value);
                        }

                        return v;
                    });
                }
                catch (Exception e)
                {
                    contexts.AddOrUpdate(context.Feature.ModuleId, context, (k, v) =>
                    {
                        v.Errors.Add(context.Feature.ModuleId, e.Message);
                        return v;
                    });
                }

                // Did any event encounter errors?
                var hasErrors = contexts
                                .Where(c => c.Value.Errors.Any());

                // No errors raise UpdatedAsync
                if (!hasErrors.Any())
                {
                    // Execute upgrade configuration
                    var configureResult = await configure(context);
                    if (!configureResult.Errors.Any())
                    {
                        try
                        {
                            // Ensure we only invoke handlers for the feature we've updated
                            if (context.Feature.ModuleId.Equals(feature.ModuleId,
                                                                StringComparison.OrdinalIgnoreCase))
                            {
                                await handler.UpdatedAsync(context);
                            }
                            contexts.AddOrUpdate(context.Feature.ModuleId, context, (k, v) =>
                            {
                                foreach (var error in context.Errors)
                                {
                                    v.Errors.Add(error.Key, error.Value);
                                }

                                return v;
                            });
                        }
                        catch (Exception e)
                        {
                            contexts.AddOrUpdate(context.Feature.ModuleId, context, (k, v) =>
                            {
                                v.Errors.Add(context.Feature.ModuleId, e.Message);
                                return v;
                            });
                        }
                    }
                    else
                    {
                        foreach (var error in configureResult.Errors)
                        {
                            if (context.Errors == null)
                            {
                                context.Errors = new Dictionary <string, string>();
                            }

                            if (!context.Errors.ContainsKey(error.Code))
                            {
                                context.Errors.Add(error.Code, error.Description);
                            }
                        }

                        contexts.AddOrUpdate(context.Feature.ModuleId, context, (k, v) =>
                        {
                            foreach (var error in configureResult.Errors)
                            {
                                if (!v.Errors.ContainsKey(error.Code))
                                {
                                    v.Errors.Add(error.Code, error.Description);
                                }
                            }

                            return v;
                        });
                    }
                }

                return contexts;
            }, async context =>
            {
                var contexts = new ConcurrentDictionary <string, IFeatureEventContext>();

                // Execute upgrade configuration
                var configureResult = await configure(context);
                if (configureResult.Errors.Any())
                {
                    foreach (var error in configureResult.Errors)
                    {
                        if (context.Errors == null)
                        {
                            context.Errors = new Dictionary <string, string>();
                        }
                        if (!context.Errors.ContainsKey(error.Code))
                        {
                            context.Errors.Add(error.Code, error.Description);
                        }
                    }

                    contexts.AddOrUpdate(context.Feature.ModuleId, context, (k, v) =>
                    {
                        foreach (var error in configureResult.Errors)
                        {
                            if (!v.Errors.ContainsKey(error.Code))
                            {
                                v.Errors.Add(error.Code, error.Description);
                            }
                        }

                        return v;
                    });
                }

                return contexts;
            }));
        }
Esempio n. 15
0
        public async Task <IActionResult> Index([FromBody] TagApiParams parameters)
        {
            // Get tags
            var tags = await GetTags(parameters);

            // Build results
            IPagedResults <TagApiResult> results = null;

            if (tags != null)
            {
                // Get feature for tags
                IShellFeature feature = null;
                if (parameters.FeatureId > 0)
                {
                    feature = await _shellFeatureStore.GetByIdAsync(parameters.FeatureId);
                }

                results = new PagedResults <TagApiResult>
                {
                    Total = tags.Total
                };

                var baseUrl = await _contextFacade.GetBaseUrlAsync();

                foreach (var tag in tags.Data)
                {
                    var url = _contextFacade.GetRouteUrl(new RouteValueDictionary()
                    {
                        ["area"]       = feature?.ModuleId ?? "Plato.Tags",
                        ["controller"] = "Home",
                        ["action"]     = "Tag",
                        ["opts.id"]    = tag.Id,
                        ["opts.alias"] = tag.Alias
                    });

                    results.Data.Add(new TagApiResult()
                    {
                        Id       = tag.Id,
                        Name     = tag.Name,
                        Entities = tag.TotalEntities.ToPrettyInt(),
                        Follows  = tag.TotalFollows.ToPrettyInt(),
                        Url      = url
                    });
                }
            }

            IPagedApiResults <TagApiResult> output = null;

            if (results != null)
            {
                output = new PagedApiResults <TagApiResult>()
                {
                    Page       = parameters.Page,
                    Size       = parameters.Size,
                    Total      = results.Total,
                    TotalPages = results.Total.ToSafeCeilingDivision(parameters.Size),
                    Data       = results.Data
                };
            }

            return(output != null
                ? base.Result(output)
                : base.NoResults());
        }
        async Task <IShellFeature> GetEntityFeatureAsync(IShellFeature feature)
        {
            var featureId = feature.ModuleId.Replace(".Categories", "");

            return(await _featureFacade.GetFeatureByIdAsync(featureId));
        }
Esempio n. 17
0
 public ShellModule(IShellFeature feature)
 {
     this.Id       = feature.Id;
     this.ModuleId = feature.ModuleId;
     this.Version  = feature.Version;
 }