/// <summary> /// Updates the relation. /// </summary> public async Task UpdateAsync(RelationEditorVM vm, ClaimsPrincipal principal, Guid?revertedId = null) { await ValidateRequestAsync(vm, isNew : false); var rel = await _db.Relations .GetAsync(x => x.Id == vm.Id && x.IsComplementary == false && (x.IsDeleted == false || revertedId != null), "Связь не найдена"); var compRel = await FindComplementaryRelationAsync(rel, revertedId != null); var user = await GetUserAsync(principal); var prevVm = rel.IsDeleted ? null : _mapper.Map <RelationEditorVM>(rel); var changeset = GetChangeset(prevVm, vm, rel.Id, user, revertedId); _db.Changes.Add(changeset); _mapper.Map(vm, rel); MapComplementaryRelation(rel, compRel); if (revertedId != null) { rel.IsDeleted = false; } await _validator.ValidateAsync(new[] { rel, compRel }); _cache.Clear(); }
/// <summary> /// Creates a new relation. /// </summary> public async Task CreateAsync(RelationEditorVM vm, ClaimsPrincipal principal) { await ValidateRequestAsync(vm, isNew : true); var rels = new List <Relation>(); var changesets = new List <Changeset>(); var groupId = vm.SourceIds.Length > 1 ? Guid.NewGuid() : (Guid?)null; var user = await GetUserAsync(principal); foreach (var srcId in vm.SourceIds) { var rel = _mapper.Map <Relation>(vm); rel.Id = Guid.NewGuid(); rel.SourceId = srcId; var compRel = new Relation { Id = Guid.NewGuid() }; MapComplementaryRelation(rel, compRel); rels.Add(rel); rels.Add(compRel); changesets.Add(GetChangeset(null, _mapper.Map <RelationEditorVM>(rel), rel.Id, user, null, groupId)); } await _validator.ValidateAsync(rels); _db.Changes.AddRange(changesets); _db.Relations.AddRange(rels); _cache.Clear(); }
/// <summary> /// Creates a new relation. /// </summary> public async Task CreateAsync(RelationEditorVM vm, ClaimsPrincipal principal) { await ValidateRequestAsync(vm, isNew : true); var newRels = new List <Relation>(); var updatedRels = new List <Relation>(); var groupId = vm.SourceIds.Length > 1 ? Guid.NewGuid() : (Guid?)null; var removedRelations = await _db.Relations .Where(x => vm.SourceIds.Contains(x.SourceId) && x.DestinationId == vm.DestinationId && x.Type == vm.Type && x.Id != vm.Id && x.IsDeleted == true) .ToDictionaryAsync(x => x.SourceId, x => x); var user = await GetUserAsync(principal); foreach (var srcId in vm.SourceIds) { Relation rel; if (removedRelations.TryGetValue(srcId, out rel)) { rel.IsDeleted = false; updatedRels.Add(rel); } else { rel = _mapper.Map <Relation>(vm); rel.Id = Guid.NewGuid(); rel.SourceId = srcId; newRels.Add(rel); } var compRel = new Relation { Id = Guid.NewGuid() }; MapComplementaryRelation(rel, compRel); newRels.Add(compRel); _db.Changes.Add(GetChangeset(null, _mapper.Map <RelationEditorVM>(rel), rel.Id, user, null, groupId)); } await _validator.ValidateAsync(newRels.Concat(updatedRels).ToList()); _db.Relations.AddRange(newRels); _cache.Clear(); }
/// <summary> /// Displays the editor. /// </summary> private async Task <ActionResult> ViewEditorFormAsync(RelationEditorVM vm) { if (vm.SourceIds == null) { vm.SourceIds = Array.Empty <Guid>(); } var pageIds = new[] { vm.DestinationId, vm.EventId }.Concat(vm.SourceIds.Cast <Guid?>()).ToList(); var pageLookup = await _pages.FindPagesByIdsAsync(pageIds); ViewBag.Data = new RelationEditorDataVM { IsNew = vm.Id == Guid.Empty, SourceItems = GetPageLookup(vm.SourceIds), DestinationItem = GetPageLookup(vm.DestinationId ?? Guid.Empty), EventItem = GetPageLookup(vm.EventId ?? Guid.Empty), Properties = _rels.GetPropertiesForRelationType(vm.Type), RelationTypes = EnumHelper.GetEnumValues <RelationType>() .Select(x => new SelectListItem { Value = x.ToString(), Text = x.GetEnumDescription(), Selected = x == vm.Type }) }; return(View("Editor", vm)); IReadOnlyList <SelectListItem> GetPageLookup(params Guid[] ids) { var result = new List <SelectListItem>(); foreach (var id in ids) { if (pageLookup.TryGetValue(id, out var page)) { result.Add(new SelectListItem { Selected = true, Text = page.Title, Value = page.Id.ToString() }); } } return(result); } }
/// <summary> /// Gets the changeset for updates. /// </summary> private Changeset GetChangeset(RelationEditorVM prev, RelationEditorVM next, Guid id, AppUser user, Guid?revertedId, Guid?groupId = null) { if (prev == null && next == null) { throw new ArgumentNullException(); } return(new Changeset { Id = Guid.NewGuid(), RevertedChangesetId = revertedId, GroupId = groupId, Type = ChangesetEntityType.Relation, Date = DateTime.Now, EditedRelationId = id, Author = user, OriginalState = prev == null ? null : JsonConvert.SerializeObject(prev), UpdatedState = next == null ? null : JsonConvert.SerializeObject(next), }); }
public async Task <ActionResult> Create(RelationEditorVM vm) { if (!ModelState.IsValid) { return(await ViewEditorFormAsync(vm)); } try { await _rels.CreateAsync(vm, User); await _db.SaveChangesAsync(); return(RedirectToSuccess("Связь создана")); } catch (ValidationException ex) { SetModelState(ex); return(await ViewEditorFormAsync(vm)); } }
public async Task <ActionResult> Update(RelationEditorVM vm) { if (!ModelState.IsValid) { return(await ViewEditorFormAsync(vm)); } try { await _rels.UpdateAsync(vm, User); await _db.SaveChangesAsync(); _alarm.FireTreeLayoutRegenerationRequired(); return(RedirectToSuccess("Связь обновлена")); } catch (ValidationException ex) { SetModelState(ex); return(await ViewEditorFormAsync(vm)); } }
/// <summary> /// Checks if the create/update request contains valid data. /// </summary> private async Task ValidateRequestAsync(RelationEditorVM vm, bool isNew) { var val = new Validator(); vm.SourceIds = vm.SourceIds ?? new Guid[0]; var pageIds = vm.SourceIds .Concat(new [] { vm.DestinationId ?? Guid.Empty, vm.EventId ?? Guid.Empty }) .ToList(); var pages = await _db.Pages .Where(x => pageIds.Contains(x.Id)) .ToDictionaryAsync(x => x.Id, x => x.Type); var sourceTypes = vm.SourceIds.Select(x => pages.TryGetNullableValue(x)).ToList(); var destType = pages.TryGetNullableValue(vm.DestinationId ?? Guid.Empty); var eventType = pages.TryGetNullableValue(vm.EventId ?? Guid.Empty); if (vm.SourceIds == null || vm.SourceIds.Length == 0) { val.Add(nameof(vm.SourceIds), "Выберите страницу"); } else if (isNew == false && vm.SourceIds.Length > 1) { val.Add(nameof(vm.SourceIds), "При редактировании может быть указана только одна страница"); } else if (sourceTypes.Any(x => x == null)) { val.Add(nameof(vm.SourceIds), "Страница не найдена"); } if (vm.DestinationId == null) { val.Add(nameof(vm.DestinationId), "Выберите страницу"); } else if (destType == null) { val.Add(nameof(vm.DestinationId), "Страница не найдена"); } if (destType != null && sourceTypes.Any(x => x != null && !RelationHelper.IsRelationAllowed(x.Value, destType.Value, vm.Type))) { val.Add(nameof(vm.Type), "Тип связи недопустимм для данных страниц"); } if (vm.EventId != null) { if (eventType == null) { val.Add(nameof(vm.EventId), "Страница не найдена"); } else if (eventType != PageType.Event) { val.Add(nameof(vm.EventId), "Требуется страница события"); } else if (!RelationHelper.IsRelationEventReferenceAllowed(vm.Type)) { val.Add(nameof(vm.EventId), "Событие нельзя привязать к данному типу связи"); } } if (!string.IsNullOrEmpty(vm.DurationStart) || !string.IsNullOrEmpty(vm.DurationEnd)) { if (!RelationHelper.IsRelationDurationAllowed(vm.Type)) { val.Add(nameof(vm.DurationStart), "Дату нельзя указать для данного типа связи"); } else { var from = FuzzyDate.TryParse(vm.DurationStart); var to = FuzzyDate.TryParse(vm.DurationEnd); if (from > to) { val.Add(nameof(vm.DurationStart), "Дата начала не может быть больше даты конца"); } else if (FuzzyRange.TryParse(FuzzyRange.TryCombine(vm.DurationStart, vm.DurationEnd)) == null) { val.Add(nameof(vm.DurationStart), "Введите дату в корректном формате"); } } } var existingRelation = await _db.Relations .AnyAsync(x => vm.SourceIds.Contains(x.SourceId) && x.DestinationId == vm.DestinationId && x.Type == vm.Type && x.Id != vm.Id); if (existingRelation) { val.Add(nameof(vm.DestinationId), "Такая связь уже существует!"); } val.ThrowIfInvalid(); }