private async Task <string> TrySaveFlags(FeatureFlagsViewModel model, string contentId) { var flags = new FeatureFlags( model.Features.ToDictionary(f => f.Name, f => f.Status), model.Flights.ToDictionary(f => f.Name, f => f.AsFlight())); var result = await _storage.TrySaveAsync(flags, contentId); switch (result) { case FeatureFlagSaveResult.Ok: // The flags have been persisted. Refresh this instance's cache immediately. await _cache.RefreshAsync(); var refreshSeconds = _config.FeatureFlagsRefreshInterval.TotalSeconds; TempData["Message"] = $"Your feature flags have been saved! It may take up to {refreshSeconds} seconds for this change to propagate everywhere."; return(null); case FeatureFlagSaveResult.Conflict: return("Your changes were not applied as the feature flags were modified by someone else. Please reload the page and try again."); default: return($"Unknown save result '{result}'."); } }
public async Task <ActionResult> Index(FeatureFlagsViewModel model) { if (ModelState.IsValid) { var result = await _storage.TrySaveAsync(model.Flags, model.ContentId); switch (result.Type) { case FeatureFlagSaveResultType.Ok: // The flags have been persisted. Refresh this instance's cache immediately. await _cache.RefreshAsync(); var refreshSeconds = _config.FeatureFlagsRefreshInterval.TotalSeconds; TempData["Message"] = $"Your feature flags have been saved! It may take up to {refreshSeconds} seconds for this change to propagate everywhere."; return(Redirect(Url.Action(actionName: "Index", controllerName: "Features"))); case FeatureFlagSaveResultType.Conflict: TempData["ErrorMessage"] = "Your changes were not applied as the feature flags were modified by someone else. " + "Please reload the page and try again."; break; case FeatureFlagSaveResultType.Invalid: ModelState.AddModelError(nameof(model.Flags), $"Invalid flags: {result.Message}"); break; default: TempData["ErrorMessage"] = $"Unknown save result '{result}': {result.Message}."; break; } } return(View(model)); }
private string ApplyChange <TModify, TBase>( FeatureFlagsViewModel model, TModify change, ChangeType type) where TModify : IModifyFeatureFlagsViewModel <TBase>, TBase where TBase : IFeatureFlagsObjectViewModel { var validationError = change.GetValidationError(_userService); if (validationError != null) { return(validationError); } var existingList = change.GetExistingList(model); var existing = existingList.SingleOrDefault(f => f.Name == change.Name); switch (type) { case ChangeType.Add: if (existing == null) { existingList.Add(change); return(null); } else { return($"The {change.PrettyName} '{change.Name}' already exists. " + $"You cannot add a {change.PrettyName} that already exists."); } case ChangeType.Edit: if (existing == null) { return($"The {change.PrettyName} '{change.Name}' does not exist. " + $"You cannot edit a {change.PrettyName} that does not exist."); } else { change.ApplyTo(existing); return(null); } case ChangeType.Delete: if (existing == null) { return($"The {change.PrettyName} '{change.Name}' does not exist. " + $"You cannot delete a {change.PrettyName} that does not exist."); } else { existingList.Remove(existing); return(null); } default: throw new ArgumentOutOfRangeException(nameof(type)); } }
public static void AssertFlags(FeatureFlags flags, FeatureFlagsViewModel model) { Assert.Equal(flags.Features.Count, model.Features.Count); Assert.Equal(flags.Flights.Count, model.Flights.Count); foreach (var feature in model.Features) { Assert.True(flags.Features.ContainsKey(feature.Name)); Assert.Equal(flags.Features[feature.Name], feature.Status); } foreach (var flight in model.Flights) { Assert.True(flags.Flights.ContainsKey(flight.Name)); AssertFlight(flags.Flights[flight.Name], flight); } }
public static void AssertFlags( FeatureFlags flags, FeatureFlagsViewModel model, bool hasLastUpdated, TimeSpan refreshInterval, string contentId) { if (hasLastUpdated) { Assert.True(model.TimeSinceLastRefresh > TimeSpan.Zero); } else { Assert.Null(model.TimeSinceLastRefresh); } Assert.Equal(refreshInterval, model.RefreshInterval); Assert.Equal(contentId, model.ContentId); AssertFlags(flags, model); }