mirror of https://github.com/Squidex/squidex.git
45 changed files with 779 additions and 501 deletions
@ -0,0 +1,21 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
|
||||
|
namespace Squidex.Domain.Apps.Core.HandleRules |
||||
|
{ |
||||
|
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] |
||||
|
public sealed class RuleActionAttribute : Attribute |
||||
|
{ |
||||
|
public string Link { get; set; } |
||||
|
|
||||
|
public string Display { get; set; } |
||||
|
|
||||
|
public string Description { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,30 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
using Squidex.Infrastructure; |
||||
|
|
||||
|
namespace Squidex.Domain.Apps.Core.HandleRules |
||||
|
{ |
||||
|
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] |
||||
|
public sealed class RuleActionHandlerAttribute : Attribute |
||||
|
{ |
||||
|
public Type HandlerType { get; } |
||||
|
|
||||
|
public RuleActionHandlerAttribute(Type handlerType) |
||||
|
{ |
||||
|
Guard.NotNull(handlerType, nameof(handlerType)); |
||||
|
|
||||
|
HandlerType = handlerType; |
||||
|
|
||||
|
if (!typeof(IRuleActionHandler).IsAssignableFrom(handlerType)) |
||||
|
{ |
||||
|
throw new ArgumentException($"Handler type must implement {typeof(IRuleActionHandler)}.", nameof(handlerType)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,42 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
using Squidex.Domain.Apps.Core.HandleRules; |
||||
|
using Squidex.Domain.Apps.Core.Rules; |
||||
|
using Squidex.Infrastructure; |
||||
|
|
||||
|
namespace Squidex.Domain.Apps.Rules.Actions.Discourse |
||||
|
{ |
||||
|
[RuleActionHandler(typeof(DiscourseActionHandler))] |
||||
|
[RuleAction(Description = "")] |
||||
|
public sealed class DiscourseAction : RuleAction |
||||
|
{ |
||||
|
[AbsoluteUrl] |
||||
|
[Required] |
||||
|
[Display(Name = "Url", Description = "he url to the discourse server.")] |
||||
|
public Uri Url { get; set; } |
||||
|
|
||||
|
[Required] |
||||
|
[Display(Name = "Api Key", Description = "The api key.")] |
||||
|
public string ApiKey { get; set; } |
||||
|
|
||||
|
[Required] |
||||
|
[Display(Name = "Text", Description = "The text as markdown.")] |
||||
|
public string Text { get; set; } |
||||
|
|
||||
|
[Display(Name = "Title", Description = "The optional title when creating new topics.")] |
||||
|
public string Title { get; set; } |
||||
|
|
||||
|
[Display(Name = "Topic", Description = "The optional topic id.")] |
||||
|
public int? Topic { get; set; } |
||||
|
|
||||
|
[Display(Name = "Category", Description = "The optional category id.")] |
||||
|
public int? Category { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,48 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
using System.Net.Http; |
||||
|
using System.Threading.Tasks; |
||||
|
using Squidex.Domain.Apps.Core.HandleRules; |
||||
|
using Squidex.Domain.Apps.Core.HandleRules.EnrichedEvents; |
||||
|
|
||||
|
namespace Squidex.Domain.Apps.Rules.Actions.Discourse |
||||
|
{ |
||||
|
public sealed class DiscourseActionHandler : RuleActionHandler<DiscourseAction, DiscourseJob> |
||||
|
{ |
||||
|
private readonly IHttpClientFactory httpClientFactory; |
||||
|
|
||||
|
public DiscourseActionHandler(RuleEventFormatter formatter, IHttpClientFactory httpClientFactory) |
||||
|
: base(formatter) |
||||
|
{ |
||||
|
this.httpClientFactory = httpClientFactory; |
||||
|
} |
||||
|
|
||||
|
protected override Task<(string Description, DiscourseJob Data)> CreateJobAsync(EnrichedEvent @event, DiscourseAction action) |
||||
|
{ |
||||
|
return base.CreateJobAsync(@event, action); |
||||
|
} |
||||
|
|
||||
|
protected override Task<(string Dump, Exception Exception)> ExecuteJobAsync(DiscourseJob job) |
||||
|
{ |
||||
|
using (var client = httpClientFactory.CreateClient()) |
||||
|
{ |
||||
|
// Foo
|
||||
|
} |
||||
|
|
||||
|
return Task.FromResult<(string Dump, Exception Exception)>((string.Empty, null)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public sealed class DiscourseJob |
||||
|
{ |
||||
|
public string RequestUrl { get; set; } |
||||
|
|
||||
|
public string RequestBody { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -1,106 +0,0 @@ |
|||||
// ==========================================================================
|
|
||||
// Squidex Headless CMS
|
|
||||
// ==========================================================================
|
|
||||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|
||||
// All rights reserved. Licensed under the MIT license.
|
|
||||
// ==========================================================================
|
|
||||
|
|
||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using Squidex.Domain.Apps.Core.HandleRules; |
|
||||
using Squidex.Domain.Apps.Core.Rules; |
|
||||
using Squidex.Domain.Apps.Rules.Action.Algolia; |
|
||||
using Squidex.Domain.Apps.Rules.Action.AzureQueue; |
|
||||
using Squidex.Domain.Apps.Rules.Action.ElasticSearch; |
|
||||
using Squidex.Domain.Apps.Rules.Action.Fastly; |
|
||||
using Squidex.Domain.Apps.Rules.Action.Medium; |
|
||||
using Squidex.Domain.Apps.Rules.Action.Slack; |
|
||||
using Squidex.Domain.Apps.Rules.Action.Twitter; |
|
||||
using Squidex.Domain.Apps.Rules.Action.Webhook; |
|
||||
using Squidex.Infrastructure; |
|
||||
|
|
||||
namespace Squidex.Domain.Apps.Rules.Actions |
|
||||
{ |
|
||||
public static class RuleActionRegistry |
|
||||
{ |
|
||||
private const string Suffix = "Action"; |
|
||||
private static readonly HashSet<Type> ActionHandlerTypes = new HashSet<Type>(); |
|
||||
private static readonly Dictionary<string, Type> ActionTypes = new Dictionary<string, Type>(); |
|
||||
|
|
||||
public static IReadOnlyDictionary<string, Type> Actions |
|
||||
{ |
|
||||
get { return ActionTypes; } |
|
||||
} |
|
||||
|
|
||||
public static IReadOnlyCollection<Type> ActionHandlers |
|
||||
{ |
|
||||
get { return ActionHandlerTypes; } |
|
||||
} |
|
||||
|
|
||||
static RuleActionRegistry() |
|
||||
{ |
|
||||
Register< |
|
||||
AlgoliaAction, |
|
||||
AlgoliaActionHandler>(); |
|
||||
|
|
||||
Register< |
|
||||
AzureQueueAction, |
|
||||
AzureQueueActionHandler>(); |
|
||||
|
|
||||
Register< |
|
||||
ElasticSearchAction, |
|
||||
ElasticSearchActionHandler>(); |
|
||||
|
|
||||
Register< |
|
||||
FastlyAction, |
|
||||
FastlyActionHandler>(); |
|
||||
|
|
||||
Register< |
|
||||
MediumAction, |
|
||||
MediumActionHandler>(); |
|
||||
|
|
||||
Register< |
|
||||
SlackAction, |
|
||||
SlackActionHandler>(); |
|
||||
|
|
||||
Register< |
|
||||
TweetAction, |
|
||||
TweetActionHandler>(); |
|
||||
|
|
||||
Register< |
|
||||
WebhookAction, |
|
||||
WebhookActionHandler>(); |
|
||||
} |
|
||||
|
|
||||
public static void Register<TAction, THandler>() where TAction : RuleAction where THandler : IRuleActionHandler |
|
||||
{ |
|
||||
AddActionType<TAction>(); |
|
||||
AddActionHandler<THandler>(); |
|
||||
} |
|
||||
|
|
||||
private static void AddActionHandler<THandler>() where THandler : IRuleActionHandler |
|
||||
{ |
|
||||
ActionHandlerTypes.Add(typeof(THandler)); |
|
||||
} |
|
||||
|
|
||||
private static void AddActionType<TAction>() where TAction : RuleAction |
|
||||
{ |
|
||||
var name = typeof(TAction).Name; |
|
||||
|
|
||||
if (name.EndsWith(Suffix, StringComparison.Ordinal)) |
|
||||
{ |
|
||||
name = name.Substring(0, name.Length - Suffix.Length); |
|
||||
} |
|
||||
|
|
||||
ActionTypes.Add(name, typeof(TAction)); |
|
||||
} |
|
||||
|
|
||||
public static void RegisterTypes(TypeNameRegistry typeNameRegistry) |
|
||||
{ |
|
||||
foreach (var actionType in ActionTypes.Values) |
|
||||
{ |
|
||||
typeNameRegistry.Map(actionType, actionType.Name); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,32 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
|
||||
|
namespace Squidex.Domain.Apps.Rules.Actions |
||||
|
{ |
||||
|
public sealed class RuleElement |
||||
|
{ |
||||
|
public Type Type { get; } |
||||
|
|
||||
|
public string Link { get; set; } |
||||
|
|
||||
|
public string Display { get; } |
||||
|
|
||||
|
public string Description { get; } |
||||
|
|
||||
|
public RuleElement(Type type, string display, string description, string link = null) |
||||
|
{ |
||||
|
Type = type; |
||||
|
|
||||
|
Display = display; |
||||
|
Description = description; |
||||
|
|
||||
|
Link = link; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,92 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Reflection; |
||||
|
using Squidex.Domain.Apps.Core.HandleRules; |
||||
|
using Squidex.Domain.Apps.Core.Rules; |
||||
|
using Squidex.Domain.Apps.Core.Rules.Triggers; |
||||
|
using Squidex.Infrastructure; |
||||
|
|
||||
|
namespace Squidex.Domain.Apps.Rules.Actions |
||||
|
{ |
||||
|
public static class RuleElementRegistry |
||||
|
{ |
||||
|
private const string Suffix = "Action"; |
||||
|
private static readonly HashSet<Type> ActionHandlerTypes = new HashSet<Type>(); |
||||
|
private static readonly Dictionary<string, RuleElement> ActionTypes = new Dictionary<string, RuleElement>(); |
||||
|
private static readonly Dictionary<string, RuleElement> TriggerTypes = new Dictionary<string, RuleElement>(); |
||||
|
|
||||
|
public static IReadOnlyDictionary<string, RuleElement> Actions |
||||
|
{ |
||||
|
get { return ActionTypes; } |
||||
|
} |
||||
|
|
||||
|
public static IReadOnlyDictionary<string, RuleElement> Triggers |
||||
|
{ |
||||
|
get { return TriggerTypes; } |
||||
|
} |
||||
|
|
||||
|
public static IReadOnlyCollection<Type> ActionHandlers |
||||
|
{ |
||||
|
get { return ActionHandlerTypes; } |
||||
|
} |
||||
|
|
||||
|
static RuleElementRegistry() |
||||
|
{ |
||||
|
TriggerTypes["ContentChanged"] = |
||||
|
new RuleElement( |
||||
|
typeof(ContentChangedTrigger), |
||||
|
"Content changed", |
||||
|
"Content changed like created, updated, published, unpublished..."); |
||||
|
|
||||
|
TriggerTypes["AssetChanged"] = |
||||
|
new RuleElement( |
||||
|
typeof(AssetChangedTrigger), |
||||
|
"Asset changed", |
||||
|
"Asset changed like created, updated, renamed..."); |
||||
|
|
||||
|
var actionTypes = |
||||
|
typeof(RuleElementRegistry).Assembly |
||||
|
.GetTypes() |
||||
|
.Where(x => typeof(RuleAction).IsAssignableFrom(x)) |
||||
|
.Where(x => x.GetCustomAttribute<RuleActionAttribute>() != null) |
||||
|
.Where(x => x.GetCustomAttribute<RuleActionHandlerAttribute>() != null) |
||||
|
.ToList(); |
||||
|
|
||||
|
foreach (var actionType in actionTypes) |
||||
|
{ |
||||
|
var name = actionType.Name; |
||||
|
|
||||
|
if (name.EndsWith(Suffix, StringComparison.Ordinal)) |
||||
|
{ |
||||
|
name = name.Substring(0, name.Length - Suffix.Length); |
||||
|
} |
||||
|
|
||||
|
var metadata = actionType.GetCustomAttribute<RuleActionAttribute>(); |
||||
|
|
||||
|
ActionTypes[name] = |
||||
|
new RuleElement(actionType, |
||||
|
metadata.Display, |
||||
|
metadata.Description, |
||||
|
metadata.Link); |
||||
|
|
||||
|
ActionHandlerTypes.Add(actionType.GetCustomAttribute<RuleActionHandlerAttribute>().HandlerType); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public static void RegisterTypes(TypeNameRegistry typeNameRegistry) |
||||
|
{ |
||||
|
foreach (var actionType in ActionTypes.Values) |
||||
|
{ |
||||
|
typeNameRegistry.Map(actionType.Type, actionType.Type.Name); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,31 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
|
||||
|
namespace Squidex.Areas.Api.Controllers.Rules.Models |
||||
|
{ |
||||
|
public sealed class RuleElementDto |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Describes the action or trigger type.
|
||||
|
/// </summary>
|
||||
|
[Required] |
||||
|
public string Description { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// The label for the action or trigger type.
|
||||
|
/// </summary>
|
||||
|
[Required] |
||||
|
public string Display { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// The optional link to the product that is integrated.
|
||||
|
/// </summary>
|
||||
|
public string Link { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,40 @@ |
|||||
|
/* |
||||
|
* Squidex Headless CMS |
||||
|
* |
||||
|
* @license |
||||
|
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. |
||||
|
*/ |
||||
|
|
||||
|
import { ComponentFactoryResolver, ComponentRef, Input, OnInit, ViewChild, ViewContainerRef } from '@angular/core'; |
||||
|
import { FormGroup } from '@angular/forms'; |
||||
|
|
||||
|
export class RuleActionContainer implements OnInit { |
||||
|
@Input() |
||||
|
public actionType: string; |
||||
|
|
||||
|
@Input() |
||||
|
public action: any; |
||||
|
|
||||
|
@Input() |
||||
|
public actionForm: FormGroup; |
||||
|
|
||||
|
@Input() |
||||
|
public actionFormSubmitted = false; |
||||
|
|
||||
|
@ViewChild('container', { read: ViewContainerRef }) |
||||
|
public entry: ViewContainerRef; |
||||
|
|
||||
|
private component: ComponentRef<any>; |
||||
|
|
||||
|
constructor( |
||||
|
private readonly componentFactoryResolver: ComponentFactoryResolver |
||||
|
) { |
||||
|
} |
||||
|
|
||||
|
public ngOnInit() { |
||||
|
const factories = Array.from(this.componentFactoryResolver['_factories'].values()); |
||||
|
const factory: any = factories.find((x: any) => x.selector === this.actionType); |
||||
|
|
||||
|
this.component = this.entry.createComponent(factory); |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue