/// <summary> /// Activates a theme. /// </summary> /// <param name="folderName">Theme's folder name.</param> /// <returns></returns> /// <remarks> /// It registers theme and the widget areas used by the theme. /// </remarks> public async Task ActivateThemeAsync(string folderName) { // verify folderName var regex = new Regex(THEME_FOLDER_REGEX); if (!regex.IsMatch(folderName)) { throw new FanException($"Theme {folderName} contains invalid characters."); } // register theme if not exist if (await metaRepository.GetAsync(folderName, EMetaType.Theme) == null) { await metaRepository.CreateAsync(new Meta { Key = folderName.ToLower(), // lower case Value = "", // empty for now Type = EMetaType.Theme, }); } // register theme-defined widget areas var installedThemes = await GetInstalledThemesInfoAsync(); var themeToActivate = installedThemes.Single(t => t.Name.Equals(folderName, StringComparison.OrdinalIgnoreCase)); // check if there is any empty area ids if (themeToActivate.WidgetAreas.Any(a => a.Id.IsNullOrEmpty())) { throw new FanException("Widget area id cannot be empty."); } var themeDefinedAreas = themeToActivate.WidgetAreas.Where(ta => !WidgetService.SystemDefinedWidgetAreaInfos.Any(sa => sa.Id == ta.Id)); foreach (var area in themeDefinedAreas) { var key = string.Format($"{folderName}-{area.Id}").ToLower(); // register only if not exist if (await metaRepository.GetAsync(key, EMetaType.WidgetAreaByTheme) == null) { var widgetArea = new WidgetArea { Id = area.Id }; await metaRepository.CreateAsync(new Meta { Key = key, Value = JsonConvert.SerializeObject(widgetArea), Type = EMetaType.WidgetAreaByTheme, }); } } }
public async void When_user_activates_a_theme_the_theme_and_its_defined_widget_areas_will_be_registered() { // When user activates a theme await _svc.ActivateThemeAsync("Clarity"); // Then the theme is registered var metaTheme = await _metaRepo.GetAsync("clarity", EMetaType.Theme); var metaArea = await _metaRepo.GetAsync("clarity-my-area", EMetaType.WidgetAreaByTheme); Assert.Equal("clarity", metaTheme.Key); Assert.Equal("clarity-my-area", metaArea.Key); }
// -------------------------------------------------------------------- get / update /// <summary> /// Returns a <see cref="Widget"/> for update. /// </summary> /// <param name="widgetType"></param> /// <returns></returns> public async Task <Widget> GetWidgetAsync(int id) { var widgetMeta = await metaRepository.GetAsync(id); var widgetBase = (Widget)JsonConvert.DeserializeObject(widgetMeta.Value, typeof(Widget)); var type = Type.GetType(widgetBase.Type); var widget = (Widget)JsonConvert.DeserializeObject(widgetMeta.Value, type); widget.Id = id; // the actual widget is returned return(widget); }
// -------------------------------------------------------------------- private methods private async Task <IList <Nav> > QueryMenuAsync(EMenu menuId, bool includeNavUrl = false) { // meta var meta = await metaRepository.GetAsync(menuId.ToString().ToLower(), EMetaType.Menu); if (meta == null) { // if not found create a meta meta = await metaRepository.CreateAsync(new Meta { Key = menuId.ToString().ToLower(), Value = JsonConvert.SerializeObject(new List <Nav>()), Type = EMetaType.Menu, }); } // navList var navList = JsonConvert.DeserializeObject <IList <Nav> >(meta.Value); // lookup nav foreach (var nav in navList) { try { if (nav.Type == ENavType.CustomLink || !includeNavUrl) { continue; } var navProvider = navProviders.SingleOrDefault(p => p.CanProvideNav(nav.Type)); nav.Url = await navProvider.GetNavUrlAsync(nav.Id); if (!nav.Url.StartsWith('/')) { nav.Url = $"/{nav.Url}"; } } catch (MokException ex) when(ex.ExceptionType == EExceptionType.ResourceNotFound) { continue; } } return(navList); }
/// <summary> /// Creates or updates a Settings, if a particular setting exists then updates it, else inserts it. /// Invalidates cache for the Settings when done. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="settings"></param> /// <returns></returns> public async Task <T> UpsertSettingsAsync <T>(T settings) where T : class, ISettings, new() { var settingsCreate = new List <Meta>(); var settingsUpdate = new List <Meta>(); var allSettings = await GetAllSettingsAsync(); foreach (var property in typeof(T).GetProperties()) { if (!property.CanRead || !property.CanWrite) { continue; } var value = property.GetValue(settings); var valueStr = TypeDescriptor.GetConverter(property.PropertyType).CanConvertFrom(typeof(string)) ? TypeDescriptor.GetConverter(typeof(object)).ConvertToInvariantString(value) : JsonConvert.SerializeObject(value); var key = (typeof(T).Name + "." + property.Name).ToLowerInvariant(); if (allSettings == null || !allSettings.Any(s => s.Key == key)) { settingsCreate.Add(new Meta { Key = key, Value = valueStr }); } else { var setting = await _repo.GetAsync(key); if (setting != null && setting.Value != valueStr) { setting.Value = valueStr; settingsUpdate.Add(setting); } } } if (settingsCreate.Count > 0) { await _repo.CreateRangeAsync(settingsCreate); } if (settingsUpdate.Count > 0) { await _repo.UpdateAsync(settingsUpdate); } string cacheKey = typeof(T).Name; await _cache.RemoveAsync(cacheKey); await _cache.RemoveAsync(CACHE_KEY_ALL_SETTINGS); return(settings); }
/// <summary> /// Returns an extension of the real derived type. /// </summary> /// <param name="id"></param> /// <returns></returns> public virtual async Task <TExtension> GetExtensionAsync(int id) { var meta = await metaRepository.GetAsync(id); var baseType = JsonConvert.DeserializeObject <TExtension>(meta.Value); var actualType = await GetManifestTypeByFolderAsync(baseType.Folder); var extension = (TExtension)JsonConvert.DeserializeObject(meta.Value, actualType); return(extension); }
public Task <TEntity> GetAsync(TKey id) { return(repository.GetAsync(id)); }