WIP user management

This commit is contained in:
Frede Hundewadt 2023-03-04 12:14:21 +01:00
parent 5feffbb068
commit fed3ea2112
39 changed files with 373 additions and 245 deletions

View file

@ -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>

View file

@ -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();

View file

@ -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>

View file

@ -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();

View file

@ -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);
}
}

View file

@ -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>

View file

@ -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();

View file

@ -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>
}

View file

@ -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()
{

View file

@ -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>

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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

View file

@ -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)

View 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; }
}

View 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; } = "";
}

View file

@ -16,7 +16,7 @@
namespace Wonky.Client.Models;
public enum PTarget
public enum PrintTarget
{
None,
All,

View file

@ -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
}

View file

@ -16,7 +16,7 @@
namespace Wonky.Client.Models;
public enum PSort
public enum ProductSort
{
None,
Desc,

View file

@ -25,5 +25,5 @@ public class QuoteCallbackArgs
/// <summary>
/// QStatus
/// </summary>
public QStatus Status { get; set; }
public QuoteStatus Status { get; set; }
}

View file

@ -16,10 +16,10 @@
namespace Wonky.Client.Models;
public enum QStatus
public enum QuoteStatus
{
None,
Win,
Order,
Lose,
Archive,
Note,

View file

@ -1,9 +1,9 @@
namespace Wonky.Client.Models;
public enum VType
public enum ValidateType
{
Id,
ISODate,
IsoDate,
Passwd,
Email
}

View file

@ -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>

View file

@ -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();

View file

@ -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>

View file

@ -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();

View file

@ -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>

View file

@ -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);

View file

@ -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();

View file

@ -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>

View file

@ -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();

View file

@ -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/>
}
}

View file

@ -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;
}
}

View file

@ -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">

View file

@ -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);

View file

@ -9,7 +9,7 @@
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"System": "Debug",
"Microsoft": "Information"
},
"Debug": {

View 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; }
}

View 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();
}

View file

@ -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();
}