Пример #1
0
        public async Task <IHtmlContent> TabContainer(IDisplayHelper displayAsync, GroupingsViewModel shape, IShapeFactory shapeFactory)
        {
            var localNavigation = await shapeFactory.CreateAsync("LocalNavigation", Arguments.From(new
            {
                shape.Identifier,
                Tabs = shape.Groupings
            }));

            var htmlContentBuilder = new HtmlContentBuilder();

            htmlContentBuilder.AppendHtml(await displayAsync.ShapeExecuteAsync(localNavigation));

            var tagBuilder = shape.GetTagBuilder("div");

            tagBuilder.AddCssClass("tab-content");

            htmlContentBuilder.AppendHtml(tagBuilder);

            var first = true;

            foreach (var tab in shape.Items.OfType <IShape>())
            {
                if (first)
                {
                    first = false;
                    tab.Classes.Add("show active");
                }

                tagBuilder.InnerHtml.AppendHtml(await displayAsync.ShapeExecuteAsync(tab));
            }

            return(htmlContentBuilder);
        }
        protected async Task <bool> SendEmailAsync(string email, string subject, IShape model)
        {
            var body = string.Empty;

            using (var sb = StringBuilderPool.GetInstance())
            {
                using (var sw = new StringWriter(sb.Builder))
                {
                    var htmlContent = await _displayHelper.ShapeExecuteAsync(model);

                    htmlContent.WriteTo(sw, HtmlEncoder.Default);
                    body = sw.ToString();
                }
            }

            var message = new MailMessage()
            {
                To         = email,
                Subject    = subject,
                Body       = body,
                IsBodyHtml = true
            };

            var result = await _smtpService.SendAsync(message);

            return(result.Succeeded);
        }
Пример #3
0
        public Task <IHtmlContent> LocalNavigation(IDisplayHelper displayAsync, IShape shape)
        {
            // Morphing this shape to keep Model untouched.
            shape.Metadata.Alternates.Clear();
            shape.Metadata.Type = "AdminTabs";

            return(displayAsync.ShapeExecuteAsync(shape));
        }
Пример #4
0
        public async Task <IHtmlContent> Zone(IDisplayHelper DisplayAsync, IEnumerable <object> Shape)
        {
            var htmlContentBuilder = new HtmlContentBuilder();

            foreach (var item in Shape)
            {
                htmlContentBuilder.AppendHtml(await DisplayAsync.ShapeExecuteAsync((IShape)item));
            }

            return(htmlContentBuilder);
        }
Пример #5
0
        public async Task <IHtmlContent> Card(IDisplayHelper displayAsync, GroupingViewModel shape)
        {
            var tagBuilder = shape.GetTagBuilder("div");

            tagBuilder.AddCssClass("card-body");
            shape.Metadata.Alternates.Clear();
            shape.Metadata.Type = "ColumnGrouping";

            tagBuilder.InnerHtml.AppendHtml(await displayAsync.ShapeExecuteAsync(shape));
            var cardIdPrefix = $"card-{shape.Identifier}-{shape.Grouping.Key}".HtmlClassify();

            var cardTag = new TagBuilder("div");

            cardTag.AddCssClass("card mb-2");

            var headerArrowTag = new TagBuilder("div");

            headerArrowTag.AddCssClass("card-header");
            headerArrowTag.Attributes["id"] = $"heading-{cardIdPrefix}";

            var headerTitleTag = new TagBuilder("h5");

            headerTitleTag.AddCssClass("float-start mb-0 mt-1");
            headerTitleTag.InnerHtml.Append(shape.Grouping.Key);

            var buttonTag = new TagBuilder("button");

            buttonTag.AddCssClass("btn btn-link btn-block text-start float-end");
            buttonTag.Attributes["type"]           = "button";
            buttonTag.Attributes["data-bs-toggle"] = "collapse";
            buttonTag.Attributes["data-bs-target"] = $"#collapse-{cardIdPrefix}";
            buttonTag.Attributes["aria-expanded"]  = "true";
            buttonTag.Attributes["aria-controls"]  = $"collapse-{cardIdPrefix}";

            var buttonIconTag = new TagBuilder("i");

            buttonIconTag.AddCssClass("fa-solid fa-angle-down");

            buttonTag.InnerHtml.AppendHtml(buttonIconTag);

            headerArrowTag.InnerHtml.AppendHtml(headerTitleTag);
            headerArrowTag.InnerHtml.AppendHtml(buttonTag);

            var bodyTag = new TagBuilder("div");

            bodyTag.AddCssClass("collapse show");
            bodyTag.Attributes["id"] = $"collapse-{cardIdPrefix}";

            bodyTag.InnerHtml.AppendHtml(tagBuilder);
            cardTag.InnerHtml.AppendHtml(headerArrowTag);
            cardTag.InnerHtml.AppendHtml(bodyTag);

            return(cardTag);
        }
Пример #6
0
        public async Task <IHtmlContent> Column(IDisplayHelper displayAsync, GroupViewModel shape)
        {
            var tagBuilder = shape.GetTagBuilder("div");

            foreach (var column in shape.Items)
            {
                tagBuilder.InnerHtml.AppendHtml(await displayAsync.ShapeExecuteAsync((IShape)column));
            }

            return(tagBuilder);
        }
Пример #7
0
        public async Task <IHtmlContent> CardContainer(IDisplayHelper displayAsync, GroupViewModel shape)
        {
            var tagBuilder = shape.GetTagBuilder("div");

            tagBuilder.AddCssClass("mb-3");

            foreach (var card in shape.Items.OfType <IShape>())
            {
                tagBuilder.InnerHtml.AppendHtml(await displayAsync.ShapeExecuteAsync(card));
            }

            return(tagBuilder);
        }
Пример #8
0
        public async Task <IHtmlContent> Tab(IDisplayHelper displayAsync, GroupingViewModel shape)
        {
            var tagBuilder = shape.GetTagBuilder("div");

            tagBuilder.Attributes["id"] = $"tab-{shape.Grouping.Key}-{shape.Identifier}".HtmlClassify();
            tagBuilder.AddCssClass("tab-pane fade");

            // Morphing this shape to a grouping shape to keep Model untouched.
            shape.Metadata.Alternates.Clear();
            shape.Metadata.Type = "CardGrouping";

            tagBuilder.InnerHtml.AppendHtml(await displayAsync.ShapeExecuteAsync(shape));

            return(tagBuilder);
        }
Пример #9
0
        public async Task <IHtmlContent> ContentZone(IDisplayHelper DisplayAsync, dynamic Shape, IShapeFactory ShapeFactory)
        {
            var htmlContentBuilder = new HtmlContentBuilder();

            // This maybe a collection of IShape, IHtmlContent, or plain object.
            var shapes = ((IEnumerable <object>)Shape);

            // Evaluate shapes for grouping metadata, when it is not an IShape it cannot be grouped.
            var isGrouped = shapes.Any(x => x is IShape s &&
                                       (!String.IsNullOrEmpty(s.Metadata.Tab) ||
                                        !String.IsNullOrEmpty(s.Metadata.Card) ||
                                        !String.IsNullOrEmpty(s.Metadata.Column)));

            // When there is no grouping metadata on any shapes just render the Zone.
            if (!isGrouped)
            {
                foreach (var item in shapes)
                {
                    htmlContentBuilder.AppendHtml(await DisplayAsync.ShapeExecuteAsync((IShape)item));
                }

                return(htmlContentBuilder);
            }

            string identifier = Shape.Identifier ?? String.Empty;

            var groupings = shapes.ToLookup(x =>
            {
                if (x is IShape s)
                {
                    var key = s.Metadata.Tab;
                    if (String.IsNullOrEmpty(key))
                    {
                        return(ContentKey);
                    }

                    // Remove any positioning modifier.
                    var modifierIndex = key.IndexOf(';');
                    if (modifierIndex != -1)
                    {
                        key = key.Substring(0, modifierIndex);
                    }

                    return(key);
                }

                return(ContentKey);
            });

            // Process Tabs first, then Cards, then Columns.
            if (groupings.Count > 1)
            {
                var orderedGroupings = groupings.OrderBy(grouping =>
                {
                    var firstGroupWithModifier = grouping.FirstOrDefault(group =>
                    {
                        if (group is IShape s && !String.IsNullOrEmpty(s.Metadata.Tab) && s.Metadata.Tab.IndexOf(';') != -1)
                        {
                            return(true);
                        }

                        return(false);
                    });

                    if (firstGroupWithModifier is IShape shape)
                    {
                        var key           = shape.Metadata.Tab;
                        var modifierIndex = key.IndexOf(';');

                        return(new PositionalGrouping(key.Substring(modifierIndex)));
                    }

                    return(new PositionalGrouping(null));
                }, FlatPositionComparer.Instance).ToArray();

                var container = (GroupingsViewModel)await ShapeFactory.CreateAsync <GroupingsViewModel>("TabContainer", m =>
                {
                    m.Identifier = identifier;
                    m.Groupings  = orderedGroupings;
                });

                container.Classes.Add("accordion");

                foreach (var orderedGrouping in orderedGroupings)
                {
                    var groupingShape = (GroupingViewModel)await ShapeFactory.CreateAsync <GroupingViewModel>("Tab", m =>
                    {
                        m.Identifier = identifier;
                        m.Grouping   = orderedGrouping;
                    });

                    foreach (var item in orderedGrouping)
                    {
                        await groupingShape.AddAsync(item);
                    }

                    await container.AddAsync(groupingShape);
                }

                htmlContentBuilder.AppendHtml(await DisplayAsync.ShapeExecuteAsync(container));
            }
            else if (groupings.Count == 1)
            {
                // Evaluate for cards.
                var cardGrouping = (GroupingViewModel)await ShapeFactory.CreateAsync <GroupingViewModel>("CardGrouping", m =>
                {
                    m.Identifier = identifier;
                    m.Grouping   = groupings.ElementAt(0);
                });

                htmlContentBuilder.AppendHtml(await DisplayAsync.ShapeExecuteAsync(cardGrouping));
            }

            return(htmlContentBuilder);
        }
Пример #10
0
        public async Task <IHtmlContent> ColumnGrouping(IDisplayHelper DisplayAsync, GroupingViewModel Shape, IShapeFactory ShapeFactory)
        {
            var htmlContentBuilder = new HtmlContentBuilder();

            var groupings = Shape.Grouping.ToLookup(x =>
            {
                if (x is IShape s)
                {
                    var key = s.Metadata.Column;
                    if (String.IsNullOrEmpty(key))
                    {
                        return(ContentKey);
                    }

                    // Remove column modifier.
                    var modifierIndex = key.IndexOf('_');
                    if (modifierIndex != -1)
                    {
                        key = key.Substring(0, modifierIndex);
                    }

                    // Remove positional modifier.
                    modifierIndex = key.IndexOf(';');
                    if (modifierIndex != -1)
                    {
                        key = key.Substring(0, modifierIndex);
                    }

                    return(key);
                }

                return(ContentKey);
            });

            if (groupings.Count > 1)
            {
                var positionModifiers = GetColumnPositions(groupings);

                var orderedGroupings = groupings.OrderBy(grouping =>
                {
                    if (positionModifiers.TryGetValue(grouping.Key, out var position))
                    {
                        return(new PositionalGrouping {
                            Position = position
                        });
                    }
                    else
                    {
                        return(new PositionalGrouping());
                    }
                }, FlatPositionComparer.Instance);

                var columnModifiers = GetColumnModifiers(orderedGroupings);

                var container = (GroupViewModel)await ShapeFactory.CreateAsync <GroupViewModel>("ColumnContainer", m =>
                {
                    m.Identifier = Shape.Identifier;
                });

                foreach (var orderedGrouping in orderedGroupings)
                {
                    var groupingShape = (GroupingViewModel)await ShapeFactory.CreateAsync <GroupingViewModel>("Column", m =>
                    {
                        m.Identifier = Shape.Identifier;
                        m.Grouping   = orderedGrouping;
                    });

                    groupingShape.Classes.Add("ta-col-grouping");
                    groupingShape.Classes.Add("column-" + orderedGrouping.Key.HtmlClassify());

                    // To adjust this breakpoint apply a modifier of lg-3 to every column.
                    var columnClasses = "col-12 col-md";
                    if (columnModifiers.TryGetValue(orderedGrouping.Key, out var columnModifier))
                    {
                        // When the modifier also has a - assume it is providing a breakpointed class.
                        if (columnModifier.IndexOf('-') != -1)
                        {
                            columnClasses = "col-12 col-" + columnModifier;
                        }
                        else // Otherwise assume a default md breakpoint.
                        {
                            columnClasses = "col-12 col-md-" + columnModifier;
                        }
                    }

                    groupingShape.Classes.Add(columnClasses);

                    foreach (var item in orderedGrouping)
                    {
                        await groupingShape.AddAsync(item);
                    }
                    await container.AddAsync(groupingShape);
                }

                htmlContentBuilder.AppendHtml(await DisplayAsync.ShapeExecuteAsync(container));
            }
            else
            {
                // When nothing is grouped in a column, the grouping is rendered directly.
                foreach (var item in Shape.Grouping)
                {
                    htmlContentBuilder.AppendHtml(await DisplayAsync.ShapeExecuteAsync((IShape)item));
                }
            }

            return(htmlContentBuilder);
        }
Пример #11
0
        public async Task <IHtmlContent> CardGrouping(IDisplayHelper DisplayAsync, GroupingViewModel Shape, IShapeFactory ShapeFactory)
        {
            var htmlContentBuilder = new HtmlContentBuilder();

            var groupings = Shape.Grouping.ToLookup(x =>
            {
                if (x is IShape s)
                {
                    var key = s.Metadata.Card;
                    if (String.IsNullOrEmpty(key))
                    {
                        return(ContentKey);
                    }

                    // Remove positional modifier.
                    var modifierIndex = key.IndexOf(';');
                    if (modifierIndex != -1)
                    {
                        key = key.Substring(0, modifierIndex);
                    }

                    return(key);
                }

                return(ContentKey);
            });

            if (groupings.Count > 1)
            {
                var orderedGroupings = groupings.OrderBy(grouping =>
                {
                    var firstGroupWithModifier = grouping.FirstOrDefault(group =>
                    {
                        if (group is IShape s && !String.IsNullOrEmpty(s.Metadata.Card) && s.Metadata.Card.IndexOf(';') != -1)
                        {
                            return(true);
                        }

                        return(false);
                    });

                    if (firstGroupWithModifier is IShape shape)
                    {
                        var key           = shape.Metadata.Card;
                        var modifierIndex = key.IndexOf(';');
                        return(new PositionalGrouping(key.Substring(modifierIndex)));
                    }

                    return(new PositionalGrouping());
                }, FlatPositionComparer.Instance);

                var container = (GroupViewModel)await ShapeFactory.CreateAsync <GroupViewModel>("CardContainer", m =>
                {
                    m.Identifier = Shape.Identifier;
                });

                container.Classes.Add("accordion");

                foreach (var orderedGrouping in orderedGroupings)
                {
                    var groupingShape = (GroupingViewModel)await ShapeFactory.CreateAsync <GroupingViewModel>("Card", m =>
                    {
                        m.Identifier = Shape.Identifier;
                        m.Grouping   = orderedGrouping;
                    });

                    foreach (var item in orderedGrouping)
                    {
                        await groupingShape.AddAsync(item);
                    }

                    await container.AddAsync(groupingShape);
                }

                htmlContentBuilder.AppendHtml(await DisplayAsync.ShapeExecuteAsync(container));
            }
            else
            {
                // Evaluate for columns.
                var groupingShape = (GroupingViewModel)await ShapeFactory.CreateAsync <GroupingViewModel>("ColumnGrouping", m =>
                {
                    m.Identifier = Shape.Identifier;
                    m.Grouping   = Shape.Grouping;
                });

                htmlContentBuilder.AppendHtml(await DisplayAsync.ShapeExecuteAsync(groupingShape));
            }

            return(htmlContentBuilder);
        }
Пример #12
0
        public override async Task ProcessAsync(TagHelperContext tagHelperContext, TagHelperOutput output)
        {
            // Extract all attributes from the tag helper to
            var properties = output.Attributes
                             .Where(x => !InternalProperties.Contains(x.Name))
                             .ToDictionary(x => LowerKebabToPascalCase(x.Name), x => (object)x.Value.ToString())
            ;

            if (string.IsNullOrWhiteSpace(Type))
            {
                Type = output.TagName;
            }

            if (string.IsNullOrWhiteSpace(Cache) && output.Attributes.ContainsName("cache-id"))
            {
                Cache = Convert.ToString(output.Attributes["cache-id"].Value);
            }

            if (string.IsNullOrWhiteSpace(Context) && output.Attributes.ContainsName("cache-context"))
            {
                Context = Convert.ToString(output.Attributes["cache-context"].Value);
            }

            if (string.IsNullOrWhiteSpace(Tag) && output.Attributes.ContainsName("cache-tag"))
            {
                Tag = Convert.ToString(output.Attributes["cache-tag"].Value);
            }

            if (!FixedDuration.HasValue && output.Attributes.ContainsName("cache-fixed-duration"))
            {
                TimeSpan timespan;
                if (TimeSpan.TryParse(Convert.ToString(output.Attributes["cache-fixed-duration"].Value), out timespan))
                {
                    FixedDuration = timespan;
                }
            }

            if (!SlidingDuration.HasValue && output.Attributes.ContainsName("cache-sliding-duration"))
            {
                TimeSpan timespan;
                if (TimeSpan.TryParse(Convert.ToString(output.Attributes["cache-sliding-duration"].Value), out timespan))
                {
                    SlidingDuration = timespan;
                }
            }

            var shape = await _shapeFactory.CreateAsync(Type, Arguments.From(properties));

            if (output.Attributes.ContainsName("id"))
            {
                shape.Id = Convert.ToString(output.Attributes["id"].Value);
            }

            if (output.Attributes.ContainsName("alternate"))
            {
                shape.Metadata.Alternates.Add(Convert.ToString(output.Attributes["alternate"].Value));
            }

            if (output.Attributes.ContainsName("wrapper"))
            {
                shape.Metadata.Wrappers.Add(Convert.ToString(output.Attributes["wrapper"].Value));
            }

            tagHelperContext.Items.Add(typeof(IShape), shape);

            if (!string.IsNullOrWhiteSpace(Cache))
            {
                var metadata = shape.Metadata;

                metadata.Cache(Cache);

                if (FixedDuration.HasValue)
                {
                    metadata.Cache().WithExpiryAfter(FixedDuration.Value);
                }

                if (SlidingDuration.HasValue)
                {
                    metadata.Cache().WithExpirySliding(SlidingDuration.Value);
                }

                if (!string.IsNullOrWhiteSpace(Context))
                {
                    var contexts = Context.Split(Separators, StringSplitOptions.RemoveEmptyEntries);
                    metadata.Cache().AddContext(contexts);
                }

                if (!string.IsNullOrWhiteSpace(Tag))
                {
                    var tags = Tag.Split(Separators, StringSplitOptions.RemoveEmptyEntries);
                    metadata.Cache().AddTag(tags);
                }
            }

            await output.GetChildContentAsync();

            output.Content.SetHtmlContent(await _displayHelper.ShapeExecuteAsync(shape));

            // We don't want any encapsulating tag around the shape
            output.TagName = null;
        }
Пример #13
0
 /// <summary>
 /// Renders a shape.
 /// </summary>
 /// <param name="shape">The shape.</param>
 public Task <IHtmlContent> DisplayAsync(dynamic shape)
 {
     EnsureDisplayHelper();
     return(_displayHelper.ShapeExecuteAsync(shape));
 }
        public override async Task ProcessAsync(TagHelperContext tagHelperContext, TagHelperOutput output)
        {
            var properties = new Dictionary <string, object>();

            // These prefixed properties are bound with their original type and not converted as IHtmlContent
            foreach (var property in Properties)
            {
                var normalizedName = property.Key.ToPascalCaseDash();
                properties.Add(normalizedName, property.Value);
            }

            // Extract all other attributes from the tag helper, which are passed as IHtmlContent
            foreach (var pair in output.Attributes)
            {
                // Check it's not a reserved property name
                if (!InternalProperties.Contains(pair.Name))
                {
                    var normalizedName = pair.Name.ToPascalCaseDash();

                    if (!properties.ContainsKey(normalizedName))
                    {
                        properties.Add(normalizedName, pair.Value.ToString());
                    }
                }
            }

            if (string.IsNullOrWhiteSpace(Type))
            {
                Type = output.TagName;
            }

            if (string.IsNullOrWhiteSpace(Cache) && output.Attributes.ContainsName("cache-id"))
            {
                Cache = Convert.ToString(output.Attributes["cache-id"].Value);
            }

            if (string.IsNullOrWhiteSpace(Context) && output.Attributes.ContainsName("cache-context"))
            {
                Context = Convert.ToString(output.Attributes["cache-context"].Value);
            }

            if (string.IsNullOrWhiteSpace(Tag) && output.Attributes.ContainsName("cache-tag"))
            {
                Tag = Convert.ToString(output.Attributes["cache-tag"].Value);
            }

            if (!FixedDuration.HasValue && output.Attributes.ContainsName("cache-fixed-duration"))
            {
                TimeSpan timespan;
                if (TimeSpan.TryParse(Convert.ToString(output.Attributes["cache-fixed-duration"].Value), out timespan))
                {
                    FixedDuration = timespan;
                }
            }

            if (!SlidingDuration.HasValue && output.Attributes.ContainsName("cache-sliding-duration"))
            {
                TimeSpan timespan;
                if (TimeSpan.TryParse(Convert.ToString(output.Attributes["cache-sliding-duration"].Value), out timespan))
                {
                    SlidingDuration = timespan;
                }
            }

            var shape = await _shapeFactory.CreateAsync(Type, Arguments.From(properties));

            if (output.Attributes.ContainsName("id"))
            {
                shape.Id = Convert.ToString(output.Attributes["id"].Value);
            }

            if (output.Attributes.ContainsName("alternate"))
            {
                shape.Metadata.Alternates.Add(Convert.ToString(output.Attributes["alternate"].Value));
            }

            if (output.Attributes.ContainsName("wrapper"))
            {
                shape.Metadata.Wrappers.Add(Convert.ToString(output.Attributes["wrapper"].Value));
            }

            tagHelperContext.Items.Add(typeof(IShape), shape);

            if (!string.IsNullOrWhiteSpace(Cache))
            {
                var metadata = shape.Metadata;

                metadata.Cache(Cache);

                if (FixedDuration.HasValue)
                {
                    metadata.Cache().WithExpiryAfter(FixedDuration.Value);
                }

                if (SlidingDuration.HasValue)
                {
                    metadata.Cache().WithExpirySliding(SlidingDuration.Value);
                }

                if (!string.IsNullOrWhiteSpace(Context))
                {
                    var contexts = Context.Split(Separators, StringSplitOptions.RemoveEmptyEntries);
                    metadata.Cache().AddContext(contexts);
                }

                if (!string.IsNullOrWhiteSpace(Tag))
                {
                    var tags = Tag.Split(Separators, StringSplitOptions.RemoveEmptyEntries);
                    metadata.Cache().AddTag(tags);
                }
            }

            await output.GetChildContentAsync();

            output.Content.SetHtmlContent(await _displayHelper.ShapeExecuteAsync(shape));

            // We don't want any encapsulating tag around the shape
            output.TagName = null;
        }