Skip to content

Commit

Permalink
C2T UI (#207)
Browse files Browse the repository at this point in the history
* Creating C2T form

* Typo fix

* Adds section 10

* Adds remaining questions

* Validation for section 10

* radio button and validation update

* Adds turbo

* Add dropdowns to beginning of form

* Add dynamic change on modality

* progress commit

* displays unobtrusive validation on dynamic form change

* Add turbo stream to display validation errors

* Remove turbo cdn from layout

* Remove Mode and RMMode inputs on partial

* Adjusts data annotations

* Adds javascript file and updates stimulus

* Fix for small js bug

* Update views and js

* Making the linter happy?

* Linter round 2

* remove script tags in partials

* correct enum dropdown

* add custom jquery validation to partials

* Add data annotation for telephone/in-person

* Update validation

* remove rmmode label on C2

* Add/maps missing properties

* Using rowCSS variable in views

* fix typo

* cleaning things up

* adds tailwind border around section headers

* additional tailwind styling

* Add info alert to top of page

* Additional validation

* Turn off Turbo for participation create

* Formatted instructions

* Fixes MOCATOS validation

* Update dependencies

* Bump version number

---------

Co-authored-by: Ashley Wilson <[email protected]>
  • Loading branch information
Oddvocado and ashleybot authored Nov 7, 2024
1 parent efc2829 commit f85859b
Show file tree
Hide file tree
Showing 25 changed files with 3,775 additions and 1,843 deletions.
2 changes: 1 addition & 1 deletion src/UDS.Net.Forms.Tests/UDS.Net.Forms.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<ReleaseVersion>4.1.3</ReleaseVersion>
<ReleaseVersion>4.2.0</ReleaseVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UDS.Net.Forms.Models;
using UDS.Net.Services.Enums;

namespace UDS.Net.Forms.DataAnnotations
{
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class RequiredIfInPersonVisitAttribute : ValidationAttribute, IClientModelValidator
{
private string _watchedField = "";
private string _watchedFieldValue = "";

public RequiredIfInPersonVisitAttribute(string watchedField, string value) : base()
{
_watchedField = watchedField;
_watchedFieldValue = value;
}
protected override ValidationResult? IsValid(object? value, ValidationContext validationContext)
{
// does the form have a status and is it attempting to be finalized?
if (validationContext.ObjectType.IsSubclassOf(typeof(FormModel)))
{
var form = (FormModel)validationContext.ObjectInstance;

// only validate if the form is attempting to be completed
if (form.Status == FormStatus.Finalized)

if (form.MODE == FormMode.InPerson || form.RMMODE == RemoteModality.Video)
{
// get the watched property and compare
var type = validationContext.ObjectType;

if (type != null)
{
var watchedProperty = type.GetProperty(_watchedField);

if (watchedProperty != null)
{
var currentValue = watchedProperty.GetValue(validationContext.ObjectInstance, null);
if (currentValue != null)
{
if (currentValue.ToString() == _watchedFieldValue)
{
// if the watched field's value matches what we're looking for then this field requires a value
if (value == null)
return new ValidationResult(this.ErrorMessage);
}
}
}
}
}
}


return ValidationResult.Success;
}

public void AddValidation(ClientModelValidationContext context)
{
MergeAttribute(context.Attributes, "data-val", "true");
MergeAttribute(context.Attributes, "data-val-requiredif", this.ErrorMessage);
string watched = _watchedField;
var containerName = context.ModelMetadata.ContainerType.Name;
if (!String.IsNullOrEmpty(containerName))
{
watched = containerName + "." + _watchedField;
}
MergeAttribute(context.Attributes, "data-val-requiredif-watchedfield", watched);
MergeAttribute(context.Attributes, "data-val-requiredif-watchedfieldvalue", _watchedFieldValue);
}

/// <summary>
/// See https://learn.microsoft.com/en-us/aspnet/core/mvc/models/validation?view=aspnetcore-7.0#iclientmodelvalidator-for-client-side-validation
/// </summary>
private static bool MergeAttribute(IDictionary<string, string> attributes, string key, string value)
{
if (attributes.ContainsKey(key))
{
return false;
}

attributes.Add(key, value);
return true;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UDS.Net.Forms.Models;
using UDS.Net.Services.Enums;

namespace UDS.Net.Forms.DataAnnotations
{
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class RequiredIfTelephoneVisitAttribute : ValidationAttribute, IClientModelValidator
{
private string _watchedField = "";
private string _watchedFieldValue = "";

public RequiredIfTelephoneVisitAttribute(string watchedField, string value) : base()
{
_watchedField = watchedField;
_watchedFieldValue = value;
}
protected override ValidationResult? IsValid(object? value, ValidationContext validationContext)
{
// does the form have a status and is it attempting to be finalized?
if (validationContext.ObjectType.IsSubclassOf(typeof(FormModel)))
{
var form = (FormModel)validationContext.ObjectInstance;

// only validate if the form is attempting to be completed
if (form.Status == FormStatus.Finalized && form.RMMODE == RemoteModality.Telephone)
{
// get the watched property and compare
var type = validationContext.ObjectType;

if (type != null)
{
var watchedProperty = type.GetProperty(_watchedField);

if (watchedProperty != null)
{
var currentValue = watchedProperty.GetValue(validationContext.ObjectInstance, null);
if (currentValue != null)
{
if (currentValue.ToString() == _watchedFieldValue)
{
// if the watched field's value matches what we're looking for then this field requires a value
if (value == null)
return new ValidationResult(this.ErrorMessage);
}
}
}
}
}
}


return ValidationResult.Success;
}

public void AddValidation(ClientModelValidationContext context)
{
MergeAttribute(context.Attributes, "data-val", "true");
MergeAttribute(context.Attributes, "data-val-requiredif", this.ErrorMessage);
string watched = _watchedField;
var containerName = context.ModelMetadata.ContainerType.Name;
if (!String.IsNullOrEmpty(containerName))
{
watched = containerName + "." + _watchedField;
}
MergeAttribute(context.Attributes, "data-val-requiredif-watchedfield", watched);
MergeAttribute(context.Attributes, "data-val-requiredif-watchedfieldvalue", _watchedFieldValue);
}

/// <summary>
/// See https://learn.microsoft.com/en-us/aspnet/core/mvc/models/validation?view=aspnetcore-7.0#iclientmodelvalidator-for-client-side-validation
/// </summary>
private static bool MergeAttribute(IDictionary<string, string> attributes, string key, string value)
{
if (attributes.ContainsKey(key))
{
return false;
}

attributes.Add(key, value);
return true;
}
}
}
7 changes: 7 additions & 0 deletions src/UDS.Net.Forms/Extensions/DomainToViewModelMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1257,6 +1257,7 @@ public static C2 ToVM(this C2FormFields fields, int formId)
MOCAVIS = fields.MOCAVIS,
MOCAHEAR = fields.MOCAHEAR,
MOCATOTS = fields.MOCATOTS,
MOCBTOTS = fields.MOCBTOTS,
MOCATRAI = fields.MOCATRAI,
MOCACUBE = fields.MOCACUBE,
MOCACLOC = fields.MOCACLOC,
Expand Down Expand Up @@ -1354,6 +1355,12 @@ public static C2 ToVM(this C2FormFields fields, int formId)
CERADJ6INT = fields.CERADJ6INT,
CERADJ7YES = fields.CERADJ7YES,
CERADJ7NO = fields.CERADJ7NO,
OTRAILA = fields.OTRAILA,
OTRLARR = fields.OTRLARR,
OTRLALI = fields.OTRLALI,
OTRAILB = fields.OTRAILB,
OTRLBRR = fields.OTRLBRR,
OTRLBLI = fields.OTRLBLI,
VNTTOTW = fields.VNTTOTW,
VNTPCNC = fields.VNTPCNC,
RESPVAL = fields.RESPVAL,
Expand Down
7 changes: 7 additions & 0 deletions src/UDS.Net.Forms/Extensions/ViewModelToDomainMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -942,6 +942,7 @@ public static IFormFields GetFormFields(this C2 vm)
MOCAVIS = vm.MOCAVIS,
MOCAHEAR = vm.MOCAHEAR,
MOCATOTS = vm.MOCATOTS,
MOCBTOTS = vm.MOCBTOTS,
MOCATRAI = vm.MOCATRAI,
MOCACUBE = vm.MOCACUBE,
MOCACLOC = vm.MOCACLOC,
Expand Down Expand Up @@ -1039,6 +1040,12 @@ public static IFormFields GetFormFields(this C2 vm)
CERADJ6INT = vm.CERADJ6INT,
CERADJ7YES = vm.CERADJ7YES,
CERADJ7NO = vm.CERADJ7NO,
OTRAILA = vm.OTRAILA,
OTRLARR = vm.OTRLARR,
OTRLALI = vm.OTRLALI,
OTRAILB = vm.OTRAILB,
OTRLBRR = vm.OTRLBRR,
OTRLBLI = vm.OTRLBLI,
VNTTOTW = vm.VNTTOTW,
VNTPCNC = vm.VNTPCNC,
RESPVAL = vm.RESPVAL,
Expand Down
20 changes: 20 additions & 0 deletions src/UDS.Net.Forms/Models/PageModels/FormPageModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,26 @@ protected async Task<IActionResult> OnPostAsync(int id)

Visit = visit.ToVM();

if (BaseForm.Kind == "C2")
{
if (BaseForm != null)
{
var C2 = new C2Model(_visitService);

C2.Visit = Visit;
C2.BaseForm = BaseForm;
C2.C2 = (C2)BaseForm;

var form = visit.Forms.Where(f => f.Kind == _formKind).FirstOrDefault();

if (!ModelState.IsValid)
{
Response.ContentType = "text/vnd.turbo-stream.html";
return Partial("_C2Validation", C2);
}
};
}

return Page();
}

Expand Down
Loading

0 comments on commit f85859b

Please sign in to comment.