/// <summary> /// Adds the AppText admin UI. By default it uses the same virtual path as the API. It can be overridden via the options. /// </summary> /// <param name="appTextBuilder">AppText components builder</param> /// <param name="setupAction">Configures AppText.AdminApp options (optionally)</param> /// <returns></returns> public static AppTextBuilder AddAdmin(this AppTextBuilder appTextBuilder, Action <AppTextAdminConfigurationOptions> setupAction = null) { // Register as application part with embedded views var mvcBuilder = appTextBuilder.Services.AddMvcCore(); var assembly = typeof(AdminController).Assembly; mvcBuilder.AddApplicationPart(assembly); var options = GetOptions(appTextBuilder.Services, appTextBuilder.ApiConfiguration, setupAction); ConfigureServices(appTextBuilder.Services, assembly, options); mvcBuilder.AddMvcOptions(mvcOptions => { mvcOptions.Conventions.Insert(0, new AppTextRouteConvention(options.RoutePrefix, assembly)); mvcOptions.Conventions.Add(new AppTextAuthorizationConvention( options.RequireAuthenticatedUser.HasValue ? options.RequireAuthenticatedUser.Value : false, options.RequiredAuthorizationPolicy, assembly)); }); // Enable Translations module for our own translations. appTextBuilder.AddTranslations(); // Create AdminApp appTextBuilder.InitializeApp(Constants.AppTextAdminAppId, Constants.AppTextAdminAppDescription, new[] { "en", "nl" }, "en", isSystem: true); // Import translations (register as IHostedService) appTextBuilder.Services.AddHostedService <AppTextAdminInitializer>(); return(appTextBuilder); }
public static AppTextBuilder AddLiteDbStorage(this AppTextBuilder builder, string connectionString) { builder.Services.AddSingleton(sp => new LiteDatabase(connectionString)); builder.Services.AddSingleton(sp => new LiteRepository(sp.GetRequiredService <LiteDatabase>())); builder.Services.AddScoped <IApplicationStore, ApplicationStore>(); builder.Services.AddScoped <IContentDefinitionStore, ContentDefinitionStore>(); builder.Services.AddScoped <IContentStore, ContentStore>(); builder.Services.AddScoped <IVersioner, Versioner>(); return(builder); }
/// <summary> /// Initialize an app in AppText from code. /// </summary> /// <param name="builder">Apptext components builder</param> /// <param name="appId">The App identifier (no spaces)</param> /// <param name="displayName">Display name of the app</param> /// <param name="languages">Array with available languages</param> /// <param name="defaultLanguage">Default language</param> /// <param name="isSystem">Indicates if the app should function as a system app. This prevents accidental removal for example.</param> /// <returns></returns> public static AppTextBuilder InitializeApp(this AppTextBuilder builder, string appId, string displayName, string[] languages, string defaultLanguage, bool isSystem = false) { builder.Services.Configure <AppInitializerOptions>(o => o.Apps.Add(new App { Id = appId, DisplayName = displayName, Languages = languages, DefaultLanguage = defaultLanguage, IsSystemApp = isSystem })); builder.Services.AddHostedService <AppInitializer>(); return(builder); }
/// <summary> /// Adds AppText as localization implementation for standard .NET Core Localization functionality. When added to an application, you can use the /// standard .NET Core localization facilities (IStringLocalizer, IViewLocalizer), but with AppText as content backend. /// </summary> /// <param name="appTextBuilder">AppText components builder</param> /// <param name="setupAction">Configures AppText.Localization options</param> /// <returns></returns> public static AppTextBuilder AddAppTextLocalization(this AppTextBuilder appTextBuilder, Action <AppTextLocalizationOptions> setupAction = null) { var services = appTextBuilder.Services; services.AddSingleton <IStringLocalizerFactory, AppTextStringLocalizerFactory>(); services.AddSingleton <IHtmlLocalizerFactory, AppTextHtmlLocalizerFactory>(); services.AddSingleton <AppTextBridge>(); services.TryAddTransient(typeof(IStringLocalizer <>), typeof(StringLocalizer <>)); services.AddScoped <IEventHandler <ContentItemChangedEvent>, ContentItemChangedEventHandler>(); services.AddScoped <IEventHandler <AppChangedEvent>, AppChangedEventHandler>(); // Register for IOptions<AppTextLocalizationOptions> if (setupAction != null) { services.Configure(setupAction); } // Enable Translations module for our own translations. appTextBuilder.AddTranslations(); // Add initializer as hosted service appTextBuilder.Services.AddHostedService <LocalizationInitializer>(); // Configure RequestLocalizationOptions var enrichOptions = setupAction ?? delegate { }; var options = new AppTextLocalizationOptions(); enrichOptions(options); if (options.ConfigureRequestLocalizationOptions) { services.AddOptions <RequestLocalizationOptions>() .Configure <IServiceScopeFactory>((locOptions, serviceScopeFactory) => { using (var scope = serviceScopeFactory.CreateScope()) { var applicationStore = scope.ServiceProvider.GetRequiredService <IApplicationStore>(); var app = AsyncHelper.RunSync(() => applicationStore.GetApp(App.SanitizeAppId(options.AppId))); locOptions.SupportedUICultures = app.Languages.Select(lang => new CultureInfo(lang)).ToList(); locOptions.DefaultRequestCulture = new RequestCulture(CultureInfo.CurrentCulture, new CultureInfo(app.DefaultLanguage)); } }); } return(appTextBuilder); }
public static AppTextBuilder AddNoDbStorage(this AppTextBuilder builder, string baseFolder) { builder.Services.AddNoDb <App>(); builder.Services.AddNoDb <ApiKey>(); builder.Services.AddNoDb <ContentType>(); builder.Services.AddNoDb <ContentCollection>(); builder.Services.AddNoDb <ContentItem>(); builder.Services.AddSingleton <IStoragePathOptionsResolver>(new AppTextStoragePathOptionsResolver(baseFolder)); builder.Services.AddScoped <IApplicationStore, ApplicationStore>(); builder.Services.AddScoped <IContentDefinitionStore, ContentDefinitionStore>(); builder.Services.AddScoped <IContentStore, ContentStore>(); builder.Services.AddScoped <IVersioner, Versioner>(); return(builder); }
/// <summary> /// Adds the Translation Content Type and extra endpoints to support specific translation formats (JSON, .NET RESX, GNU Gettext PO files). /// </summary> /// <param name="appTextBuilder">AppText components builder</param> /// <param name="setupAction">Configures the AppText.Translations add-on</param> /// <returns></returns> public static AppTextBuilder AddTranslations(this AppTextBuilder appTextBuilder, Action <AppTextTranslationsConfigurationOptions> setupAction = null) { // First, check existence of TranslationsInitializer. If registered, we assume that this module already has been registered. if (appTextBuilder.Services.Any(s => s.ImplementationType == typeof(TranslationsInitializer))) { return(appTextBuilder); } // Set options var enrichOptions = setupAction ?? delegate { }; var options = new AppTextTranslationsConfigurationOptions(); enrichOptions(options); var apiConfiguration = appTextBuilder.ApiConfiguration; if (apiConfiguration == null) { throw new NullReferenceException("The ApiConfiguration of AppText was not set in AppTextBuilder but it is required for the Translations module."); } // Try to inherit auth options from api configuration when not set if (!options.RequireAuthenticatedUser.HasValue) { options.RequireAuthenticatedUser = apiConfiguration.RequireAuthenticatedUser; } if (options.RequiredAuthorizationPolicy == null) { options.RequiredAuthorizationPolicy = apiConfiguration.RequiredAuthorizationPolicy; } // Add translations initializer. appTextBuilder.Services.AddHostedService <TranslationsInitializer>(); // Add controller routes var mvcBuilder = appTextBuilder.Services.AddMvcCore(); var assembly = typeof(TranslationsController).Assembly; mvcBuilder.AddApplicationPart(assembly); // Try to find a route prefix for the AppText api. When found, use that one also for the controllers of this assembly. Otherwise leave empty. var translationsPrefix = apiConfiguration != null ? apiConfiguration.RoutePrefix : String.Empty; mvcBuilder.AddMvcOptions(mvcOptions => { mvcOptions.Conventions.Insert(0, new AppTextRouteConvention(translationsPrefix, assembly)); mvcOptions.Conventions.Add(new AppTextAuthorizationConvention( options.RequireAuthenticatedUser.HasValue ? options.RequireAuthenticatedUser.Value : false, options.RequiredAuthorizationPolicy, assembly)); }); // Add the custom output formatters mvcBuilder.AddMvcOptions(mvcOptions => { mvcOptions.OutputFormatters.Insert(0, new TranslationResultJsonFormatter()); mvcOptions.OutputFormatters.Add(new TranslationResultResxFormatter()); mvcOptions.OutputFormatters.Add(new TranslationResultPoFormatter()); }); mvcBuilder.AddFormatterMappings(formatterOptions => { formatterOptions.SetMediaTypeMappingForFormat("resx", "text/microsoft-resx"); formatterOptions.SetMediaTypeMappingForFormat("po", "text/x-gettext-translation"); }); return(appTextBuilder); }