/// <summary> /// Gets or sets the form. /// </summary> /// <value> /// The form. /// </value> public WorkflowActionForm GetForm() { EnsureChildControls(); var form = new WorkflowActionForm(); form.Guid = _hfFormGuid.Value.AsGuid(); if ( form.Guid != Guid.Empty ) { form.NotificationSystemEmailId = _ddlNotificationSystemEmail.SelectedValueAsId(); form.IncludeActionsInNotification = _cbIncludeActions.Checked; form.Header = _ceHeaderText.Text; form.Footer = _ceFooterText.Text; form.Actions = _falActions.Value; foreach ( var row in AttributeRows ) { var formAttribute = new WorkflowActionFormAttribute(); formAttribute.Attribute = new Rock.Model.Attribute { Guid = row.AttributeGuid, Name = row.AttributeName }; formAttribute.Guid = row.Guid; formAttribute.Order = row.Order; formAttribute.IsVisible = row.IsVisible; formAttribute.IsReadOnly = !row.IsEditable; formAttribute.IsRequired = row.IsRequired; form.FormAttributes.Add( formAttribute ); } form.ActionAttributeGuid = _ddlActionAttribute.SelectedValueAsGuid(); return form; } return null; }
/// <summary> /// Sets the form. /// </summary> /// <param name="value">The value.</param> /// <param name="workflowTypeAttributes">The workflow type attributes.</param> public void SetForm(WorkflowActionForm value, Dictionary <Guid, Rock.Model.Attribute> workflowTypeAttributes) { EnsureChildControls(); if (value != null) { _hfFormGuid.Value = value.Guid.ToString(); _ddlNotificationSystemEmail.SetValue(value.NotificationSystemEmailId); _cbIncludeActions.Checked = value.IncludeActionsInNotification; _ceHeaderText.Text = value.Header; _ceFooterText.Text = value.Footer; _falActions.Value = value.Actions; _cbAllowNotes.Checked = value.AllowNotes.HasValue && value.AllowNotes.Value; // Remove any existing rows (shouldn't be any) foreach (var attributeRow in Controls.OfType <WorkflowFormAttributeRow>()) { Controls.Remove(attributeRow); } foreach (var formAttribute in value.FormAttributes.OrderBy(a => a.Order)) { var row = new WorkflowFormAttributeRow(); row.AttributeGuid = formAttribute.Attribute.Guid; row.AttributeName = formAttribute.Attribute.Name; row.Guid = formAttribute.Guid; row.IsVisible = formAttribute.IsVisible; row.IsEditable = !formAttribute.IsReadOnly; row.IsRequired = formAttribute.IsRequired; row.HideLabel = formAttribute.HideLabel; row.PreHtml = formAttribute.PreHtml; row.PostHtml = formAttribute.PostHtml; Controls.Add(row); } _ddlActionAttribute.Items.Clear(); _ddlActionAttribute.Items.Add(new ListItem()); foreach (var attributeItem in workflowTypeAttributes) { var fieldType = FieldTypeCache.Get(attributeItem.Value.FieldTypeId); if (fieldType != null && fieldType.Field is Rock.Field.Types.TextFieldType) { var li = new ListItem(attributeItem.Value.Name, attributeItem.Key.ToString()); li.Selected = value.ActionAttributeGuid.HasValue && value.ActionAttributeGuid.Value.ToString() == li.Value; _ddlActionAttribute.Items.Add(li); } } } else { _hfFormGuid.Value = string.Empty; _ddlNotificationSystemEmail.SelectedIndex = 0; _cbIncludeActions.Checked = true; _ceHeaderText.Text = string.Empty; _ceFooterText.Text = string.Empty; _falActions.Value = "Submit^^^Your information has been submitted successfully."; _ddlNotificationSystemEmail.SelectedIndex = 0; _cbAllowNotes.Checked = false; } }
/// <summary> /// Adds a new form section or updates an existing form section in the /// <paramref name="actionForm"/>. This also handles the creation of /// any new form attributes as needed. /// </summary> /// <param name="actionForm">The <see cref="WorkflowActionForm"/> being updated.</param> /// <param name="workflowType">The <see cref="WorkflowType"/> being updated.</param> /// <param name="attributeService">The database service that provides access to the attributes.</param> /// <param name="formAttributeService">The database service that provides access to the form attributes.</param> /// <param name="formSectionService">The database service that provides access to the form sections.</param> /// <param name="section">The section view model that will be used as the source of information.</param> /// <param name="nextAttributeOrder">The next attribute order number to use when creating a new attribute.</param> /// <returns>The <see cref="WorkflowActionFormSection"/> entity that was either updated or created.</returns> private static WorkflowActionFormSection AddOrUpdateFormSection(WorkflowActionForm actionForm, WorkflowType workflowType, AttributeService attributeService, WorkflowActionFormAttributeService formAttributeService, WorkflowActionFormSectionService formSectionService, FormSectionViewModel section, List <FormFieldViewModel> formFields, ref int nextAttributeOrder) { var formSection = actionForm.FormSections.FirstOrDefault(s => s.Guid == section.Guid); // If the section was not found then create a new one and add it // to the form. if (formSection == null) { formSection = new WorkflowActionFormSection { Guid = section.Guid }; actionForm.FormSections.Add(formSection); formSectionService.Add(formSection); } // Update the standard section properties from the view model. formSection.Description = section.Description; formSection.Title = section.Title; formSection.ShowHeadingSeparator = section.ShowHeadingSeparator; formSection.SectionTypeValueId = Rock.Blocks.WorkFlow.FormBuilder.Utility.GetDefinedValueId(section.Type); formSection.SectionVisibilityRules = section.VisibilityRule?.FromViewModel(formFields); // Loop through all fields that need to be either added or updated. for (int fieldOrder = 0; fieldOrder < section.Fields.Count; fieldOrder++) { var field = section.Fields[fieldOrder]; var formField = AddOrUpdateFormField(actionForm, workflowType, attributeService, formAttributeService, formSection, field, formFields, ref nextAttributeOrder); formField.Order = fieldOrder; } return(formSection); }
/// <summary> /// Updates a workflow type with values from the view model. /// </summary> /// <param name="formSettings">The view model that contains the settings to be updated.</param> /// <param name="actionForm">The <see cref="WorkflowActionForm"/> to be updated.</param> /// <param name="workflowType">The <see cref="WorkflowType"/> to be updated.</param> /// <param name="rockContext">The database context to use for data lookups.</param> private static void UpdateWorkflowType(FormSettingsViewModel formSettings, WorkflowActionForm actionForm, WorkflowType workflowType, RockContext rockContext) { actionForm.Header = formSettings.HeaderContent; actionForm.Footer = formSettings.FooterContent; actionForm.AllowPersonEntry = formSettings.AllowPersonEntry; if (formSettings.AllowPersonEntry) { actionForm.PersonEntryAddressEntryOption = formSettings.PersonEntry.Address.ToPersonEntryOption(); actionForm.PersonEntryGroupLocationTypeValueId = Rock.Blocks.WorkFlow.FormBuilder.Utility.GetDefinedValueId(formSettings.PersonEntry.AddressType); actionForm.PersonEntryAutofillCurrentPerson = formSettings.PersonEntry.AutofillCurrentPerson; actionForm.PersonEntryBirthdateEntryOption = formSettings.PersonEntry.Birthdate.ToPersonEntryOption(); actionForm.PersonEntryCampusStatusValueId = Rock.Blocks.WorkFlow.FormBuilder.Utility.GetDefinedValueId(formSettings.PersonEntry.CampusStatus); actionForm.PersonEntryCampusTypeValueId = Rock.Blocks.WorkFlow.FormBuilder.Utility.GetDefinedValueId(formSettings.PersonEntry.CampusType); actionForm.PersonEntryConnectionStatusValueId = Rock.Blocks.WorkFlow.FormBuilder.Utility.GetDefinedValueId(formSettings.PersonEntry.ConnectionStatus); actionForm.PersonEntryEmailEntryOption = formSettings.PersonEntry.Email.ToPersonEntryOption(); actionForm.PersonEntryGenderEntryOption = formSettings.PersonEntry.Gender.ToPersonEntryOption(); actionForm.PersonEntryHideIfCurrentPersonKnown = formSettings.PersonEntry.HideIfCurrentPersonKnown; actionForm.PersonEntryMaritalStatusEntryOption = formSettings.PersonEntry.MaritalStatus.ToPersonEntryOption(); actionForm.PersonEntryMobilePhoneEntryOption = formSettings.PersonEntry.MobilePhone.ToPersonEntryOption(); actionForm.PersonEntryRecordStatusValueId = Rock.Blocks.WorkFlow.FormBuilder.Utility.GetDefinedValueId(formSettings.PersonEntry.RecordStatus); actionForm.PersonEntryCampusIsVisible = formSettings.PersonEntry.ShowCampus; actionForm.PersonEntrySpouseEntryOption = formSettings.PersonEntry.SpouseEntry.ToPersonEntryOption(); actionForm.PersonEntrySpouseLabel = formSettings.PersonEntry.SpouseLabel; } UpdateFormSections(formSettings, actionForm, workflowType, rockContext); // Update the workflow type properties. workflowType.Name = formSettings.General.Name.Trim(); workflowType.Description = formSettings.General.Description.Trim(); workflowType.FormStartDateTime = formSettings.General.EntryStarts?.DateTime; workflowType.FormEndDateTime = formSettings.General.EntryEnds?.DateTime; workflowType.IsLoginRequired = formSettings.General.IsLoginRequired; workflowType.CategoryId = CategoryCache.GetId(formSettings.General.Category.Value.AsGuid()).Value; // Update the workflow type form template. if (formSettings.General.Template.HasValue) { workflowType.FormBuilderTemplateId = new WorkflowFormBuilderTemplateService(rockContext) .GetId(formSettings.General.Template.Value); } else { workflowType.FormBuilderTemplateId = null; } // Update the settings stored in the JSON blob. var settings = workflowType.FormBuilderSettingsJson.FromJsonOrNull <Rock.Workflow.FormBuilder.FormSettings>() ?? new Rock.Workflow.FormBuilder.FormSettings(); settings.CompletionAction = formSettings.Completion.FromViewModel(); settings.ConfirmationEmail = formSettings.ConfirmationEmail.FromViewModel(rockContext); settings.NotificationEmail = formSettings.NotificationEmail.FromViewModel(rockContext); settings.CampusSetFrom = formSettings.CampusSetFrom?.FromViewModel(); workflowType.FormBuilderSettingsJson = settings.ToJson(); }
/// <summary> /// Gets the list of view models that represent all the sections and fields /// of a form. /// </summary> /// <param name="actionForm">The <see cref="WorkflowActionForm"/> to be represented.</param> /// <returns>A collection of view models that represent that sections that will be edited.</returns> private static List <FormSectionViewModel> GetFormSectionViewModels(WorkflowActionForm actionForm) { var sectionViewModels = new List <FormSectionViewModel>(); foreach (var workflowFormSection in actionForm.FormSections.OrderBy(s => s.Order)) { // Create the basic section view model. var sectionViewModel = new FormSectionViewModel { Guid = workflowFormSection.Guid, Description = workflowFormSection.Description, Fields = new List <FormFieldViewModel>(), ShowHeadingSeparator = workflowFormSection.ShowHeadingSeparator, Title = workflowFormSection.Title, Type = Rock.Blocks.WorkFlow.FormBuilder.Utility.GetDefinedValueGuid(workflowFormSection.SectionTypeValueId), VisibilityRule = workflowFormSection.SectionVisibilityRules?.ToViewModel() }; // Get all the form attributes for this section. var formAttributes = actionForm.FormAttributes .Where(a => a.ActionFormSectionId == workflowFormSection.Id) .ToList(); // Loop through each form attribute and make a view model out of it. foreach (var formAttribute in formAttributes.OrderBy(a => a.Order)) { var attribute = AttributeCache.Get(formAttribute.AttributeId); var fieldType = FieldTypeCache.Get(attribute.FieldTypeId); if (fieldType == null || fieldType.Field == null) { continue; } sectionViewModel.Fields.Add(new FormFieldViewModel { ConfigurationValues = fieldType.Field.GetPublicConfigurationValues(attribute.ConfigurationValues, Field.ConfigurationValueUsage.Configure, null), DefaultValue = fieldType.Field.GetPublicEditValue(attribute.DefaultValue, attribute.ConfigurationValues), Description = attribute.Description, FieldTypeGuid = fieldType.Guid, Guid = attribute.Guid, IsHideLabel = formAttribute.HideLabel, IsRequired = attribute.IsRequired, IsShowOnGrid = attribute.IsGridColumn, Key = attribute.Key, Name = attribute.Name, Size = formAttribute.ColumnSize ?? 12, VisibilityRule = formAttribute.FieldVisibilityRules?.ToViewModel() }); } sectionViewModels.Add(sectionViewModel); } return(sectionViewModels); }
/// <summary> /// /// </summary> /// <returns></returns> private static WorkflowActionForm CreateNewWorkflowForm() { var workflowActionForm = new WorkflowActionForm(); workflowActionForm.PersonEntryConnectionStatusValueId = DefinedValueCache.GetId(Rock.SystemGuid.DefinedValue.PERSON_CONNECTION_STATUS_VISITOR.AsGuid()); workflowActionForm.PersonEntryRecordStatusValueId = DefinedValueCache.GetId(Rock.SystemGuid.DefinedValue.PERSON_RECORD_STATUS_PENDING.AsGuid()); workflowActionForm.PersonEntryGroupLocationTypeValueId = DefinedValueCache.GetId(Rock.SystemGuid.DefinedValue.GROUP_LOCATION_TYPE_HOME.AsGuid()); workflowActionForm.Actions = "Submit^^^Your information has been submitted successfully."; var systemEmail = new SystemCommunicationService(new RockContext()).Get(SystemGuid.SystemCommunication.WORKFLOW_FORM_NOTIFICATION.AsGuid()); if (systemEmail != null) { workflowActionForm.NotificationSystemCommunicationId = systemEmail.Id; } return(workflowActionForm); }
/// <summary> /// Gets the view model that represents a workflow form builder form in /// its entirety. /// </summary> /// <param name="actionForm">The <see cref="WorkflowActionForm"/> to be represented by the view model.</param> /// <param name="workflowType">The <see cref="WorkflowType"/> to be represented by the view model.</param> /// <param name="rockContext">The database context used for data lookup.</param> /// <returns>A view model that represents the form.</returns> private static FormSettingsViewModel GetFormSettingsViewModel(WorkflowActionForm actionForm, WorkflowType workflowType, RockContext rockContext) { var settings = workflowType.FormBuilderSettingsJson.FromJsonOrNull <Rock.Workflow.FormBuilder.FormSettings>(); var form = new FormSettingsViewModel { HeaderContent = actionForm.Header, FooterContent = actionForm.Footer, General = GetFormGeneralViewModel(workflowType), Sections = GetFormSectionViewModels(actionForm), ConfirmationEmail = settings?.ConfirmationEmail.ToViewModel(rockContext), NotificationEmail = settings?.NotificationEmail.ToViewModel(rockContext), Completion = settings?.CompletionAction.ToViewModel(), CampusSetFrom = settings?.CampusSetFrom?.ToViewModel() }; // Build the person entry settings. if (actionForm.AllowPersonEntry) { form.AllowPersonEntry = true; form.PersonEntry = new FormPersonEntryViewModel { Address = actionForm.PersonEntryAddressEntryOption.ToFormFieldVisibility(), AddressType = Rock.Blocks.WorkFlow.FormBuilder.Utility.GetDefinedValueGuid(actionForm.PersonEntryGroupLocationTypeValueId), AutofillCurrentPerson = actionForm.PersonEntryAutofillCurrentPerson, Birthdate = actionForm.PersonEntryBirthdateEntryOption.ToFormFieldVisibility(), CampusStatus = Rock.Blocks.WorkFlow.FormBuilder.Utility.GetDefinedValueGuid(actionForm.PersonEntryCampusStatusValueId), CampusType = Rock.Blocks.WorkFlow.FormBuilder.Utility.GetDefinedValueGuid(actionForm.PersonEntryCampusTypeValueId), ConnectionStatus = Rock.Blocks.WorkFlow.FormBuilder.Utility.GetDefinedValueGuid(actionForm.PersonEntryConnectionStatusValueId), Email = actionForm.PersonEntryEmailEntryOption.ToFormFieldVisibility(), Gender = actionForm.PersonEntryGenderEntryOption.ToFormFieldVisibility(), HideIfCurrentPersonKnown = actionForm.PersonEntryHideIfCurrentPersonKnown, MaritalStatus = actionForm.PersonEntryMaritalStatusEntryOption.ToFormFieldVisibility(), MobilePhone = actionForm.PersonEntryMobilePhoneEntryOption.ToFormFieldVisibility(), RecordStatus = Rock.Blocks.WorkFlow.FormBuilder.Utility.GetDefinedValueGuid(actionForm.PersonEntryRecordStatusValueId), ShowCampus = actionForm.PersonEntryCampusIsVisible, SpouseEntry = actionForm.PersonEntrySpouseEntryOption.ToFormFieldVisibility(), SpouseLabel = actionForm.PersonEntrySpouseLabel }; } return(form); }
/// <summary> /// Gets or sets the form. /// </summary> /// <value> /// The form. /// </value> public WorkflowActionForm GetForm() { EnsureChildControls(); var form = new WorkflowActionForm(); form.Guid = _hfFormGuid.Value.AsGuid(); if (form.Guid != Guid.Empty) { form.NotificationSystemEmailId = _ddlNotificationSystemEmail.SelectedValueAsId(); form.IncludeActionsInNotification = _cbIncludeActions.Checked; form.Header = _ceHeaderText.Text; form.Footer = _ceFooterText.Text; form.Actions = _falActions.Value; form.AllowNotes = _cbAllowNotes.Checked; foreach (var row in AttributeRows) { var formAttribute = new WorkflowActionFormAttribute(); formAttribute.Attribute = new Rock.Model.Attribute { Guid = row.AttributeGuid, Name = row.AttributeName }; formAttribute.Guid = row.Guid; formAttribute.Order = row.Order; formAttribute.IsVisible = row.IsVisible; formAttribute.IsReadOnly = !row.IsEditable; formAttribute.IsRequired = row.IsRequired; formAttribute.HideLabel = row.HideLabel; formAttribute.PreHtml = row.PreHtml; formAttribute.PostHtml = row.PostHtml; form.FormAttributes.Add(formAttribute); } form.ActionAttributeGuid = _ddlActionAttribute.SelectedValueAsGuid(); return(form); } return(null); }
/// <summary> /// Sets the form. /// </summary> /// <param name="value">The value.</param> /// <param name="workflowTypeAttributes">The workflow type attributes.</param> public void SetForm( WorkflowActionForm value, Dictionary<Guid, Rock.Model.Attribute> workflowTypeAttributes ) { EnsureChildControls(); if ( value != null ) { _hfFormGuid.Value = value.Guid.ToString(); _ddlNotificationSystemEmail.SetValue( value.NotificationSystemEmailId ); _cbIncludeActions.Checked = value.IncludeActionsInNotification; _ceHeaderText.Text = value.Header; _ceFooterText.Text = value.Footer; _falActions.Value = value.Actions; // Remove any existing rows (shouldn't be any) foreach ( var attributeRow in Controls.OfType<WorkflowFormAttributeRow>() ) { Controls.Remove( attributeRow ); } foreach ( var formAttribute in value.FormAttributes.OrderBy( a => a.Order ) ) { var row = new WorkflowFormAttributeRow(); row.AttributeGuid = formAttribute.Attribute.Guid; row.AttributeName = formAttribute.Attribute.Name; row.Guid = formAttribute.Guid; row.IsVisible = formAttribute.IsVisible; row.IsEditable = !formAttribute.IsReadOnly; row.IsRequired = formAttribute.IsRequired; Controls.Add( row ); } _ddlActionAttribute.Items.Clear(); _ddlActionAttribute.Items.Add( new ListItem() ); foreach ( var attributeItem in workflowTypeAttributes ) { var fieldType = FieldTypeCache.Read( attributeItem.Value.FieldTypeId ); if ( fieldType != null && fieldType.Field is Rock.Field.Types.TextFieldType ) { var li = new ListItem( attributeItem.Value.Name, attributeItem.Key.ToString() ); li.Selected = value.ActionAttributeGuid.HasValue && value.ActionAttributeGuid.Value.ToString() == li.Value; _ddlActionAttribute.Items.Add( li ); } } } else { _hfFormGuid.Value = string.Empty; _ddlNotificationSystemEmail.SelectedIndex = 0; _cbIncludeActions.Checked = true; _ceHeaderText.Text = string.Empty; _ceFooterText.Text = string.Empty; _falActions.Value = "Submit^^^Your information has been submitted successfully."; _ddlNotificationSystemEmail.SelectedIndex = 0; } }
/// <summary> /// Adds a new form field or updates an existing form field in the form. /// This will also handle creating the attribute if a new form field must /// be created. /// </summary> /// <param name="actionForm">The <see cref="WorkflowActionForm"/> being updated.</param> /// <param name="workflowType">The <see cref="WorkflowType"/> being updated.</param> /// <param name="attributeService">The database service that provides access to attributes.</param> /// <param name="formAttributeService">The database service that provides access to form attributes.</param> /// <param name="formSection">The <see cref="WorkflowActionFormSection"/> being updated.</param> /// <param name="field">The field view model that contains the source information.</param> /// <param name="nextAttributeOrder">The next attribute Order value to use when adding a new attribute.</param> /// <returns>The <see cref="WorkflowActionFormAttribute"/> that was either created or updated.</returns> private static WorkflowActionFormAttribute AddOrUpdateFormField(WorkflowActionForm actionForm, WorkflowType workflowType, AttributeService attributeService, WorkflowActionFormAttributeService formAttributeService, WorkflowActionFormSection formSection, FormFieldViewModel field, List <FormFieldViewModel> formFields, ref int nextAttributeOrder) { var fieldType = FieldTypeCache.Get(field.FieldTypeGuid); // If the field type or its C# component could not be found then // we abort with a hard error. We need it to convert data. if (fieldType == null || fieldType.Field == null) { throw new Exception($"Field type '{field.FieldTypeGuid}' not found."); } var formField = actionForm.FormAttributes.FirstOrDefault(a => a.Attribute.Guid == field.Guid); // If the form field was not found then create a new attribute and // new form field. if (formField == null) { var attribute = new Rock.Model.Attribute { Guid = field.Guid, EntityTypeId = EntityTypeCache.Get <Rock.Model.Workflow>().Id, EntityTypeQualifierColumn = nameof(Rock.Model.Workflow.WorkflowTypeId), EntityTypeQualifierValue = workflowType.Id.ToString(), FieldTypeId = fieldType.Id, IsSystem = true, Order = nextAttributeOrder++ }; formField = new WorkflowActionFormAttribute { Attribute = attribute }; actionForm.FormAttributes.Add(formField); attributeService.Add(attribute); formAttributeService.Add(formField); } // Convert the attribute configuration into values that can be stored // in the database. var configurationValues = fieldType.Field.GetPrivateConfigurationValues(field.ConfigurationValues); // Update all the standard properties. formField.ActionFormSection = formSection; formField.Attribute.DefaultValue = fieldType.Field.GetPrivateEditValue(field.DefaultValue, configurationValues); formField.Attribute.Description = field.Description; formField.Attribute.IsRequired = field.IsRequired; formField.IsRequired = field.IsRequired; formField.Attribute.IsGridColumn = field.IsShowOnGrid; formField.Attribute.Key = field.Key; formField.Attribute.Name = field.Name; formField.ColumnSize = field.Size; formField.IsVisible = true; formField.HideLabel = field.IsHideLabel; formField.FieldVisibilityRules = field.VisibilityRule?.FromViewModel(formFields); // Add or update the attribute qualifiers. Do not delete any old ones. foreach (var kvp in configurationValues) { var qualifier = formField.Attribute.AttributeQualifiers.FirstOrDefault(q => q.Key == kvp.Key); if (qualifier == null) { formField.Attribute.AttributeQualifiers.Add(new AttributeQualifier { IsSystem = false, Key = kvp.Key, Value = kvp.Value ?? string.Empty }); } else { qualifier.Value = kvp.Value ?? string.Empty; } } return(formField); }
/// <summary> /// Handles logic for updating all the form sections as well as attributes. /// This will create any new items and delete any removed items as well. /// </summary> /// <param name="formSettings">The form settings that contain all the configuration information.</param> /// <param name="actionForm">The <see cref="WorkflowActionForm"/> entity being updated.</param> /// <param name="workflowType">The <see cref="WorkflowType"/> that is being updated.</param> /// <param name="rockContext">The database context to operate in.</param> private static void UpdateFormSections(FormSettingsViewModel formSettings, WorkflowActionForm actionForm, WorkflowType workflowType, RockContext rockContext) { var attributeService = new AttributeService(rockContext); var formAttributeService = new WorkflowActionFormAttributeService(rockContext); var formSectionService = new WorkflowActionFormSectionService(rockContext); var nextAttributeOrder = actionForm.FormAttributes != null && actionForm.FormAttributes.Any() ? actionForm.FormAttributes.Select(a => a.Order).Max() + 1 : 0; if (formSettings.Sections != null) { // Get all the section identifiers that are sticking around. var allValidSectionGuids = formSettings.Sections .Select(s => s.Guid) .ToList(); // Get all the attribute identifiers that are sticking around. var allValidAttributeGuids = formSettings.Sections .SelectMany(s => s.Fields) .Select(f => f.Guid) .ToList(); // Find all sections that no longer exist in this form. var sectionsToDelete = actionForm.FormSections .Where(s => !allValidSectionGuids.Contains(s.Guid)) .ToList(); // Find all form attributes that no longer exist in this form. var formAttributesToDelete = actionForm.FormAttributes .Where(a => !allValidAttributeGuids.Contains(a.Attribute.Guid)) .ToList(); var allFormFields = formSettings.Sections.SelectMany(s => s.Fields).ToList(); // Delete all sections that no longer exist in this form. sectionsToDelete.ForEach(s => { formSectionService.Delete(s); }); // Delete all form attributes that no longer exist in this form. formAttributesToDelete.ForEach(a => { if (a.Attribute.IsSystem) { attributeService.Delete(a.Attribute); } formAttributeService.Delete(a); }); // Loop through all sections that need to be either added or updated. for (int sectionOrder = 0; sectionOrder < formSettings.Sections.Count; sectionOrder++) { var section = formSettings.Sections[sectionOrder]; var formSection = AddOrUpdateFormSection(actionForm, workflowType, attributeService, formAttributeService, formSectionService, section, allFormFields, ref nextAttributeOrder); formSection.Order = sectionOrder; } } else { // Remove all form attributes and sections. var nonUserAttributes = actionForm.FormAttributes .Select(a => a.Attribute) .Where(a => a.IsSystem) .ToList(); attributeService.DeleteRange(nonUserAttributes); formAttributeService.DeleteRange(actionForm.FormAttributes); formSectionService.DeleteRange(actionForm.FormSections); } }