WIP user management
This commit is contained in:
parent
5feffbb068
commit
fed3ea2112
39 changed files with 373 additions and 245 deletions
|
@ -25,9 +25,9 @@
|
|||
<div class="list-group mt-2">
|
||||
<div class="list-group-item">
|
||||
<div class="row">
|
||||
<div class="col-sm-4" style="cursor: pointer;" @onclick="() => SortProducts(PSort.Desc)"><i class="bi-sort-alpha-down"></i> Navn <i class="bi-sort-alpha-up-alt"></i></div>
|
||||
<div class="col-sm-3" style="cursor: pointer;" @onclick="() => SortProducts(PSort.Sku)"><i class="bi-sort-alpha-down"></i> Varenr <i class="bi-sort-alpha-up-alt"></i></div>
|
||||
<div class="col-sm-2 text-center" style="cursor: pointer;" @onclick="() => SortProducts(PSort.Qty)"><i class="bi-sort-numeric-down"></i> Antal <i class="bi-sort-numeric-up-alt"></i></div>
|
||||
<div class="col-sm-4" style="cursor: pointer;" @onclick="() => SortProducts(ProductSort.Desc)"><i class="bi-sort-alpha-down"></i> Navn <i class="bi-sort-alpha-up-alt"></i></div>
|
||||
<div class="col-sm-3" style="cursor: pointer;" @onclick="() => SortProducts(ProductSort.Sku)"><i class="bi-sort-alpha-down"></i> Varenr <i class="bi-sort-alpha-up-alt"></i></div>
|
||||
<div class="col-sm-2 text-center" style="cursor: pointer;" @onclick="() => SortProducts(ProductSort.Qty)"><i class="bi-sort-numeric-down"></i> Antal <i class="bi-sort-numeric-up-alt"></i></div>
|
||||
<div class="col-sm-2"></div>
|
||||
<div class="col-sm-1"></div>
|
||||
</div>
|
||||
|
|
|
@ -37,12 +37,12 @@ public partial class CustomerInventoryListComponent
|
|||
if(Inventory.Any())
|
||||
Inventory = Inventory.OrderBy(x => x.Description).ToList();
|
||||
}
|
||||
private void SortProducts(PSort column)
|
||||
private void SortProducts(ProductSort column)
|
||||
{
|
||||
Descending = !Descending;
|
||||
switch (column)
|
||||
{
|
||||
case PSort.Desc:
|
||||
case ProductSort.Desc:
|
||||
if (Descending)
|
||||
{
|
||||
Inventory = Inventory.OrderByDescending(x => x.Description).ToList();
|
||||
|
@ -50,7 +50,7 @@ public partial class CustomerInventoryListComponent
|
|||
}
|
||||
Inventory = Inventory.OrderBy(x => x.Description).ToList();
|
||||
break;
|
||||
case PSort.Sku:
|
||||
case ProductSort.Sku:
|
||||
if (Descending)
|
||||
{
|
||||
Inventory = Inventory.OrderByDescending(x => x.Sku).ToList();
|
||||
|
@ -58,7 +58,7 @@ public partial class CustomerInventoryListComponent
|
|||
}
|
||||
Inventory = Inventory.OrderBy(x => x.Sku).ToList();
|
||||
break;
|
||||
case PSort.Qty:
|
||||
case ProductSort.Qty:
|
||||
if (Descending)
|
||||
{
|
||||
Inventory = Inventory.OrderByDescending(x => x.Quantity).ToList();
|
||||
|
@ -66,10 +66,10 @@ public partial class CustomerInventoryListComponent
|
|||
}
|
||||
Inventory = Inventory.OrderBy(x => x.Quantity).ToList();
|
||||
break;
|
||||
case PSort.None:
|
||||
case ProductSort.None:
|
||||
Inventory = Inventory.OrderBy(x => x.Description).ToList();
|
||||
break;
|
||||
case PSort.Abbr:
|
||||
case ProductSort.Abbr:
|
||||
break;
|
||||
default:
|
||||
Inventory = Inventory.OrderBy(x => x.Description).ToList();
|
||||
|
|
|
@ -24,9 +24,9 @@
|
|||
<div class="list-group mt-2">
|
||||
<div class="list-group-item">
|
||||
<div class="row">
|
||||
<div class="col-sm-4" style="cursor: pointer;" @onclick="() => SortProducts(PSort.Desc)"><i class="bi-sort-alpha-down"></i> Navn <i class="bi-sort-alpha-up-alt"></i></div>
|
||||
<div class="col-sm-3" style="cursor: pointer;" @onclick="() => SortProducts(PSort.Sku)"><i class="bi-sort-alpha-down"></i> Varenr <i class="bi-sort-alpha-up-alt"></i></div>
|
||||
<div class="col-sm-2 text-center" style="cursor: pointer;" @onclick="() => SortProducts(PSort.Qty)"><i class="bi-sort-numeric-down"></i> Antal <i class="bi-sort-numeric-up-alt"></i></div>
|
||||
<div class="col-sm-4" style="cursor: pointer;" @onclick="() => SortProducts(ProductSort.Desc)"><i class="bi-sort-alpha-down"></i> Navn <i class="bi-sort-alpha-up-alt"></i></div>
|
||||
<div class="col-sm-3" style="cursor: pointer;" @onclick="() => SortProducts(ProductSort.Sku)"><i class="bi-sort-alpha-down"></i> Varenr <i class="bi-sort-alpha-up-alt"></i></div>
|
||||
<div class="col-sm-2 text-center" style="cursor: pointer;" @onclick="() => SortProducts(ProductSort.Qty)"><i class="bi-sort-numeric-down"></i> Antal <i class="bi-sort-numeric-up-alt"></i></div>
|
||||
<div class="col-sm-2"></div>
|
||||
<div class="col-sm-1"></div>
|
||||
</div>
|
||||
|
|
|
@ -34,12 +34,12 @@ public partial class CustomerProductCheckListComponent
|
|||
Inventory = Inventory.OrderBy(x => x.Description).ToList();
|
||||
}
|
||||
|
||||
private void SortProducts(PSort column)
|
||||
private void SortProducts(ProductSort column)
|
||||
{
|
||||
Descending = !Descending;
|
||||
switch (column)
|
||||
{
|
||||
case PSort.Desc:
|
||||
case ProductSort.Desc:
|
||||
if (Descending)
|
||||
{
|
||||
Inventory = Inventory.OrderByDescending(x => x.Description).ToList();
|
||||
|
@ -47,7 +47,7 @@ public partial class CustomerProductCheckListComponent
|
|||
}
|
||||
Inventory = Inventory.OrderBy(x => x.Description).ToList();
|
||||
break;
|
||||
case PSort.Sku:
|
||||
case ProductSort.Sku:
|
||||
if (Descending)
|
||||
{
|
||||
Inventory = Inventory.OrderByDescending(x => x.Sku).ToList();
|
||||
|
@ -55,7 +55,7 @@ public partial class CustomerProductCheckListComponent
|
|||
}
|
||||
Inventory = Inventory.OrderBy(x => x.Sku).ToList();
|
||||
break;
|
||||
case PSort.Qty:
|
||||
case ProductSort.Qty:
|
||||
if (Descending)
|
||||
{
|
||||
Inventory = Inventory.OrderByDescending(x => x.Quantity).ToList();
|
||||
|
@ -63,9 +63,9 @@ public partial class CustomerProductCheckListComponent
|
|||
}
|
||||
Inventory = Inventory.OrderBy(x => x.Quantity).ToList();
|
||||
break;
|
||||
case PSort.None:
|
||||
case ProductSort.None:
|
||||
break;
|
||||
case PSort.Abbr:
|
||||
case ProductSort.Abbr:
|
||||
break;
|
||||
default:
|
||||
Inventory = Inventory.OrderByDescending(x => x.Quantity).ToList();
|
||||
|
|
|
@ -61,7 +61,7 @@ public partial class OfficeCountryCustomerListComponent
|
|||
private async Task ShowInvoiceList(string companyId)
|
||||
{
|
||||
// check for console manipulation
|
||||
if (!Utils.Validate(VType.Id, companyId)) return;
|
||||
if (!Utils.Validate(ValidateType.Id, companyId)) return;
|
||||
SelectedCompany = CompanyList.First(x => x.CompanyId == companyId);
|
||||
// call erp to crm sync before requesting invoices
|
||||
var newSyncDate = await HistoryRepo.RequestErpToCrmSync(CountryCode, companyId, SelectedCompany.HistorySync);
|
||||
|
@ -74,7 +74,7 @@ public partial class OfficeCountryCustomerListComponent
|
|||
private async Task ShowActivityList(string companyId)
|
||||
{
|
||||
// check for console manipulation
|
||||
if (!Utils.Validate(VType.Id, companyId)) return;
|
||||
if (!Utils.Validate(ValidateType.Id, companyId)) return;
|
||||
SelectedCompany = CompanyList.First(x => x.CompanyId == companyId);
|
||||
ActivityList = await ActivityRepo.RequestActivityList(companyId);
|
||||
ActivityListOverlay.Show();
|
||||
|
@ -83,7 +83,7 @@ public partial class OfficeCountryCustomerListComponent
|
|||
private async Task ShowInventory(string companyId)
|
||||
{
|
||||
// check for console manipulation
|
||||
if (!Utils.Validate(VType.Id, companyId)) return;
|
||||
if (!Utils.Validate(ValidateType.Id, companyId)) return;
|
||||
SelectedCompany = CompanyList.First(x => x.CompanyId == companyId);
|
||||
// call erp to crm sync before requesting products
|
||||
var newSyncDate = await HistoryRepo.RequestErpToCrmSync(CountryCode, companyId, SelectedCompany.HistorySync);
|
||||
|
@ -96,7 +96,7 @@ public partial class OfficeCountryCustomerListComponent
|
|||
private async Task ShowOrder(string companyId)
|
||||
{
|
||||
// check for console manipulation
|
||||
if (!Utils.Validate(VType.Id, companyId)) return;
|
||||
if (!Utils.Validate(ValidateType.Id, companyId)) return;
|
||||
SelectedCompany = CompanyList.First(x => x.CompanyId == companyId);
|
||||
}
|
||||
}
|
|
@ -25,9 +25,9 @@
|
|||
<div class="list-group mt-2">
|
||||
<div class="list-group-item">
|
||||
<div class="row">
|
||||
<div class="col-sm-4" style="cursor: pointer;" @onclick="() => SortProducts(PSort.Desc)"><i class="bi-sort-alpha-down"></i> Navn <i class="bi-sort-alpha-up-alt"></i></div>
|
||||
<div class="col-sm-3" style="cursor: pointer;" @onclick="() => SortProducts(PSort.Sku)"><i class="bi-sort-alpha-down"></i> Varenr <i class="bi-sort-alpha-up-alt"></i></div>
|
||||
<div class="col-sm-2 text-center" style="cursor: pointer;" @onclick="() => SortProducts(PSort.Qty)"><i class="bi-sort-numeric-down"></i> Antal <i class="bi-sort-numeric-up-alt"></i></div>
|
||||
<div class="col-sm-4" style="cursor: pointer;" @onclick="() => SortProducts(ProductSort.Desc)"><i class="bi-sort-alpha-down"></i> Navn <i class="bi-sort-alpha-up-alt"></i></div>
|
||||
<div class="col-sm-3" style="cursor: pointer;" @onclick="() => SortProducts(ProductSort.Sku)"><i class="bi-sort-alpha-down"></i> Varenr <i class="bi-sort-alpha-up-alt"></i></div>
|
||||
<div class="col-sm-2 text-center" style="cursor: pointer;" @onclick="() => SortProducts(ProductSort.Qty)"><i class="bi-sort-numeric-down"></i> Antal <i class="bi-sort-numeric-up-alt"></i></div>
|
||||
<div class="col-sm-2"></div>
|
||||
<div class="col-sm-1"></div>
|
||||
</div>
|
||||
|
|
|
@ -41,12 +41,12 @@ public partial class OfficeInventoryListComponent
|
|||
Inventory = Inventory.OrderBy(x => x.Description).ToList();
|
||||
}
|
||||
|
||||
private void SortProducts(PSort column)
|
||||
private void SortProducts(ProductSort column)
|
||||
{
|
||||
Descending = !Descending;
|
||||
switch (column)
|
||||
{
|
||||
case PSort.Desc:
|
||||
case ProductSort.Desc:
|
||||
if (Descending)
|
||||
{
|
||||
Inventory = Inventory.OrderByDescending(x => x.Description).ToList();
|
||||
|
@ -54,7 +54,7 @@ public partial class OfficeInventoryListComponent
|
|||
}
|
||||
Inventory = Inventory.OrderBy(x => x.Description).ToList();
|
||||
break;
|
||||
case PSort.Sku:
|
||||
case ProductSort.Sku:
|
||||
if (Descending)
|
||||
{
|
||||
Inventory = Inventory.OrderByDescending(x => x.Sku).ToList();
|
||||
|
@ -62,7 +62,7 @@ public partial class OfficeInventoryListComponent
|
|||
}
|
||||
Inventory = Inventory.OrderBy(x => x.Sku).ToList();
|
||||
break;
|
||||
case PSort.Qty:
|
||||
case ProductSort.Qty:
|
||||
if (Descending)
|
||||
{
|
||||
Inventory = Inventory.OrderByDescending(x => x.Quantity).ToList();
|
||||
|
@ -70,9 +70,9 @@ public partial class OfficeInventoryListComponent
|
|||
}
|
||||
Inventory = Inventory.OrderBy(x => x.Quantity).ToList();
|
||||
break;
|
||||
case PSort.None:
|
||||
case ProductSort.None:
|
||||
break;
|
||||
case PSort.Abbr:
|
||||
case ProductSort.Abbr:
|
||||
break;
|
||||
default:
|
||||
Inventory = Inventory.OrderByDescending(x => x.Quantity).ToList();
|
||||
|
|
|
@ -51,18 +51,18 @@
|
|||
@quote.OrderDate
|
||||
</div>
|
||||
<div class="col-sm-3">
|
||||
<button type="button" class="btn btn-outline-dark me-2" @onclick="() => SetQuote(quote.ESalesNumber, QStatus.Lose)">
|
||||
<button type="button" class="btn btn-outline-dark me-2" @onclick="() => SetQuote(quote.ESalesNumber, QuoteStatus.Lose)">
|
||||
<i class="bi-trash-fill"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-dark me-2" @onclick="() => SetQuote(quote.ESalesNumber, QStatus.Archive)">
|
||||
<button type="button" class="btn btn-outline-dark me-2" @onclick="() => SetQuote(quote.ESalesNumber, QuoteStatus.Archive)">
|
||||
<i class="bi-archive-fill"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-dark me-2" @onclick="() => SetQuote(quote.ESalesNumber, QStatus.Note)">
|
||||
<button type="button" class="btn btn-outline-dark me-2" @onclick="() => SetQuote(quote.ESalesNumber, QuoteStatus.Note)">
|
||||
<i class="bi-tag-fill"></i>
|
||||
</button>
|
||||
@if (quote.QuoteStatusEnum == "None")
|
||||
{
|
||||
<button type="button" class="btn btn-success" @onclick="() => SetQuote(quote.ESalesNumber, QStatus.Win)">
|
||||
<button type="button" class="btn btn-success" @onclick="() => SetQuote(quote.ESalesNumber, QuoteStatus.Order)">
|
||||
<i class="bi-cart-fill"></i>
|
||||
</button>
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ public partial class QuoteListComponent
|
|||
public List<ReportItemView> Quotes { get; set; } = new();
|
||||
[Parameter] public EventCallback<QuoteCallbackArgs> OnChangedCallback { get; set; }
|
||||
|
||||
private async Task SetQuote(string eSalesNumber, QStatus status)
|
||||
private async Task SetQuote(string eSalesNumber, QuoteStatus status)
|
||||
{
|
||||
var args = new QuoteCallbackArgs()
|
||||
{
|
||||
|
|
|
@ -21,13 +21,13 @@
|
|||
<div class="row mb-3">
|
||||
<div class="col-sm-4">
|
||||
<div class="btn-group" role="group" aria-label="Ordre status">
|
||||
<input type="radio" class="btn-check" name="btn-order" id="btn-order1" @onchange="() => GetWithStatus(PStatus.None)" autocomplete="off" checked="checked"/>
|
||||
<input type="radio" class="btn-check" name="btn-order" id="btn-order1" @onchange="() => GetWithStatus(ProcessStatus.None)" autocomplete="off" checked="checked"/>
|
||||
<label class="btn btn-success" for="btn-order1">Ubehandlet</label>
|
||||
|
||||
<input type="radio" class="btn-check" name="btn-order" id="btn-order2" @onchange="() => GetWithStatus(PStatus.Picked)" autocomplete="off"/>
|
||||
<input type="radio" class="btn-check" name="btn-order" id="btn-order2" @onchange="() => GetWithStatus(ProcessStatus.Picked)" autocomplete="off"/>
|
||||
<label class="btn btn-warning" for="btn-order2">Plukket</label>
|
||||
|
||||
<input type="radio" class="btn-check" name="btn-order" id="btn-order3" @onchange="() => GetWithStatus(PStatus.Packed)" autocomplete="off"/>
|
||||
<input type="radio" class="btn-check" name="btn-order" id="btn-order3" @onchange="() => GetWithStatus(ProcessStatus.Packed)" autocomplete="off"/>
|
||||
<label class="btn btn-danger" for="btn-order3">Pakket</label>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -24,7 +24,7 @@ public partial class WarehouseListComponent
|
|||
[Parameter] public string Header { get; set; } = "";
|
||||
[Parameter] public List<WarehouseOrderView> OrderList { get; set; } = new();
|
||||
[Parameter] public bool ReadyToShip { get; set; }
|
||||
[Parameter] public EventCallback<PStatus> OnGetStatus { get; set; }
|
||||
[Parameter] public EventCallback<ProcessStatus> OnGetStatus { get; set; }
|
||||
[Parameter] public EventCallback OnSetShipped { get; set; }
|
||||
[Parameter] public EventCallback<string> OnQPak { get; set; }
|
||||
|
||||
|
@ -43,7 +43,7 @@ public partial class WarehouseListComponent
|
|||
await OnSetShipped.InvokeAsync();
|
||||
}
|
||||
|
||||
private async Task GetWithStatus(PStatus status)
|
||||
private async Task GetWithStatus(ProcessStatus status)
|
||||
{
|
||||
await OnGetStatus.InvokeAsync(status);
|
||||
}
|
||||
|
|
|
@ -23,14 +23,14 @@ namespace Wonky.Client.Helpers;
|
|||
/// </summary>
|
||||
public static class Utils
|
||||
{
|
||||
public static bool Validate(VType vType, string toValidate)
|
||||
public static bool Validate(ValidateType validateType, string toValidate)
|
||||
{
|
||||
return vType switch
|
||||
return validateType switch
|
||||
{
|
||||
VType.ISODate => toValidate.Length == 10 && DateTime.TryParse(toValidate, out _),
|
||||
VType.Id => Squid.TryDecode(toValidate, out _),
|
||||
VType.Passwd => IsValidPasswd(toValidate),
|
||||
VType.Email => IsValidEmail(toValidate),
|
||||
ValidateType.IsoDate => toValidate.Length == 10 && DateTime.TryParse(toValidate, out _),
|
||||
ValidateType.Id => Squid.TryDecode(toValidate, out _),
|
||||
ValidateType.Passwd => IsValidPasswd(toValidate),
|
||||
ValidateType.Email => IsValidEmail(toValidate),
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
|
@ -51,17 +51,20 @@ public static class Utils
|
|||
{
|
||||
validConditions++;
|
||||
}
|
||||
else return false;
|
||||
|
||||
if (toValidate.Any(c => c is >= 'A' and <= 'Z'))
|
||||
{
|
||||
validConditions++;
|
||||
}
|
||||
else return false;
|
||||
|
||||
if (toValidate.Any(c => c is >= '0' and <= '9'))
|
||||
{
|
||||
validConditions++;
|
||||
}
|
||||
|
||||
else return false;
|
||||
|
||||
return validConditions == 3;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ public interface ISystemUserRepository
|
|||
/// </summary>
|
||||
/// <param name="model"></param>
|
||||
/// <returns></returns>
|
||||
Task<UserManagerEditView> CreateUser(UserManagerEditView model);
|
||||
Task<UserManagerEditView> CreateUser(UserManagerCreate model);
|
||||
|
||||
/// <summary>
|
||||
/// Update Advisor using userId and updated data
|
||||
|
|
|
@ -69,7 +69,7 @@ public class SystemUserRepository : ISystemUserRepository
|
|||
/// </summary>
|
||||
/// <param name="model"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<UserManagerEditView> CreateUser(UserManagerEditView model)
|
||||
public async Task<UserManagerEditView> CreateUser(UserManagerCreate model)
|
||||
{
|
||||
var result = await _client.PostAsJsonAsync($"{_api.UserManager}", model, _options);
|
||||
if (!result.IsSuccessStatusCode)
|
||||
|
|
13
Wonky.Client/Models/AssignedRoles.cs
Normal file
13
Wonky.Client/Models/AssignedRoles.cs
Normal file
|
@ -0,0 +1,13 @@
|
|||
namespace Wonky.Client.Models;
|
||||
|
||||
public class AssignedRoles
|
||||
{
|
||||
public bool Admin { get; set; }
|
||||
public bool Advisor { get; set; }
|
||||
public bool EShop { get; set; }
|
||||
public bool EDoc { get; set; }
|
||||
public bool Management { get; set; }
|
||||
public bool Office { get; set; }
|
||||
public bool Supervisor { get; set; }
|
||||
public bool Warehouse { get; set; }
|
||||
}
|
18
Wonky.Client/Models/PasswordInput.cs
Normal file
18
Wonky.Client/Models/PasswordInput.cs
Normal file
|
@ -0,0 +1,18 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Wonky.Client.Models;
|
||||
|
||||
public class PasswordInput
|
||||
{
|
||||
/// <summary>
|
||||
/// New password
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "Kode skal udfyldes")][MinLength(10, ErrorMessage = "Password skal være mindst 10 tegn og indeholde a-z, A-Z, 0-9")]
|
||||
public string NewPassword { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Password confirmation
|
||||
/// </summary>
|
||||
[Compare(nameof(NewPassword), ErrorMessage = "Koderne er ikke ens.")]
|
||||
public string ConfirmPassword { get; set; } = "";
|
||||
}
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
namespace Wonky.Client.Models;
|
||||
|
||||
public enum PTarget
|
||||
public enum PrintTarget
|
||||
{
|
||||
None,
|
||||
All,
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
namespace Wonky.Client.Models;
|
||||
|
||||
public enum PStatus
|
||||
public enum ProcessStatus
|
||||
{
|
||||
None,
|
||||
Picked,
|
||||
|
@ -24,5 +24,5 @@ public enum PStatus
|
|||
Shipped,
|
||||
All,
|
||||
Express,
|
||||
Accepted
|
||||
Printed
|
||||
}
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
namespace Wonky.Client.Models;
|
||||
|
||||
public enum PSort
|
||||
public enum ProductSort
|
||||
{
|
||||
None,
|
||||
Desc,
|
|
@ -25,5 +25,5 @@ public class QuoteCallbackArgs
|
|||
/// <summary>
|
||||
/// QStatus
|
||||
/// </summary>
|
||||
public QStatus Status { get; set; }
|
||||
public QuoteStatus Status { get; set; }
|
||||
}
|
|
@ -16,10 +16,10 @@
|
|||
|
||||
namespace Wonky.Client.Models;
|
||||
|
||||
public enum QStatus
|
||||
public enum QuoteStatus
|
||||
{
|
||||
None,
|
||||
Win,
|
||||
Order,
|
||||
Lose,
|
||||
Archive,
|
||||
Note,
|
|
@ -1,9 +1,9 @@
|
|||
namespace Wonky.Client.Models;
|
||||
|
||||
public enum VType
|
||||
public enum ValidateType
|
||||
{
|
||||
Id,
|
||||
ISODate,
|
||||
IsoDate,
|
||||
Passwd,
|
||||
Email
|
||||
}
|
|
@ -30,9 +30,9 @@
|
|||
<div class="list-group mt-2">
|
||||
<div class="list-group-item bg-dark text-white">
|
||||
<div class="row">
|
||||
<div class="col-sm-4" style="cursor: pointer;" @onclick="() => SortProducts(PSort.Desc)"><i class="bi-sort-alpha-down"></i> Navn <i class="bi-sort-alpha-up-alt"></i></div>
|
||||
<div class="col-sm-3" style="cursor: pointer;" @onclick="() => SortProducts(PSort.Sku)"><i class="bi-sort-alpha-down"></i> Varenr <i class="bi-sort-alpha-up-alt"></i></div>
|
||||
<div class="col-sm-2 text-center" style="cursor: pointer;" @onclick="() => SortProducts(PSort.Qty)"><i class="bi-sort-numeric-down"></i> Antal <i class="bi-sort-numeric-up-alt"></i></div>
|
||||
<div class="col-sm-4" style="cursor: pointer;" @onclick="() => SortProducts(ProductSort.Desc)"><i class="bi-sort-alpha-down"></i> Navn <i class="bi-sort-alpha-up-alt"></i></div>
|
||||
<div class="col-sm-3" style="cursor: pointer;" @onclick="() => SortProducts(ProductSort.Sku)"><i class="bi-sort-alpha-down"></i> Varenr <i class="bi-sort-alpha-up-alt"></i></div>
|
||||
<div class="col-sm-2 text-center" style="cursor: pointer;" @onclick="() => SortProducts(ProductSort.Qty)"><i class="bi-sort-numeric-down"></i> Antal <i class="bi-sort-numeric-up-alt"></i></div>
|
||||
<div class="col-sm-2"></div>
|
||||
<div class="col-sm-1"></div>
|
||||
</div>
|
||||
|
|
|
@ -58,12 +58,12 @@ public partial class OfficeCustomerProductListOverlay : IDisposable
|
|||
ReorderOverlay.Show();
|
||||
}
|
||||
|
||||
private void SortProducts(PSort column)
|
||||
private void SortProducts(ProductSort column)
|
||||
{
|
||||
Descending = !Descending;
|
||||
switch (column)
|
||||
{
|
||||
case PSort.Desc:
|
||||
case ProductSort.Desc:
|
||||
if (Descending)
|
||||
{
|
||||
Inventory = Inventory.OrderByDescending(x => x.Description).ToList();
|
||||
|
@ -72,7 +72,7 @@ public partial class OfficeCustomerProductListOverlay : IDisposable
|
|||
|
||||
Inventory = Inventory.OrderBy(x => x.Description).ToList();
|
||||
break;
|
||||
case PSort.Sku:
|
||||
case ProductSort.Sku:
|
||||
if (Descending)
|
||||
{
|
||||
Inventory = Inventory.OrderByDescending(x => x.Sku).ToList();
|
||||
|
@ -81,7 +81,7 @@ public partial class OfficeCustomerProductListOverlay : IDisposable
|
|||
|
||||
Inventory = Inventory.OrderBy(x => x.Sku).ToList();
|
||||
break;
|
||||
case PSort.Qty:
|
||||
case ProductSort.Qty:
|
||||
if (Descending)
|
||||
{
|
||||
Inventory = Inventory.OrderByDescending(x => x.Quantity).ToList();
|
||||
|
@ -90,9 +90,9 @@ public partial class OfficeCustomerProductListOverlay : IDisposable
|
|||
|
||||
Inventory = Inventory.OrderBy(x => x.Quantity).ToList();
|
||||
break;
|
||||
case PSort.None:
|
||||
case ProductSort.None:
|
||||
break;
|
||||
case PSort.Abbr:
|
||||
case ProductSort.Abbr:
|
||||
break;
|
||||
default:
|
||||
Inventory = Inventory.OrderByDescending(x => x.Quantity).ToList();
|
||||
|
|
|
@ -27,22 +27,22 @@
|
|||
<div class="col-sm-4 text-end">
|
||||
<div class="btn-group btn-group" role="group" aria-label="Filter tilbud">
|
||||
|
||||
<input type="radio" class="btn-check" name="btn-filter" id="btn-filter4" autocomplete="off" @onchange="() => FilterQuotes(QStatus.All)"/>
|
||||
<input type="radio" class="btn-check" name="btn-filter" id="btn-filter4" autocomplete="off" @onchange="() => FilterQuotes(QuoteStatus.All)"/>
|
||||
<label class="btn btn-dark" for="btn-filter4"><i class="bi-list"style="font-size: 1.3rem"></i></label>
|
||||
|
||||
<input type="radio" class="btn-check" name="btn-filter" id="btn-filter1" autocomplete="off" @onchange="() => FilterQuotes(QStatus.Lose)"/>
|
||||
<input type="radio" class="btn-check" name="btn-filter" id="btn-filter1" autocomplete="off" @onchange="() => FilterQuotes(QuoteStatus.Lose)"/>
|
||||
<label class="btn btn-dark" for="btn-filter1"><i class="bi-trash-fill"style="font-size: 1.3rem"></i></label>
|
||||
|
||||
<input type="radio" class="btn-check" name="btn-filter" id="btn-filter2" autocomplete="off" @onchange="() => FilterQuotes(QStatus.Archive)"/>
|
||||
<input type="radio" class="btn-check" name="btn-filter" id="btn-filter2" autocomplete="off" @onchange="() => FilterQuotes(QuoteStatus.Archive)"/>
|
||||
<label class="btn btn-dark" for="btn-filter2"><i class="bi-archive-fill"style="font-size: 1.3rem"></i></label>
|
||||
|
||||
<input type="radio" class="btn-check" name="btn-filter" id="btn-filter5" autocomplete="off" @onchange="() => FilterQuotes(QStatus.None)"/>
|
||||
<input type="radio" class="btn-check" name="btn-filter" id="btn-filter5" autocomplete="off" @onchange="() => FilterQuotes(QuoteStatus.None)"/>
|
||||
<label class="btn btn-dark" for="btn-filter5"><i class="bi-question-circle-fill"style="font-size: 1.3rem"></i></label>
|
||||
|
||||
<input type="radio" class="btn-check" name="btn-filter" id="btn-filter3" autocomplete="off" @onchange="() => FilterQuotes(QStatus.Note)"/>
|
||||
<input type="radio" class="btn-check" name="btn-filter" id="btn-filter3" autocomplete="off" @onchange="() => FilterQuotes(QuoteStatus.Note)"/>
|
||||
<label class="btn btn-dark" for="btn-filter3"><i class="bi-tag-fill"style="font-size: 1.3rem"></i></label>
|
||||
|
||||
<input type="radio" class="btn-check" name="btn-filter" id="btn-filter6" autocomplete="off" @onchange="() => FilterQuotes(QStatus.NoteOpen)" checked/>
|
||||
<input type="radio" class="btn-check" name="btn-filter" id="btn-filter6" autocomplete="off" @onchange="() => FilterQuotes(QuoteStatus.NoteOpen)" checked/>
|
||||
<label class="btn btn-dark" for="btn-filter6"><i class="bi-activity"style="font-size: 1.3rem"></i></label>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ public partial class AdvisorQuoteListPage : IDisposable
|
|||
private List<ReportItemView> QuoteList { get; set; } = new();
|
||||
private List<ReportItemView> FilteredQuotes { get; set; } = new();
|
||||
private bool Working { get; set; }
|
||||
private QStatus QFilter { get; set; } = QStatus.NoteOpen;
|
||||
private QuoteStatus QuoteFilter { get; set; } = QuoteStatus.NoteOpen;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
|
@ -48,20 +48,20 @@ public partial class AdvisorQuoteListPage : IDisposable
|
|||
Working = false;
|
||||
// filter quotes - if any - default to QStatus.NoteOpen
|
||||
if (QuoteList.Any())
|
||||
await FilterQuotes(QFilter);
|
||||
await FilterQuotes(QuoteFilter);
|
||||
}
|
||||
|
||||
private async Task FilterQuotes(QStatus status)
|
||||
private async Task FilterQuotes(QuoteStatus status)
|
||||
{
|
||||
QFilter = status;
|
||||
QuoteFilter = status;
|
||||
QuoteList = await Storage.GetItemAsync<List<ReportItemView>>("quotes");
|
||||
FilteredQuotes = QFilter switch
|
||||
FilteredQuotes = QuoteFilter switch
|
||||
{
|
||||
QStatus.None => QuoteList.Where(x => x.QuoteStatusEnum is "None").ToList(),
|
||||
QStatus.Lose => QuoteList.Where(x => x.QuoteStatusEnum is "Lose").ToList(),
|
||||
QStatus.Archive => QuoteList.Where(x => x.QuoteStatusEnum is "Archive").ToList(),
|
||||
QStatus.Note => QuoteList.Where(x => x.QuoteStatusEnum is "Note").ToList(),
|
||||
QStatus.NoteOpen => QuoteList.Where(x => x.QuoteStatusEnum is "Note" or "None").ToList(),
|
||||
QuoteStatus.None => QuoteList.Where(x => x.QuoteStatusEnum is "None").ToList(),
|
||||
QuoteStatus.Lose => QuoteList.Where(x => x.QuoteStatusEnum is "Lose").ToList(),
|
||||
QuoteStatus.Archive => QuoteList.Where(x => x.QuoteStatusEnum is "Archive").ToList(),
|
||||
QuoteStatus.Note => QuoteList.Where(x => x.QuoteStatusEnum is "Note").ToList(),
|
||||
QuoteStatus.NoteOpen => QuoteList.Where(x => x.QuoteStatusEnum is "Note" or "None").ToList(),
|
||||
_ => QuoteList.ToList()
|
||||
};
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ public partial class AdvisorQuoteListPage : IDisposable
|
|||
Working = true;
|
||||
// find the quote to update
|
||||
var quote = QuoteList.First(x => x.ESalesNumber == args.ESalesNumber);
|
||||
if (args.Status == QStatus.Win)
|
||||
if (args.Status == QuoteStatus.Order)
|
||||
quote.OrderDate = $"{DateTime.Now:yyyy-MM-dd}";
|
||||
quote.QuoteStatusEnum = Utils.EnumToString(args.Status);
|
||||
// send update request to backend
|
||||
|
@ -85,7 +85,7 @@ public partial class AdvisorQuoteListPage : IDisposable
|
|||
await Storage.SetItemAsync("quotes", QuoteList.OrderBy(x => x.Company.Name));
|
||||
// filter quotes - if any - based on active filter
|
||||
if(QuoteList.Any())
|
||||
await FilterQuotes(QFilter);
|
||||
await FilterQuotes(QuoteFilter);
|
||||
Working = false;
|
||||
// signal page state changed
|
||||
StateHasChanged();
|
||||
|
|
|
@ -26,10 +26,10 @@
|
|||
<WorkDateComponent OnChangedCallback="FetchReport"/>
|
||||
</div>
|
||||
<div class="col-sm-2 d-grid">
|
||||
<button class="btn btn-warning" @onclick="() => Print(PTarget.FrontPage)"><i class="bi-printer"></i> Forside</button>
|
||||
<button class="btn btn-warning" @onclick="() => Print(PrintTarget.FrontPage)"><i class="bi-printer"></i> Forside</button>
|
||||
</div>
|
||||
<div class="col-sm-2 d-grid">
|
||||
<button class="btn btn-success" @onclick="() => Print(PTarget.OrderPage)"><i class="bi-printer"></i> Ordrer</button>
|
||||
<button class="btn btn-success" @onclick="() => Print(PrintTarget.OrderPage)"><i class="bi-printer"></i> Ordrer</button>
|
||||
</div>
|
||||
<div class="col-sm-2 d-grid">
|
||||
<button class="btn btn-primary" type="button" onclick="window.print();"><i class="bi-printer"></i> Rapport</button>
|
||||
|
|
|
@ -58,21 +58,21 @@ public partial class AdvisorReportViewPage : IDisposable
|
|||
await FetchReport(ReportDate);
|
||||
}
|
||||
|
||||
private void Print(PTarget target)
|
||||
private void Print(PrintTarget target)
|
||||
{
|
||||
ReturnUrl = new Uri(Navigator.Uri).AbsolutePath;
|
||||
|
||||
switch (target)
|
||||
{
|
||||
case PTarget.OrderPage:
|
||||
case PrintTarget.OrderPage:
|
||||
Navigator.NavigateTo($"/report/print/orders/{XUserInfo.CountryCode.ToLower()}/{XUserInfo.UserId}/{ReportDate}?returnUrl={ReturnUrl}");
|
||||
break;
|
||||
case PTarget.FrontPage:
|
||||
case PrintTarget.FrontPage:
|
||||
Navigator.NavigateTo($"/report/print/summary/{XUserInfo.CountryCode.ToLower()}/{XUserInfo.UserId}/{ReportDate}?returnUrl={ReturnUrl}");
|
||||
break;
|
||||
case PTarget.None:
|
||||
case PrintTarget.None:
|
||||
break;
|
||||
case PTarget.All:
|
||||
case PrintTarget.All:
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(target), target, null);
|
||||
|
|
|
@ -74,7 +74,7 @@ public partial class CommonReportPrintOrderPage
|
|||
await ProcessRepo.UpdateWarehouseOrderStatus(new OrderProcessState
|
||||
{
|
||||
OrderId = item.ActivityId,
|
||||
ProcessStatusEnum = Utils.EnumToString(PStatus.Accepted)
|
||||
ProcessStatusEnum = Utils.EnumToString(ProcessStatus.Printed)
|
||||
});
|
||||
}
|
||||
Toaster.ClearAll();
|
||||
|
|
|
@ -26,10 +26,10 @@
|
|||
<WorkDateComponent OnChangedCallback="FetchUserReport"/>
|
||||
</div>
|
||||
<div class="col-sm-2 d-grid">
|
||||
<button class="btn btn-warning" @onclick="() => Print(PTarget.FrontPage)"><i class="bi-printer"></i> Forside</button>
|
||||
<button class="btn btn-warning" @onclick="() => Print(PrintTarget.FrontPage)"><i class="bi-printer"></i> Forside</button>
|
||||
</div>
|
||||
<div class="col-sm-2 d-grid">
|
||||
<button class="btn btn-success" @onclick="() => Print(PTarget.OrderPage)"><i class="bi-printer"></i> Ordrer</button>
|
||||
<button class="btn btn-success" @onclick="() => Print(PrintTarget.OrderPage)"><i class="bi-printer"></i> Ordrer</button>
|
||||
</div>
|
||||
<div class="col-sm-2 d-grid">
|
||||
<button class="btn btn-primary" type="button" @onclick="Print"><i class="bi-printer"></i> Rapport</button>
|
||||
|
|
|
@ -69,20 +69,20 @@ public partial class OfficeAdvisorReportViewPage : IDisposable
|
|||
.InvokeAsync<IJSObjectReference>("import", "/scripts/print-invoke.js");
|
||||
}
|
||||
}
|
||||
private void Print(PTarget target)
|
||||
private void Print(PrintTarget target)
|
||||
{
|
||||
_returnUrl = new Uri(Navigator.Uri).AbsolutePath;
|
||||
switch (target)
|
||||
{
|
||||
case PTarget.OrderPage:
|
||||
case PrintTarget.OrderPage:
|
||||
Navigator.NavigateTo($"/report/print/orders/{CountryCode}/{UserId}/{ReportDate}?returnUrl={_returnUrl}");
|
||||
break;
|
||||
case PTarget.FrontPage:
|
||||
case PrintTarget.FrontPage:
|
||||
Navigator.NavigateTo($"/report/print/summary/{CountryCode}/{UserId}/{ReportDate}?returnUrl={_returnUrl}");
|
||||
break;
|
||||
case PTarget.None:
|
||||
case PrintTarget.None:
|
||||
break;
|
||||
case PTarget.All:
|
||||
case PrintTarget.All:
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(target), target, null);
|
||||
|
@ -101,7 +101,7 @@ public partial class OfficeAdvisorReportViewPage : IDisposable
|
|||
await ProcessRepo.UpdateWarehouseOrderStatus(new OrderProcessState
|
||||
{
|
||||
OrderId = item.ActivityId,
|
||||
ProcessStatusEnum = Utils.EnumToString(PStatus.Accepted)
|
||||
ProcessStatusEnum = Utils.EnumToString(ProcessStatus.Printed)
|
||||
});
|
||||
}
|
||||
Toaster.ClearAll();
|
||||
|
|
|
@ -22,113 +22,116 @@
|
|||
|
||||
<div class="card">
|
||||
<div class="card-header bg-dark text-white">
|
||||
<h3>Bruger info</h3>
|
||||
<div class="card-title">
|
||||
<h3>Bruger oprettelse</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@if (!string.IsNullOrWhiteSpace(UserInfo.UserId))
|
||||
{
|
||||
<EditForm EditContext="UserEditContext" OnValidSubmit="CreateUser">
|
||||
<DataAnnotationsValidator/>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr class="align-middle">
|
||||
<th scope="col">
|
||||
Fornavn
|
||||
</th>
|
||||
<td>
|
||||
<InputText id="firstName" class="form-control" @bind-Value="UserInfo.FirstName" readonly="@ReadOnly" />
|
||||
<ValidationMessage For="@(() => UserInfo.FirstName)"></ValidationMessage>
|
||||
</td>
|
||||
<th scope="col">
|
||||
Efternavn
|
||||
</th>
|
||||
<td>
|
||||
<InputText id="lastName" class="form-control" @bind-Value="UserInfo.LastName" readonly="@ReadOnly" />
|
||||
<ValidationMessage For="@(() => UserInfo.LastName)"></ValidationMessage>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="align-middle">
|
||||
<th scope="col">
|
||||
Email
|
||||
</th>
|
||||
<td>
|
||||
<InputText id="email" class="form-control" @bind-Value="UserInfo.Email" readonly="@ReadOnly" />
|
||||
<ValidationMessage For="@(() => UserInfo.Email)"></ValidationMessage>
|
||||
</td>
|
||||
<th scope="col">
|
||||
Mobilnummer
|
||||
</th>
|
||||
<td>
|
||||
<InputText id="phoneNumber" class="form-control" @bind-Value="UserInfo.PhoneNumber" readonly="@ReadOnly" />
|
||||
<ValidationMessage For="@(() => UserInfo.PhoneNumber)"></ValidationMessage>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="align-middle">
|
||||
<th scope="col">
|
||||
Sælgernr.
|
||||
</th>
|
||||
<td>
|
||||
<InputText id="salesRep" class="form-control" @bind-Value="UserInfo.SalesRep" readonly="@ReadOnly" />
|
||||
<ValidationMessage For="@(() => UserInfo.SalesRep)"></ValidationMessage>
|
||||
</td>
|
||||
<th scope="col">
|
||||
Landekode
|
||||
</th>
|
||||
<td>
|
||||
<InputText id="countryCode" class="form-control" @bind-Value="UserInfo.CountryCode" readonly="@ReadOnly" />
|
||||
<ValidationMessage For="@(() => UserInfo.CountryCode)"></ValidationMessage>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="align-middle">
|
||||
<th scope="col">
|
||||
Spærret
|
||||
</th>
|
||||
<td colspan="3">
|
||||
<InputCheckbox id="lockoutEnabled" class="form-check" @bind-Value="UserInfo.LockoutEnabled"/>
|
||||
<ValidationMessage For="@(() => UserInfo.LockoutEnabled)"></ValidationMessage>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<EditForm EditContext="NewUserContext" OnValidSubmit="CreateUser">
|
||||
<DataAnnotationsValidator/>
|
||||
<div class="row g-3 mb-3">
|
||||
<label for="firstName" class="col-sm-2 col-form-label">Fornavn</label>
|
||||
<div class="col-sm-4">
|
||||
<InputText id="firstName" class="form-control" @bind-Value="NewUserInfo.FirstName"/>
|
||||
<ValidationMessage For="@(() => NewUserInfo.FirstName)"></ValidationMessage>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<button type="button" class="btn btn-danger" @onclick="() => ReadOnly = !ReadOnly">Rediger</button>
|
||||
</div>
|
||||
<div class="col">
|
||||
<button type="submit" class="btn btn-primary">Gem</button>
|
||||
</div>
|
||||
<div class="col">
|
||||
<a class="btn btn-primary" href="/system/users">Tilbage</a>
|
||||
</div>
|
||||
|
||||
<label for="lastName" class="col-sm-2 col-form-label">Efternavn</label>
|
||||
<div class="col-sm-4">
|
||||
<InputText id="lastName" class="form-control" @bind-Value="NewUserInfo.LastName"/>
|
||||
<ValidationMessage For="@(() => NewUserInfo.LastName)"></ValidationMessage>
|
||||
</div>
|
||||
</EditForm>
|
||||
<EditForm EditContext="PasswdContext" class="mt-5" >
|
||||
<DataAnnotationsValidator />
|
||||
<h3>NULSTIL ADGANGSKODE</h3>
|
||||
<div class="alert-info">
|
||||
<h4>Password politik</h4>
|
||||
<p>Mindst 10 tegn bestående af store og små bogstaver samt tal. Du kan teste pasword og danne stærke password på <a href="https://pw.nix.dk">pw.nix.dk</a></p>
|
||||
|
||||
<label for="email" class="col-sm-2 col-form-label">Email</label>
|
||||
<div class="col-sm-4">
|
||||
<InputText id="email" class="form-control" @bind-Value="NewUserInfo.Email"/>
|
||||
<ValidationMessage For="@(() => NewUserInfo.Email)"></ValidationMessage>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<label for="newPasswd" class="col-md-2 col-form-label">Ny</label>
|
||||
<div class="col-md-10">
|
||||
<InputText id="newPasswd" class="form-control" @bind-Value="@Passwords.NewPassword"/>
|
||||
<ValidationMessage For="@(() => Passwords.NewPassword)"></ValidationMessage>
|
||||
</div>
|
||||
|
||||
<label for="phoneNumber" class="col-sm-2 col-form-label">Mobil</label>
|
||||
<div class="col-sm-4">
|
||||
<InputText id="phoneNumber" class="form-control" @bind-Value="NewUserInfo.PhoneNumber"/>
|
||||
<ValidationMessage For="@(() => NewUserInfo.PhoneNumber)"></ValidationMessage>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<label for="verifyPasswd" class="col-md-2 col-form-label">Bekræft</label>
|
||||
<div class="col-md-10">
|
||||
<InputText id="verifyPasswd" class="form-control" @bind-Value="@Passwords.ConfirmPassword"/>
|
||||
<ValidationMessage For="@(() => Passwords.ConfirmPassword)"></ValidationMessage>
|
||||
</div>
|
||||
|
||||
<label for="salesRep" class="col-sm-2 col-form-label">MedarbejderId</label>
|
||||
<div class="col-sm-4">
|
||||
<InputText id="salesRep" class="form-control" @bind-Value="NewUserInfo.SalesRep"/>
|
||||
<ValidationMessage For="@(() => NewUserInfo.SalesRep)"></ValidationMessage>
|
||||
</div>
|
||||
</EditForm>
|
||||
}
|
||||
|
||||
<label for="countryCode" class="col-sm-2 col-form-label">Landekode</label>
|
||||
<div class="col-sm-4">
|
||||
<InputText id="countryCode" class="form-control" @bind-Value="NewUserInfo.CountryCode"/>
|
||||
<ValidationMessage For="@(() => NewUserInfo.CountryCode)"></ValidationMessage>
|
||||
</div>
|
||||
|
||||
@*
|
||||
<div class="ms-2 col-sm-4 form-check form-switch">
|
||||
<label for="lockoutEnabled" class="form-check-label">Spærret</label>
|
||||
<InputCheckbox id="lockoutEnabled" class="form-check-input" @bind-Value="NewUserInfo.LockoutEnabled"/>
|
||||
<ValidationMessage For="@(() => NewUserInfo.LockoutEnabled)"></ValidationMessage>
|
||||
</div>
|
||||
*@
|
||||
|
||||
<div class="ms-2 col-sm-2 form-check form-switch">
|
||||
<InputCheckbox id="admin" class="form-check-input" @bind-Value="AssignedRoles.Admin"/>
|
||||
<label for="admin" class="form-check-label">Administrator</label>
|
||||
</div>
|
||||
<div class="ms-2 col-sm-2 form-check form-switch">
|
||||
<InputCheckbox id="office" class="form-check-input" @bind-Value="AssignedRoles.Office"/>
|
||||
<label for="office" class="form-check-label">Kontor</label>
|
||||
</div>
|
||||
<div class="ms-2 col-sm-2 form-check form-switch">
|
||||
<InputCheckbox id="eshop" class="form-check-input" @bind-Value="AssignedRoles.EShop"/>
|
||||
<label for="eshop" class="form-check-label">Kunde (EShop)</label>
|
||||
</div>
|
||||
<div class="ms-2 col-sm-2 form-check form-switch">
|
||||
<InputCheckbox id="warehouse" class="form-check-input" @bind-Value="AssignedRoles.Warehouse"/>
|
||||
<label for="warehouse" class="form-check-label">Forsendelse</label>
|
||||
</div>
|
||||
<div class="ms-2 col-sm-2 form-check form-switch">
|
||||
<InputCheckbox id="management" class="form-check-input" @bind-Value="AssignedRoles.Management"/>
|
||||
<label for="management" class="form-check-label">Ledelse</label>
|
||||
</div>
|
||||
<div class="ms-2 col-sm-2 form-check form-switch">
|
||||
<InputCheckbox id="supervisor" class="form-check-input" @bind-Value="AssignedRoles.Supervisor"/>
|
||||
<label for="supervisor" class="form-check-label">Supervisor</label>
|
||||
</div>
|
||||
<div class="ms-2 col-sm-2 form-check form-switch">
|
||||
<InputCheckbox id="advisor" class="form-check-input" @bind-Value="AssignedRoles.Advisor"/>
|
||||
<label for="advisor" class="form-check-label">Sælger</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
</div>
|
||||
<div class="col">
|
||||
<a class="btn btn-primary" href="/system/users">Tilbage</a>
|
||||
</div>
|
||||
<div class="col text-end">
|
||||
<button type="submit" class="btn btn-primary" disabled="@ContextInvalid">Gem</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="alert alert-info">
|
||||
<h4>Password politik</h4>
|
||||
<p>Mindst 10 tegn bestående af store og små bogstaver samt tal. Du kan teste pasword og danne stærke password på <a href="https://pw.nix.dk">pw.nix.dk</a></p>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<label for="newPasswd" class="col-md-2 col-form-label">Ny</label>
|
||||
<div class="col-md-10">
|
||||
<InputText id="newPasswd" class="form-control" @bind-Value="@PasswdInput.NewPassword"/>
|
||||
<ValidationMessage For="@(() => PasswdInput.NewPassword)"></ValidationMessage>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<label for="verifyPasswd" class="col-md-2 col-form-label">Bekræft</label>
|
||||
<div class="col-md-10">
|
||||
<InputText id="verifyPasswd" class="form-control" @bind-Value="@PasswdInput.ConfirmPassword"/>
|
||||
<ValidationMessage For="@(() => PasswdInput.ConfirmPassword)"></ValidationMessage>
|
||||
</div>
|
||||
</div>
|
||||
</EditForm>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -136,4 +139,4 @@
|
|||
@if (Working)
|
||||
{
|
||||
<WorkingThreeDots/>
|
||||
}
|
||||
}
|
|
@ -21,6 +21,7 @@ using Microsoft.AspNetCore.Components.Forms;
|
|||
using Wonky.Client.Helpers;
|
||||
using Wonky.Client.HttpInterceptors;
|
||||
using Wonky.Client.HttpRepository;
|
||||
using Wonky.Client.Models;
|
||||
using Wonky.Entity.DTO;
|
||||
|
||||
#pragma warning disable CS8618
|
||||
|
@ -33,14 +34,14 @@ public partial class SystemUserCreatePage : IDisposable
|
|||
[Inject] public ISystemUserRepository UserRepo { get; set; }
|
||||
[Inject] public ILogger<SystemUserCreatePage> Logger { get; set; }
|
||||
[Inject] public IToastService Toaster { get; set; }
|
||||
private UserManagerEditView UserInfo { get; set; } = new();
|
||||
private EditContext UserEditContext { get; set; }
|
||||
private ResetPasswordDto Passwords { get; set; } = new();
|
||||
private EditContext PasswdContext { get; set; }
|
||||
private bool PwInvalid { get; set; } = true;
|
||||
private UserManagerCreate NewUserInfo { get; set; } = new();
|
||||
private EditContext NewUserContext { get; set; }
|
||||
private bool ContextInvalid { get; set; } = true;
|
||||
private bool Working { get; set; } = true;
|
||||
private bool ReadOnly { get; set; } = true;
|
||||
|
||||
private PasswordInput PasswdInput { get; set; } = new();
|
||||
private AssignedRoles AssignedRoles { get; set; } = new();
|
||||
|
||||
private readonly JsonSerializerOptions _options = new JsonSerializerOptions
|
||||
{
|
||||
PropertyNameCaseInsensitive = true
|
||||
|
@ -51,48 +52,65 @@ public partial class SystemUserCreatePage : IDisposable
|
|||
Interceptor.RegisterEvent();
|
||||
Interceptor.RegisterBeforeSendEvent();
|
||||
|
||||
UserEditContext = new EditContext(UserInfo);
|
||||
PasswdContext = new EditContext(Passwords);
|
||||
NewUserContext = new EditContext(NewUserInfo);
|
||||
|
||||
PasswdContext.OnFieldChanged += PwHandleFieldChanged!;
|
||||
PasswdContext.OnValidationStateChanged += PwValidationChanged;
|
||||
NewUserContext.OnFieldChanged += ContextHandleFieldChanged!;
|
||||
NewUserContext.OnValidationStateChanged += ContextValidationChanged;
|
||||
Working = false;
|
||||
}
|
||||
|
||||
private async Task CreateUser()
|
||||
{
|
||||
// NewUserInfo.AssignedRoles = new List<UserRoleAssignment>()
|
||||
// {
|
||||
// new (){ Name = "Admin", Assigned = false },
|
||||
// new (){ Name = "Advisor", Assigned = false },
|
||||
// new (){ Name = "Management", Assigned = false },
|
||||
// new (){ Name = "Office", Assigned = false },
|
||||
// new (){ Name = "Supervisor", Assigned = false },
|
||||
// new (){ Name = "Warehouse", Assigned = false },
|
||||
// };
|
||||
|
||||
ReadOnly = true;
|
||||
Working = true;
|
||||
Toaster.ShowInfo("Sender data til server ...");
|
||||
await UserRepo.CreateUser(UserInfo);
|
||||
await UserRepo.CreateUser(NewUserInfo);
|
||||
Working = false;
|
||||
Toaster.ShowInfo("Bruger er oprettet ...");
|
||||
}
|
||||
|
||||
private void PwHandleFieldChanged(object sender, FieldChangedEventArgs e)
|
||||
private void ContextHandleFieldChanged(object sender, FieldChangedEventArgs e)
|
||||
{
|
||||
PwInvalid = !PasswdContext.Validate();
|
||||
Logger.LogDebug("contextHandleFieldChanged => e.FieldIdentifier.FieldName {}", e.FieldIdentifier.FieldName);
|
||||
if (e.FieldIdentifier.FieldName == "NewPassword")
|
||||
{
|
||||
if (!Utils.IsValidPasswd(PasswdInput.NewPassword))
|
||||
{
|
||||
ContextInvalid = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
NewUserInfo.Passwd = PasswdInput.NewPassword;
|
||||
ContextInvalid = !NewUserContext.Validate();
|
||||
StateHasChanged();
|
||||
}
|
||||
private void PwValidationChanged(object? sender, ValidationStateChangedEventArgs e)
|
||||
private void ContextValidationChanged(object? sender, ValidationStateChangedEventArgs e)
|
||||
{
|
||||
PwInvalid = true;
|
||||
if (!Utils.IsValidPasswd(Passwords.NewPassword))
|
||||
return;
|
||||
ContextInvalid = true;
|
||||
|
||||
PasswdContext.OnFieldChanged -= PwHandleFieldChanged!;
|
||||
PasswdContext.OnValidationStateChanged -= PwValidationChanged;
|
||||
NewUserContext.OnFieldChanged -= ContextHandleFieldChanged!;
|
||||
NewUserContext.OnValidationStateChanged -= ContextValidationChanged;
|
||||
|
||||
PasswdContext = new EditContext(Passwords);
|
||||
NewUserContext = new EditContext(NewUserInfo);
|
||||
|
||||
PasswdContext.OnFieldChanged += PwHandleFieldChanged!;
|
||||
PasswdContext.OnValidationStateChanged += PwValidationChanged;
|
||||
NewUserContext.OnFieldChanged += ContextHandleFieldChanged!;
|
||||
NewUserContext.OnValidationStateChanged += ContextValidationChanged;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Interceptor.DisposeEvent();
|
||||
PasswdContext.OnFieldChanged -= PwHandleFieldChanged!;
|
||||
PasswdContext.OnValidationStateChanged -= PwValidationChanged;
|
||||
NewUserContext.OnFieldChanged -= ContextHandleFieldChanged!;
|
||||
NewUserContext.OnValidationStateChanged -= ContextValidationChanged;
|
||||
}
|
||||
}
|
|
@ -19,9 +19,18 @@
|
|||
@attribute [Authorize(Roles = "Admin")]
|
||||
@page "/system/users"
|
||||
|
||||
<PageTitle>Admin User List Page</PageTitle>
|
||||
<PageTitle>Administrativ - Bruger liste</PageTitle>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>Administrativ - Bruger liste</h3>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="text-end">
|
||||
<a class="btn btn-primary" href="/system/users/create"><i class="bi-plus-lg"></i>Opret bruger</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3>Admin User List Page</h3>
|
||||
|
||||
<div class="list-group">
|
||||
<div class="list-group-item">
|
||||
|
|
|
@ -44,29 +44,29 @@ public partial class WarehouseOrderListPage : IDisposable
|
|||
OrderList = await FetchOrders(Status);
|
||||
}
|
||||
|
||||
private async Task GetStatusCallback(PStatus status)
|
||||
private async Task GetStatusCallback(ProcessStatus status)
|
||||
{
|
||||
Working = true;
|
||||
OrderList = new List<WarehouseOrderView>();
|
||||
switch (status)
|
||||
{
|
||||
case PStatus.None or PStatus.Accepted:
|
||||
case ProcessStatus.None or ProcessStatus.Printed:
|
||||
Header = "Ubehandlede ordrer";
|
||||
ReadyToShip = false;
|
||||
break;
|
||||
case PStatus.Picked:
|
||||
case ProcessStatus.Picked:
|
||||
Header = "Plukkede ordrer";
|
||||
ReadyToShip = false;
|
||||
break;
|
||||
case PStatus.Packed:
|
||||
case ProcessStatus.Packed:
|
||||
Header = "Pakkede ordrer";
|
||||
ReadyToShip = true;
|
||||
break;
|
||||
case PStatus.Shipped:
|
||||
case ProcessStatus.Shipped:
|
||||
break;
|
||||
case PStatus.All:
|
||||
case ProcessStatus.All:
|
||||
break;
|
||||
case PStatus.Express:
|
||||
case ProcessStatus.Express:
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(status), status, null);
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Debug",
|
||||
"System": "Information",
|
||||
"System": "Debug",
|
||||
"Microsoft": "Information"
|
||||
},
|
||||
"Debug": {
|
||||
|
|
24
Wonky.Entity/DTO/SubjectAssignment.cs
Normal file
24
Wonky.Entity/DTO/SubjectAssignment.cs
Normal file
|
@ -0,0 +1,24 @@
|
|||
|
||||
// Copyright (C) 2022 FCS Frede's Computer Services.
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
|
||||
//
|
||||
|
||||
namespace Wonky.Entity.DTO;
|
||||
|
||||
public class SubjectAssignment
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string UserId { get; set; }
|
||||
public bool Assigned { get; set; }
|
||||
}
|
39
Wonky.Entity/DTO/UserManagerCreate.cs
Normal file
39
Wonky.Entity/DTO/UserManagerCreate.cs
Normal file
|
@ -0,0 +1,39 @@
|
|||
|
||||
// Copyright (C) 2022 FCS Frede's Computer Services.
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
|
||||
//
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Wonky.Entity.DTO;
|
||||
|
||||
public class UserManagerCreate
|
||||
{
|
||||
[MaxLength(128)] public string CompanyId { get; set; } = "";
|
||||
[MaxLength(128)] public string ContactId { get; set; } = "";
|
||||
[Required(ErrorMessage = "Landekode skal udfyldes")][MaxLength(2, ErrorMessage = "Landekode er 2 bogstaver")] public string CountryCode { get; set; } = "";
|
||||
[MaxLength(128, ErrorMessage = "Kort beskrivelse på højst 128 tegn.")] public string Description { get; set; } = "";
|
||||
[Required(ErrorMessage = "Email adresse skal udfyldes")][MaxLength(255, ErrorMessage = "Der er afsat 255 tegn til email adressen")] public string Email { get; set; } = "";
|
||||
public bool EmailConfirmed { get; set; }
|
||||
public bool EShop { get; set; }
|
||||
[Required(ErrorMessage = "Fornavn skal udfyldes")][MaxLength(50, ErrorMessage = "Der er afsat 50 tegn til fornavn")] public string FirstName { get; set; } = "";
|
||||
[Required(ErrorMessage = "Efternavn skal udfyldes")][MaxLength(50, ErrorMessage = "Der er afsat 50 tegn til efternavn")] public string LastName { get; set; } = "";
|
||||
public bool LockoutEnabled { get; set; }
|
||||
public string Passwd { get; set; } = "";
|
||||
[Required(ErrorMessage = "Telefon nummer skal udfyldes")][MaxLength(20, ErrorMessage = "Der er afsat 20 tegn til telefon nummber")] public string PhoneNumber { get; set; } = "";
|
||||
[Required(ErrorMessage = "Medarbejder ID skal udfyldes")][MaxLength(20, ErrorMessage = "Der er afsat 20 tegn til medarbejder ID")] public string SalesRep { get; set; } = "";
|
||||
public string UserId { get; set; } = "";
|
||||
public List<UserRoleAssignment> AssignedRoles { get; set; } = new();
|
||||
public List<SubjectAssignment> AssignedSubjects { get; set; } = new();
|
||||
}
|
|
@ -22,17 +22,18 @@ public class UserManagerEditView
|
|||
{
|
||||
[MaxLength(128)] public string CompanyId { get; set; } = "";
|
||||
[MaxLength(128)] public string ContactId { get; set; } = "";
|
||||
[Required][MaxLength(3)] public string CountryCode { get; set; } = "";
|
||||
[MaxLength(128)] public string Description { get; set; } = "";
|
||||
[Required][MaxLength(255)] public string Email { get; set; } = "";
|
||||
[Required(ErrorMessage = "Landekode skal udfyldes")][MaxLength(2, ErrorMessage = "Landekode er 2 bogstaver")] public string CountryCode { get; set; } = "";
|
||||
[MaxLength(128, ErrorMessage = "Kort beskrivelse på højst 128 tegn.")] public string Description { get; set; } = "";
|
||||
[Required(ErrorMessage = "Email adresse skal udfyldes")][MaxLength(255, ErrorMessage = "Der er afsat 255 tegn til email adressen")] public string Email { get; set; } = "";
|
||||
public bool EmailConfirmed { get; set; }
|
||||
public bool EShop { get; set; }
|
||||
[Required][MaxLength(50)] public string FirstName { get; set; } = "";
|
||||
[Required][MaxLength(50)] public string LastName { get; set; } = "";
|
||||
[Required(ErrorMessage = "Fornavn skal udfyldes")][MaxLength(50, ErrorMessage = "Der er afsat 50 tegn til fornavn")] public string FirstName { get; set; } = "";
|
||||
[Required(ErrorMessage = "Efternavn skal udfyldes")][MaxLength(50, ErrorMessage = "Der er afsat 50 tegn til efternavn")] public string LastName { get; set; } = "";
|
||||
public bool LockoutEnabled { get; set; }
|
||||
public string Passwd { get; set; } = "";
|
||||
[Required][MaxLength(20)] public string PhoneNumber { get; set; } = "";
|
||||
[Required][MaxLength(20)] public string SalesRep { get; set; } = "";
|
||||
[Required(ErrorMessage = "Telefon nummer skal udfyldes")][MaxLength(20, ErrorMessage = "Der er afsat 20 tegn til telefon nummber")] public string PhoneNumber { get; set; } = "";
|
||||
[Required(ErrorMessage = "Medarbejder ID skal udfyldes")][MaxLength(20, ErrorMessage = "Der er afsat 20 tegn til medarbejder ID")] public string SalesRep { get; set; } = "";
|
||||
public string UserId { get; set; } = "";
|
||||
public List<UserRoleAssignment> AssignedRoles { get; set; } = new();
|
||||
public List<UserRoleAssignment> AssignedRoles { get; set; } = new();
|
||||
public List<SubjectAssignment> AssignedSubjects { get; set; } = new();
|
||||
}
|
Loading…
Reference in a new issue