v1.3.0 Restructure Saxonite workspace and upgrade to .NET 10 (#1)

Move Saxonite’s projects into a dedicated `Workspace` folder and align the solution with .NET 10 and the current Common workspace. Update encryption integration, test project structure and coverage, and repository guidance and upgrade notes.

- Relocate application and library projects while retaining Git rename history.
- Split tests into Admin, Online, and Shared projects; add representative behavioral and serialization tests.
- Update Common integration, application version, and repository documentation.

Application version: 1.3.0

Reviewed-on: #1
Co-authored-by: andy <andy@sarand.com>
This commit was merged in pull request #1.
This commit is contained in:
2026-10-16 18:24:16 +01:00
committed by andy
parent 2c3fb146ab
commit 9f22b522df
1996 changed files with 1992 additions and 1179 deletions
@@ -0,0 +1,66 @@
@model Model_Security
@inject SaxLocaliser Localiser
@{
ViewData["Title"] = "Change Password";
}
<div class="">
<div class="sax-panel-form security">
<div class="sax-header"><div class="sax-caption">@Localiser["security.caption.change.password"]</div></div>
<div class="sax-content">
<div class="spacer4"></div>
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmChangePassword", @class = "sax-form", @onsubmit = "return false;" }))
{
@if (!Model.RequestPasswordMode)
{
/* Current password - required when setting password within user session. */
<div class="sax-form-control PasswordCurrent">
<div class="sax-label"><label for="ifPasswordCurrent"><span><span class="required">*</span> @Localiser["label.password.current"]</span></label></div>
<div class="sax-control">
@Html.PasswordFor(model => model.PasswordCurrent, new { @id = "ifPasswordCurrent", @class = "sax-input", @maxlength = Model.PasswordMaxLength })
</div>
<div class="sax-message"></div>
</div>
}
else
{
/* 'Request Password' encrypted parameters from email link. */
@Html.HiddenFor(model => model.rpe, new { @id = "ifRpe" });
}
<div class="spacer4"></div>
<div class="sax-form-control Password">
<div class="sax-label"><label for="ifPassword"><span><span class="required">*</span> @Localiser["label.password"]</span></label></div>
<div class="sax-control">
@Html.PasswordFor(model => model.Password, new { @id = "ifPassword", @class = "sax-input", @maxlength = Model.PasswordMaxLength })
</div>
<div class="row">
<div class="col-auto sax-label-text pt4">@Localiser["label.strength"]&nbsp;</div>
<div id="" class="col-auto"><div id="prgPasswordStrength" class="col-auto"></div></div>
</div>
<div class="sax-message"></div>
</div>
<div class="sax-form-control PasswordConfirm">
<div class="sax-label"><label for="ifPasswordConfirm"><span><span class="required">*</span> @Localiser["label.password.confirm"]</span></label></div>
<div class="sax-control">
@Html.PasswordFor(model => model.PasswordConfirm, new { @id = "ifPasswordConfirm", @class = "sax-input", @maxlength = Model.PasswordMaxLength })
</div>
<div class="sax-message"></div>
</div>
<div class="spacer4"></div>
<div class="">
<div id="pbChangePassword" class="sax-button-action fullwidth pointer" style="margin:16px 0;">@Localiser["security.caption.change.password"]</div>
</div>
}
</div>
</div>
</div>
@@ -0,0 +1,37 @@
@model Model_Security
@inject SaxLocaliser Localiser
@{
ViewData["Title"] = "Request Password";
}
<div class="">
<div class="sax-panel-form security">
<div class="sax-header"><div class="sax-caption">@Localiser["security.caption.request.password"]</div></div>
<div class="sax-content">
<div class="spacer4"></div>
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmRequestPassword", @class = "sax-form", @onsubmit = "return false;" }))
{
<div class="sax-form-control EmailAddress">
<div class="sax-label">
<label for="ifEmailAddress"><span><span class="required">*</span> @Localiser["label.email.address"]</span></label>
</div>
<div class="sax-control">
@Html.TextBoxFor(model => model.EmailAddress, new { @id = "ifEmailAddress", @class = "sax-input lower", @maxlength = "128" })
</div>
<div class="sax-message"></div>
</div>
<div class="spacer4"></div>
<div class="">
<div id="pbRequestPassword" class="sax-button-action fullwidth pointer" style="margin:16px 0;">@Localiser["security.caption.request.password"]</div>
</div>
}
</div>
</div>
</div>
@@ -0,0 +1,62 @@
@model Model_Security
@inject SaxLocaliser Localiser
@{
ViewData["Title"] = "Signin";
}
<div class="">
<div class="sax-panel-form security">
<div class="sax-header"><div class="sax-caption">@Localiser["security.caption.signin"]</div></div>
<div class="sax-content">
<div class="spacer4"></div>
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmSignIn", @class = "sax-form", @onsubmit = "return false;" }))
{
<div class="sax-form-control EmailAddress">
<div class="sax-label">
<label for="ifEmailAddress"><span><span class="required">*</span> @Localiser["label.email.address"]</span></label>
</div>
<div class="sax-control">
@Html.TextBoxFor(model => model.EmailAddress, new { @id = "ifEmailAddress", @class = "sax-input lower", @maxlength = @Model.GetControlMaxLength(SaxDbDfn_Core.ColumnIdx.UserAccount_EmailAddress) })
</div>
<div class="sax-message"></div>
</div>
<div class="spacer2"></div>
<div class="sax-form-control Password">
<div class="sax-label">
<label for="ifPassword"><span><span class="required">*</span> @Localiser["label.password"]</span></label>
</div>
<div class="sax-control">
@Html.PasswordFor(model => model.Password, new { @id = "ifPassword", @class = "sax-input", @maxlength = @Model.PasswordMaxLength })
</div>
<div class="sax-message"></div>
</div>
<div class="spacer2"></div>
<div class="sax-form-control">
<div class="row">
<div class="col-6">
@Html.CheckBoxFor(model => model.KeepMeSignedIn, new { @id = "chkKeepMeSignedIn" })
&nbsp;
<span class="sax-label pointer" onclick="$('#chkKeepMeSignedIn').click()">@Localiser["label.keep.signed.in"]</span>
</div>
<div class="col-6 right">
<div class="sax-action-link" style="font-size:12px;" onclick="sax.goToPage('Security/RequestPassword');">@Localiser["label.forgotten.password"]</div>
</div>
</div>
</div>
<div class="spacer2"></div>
<div class="">
<div id="pbSignIn" class="sax-button-action fullwidth pointer" style="margin:16px 0;">@Localiser["security.caption.signin"]</div>
</div>
}
</div>
</div>
</div>