use flavors for integration types
This commit is contained in:
@@ -116,7 +116,7 @@ public class IntegrationsController : ZeroApiController
|
||||
//[ZeroAuthorize(CountryPermissions.Update)]
|
||||
public virtual async Task<ActionResult<Result>> Update(string alias, Integration updateModel, [FromQuery] string changeToken = null)
|
||||
{
|
||||
if (alias != updateModel.TypeAlias)
|
||||
if (alias != updateModel.Flavor)
|
||||
{
|
||||
return BadRequest(Result.Fail(nameof(alias), "@integration.errors.noaliasmatch"));
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ public class ZeroBackofficePlugin : ZeroPlugin
|
||||
|
||||
services.AddSingleton<IIconService, IconService>();
|
||||
services.AddSingleton<IResourceService, ResourceService>();
|
||||
services.AddSingleton<ISectionService, SectionService>();
|
||||
services.AddScoped<ISectionService, SectionService>();
|
||||
|
||||
services.AddSingleton<IBackofficeAssetFileSystem, BackofficeAssetFileSystem>(svc =>
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace zero.Backoffice.Services;
|
||||
|
||||
public class SectionService : ISectionService
|
||||
{
|
||||
protected IOptions<BackofficeOptions> Options { get; set; }
|
||||
protected IZeroOptions Options { get; set; }
|
||||
|
||||
protected IBackofficeAssetFileSystem FileSystem { get; set; }
|
||||
|
||||
@@ -16,7 +16,7 @@ public class SectionService : ISectionService
|
||||
protected IEnumerable<ISettingsGroup> SettingsGroups { get; set; }
|
||||
|
||||
|
||||
public SectionService(IOptions<BackofficeOptions> options, IBackofficeAssetFileSystem fileSystem, ILogger<ISectionService> logger, IEnumerable<IBackofficeSection> sections, IEnumerable<ISettingsGroup> settingsGroups)
|
||||
public SectionService(IZeroOptions options, IBackofficeAssetFileSystem fileSystem, ILogger<ISectionService> logger, IEnumerable<IBackofficeSection> sections, IEnumerable<ISettingsGroup> settingsGroups)
|
||||
{
|
||||
Options = options;
|
||||
FileSystem = fileSystem;
|
||||
@@ -88,7 +88,7 @@ public class SectionService : ISectionService
|
||||
|
||||
List<BackofficeSettingGroupPresentation> groups = new();
|
||||
|
||||
//bool hasIntegrations = Options.For<IntegrationOptions>().Any();
|
||||
bool hasIntegrations = Options.For<FlavorOptions>().GetAll<Integration>().Any();
|
||||
|
||||
foreach (SettingsGroup group in SettingsGroups)
|
||||
{
|
||||
@@ -100,10 +100,11 @@ public class SectionService : ISectionService
|
||||
//{
|
||||
// continue;
|
||||
//}
|
||||
//if (area.Alias == Constants.Settings.Integrations && !hasIntegrations)
|
||||
//{
|
||||
// continue;
|
||||
//}
|
||||
|
||||
if (area.Alias == Constants.Settings.Integrations && !hasIntegrations)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//bool isPlugin = !(area is InternalSettingsArea);
|
||||
|
||||
|
||||
@@ -23,7 +23,13 @@ public class ConfigurationModule : ZeroModule
|
||||
services.AddScoped<IIntegrationStore, IntegrationStore>();
|
||||
|
||||
services.AddOptions<FeatureOptions>().Bind(configuration.GetSection("Zero:Features"));
|
||||
services.AddOptions<IntegrationOptions>();
|
||||
services.ConfigureOptions<ConfigureIntegrationJsonOptions>();
|
||||
|
||||
services.Configure<FlavorOptions>(opts =>
|
||||
{
|
||||
opts.Configure<Integration>(cfg =>
|
||||
{
|
||||
cfg.CanUseWithoutFlavors = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace zero.Configuration;
|
||||
|
||||
|
||||
public class ConfigureIntegrationJsonOptions : IConfigureOptions<JsonOptions>
|
||||
{
|
||||
private readonly IZeroOptions zeroOptions;
|
||||
|
||||
public ConfigureIntegrationJsonOptions(IZeroOptions options)
|
||||
{
|
||||
zeroOptions = options;
|
||||
}
|
||||
|
||||
public void Configure(JsonOptions options)
|
||||
{
|
||||
options.JsonSerializerOptions.Converters.Add(new JsonIntegrationTypeVariantConverter(zeroOptions));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using FluentValidation;
|
||||
|
||||
namespace zero.Configuration;
|
||||
|
||||
public static class FlavorOptionsExtensions
|
||||
{
|
||||
public static void AddIntegration<T>(this FlavorOptions options, string alias, string name, string description, string editorAlias = null, List<string> tags = default, string imagePath = null, IValidator validator = null) where T : Integration, new()
|
||||
{
|
||||
options.Add<Integration, T>(new IntegrationType(typeof(T))
|
||||
{
|
||||
Alias = alias,
|
||||
Name = name,
|
||||
Description = description,
|
||||
ImagePath = imagePath,
|
||||
Tags = tags,
|
||||
Validator = validator,
|
||||
Construct = cfg => new T(),
|
||||
EditorAlias = editorAlias
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,4 @@ namespace zero.Configuration;
|
||||
[RavenCollection("Integrations")]
|
||||
public class Integration : ZeroEntity
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public string TypeAlias { get; set; }
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
using FluentValidation;
|
||||
|
||||
namespace zero.Configuration;
|
||||
|
||||
public class IntegrationOptions : List<IntegrationType>
|
||||
{
|
||||
public void Add<T>(string alias, string name, string description, string editorAlias = null, List<string> tags = default, string imagePath = null, IValidator validator = null) where T : Integration , new()
|
||||
{
|
||||
Add(new IntegrationType(typeof(T))
|
||||
{
|
||||
Alias = alias,
|
||||
Name = name,
|
||||
Description = description,
|
||||
ImagePath = imagePath,
|
||||
Tags = tags,
|
||||
Validator = validator,
|
||||
Construct = cfg => new T(),
|
||||
EditorAlias = editorAlias
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void Add(Type type, string alias, string name, string description, string editorAlias = null, List<string> tags = default, string imagePath = null, IValidator validator = null)
|
||||
{
|
||||
if (!typeof(Integration).IsAssignableFrom(type))
|
||||
{
|
||||
throw new ArgumentException("Type has to inherit the Integration base model", nameof(type));
|
||||
}
|
||||
|
||||
Add(new IntegrationType(type)
|
||||
{
|
||||
Alias = alias,
|
||||
Name = name,
|
||||
Description = description,
|
||||
ImagePath = imagePath,
|
||||
Tags = tags,
|
||||
Validator = validator,
|
||||
Construct = cfg => Activator.CreateInstance(type) as Integration,
|
||||
EditorAlias = editorAlias
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -17,24 +17,16 @@ public class IntegrationStore : IIntegrationStore
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual Task<Integration> Empty(string alias)
|
||||
public virtual async Task<Integration> Empty(string alias)
|
||||
{
|
||||
IntegrationType type = IntegrationTypes.GetByAlias(alias);
|
||||
Integration integration = type?.Construct(type);
|
||||
|
||||
if (integration != null)
|
||||
{
|
||||
integration.TypeAlias = alias;
|
||||
}
|
||||
|
||||
return Task.FromResult(integration);
|
||||
return await Operations.Empty<Integration>(alias);
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual async Task<Integration> Load(string alias)
|
||||
{
|
||||
Paged<Integration> result = await Operations.Load<Integration>(1, 1, q => q.Where(x => x.TypeAlias == alias));
|
||||
Paged<Integration> result = await Operations.Load<Integration>(1, 1, q => q.Where(x => x.Flavor == alias));
|
||||
return result.Items.FirstOrDefault();
|
||||
}
|
||||
|
||||
@@ -104,19 +96,19 @@ public class IntegrationStore : IIntegrationStore
|
||||
return Result<Integration>.Fail("@integration.errors.notfound");
|
||||
}
|
||||
|
||||
IntegrationType type = IntegrationTypes.GetByAlias(model.TypeAlias);
|
||||
IntegrationType type = IntegrationTypes.GetByAlias(model.Flavor);
|
||||
|
||||
if (type == null)
|
||||
{
|
||||
return Result<Integration>.Fail("@integration.errors.typenotfound");
|
||||
}
|
||||
|
||||
if (create && await Operations.Any<Integration>(q => q.Where(x => x.TypeAlias == model.TypeAlias)))
|
||||
if (create && await Operations.Any<Integration>(q => q.Where(x => x.Flavor == model.Flavor)))
|
||||
{
|
||||
return Result<Integration>.Fail("@integration.errors.multiplenotallowed");
|
||||
}
|
||||
|
||||
if (!create && await Operations.Any<Integration>(q => q.Where(x => x.TypeAlias == model.TypeAlias && x.Id != model.Id)))
|
||||
if (!create && await Operations.Any<Integration>(q => q.Where(x => x.Flavor == model.Flavor && x.Id != model.Id)))
|
||||
{
|
||||
return Result<Integration>.Fail("@integration.errors.alreadycreated");
|
||||
}
|
||||
|
||||
@@ -7,39 +7,20 @@ namespace zero.Configuration;
|
||||
/// An integration is an application part which has a public configuration per app.
|
||||
/// It's up to the user to provide functionality.
|
||||
/// </summary>
|
||||
public class IntegrationType
|
||||
public class IntegrationType : FlavorConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// Type of the associated entity
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public Type ModelType { get; private set; }
|
||||
public IntegrationType(Type type) : base(type) { }
|
||||
|
||||
/// <summary>
|
||||
/// Alias to find the editor schema
|
||||
/// </summary>
|
||||
public string EditorAlias { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Alias for querying
|
||||
/// </summary>
|
||||
public string Alias { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Name of the flavor
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Group integrations by tags
|
||||
/// </summary>
|
||||
public List<string> Tags { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Optional description
|
||||
/// </summary>
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Image of the integration
|
||||
/// </summary>
|
||||
@@ -50,12 +31,4 @@ public class IntegrationType
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public IValidator Validator { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public Func<IntegrationType, Integration> Construct { get; set; }
|
||||
|
||||
public IntegrationType(Type type)
|
||||
{
|
||||
ModelType = type;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,36 +6,35 @@ public class IntegrationTypeService : IIntegrationTypeService
|
||||
|
||||
protected IHandlerHolder Handler { get; private set; }
|
||||
|
||||
protected IntegrationOptions Types { get; set; }
|
||||
protected FlavorOptions Flavors { get; set; }
|
||||
|
||||
|
||||
public IntegrationTypeService(IZeroContext context, IZeroOptions options, IHandlerHolder handler)
|
||||
{
|
||||
Context = context;
|
||||
Handler = handler;
|
||||
Types = options.For<IntegrationOptions>();
|
||||
Flavors = options.For<FlavorOptions>();
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<IntegrationType> GetAll()
|
||||
{
|
||||
return Types;
|
||||
return Flavors.GetAll<Integration>().Select(x => (IntegrationType)x);
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public IntegrationType GetByAlias(string integrationTypeAlias)
|
||||
{
|
||||
return Types.FirstOrDefault(x => x.Alias == integrationTypeAlias);
|
||||
return Flavors.Get<Integration>(integrationTypeAlias) as IntegrationType;
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public IntegrationType GetByType<T>() where T : Integration
|
||||
{
|
||||
Type type = typeof(T);
|
||||
return Types.FirstOrDefault(x => x.ModelType == type);
|
||||
return Flavors.Get<Integration, T>() as IntegrationType;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,281 +0,0 @@
|
||||
//using Microsoft.Extensions.Logging;
|
||||
//using Raven.Client.Documents;
|
||||
//using Raven.Client.Documents.Linq;
|
||||
|
||||
//namespace zero.Core.Configuration;
|
||||
|
||||
//public class IntegrationsCollection : EntityStore<Integration>, IIntegrationsCollection
|
||||
//{
|
||||
// /// <inheritdoc />
|
||||
// public IReadOnlyCollection<IntegrationType> RegisteredTypes { get; private set; }
|
||||
|
||||
// protected ILogger<IntegrationsCollection> Logger { get; private set; }
|
||||
|
||||
|
||||
// public IntegrationsCollection(IStoreContext<Integration> context, ILogger<IntegrationsCollection> logger) : base(context)
|
||||
// {
|
||||
// Options = new(true);
|
||||
// RegisteredTypes = Context.Options.Integrations.GetAllItems();
|
||||
// Logger = logger;
|
||||
// }
|
||||
|
||||
|
||||
// /// <inheritdoc />
|
||||
// public Integration GetEmpty(string alias)
|
||||
// {
|
||||
// IntegrationType type = RegisteredTypes.FirstOrDefault(x => x.Alias.Equals(alias, StringComparison.InvariantCultureIgnoreCase));
|
||||
|
||||
// if (type == null)
|
||||
// {
|
||||
// return null;
|
||||
// }
|
||||
|
||||
// try
|
||||
// {
|
||||
// Integration model = Activator.CreateInstance(type.ContentType) as Integration;
|
||||
// model.TypeAlias = type.Alias;
|
||||
// return model;
|
||||
// }
|
||||
// catch
|
||||
// {
|
||||
// Logger.LogWarning("Could not create integration with type {alias}", alias);
|
||||
// }
|
||||
|
||||
// return null;
|
||||
// }
|
||||
|
||||
|
||||
// /// <inheritdoc />
|
||||
// public async Task<Integration> GetByAlias(string alias)
|
||||
// {
|
||||
// IntegrationType type = RegisteredTypes.FirstOrDefault(x => x.Alias.Equals(alias, StringComparison.InvariantCultureIgnoreCase));
|
||||
// return await Load<Integration>(type);
|
||||
// }
|
||||
|
||||
|
||||
// /// <inheritdoc />
|
||||
// public async Task<T> Get<T>(string alias = null) where T : Integration, new()
|
||||
// {
|
||||
// IntegrationType type = RegisteredTypes.FirstOrDefault(x => x.ContentType == typeof(T) && (alias.IsNullOrEmpty() || x.Alias.Equals(alias, StringComparison.InvariantCultureIgnoreCase)));
|
||||
// return await Load<T>(type);
|
||||
// }
|
||||
|
||||
|
||||
// /// <inheritdoc />
|
||||
// public async Task<IList<Integration>> GetByTag(string tag)
|
||||
// {
|
||||
// IEnumerable<IntegrationType> types = RegisteredTypes.Where(x => x.Tags.Contains(tag, StringComparer.InvariantCultureIgnoreCase));
|
||||
|
||||
// if (!types.Any())
|
||||
// {
|
||||
// return new List<Integration>();
|
||||
// }
|
||||
|
||||
// string[] aliases = types.Select(x => x.Alias).ToArray();
|
||||
// return await Session.Query<Integration>().Where(x => x.TypeAlias.In(aliases)).ToListAsync();
|
||||
// }
|
||||
|
||||
|
||||
// /// <inheritdoc />
|
||||
// public async Task<bool> Any(string tag)
|
||||
// {
|
||||
// return (await GetByTag(tag)).Any(x => x.IsActive);
|
||||
// }
|
||||
|
||||
|
||||
// /// <inheritdoc />
|
||||
// public override async Task<Paged<Integration>> Load(ListQuery<Integration> query)
|
||||
// {
|
||||
// List<Integration> result = new();
|
||||
// List<Integration> models = await Session.Query<Integration>().ToListAsync();
|
||||
|
||||
// foreach (IntegrationType type in RegisteredTypes)
|
||||
// {
|
||||
// Integration model = models.FirstOrDefault(x => x.TypeAlias == type.Alias);
|
||||
|
||||
// if (model != null)
|
||||
// {
|
||||
// model.Name = type.Name;
|
||||
// result.Add(model);
|
||||
// }
|
||||
// }
|
||||
|
||||
// return result.ToQueriedList(query);
|
||||
// }
|
||||
|
||||
|
||||
// /// <inheritdoc />
|
||||
// public async Task<IList<IntegrationTypeWithStatus>> GetTypesWithStatus()
|
||||
// {
|
||||
// List<IntegrationTypeWithStatus> result = new();
|
||||
// List<Integration> models = await Session.Query<Integration>().ToListAsync();
|
||||
|
||||
// foreach (IntegrationType type in RegisteredTypes)
|
||||
// {
|
||||
// Integration model = models.FirstOrDefault(x => x.TypeAlias == type.Alias);
|
||||
|
||||
// result.Add(new()
|
||||
// {
|
||||
// Type = type,
|
||||
// Id = model?.Id,
|
||||
// IsActive = model?.IsActive ?? false,
|
||||
// IsConfigured = model != null
|
||||
// });
|
||||
// }
|
||||
|
||||
// return result.OrderByDescending(x => x.IsActive).ThenByDescending(x => x.IsConfigured).ThenByDescending(x => x.Type.Name).ToList();
|
||||
// }
|
||||
|
||||
|
||||
// /// <inheritdoc />
|
||||
// public override async Task<Result<Integration>> Save(Integration model)
|
||||
// {
|
||||
// if (model == null)
|
||||
// {
|
||||
// return Result<Integration>.Fail("@integration.errors.notfound");
|
||||
// }
|
||||
|
||||
// IntegrationType type = RegisteredTypes.FirstOrDefault(x => x.Alias.Equals(model.TypeAlias, StringComparison.InvariantCultureIgnoreCase));
|
||||
|
||||
// if (type == null)
|
||||
// {
|
||||
// return Result<Integration>.Fail("@integration.errors.typenotfound");
|
||||
// }
|
||||
|
||||
// string existingId = await Session.Query<Integration>().Where(x => x.TypeAlias == type.Alias).Select(x => x.Id).FirstOrDefaultAsync();
|
||||
|
||||
// if (!existingId.IsNullOrEmpty() && existingId != model.Id)
|
||||
// {
|
||||
// return Result<Integration>.Fail("@integration.errors.multiplenotallowed");
|
||||
// }
|
||||
|
||||
// model.Alias = type.Alias;
|
||||
// model.Name = null;
|
||||
|
||||
// Result<Integration> result = await base.Save(model);
|
||||
|
||||
// if (result.IsSuccess)
|
||||
// {
|
||||
// result.Model.Name = type.Name;
|
||||
// }
|
||||
|
||||
// return result;
|
||||
// }
|
||||
|
||||
|
||||
// /// <inheritdoc />
|
||||
// public async Task<Result<Integration>> Activate(string alias)
|
||||
// {
|
||||
// Integration model = await GetByAlias(alias);
|
||||
// if (model != null)
|
||||
// {
|
||||
// model.IsActive = true;
|
||||
// }
|
||||
// return await Save(model);
|
||||
// }
|
||||
|
||||
|
||||
// /// <inheritdoc />
|
||||
// public async Task<Result<Integration>> Deactivate(string alias)
|
||||
// {
|
||||
// Integration model = await GetByAlias(alias);
|
||||
// if (model != null)
|
||||
// {
|
||||
// model.IsActive = false;
|
||||
// }
|
||||
// return await Save(model);
|
||||
// }
|
||||
|
||||
|
||||
// /// <inheritdoc />
|
||||
// public async Task<Result<Integration>> DeleteByAlias(string alias)
|
||||
// {
|
||||
// return await base.Delete(await GetByAlias(alias));
|
||||
// }
|
||||
|
||||
|
||||
// /// <summary>
|
||||
// /// Get integration data from database
|
||||
// /// </summary>
|
||||
// protected async Task<T> Load<T>(IntegrationType type) where T : Integration, new()
|
||||
// {
|
||||
// if (type == null)
|
||||
// {
|
||||
// return default;
|
||||
// }
|
||||
|
||||
// T entity = await Session.Query<T>().FirstOrDefaultAsync(x => x.TypeAlias == type.Alias);
|
||||
|
||||
// if (entity != null)
|
||||
// {
|
||||
// entity.Name = type.Name;
|
||||
// entity.TypeAlias = type.Alias;
|
||||
// }
|
||||
|
||||
// return WhenActive(entity) as T;
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
//public interface IIntegrationsCollection
|
||||
//{
|
||||
// /// <summary>
|
||||
// /// Get all registered integration types
|
||||
// /// </summary>
|
||||
// IReadOnlyCollection<IntegrationType> RegisteredTypes { get; }
|
||||
|
||||
// /// <summary>
|
||||
// /// Get new integration model for the specified integration type alias
|
||||
// /// </summary>
|
||||
// Integration GetEmpty(string alias);
|
||||
|
||||
// /// <summary>
|
||||
// /// Get integration by an alias
|
||||
// /// </summary>
|
||||
// Task<Integration> GetByAlias(string alias);
|
||||
|
||||
// /// <summary>
|
||||
// /// Get an integration by type and optional alias
|
||||
// /// </summary>
|
||||
// Task<T> Get<T>(string alias = null) where T : Integration, new();
|
||||
|
||||
// /// <summary>
|
||||
// /// Get all integrations by a certain tag
|
||||
// /// </summary>
|
||||
// Task<IList<Integration>> GetByTag(string tag);
|
||||
|
||||
// /// <summary>
|
||||
// /// Check if any integrations of certain tag are activated
|
||||
// /// </summary>
|
||||
// Task<bool> Any(string tag);
|
||||
|
||||
// /// <summary>
|
||||
// /// Get all integrations with the specified query
|
||||
// /// </summary>
|
||||
// Task<Paged<Integration>> Load(ListQuery<Integration> query);
|
||||
|
||||
// /// <summary>
|
||||
// /// Get all integration types with their configuration status
|
||||
// /// </summary>
|
||||
// Task<IList<IntegrationTypeWithStatus>> GetTypesWithStatus();
|
||||
|
||||
// /// <summary>
|
||||
// /// Saves an integration
|
||||
// /// </summary>
|
||||
// Task<Result<Integration>> Save(Integration model);
|
||||
|
||||
// /// <summary>
|
||||
// /// Activates a configured integration
|
||||
// /// </summary>
|
||||
// Task<Result<Integration>> Activate(string alias);
|
||||
|
||||
// /// <summary>
|
||||
// /// Disables a configured integration
|
||||
// /// </summary>
|
||||
// Task<Result<Integration>> Deactivate(string alias);
|
||||
|
||||
// /// <summary>
|
||||
// /// Deletes configuration of an integration and disables it
|
||||
// /// </summary>
|
||||
// Task<Result<Integration>> DeleteByAlias(string alias);
|
||||
//}
|
||||
@@ -1,18 +0,0 @@
|
||||
namespace zero.Configuration;
|
||||
|
||||
public class JsonIntegrationTypeVariantConverter : JsonDiscriminatorConverter<ZeroEntity>
|
||||
{
|
||||
protected IntegrationOptions Integrations { get; private set; }
|
||||
|
||||
|
||||
public JsonIntegrationTypeVariantConverter(IZeroOptions options) : base("typeAlias")
|
||||
{
|
||||
Integrations = options.For<IntegrationOptions>();
|
||||
}
|
||||
|
||||
protected override Type GetTypeFromDiscriminator(Type requestedType, string discriminator)
|
||||
{
|
||||
IntegrationType type = Integrations.FirstOrDefault(x => x.Alias == discriminator);
|
||||
return type?.ModelType ?? requestedType;
|
||||
}
|
||||
}
|
||||
@@ -29,10 +29,13 @@ builder.Services.Configure<ZeroDevOptions>(opts =>
|
||||
builder.Services.Configure<FlavorOptions>(opts =>
|
||||
{
|
||||
opts.AddSpaceList<TeamMember>("team", "Team", "Members of our team", "fth-users", "spaces.team");
|
||||
opts.AddIntegration<FathomAnalyticsIntegration>("analytics.fathom", "Fathom Analytics", "Connect your website to Fathom and track page views", tags: new() { "analytics" }, imagePath: "/assets/fathom.png");
|
||||
opts.AddIntegration<GoogleAnalyticsIntegration>("analytics.google", "Google Analytics", "Connect your website to google analytics", tags: new() { "analytics" }, imagePath: "/assets/googleanalytics.png");
|
||||
|
||||
opts.Configure<Country>(x => x.CanUseWithoutFlavors = false);
|
||||
opts.Add<Country, EuropeanCountry>("eu_country", "EU country", "A country within the European Union", "fth-globe");
|
||||
opts.Add<Country, AmericanCountry>("usa_country", "USA", "A country in the United States", "fth-flag");
|
||||
|
||||
});
|
||||
|
||||
builder.Services.Configure<BlueprintOptions>(opts =>
|
||||
@@ -42,12 +45,6 @@ builder.Services.Configure<BlueprintOptions>(opts =>
|
||||
opts.Add<Translation>();
|
||||
});
|
||||
|
||||
builder.Services.Configure<IntegrationOptions>(opts =>
|
||||
{
|
||||
opts.Add<FathomAnalyticsIntegration>("analytics.fathom", "Fathom Analytics", "Connect your website to Fathom and track page views", tags: new() { "analytics" }, imagePath: "/assets/fathom.png");
|
||||
opts.Add<GoogleAnalyticsIntegration>("analytics.google", "Google Analytics", "Connect your website to google analytics", tags: new() { "analytics" }, imagePath: "/assets/googleanalytics.png");
|
||||
});
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
|
||||
Reference in New Issue
Block a user