added project files

This commit is contained in:
Frede Hundewadt 2022-03-11 14:21:04 +01:00
parent 866387fddf
commit 424dabe3ae
185 changed files with 8121 additions and 0 deletions

View file

@ -0,0 +1,13 @@
# Default ignored files
/shelf/
/workspace.xml
# Rider ignored files
/modules.xml
/projectSettingsUpdater.xml
/.idea.Wonky.Client.iml
/contentModel.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
</project>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="UserContentModel">
<attachedFolders />
<explicitIncludes />
<explicitExcludes />
</component>
</project>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="com.jetbrains.rider.android.RiderAndroidMiscFileCreationComponent">
<option name="ENSURE_MISC_FILE_EXISTS" value="true" />
</component>
</project>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

22
Wonky.Client.sln Normal file
View file

@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30114.105
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wonky.Client", "Wonky.Client\Wonky.Client.csproj", "{A001767F-6CA1-428E-938A-EA491A778D3E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A001767F-6CA1-428E-938A-EA491A778D3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A001767F-6CA1-428E-938A-EA491A778D3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A001767F-6CA1-428E-938A-EA491A778D3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A001767F-6CA1-428E-938A-EA491A778D3E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

35
Wonky.Client/App.razor Normal file
View file

@ -0,0 +1,35 @@
@using Wonky.Client.Shared
@*
// 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]
//
*@
<CascadingAuthenticationState>
<Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
<Authorizing>
<text>Checker autorisation ...</text>
</Authorizing>
</AuthorizeRouteView>
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<Page404 />
</LayoutView>
</NotFound>
</Router>
</CascadingAuthenticationState>

9
Wonky.Client/AppId.cs Normal file
View file

@ -0,0 +1,9 @@
namespace Wonky.Client;
public class AppId
{
public string Version { get; set; } = "0.2.1";
public string Name { get; set; } = "Inno Client";
public bool IsBeta { get; set; } = false;
}

View file

@ -0,0 +1,125 @@
// 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.Net.Http.Headers;
using System.Security.Claims;
using Blazored.LocalStorage;
using Microsoft.AspNetCore.Components.Authorization;
using Wonky.Entity.DTO;
namespace Wonky.Client.AuthProviders
{
public class AuthStateProvider : AuthenticationStateProvider
{
private readonly HttpClient _client;
private readonly ILocalStorageService _storage;
private readonly AuthenticationState _anonymous;
public AuthStateProvider(HttpClient client, ILocalStorageService storage)
{
_client = client;
_storage = storage;
_anonymous = new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
}
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
{
// fetch token from localStorage
var token = await _storage.GetItemAsync<string>("_tx");
if (string.IsNullOrEmpty(token))
// return anonymous if empty
return _anonymous;
// create an authorized user
var userInfo = await _storage.GetItemAsync<UserInfoDto>("_ux");
if (userInfo == null)
return _anonymous;
// set client authorization header
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", token);
var exp = await _storage.GetItemAsync<string>("_ex");
var roles = ExtractRoles(userInfo);
var claims = new List<Claim>
{
new(ClaimTypes.Name, userInfo.FullName),
new(ClaimTypes.Email, userInfo.Email),
new(ClaimTypes.MobilePhone, userInfo.PhoneNumber),
new(ClaimTypes.Expiration, exp)
};
claims.AddRange(roles.Select(role => new Claim(ClaimTypes.Role, role)));
// return the authState for the user
return new AuthenticationState(
new ClaimsPrincipal(
new ClaimsIdentity(claims, "token")));
}
public async void NotifyUserAuthenticationAsync(string token)
{
if (string.IsNullOrEmpty(token))
// do nothing
return;
// set client authorization header
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", token);
// create an authorized user
var userInfo = await _storage.GetItemAsync<UserInfoDto>("_ux");
var exp = await _storage.GetItemAsync<string>("_ex");
var roles = ExtractRoles(userInfo);
var claims = new List<Claim>
{
new(ClaimTypes.Name, userInfo.FullName),
new(ClaimTypes.Email, userInfo.Email),
new(ClaimTypes.MobilePhone, userInfo.PhoneNumber),
new(ClaimTypes.Expiration, exp)
};
claims.AddRange(roles.Select(role => new Claim(ClaimTypes.Role, role)));
// create authState
var authState = Task.FromResult(
new AuthenticationState(
new ClaimsPrincipal(
new ClaimsIdentity(claims, "token"))));
// send authState to notifier
NotifyAuthenticationStateChanged(authState);
}
public void NotifyUserLogout()
{
var authState = Task.FromResult(_anonymous);
NotifyAuthenticationStateChanged(authState);
}
private static IEnumerable<string> ExtractRoles(UserInfoDto userInfo)
{
var roles = new List<string>();
if (userInfo.IsAdmin)
roles.Add("Admin");
if (userInfo.IsAdviser)
roles.Add("Adviser");
if (userInfo.IsSupervisor)
roles.Add("Supervisor");
if(userInfo.IsEDoc)
roles.Add("EDoc");
if (userInfo.IsEShop)
roles.Add("EShop");
return roles;
}
}
}

View file

@ -0,0 +1,15 @@
@*// 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 Affero GNU 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
// Affero GNU General Public License for more details.
//
// You should have received a copy of the Affero GNU General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
//*@
<span class="version">@app.Name</span> <span class="version">@app.Version</span>@if(app.IsBeta){<span class="version">-beta</span>}

View file

@ -0,0 +1,6 @@
namespace Wonky.Client.Components;
public partial class AppVersion
{
private AppId app { get; set; } = new();
}

View file

@ -0,0 +1,27 @@
@*
// 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.Security.Claims
<AuthorizeView>
<Authorized>
@context.User.Identity.Name
<a href="Logout">Log af</a>
</Authorized>
<NotAuthorized>
<a href="Login">Log ind</a>
</NotAuthorized>
</AuthorizeView>

View file

@ -0,0 +1,25 @@
@*
// 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]
//
*@
<div class="row p-2 mb-1 border-bottom">
<div class="col-sm-1">Status</div>
<div class="col-sm-4">Navn</div>
<div class="col-sm-2">Konto</div>
<div class="col-sm-4">Bynavn</div>
<div class="col-sm-1"><i class="oi oi-info"></i></div>
</div>

View file

@ -0,0 +1,25 @@
@*
// 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]
//
*@
<div class="search-field">
<select class="form-control" @onchange="ApplyFilter">
<option value="name" selected>Navn</option>
<option value="zipCode">Postnr</option>
<option value="city">Bynavn</option>
<option value="account">Konto</option>
</select>
</div>

View file

@ -0,0 +1,33 @@
// 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 Microsoft.AspNetCore.Components;
namespace Wonky.Client.Components;
public partial class CompanySearchField
{
[Parameter]
public EventCallback<string> OnFilterChanged { get; set; }
private async Task ApplyFilter(ChangeEventArgs eventArgs)
{
if (eventArgs?.Value?.ToString() == "name")
return;
await OnFilterChanged.InvokeAsync(eventArgs?.Value?.ToString());
}
}

View file

@ -0,0 +1,3 @@
.search-field {
margin-bottom: 10px;
}

View file

@ -0,0 +1,25 @@
@*
// 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]
//
*@
<section>
<select class="form-control" @onchange="ApplySort">
<option value="-1">- sortering -</option>
<option value="name">Navn</option>
<option value="account">Konto</option>
<option value="city">Bynavn</option>
</select>
</section>

View file

@ -0,0 +1,35 @@
// 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 Microsoft.AspNetCore.Components;
namespace Wonky.Client.Components
{
public partial class CompanySort
{
[Parameter]
public EventCallback<string> OnSortChanged { get; set; }
private async Task ApplySort(ChangeEventArgs eventArgs)
{
if (eventArgs?.Value?.ToString() == "-1")
return;
await OnSortChanged.InvokeAsync(eventArgs?.Value?.ToString());
}
}
}

View file

@ -0,0 +1,69 @@
@*
// 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]
//
*@
@if (Companies.Any())
{
<CompanyListHeader />
@foreach (var company in Companies)
{
<div class="row p-2 mb-1 border-bottom">
<div class="col-sm-1"><RegStateVatNumber VatNumber="@company.VatNumber" /></div>
<div class="col-sm-4">@company.Name</div>
<div class="col-sm-2">@company.Account</div>
<div class="col-sm-4">@company.City</div>
<div class="col-sm-1"><a class="btn btn-sm btn-primary mb-1" href="/company/account/@company.Account"><i class="oi oi-arrow-circle-right"></i></a></div>
</div>
}
@*
<table class="table">
<thead>
<tr>
<th scope="col">Status</th>
<th scope="col">Navn</th>
<th scope="col">Konto</th>
<th scope="col">Bynavn</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var company in Companies)
{
<tr>
<td class="align-middle">
<CvrStatus VatNumber="@company.VatNumber" />
</td>
<td class="align-middle">
@company.Name
</td>
<td class="align-middle">
@company.Account
</td>
<td class="align-middle">
@company.City
</td>
<td class="align-middle">
<a class="btn btn-primary mb-1" href="/company/@company.Account"><i class="oi oi-arrow-circle-right"></i></a>
</td>
</tr>
}
</tbody>
</table>
*@
}
else
{
<div><img class="spinner" src="loader.gif" alt="Vent venligst..."/> Henter data...</div>
}

View file

@ -0,0 +1,44 @@
// 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 Microsoft.AspNetCore.Components;
using Wonky.Client.Shared;
using Wonky.Entity.DTO;
namespace Wonky.Client.Components
{
public partial class CompanyTable
{
[Parameter] public List<CompanyDto> Companies { get; set; } = new();
[Parameter] public EventCallback<string> OnDelete { get; set; }
private Confirmation _confirmation = new ();
private string _companyIdToDelete = string.Empty;
private void CallConfirmationModal(string companyId)
{
_companyIdToDelete = companyId;
_confirmation.Show();
}
private async Task DeleteProduct()
{
_confirmation.Hide();
await OnDelete.InvokeAsync(_companyIdToDelete);
}
}
}

View file

@ -0,0 +1,43 @@
@using Microsoft.Extensions.Logging
@implements IDisposable
<h1>@Title</h1>
<p>Current count: @CurrentCount</p>
@code {
[Parameter] public string Title { get; set; }
[Parameter] public int CurrentCount { get; set; }
[Inject] public ILogger<CounterPrint> Logger { get; set; }
protected override void OnInitialized()
{
Logger.Log(LogLevel.Information,$"OnInitialized => Title: {Title}, CurrentCount: {CurrentCount}");
}
protected override void OnParametersSet()
{
Logger.Log(LogLevel.Information,$"OnParameterSet => Title: {Title}, CurrentCount: {CurrentCount}");
}
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
Logger.Log(LogLevel.Information,"This is the first render of the component");
}
}
protected override bool ShouldRender()
{
return true;
}
public void Dispose()
{
Logger.Log(LogLevel.Information,"Component removed from the parnet's render tree.");
}
}

View file

@ -0,0 +1,19 @@
@*
// 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]
//
*@
<PageTitle>Forside</PageTitle>
<h1>@Title</h1>

View file

@ -0,0 +1,27 @@
// 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 Microsoft.AspNetCore.Components;
namespace Wonky.Client.Components
{
public partial class Home
{
[Parameter] public string Title { get; set; } = "Hej";
[Parameter] public RenderFragment? LoginContent { get; set; }
}
}

View file

@ -0,0 +1,26 @@
@*
// 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]
//
*@
<div class="form-group">
<select class="form-control" @onchange="OnPageSizeChange">
<option selected="selected">5</option>
<option>10</option>
<option>15</option>
<option>30</option>
<option>50</option>
</select>
</div>

View file

@ -0,0 +1,32 @@
// 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 Microsoft.AspNetCore.Components;
namespace Wonky.Client.Components
{
public partial class PageSizeDropDown
{
[Parameter]
public EventCallback<int> SelectedPageSize { get; set; }
private async Task OnPageSizeChange(ChangeEventArgs eventArgs)
{
await SelectedPageSize.InvokeAsync(int.Parse(eventArgs.Value?.ToString()!));
}
}
}

View file

@ -0,0 +1,4 @@
.form-control {
width: auto;
float: right;
}

View file

@ -0,0 +1,29 @@
@*
// 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]
//
*@
<nav arial-label="Pager">
<ul class="pagination justify-content-center">
@foreach (var link in _links)
{
<li @onclick="() => OnSelectedPage(link)" style="cursor: pointer"
class="page-item @(link.Enabled ? null : "disabled")
@(link.Active ? "active" : null)">
<span class="page-link" href="#">@link.Text</span>
</li>
}
</ul>
</nav>

View file

@ -0,0 +1,63 @@
// 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 Microsoft.AspNetCore.Components;
using Wonky.Client.Features;
using Wonky.Entity.Requests;
namespace Wonky.Client.Components
{
public partial class Pagination
{
[Parameter] public MetaData MetaData { get; set; } = new();
[Parameter] public int Spread { get; set; }
[Parameter] public EventCallback<int> SelectedPage { get; set; }
private List<PagingLink>? _links;
protected override void OnParametersSet()
{
CreatePaginationLinks();
}
private void CreatePaginationLinks()
{
_links = new List<PagingLink>
{
new(MetaData.CurrentPage - 1, MetaData.HasPrevious, "Forrige")
};
for (var i = 1; i <= MetaData.TotalPages; i++)
{
if (i >= MetaData.CurrentPage - Spread && i <= MetaData.CurrentPage + Spread)
{
_links.Add(new PagingLink(i, true, i.ToString()) {Active = MetaData.CurrentPage == i});
}
}
_links.Add(new PagingLink(MetaData.CurrentPage + 1, MetaData.HasNext, "Næste"));
}
private async Task OnSelectedPage(PagingLink link)
{
if (link.Page == MetaData.CurrentPage || !link.Enabled)
return;
MetaData.CurrentPage = link.Page;
await SelectedPage.InvokeAsync(link.Page);
}
}
}

View file

@ -0,0 +1,69 @@
@using Microsoft.AspNetCore.Components
@*
// 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]
//
*@
<EditForm EditContext="_editContext" OnValidSubmit="CreateLine" class="card card-body bg-light mt-5">
<DataAnnotationsValidator />
<div class="row mb-2">
<label for="sku" class="col-md-2 col-form-label">Varenummer</label>
<div class="col-md-10">
<InputText id="sku" class="form-control" @bind-Value="_orderLine.Sku" />
<ValidationMessage For="@(() => _orderLine.Sku)"></ValidationMessage>
</div>
</div>
<div class="row mb-2">
<label for="text" class="col-md-2 col-form-label">Tekst</label>
<div class="col-md-10">
<InputText id="text" class="form-control" @bind-Value="_orderLine.Text" />
<ValidationMessage For="@(() => _orderLine.Text)"></ValidationMessage>
</div>
</div>
<div class="row mb-2">
<label for="qty" class="col-md-2 col-form-label">Antal</label>
<div class="col-md-10">
<InputNumber id="qty" class="form-control" @bind-Value="_orderLine.Qty" />
<ValidationMessage For="@(() => _orderLine.Qty)"></ValidationMessage>
</div>
</div>
<div class="row mb-2">
<label for="price" class="col-md-2 col-form-label">Stk.pris</label>
<div class="col-md-10">
<InputNumber id="price" class="form-control" @bind-Value="_orderLine.Price" />
<ValidationMessage For="@(() => _orderLine.Price)"></ValidationMessage>
</div>
</div>
<div class="row mb-2">
<label for="discount" class="col-md-2 col-form-label">Rabat</label>
<div class="col-md-10">
<InputNumber id="discount" class="form-control" @bind-Value="_orderLine.Discount" />
<ValidationMessage For="@(() => _orderLine.Discount)"></ValidationMessage>
</div>
</div>
<div class="row mb-2">
<div class="col-md-12">
<button type="submit" class="btn btn-success">Opret</button>
</div>
</div>
</EditForm>

View file

@ -0,0 +1,41 @@
// 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 Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using Wonky.Client.Models;
using Wonky.Entity.DTO;
namespace Wonky.Client.Components;
public partial class PoLineCreate
{
private List<CrmActivityLine> Lines = new();
private CrmActivityLine _orderLine = new();
private EditContext _editContext;
[Parameter] public PurchaseOrder PurchaseOrder { get; set; }
protected override async Task OnInitializedAsync()
{
}
private void CreateLine()
{
Lines.Add(_orderLine);
}
}

View file

@ -0,0 +1,66 @@
@*
// 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]
//
*@
<div class="row">
<div class="col">
Varenr.
</div>
<div class="col">
Tekst
</div>
<div class="col">
Antal
</div>
<div class="col">
Stk.pris
</div>
<div class="col">
Rabat
</div>
<div class="col">
Linjesum
</div>
</div>
@if (Lines.Any())
{
foreach (var line in Lines)
{
<div class="row">
<div class="col">
@line.Sku
</div>
<div class="col">
@line.Text
</div>
<div class="col">
@line.Qty
</div>
<div class="col">
@line.Price
</div>
<div class="col">
@line.Discount
</div>
<div class="col">
@(line.Qty * (line.Price - (line.Price * line.Discount / 100 )))
</div>
<div class="col">
<button class="btn btn-warning">Slet linje</button>
</div>
</div>
}
}

View file

@ -0,0 +1,25 @@
// 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 Microsoft.AspNetCore.Components;
using Wonky.Entity.DTO;
namespace Wonky.Client.Components;
public partial class PurchaseOrderLinesTable
{
[Parameter] public List<CrmActivityLine> Lines { get; set; } = new();
}

View file

@ -0,0 +1,51 @@
@*
// 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]
//
*@
<div class="row">
<div class="col">
Id
</div>
<div class="col">
Konto
</div>
<div class="col">Firma</div>
<div class="col-sm-1"></div>
<div class="col-sm-1"></div>
<div class="col-sm-1"></div>
<div class="col-sm-1"></div>
</div>
@if (PurchaseOrders.Any())
{
@foreach (var order in PurchaseOrders)
{
<div class="row">
<div class="col">
@order.ActivityId
</div>
<div class="col">
@order.Account
</div>
<div class="col">
@order.Name
</div>
<div class="col-sm-1"><button class="btn btn-light">Vis</button></div>
<div class="col-sm-1"><button class="btn btn-warning">Slet</button></div>
<div class="col-sm-1"><button class="btn btn-primary">Tilbud</button></div>
<div class="col-sm-1"><button class="btn btn-success">Bestil</button></div>
</div>
}
}

View file

@ -0,0 +1,25 @@
// 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 Microsoft.AspNetCore.Components;
using Wonky.Client.Models;
namespace Wonky.Client.Components;
public partial class PurchaseOrderTable
{
[Parameter] public List<PurchaseOrder> PurchaseOrders { get; set; } = new();
}

View file

@ -0,0 +1,2 @@
body {
}

View file

@ -0,0 +1,37 @@
@*
// 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.Text.Encodings.Web
<div class="row">
<div class="col-md-3">
<button class="btn btn-primary text-nowrap" @onclick="GetCvrData" disabled="@CvrInvalid">Vis CVR data</button>
</div>
<div class="col-md-9">
<div style="@(HideMe ? "display:none" : "display:block")">
<div class="alert @(CurrentState == "NORMAL" ? "alert-success" : "alert-warning")">
<strong>CVR status @CurrentState</strong>
</div>
<ul class="list-group list-group-flush small">
<li class="list-group-item">@(string.IsNullOrEmpty(VirkRegInfo.Name) ? "" : VirkRegInfo.Name)</li>
<li class="list-group-item">@(string.IsNullOrEmpty(VirkRegInfo.CoName) ? "" : VirkRegInfo.CoName)</li>
<li class="list-group-item">@(string.IsNullOrEmpty(VirkRegInfo.Address) ? "" : VirkRegInfo.Address)</li>
<li class="list-group-item">@(string.IsNullOrEmpty(VirkRegInfo.ZipCode) ? "" : VirkRegInfo.ZipCode) @(string.IsNullOrEmpty(VirkRegInfo.City) ? "" : VirkRegInfo.City)</li>
</ul>
</div>
</div>
</div>

View file

@ -0,0 +1,47 @@
// 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 Microsoft.AspNetCore.Components;
using Wonky.Client.Services;
using Wonky.Entity.Models;
using Wonky.Entity.Requests;
namespace Wonky.Client.Components;
public partial class RegInfoCompany
{
[Inject] public VirkRegistryService VirkRegistryService { get; set; }
[Parameter] public string VatNumber { get; set; } = "";
private VirkRegInfo VirkRegInfo { get; set; } = new();
private bool HideMe = true;
private bool CvrInvalid => string.IsNullOrEmpty(VatNumber);
private VirkParams _virkParams = new();
private string CurrentState = "UKENDT";
private async Task GetCvrData()
{
_virkParams.VatNumber = VatNumber;
if (string.IsNullOrWhiteSpace(VirkRegInfo.VatNumber))
{
var result = await VirkRegistryService.QueryVirkRegistry(_virkParams);
if (result.Any())
{
CurrentState = VirkRegInfo.States[^1].State;
}
}
HideMe = !HideMe;
}
}

View file

@ -0,0 +1,111 @@
@*
// 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]
//
*@
<EditForm Model="AdrContext" OnValidSubmit="FetchAddressData">
<div class="row mb-3">
<DataAnnotationsValidator/>
<div class="col">
<input type="text" id="streetName" class="form-control" placeholder="Vejnavn"
@bind-value="AdrQuery.StreetName" required />
<ValidationMessage For="@(() => AdrQuery.StreetName)"></ValidationMessage>
</div>
<div class="col">
<input type="text" id="houseNumber" class="form-control" placeholder="Husnummer"
@bind-value="AdrQuery.HouseNumber" required/>
<ValidationMessage For="@(() => AdrQuery.HouseNumber)"></ValidationMessage>
</div>
<div class="col">
<input type="text" id="zipCode" class="form-control" placeholder="Postnummer"
@bind-value="AdrQuery.ZipCode" required/>
<ValidationMessage For="@(() => AdrQuery.ZipCode)"></ValidationMessage>
</div>
<div class="col">
<button class="btn btn-primary" type="submit">Vis</button>
</div>
</div>
</EditForm>
<div style="@(ShowAdrResult ? "" : "display:none;")">
@if (_adrInfos.Any())
{
<div class="row mb-3">
@foreach (var info in _adrInfos)
{
@if(info.Name == "INGEN DATA")
{
<div class="card mx-3 mb-3 col-sm-12 col-md-6 col-lg-4" style="width: 30rem;">
<div class="card-header">@info.Name</div>
</div>
}
else
{
<div class="card mx-3 mb-3 col-sm-12 col-md-6 col-lg-4 @(info.States[^1].State == "NORMAL" ? "border-success" : "border-warning")" style="width: 30rem;">
<div class="card-header @(info.States[^1].State == "NORMAL" ? "bg-success text-white" : "bg-light")">
<div class="card-title"><i class="@(info.States[^1].State == "NORMAL" ? "oi oi-check" : "oi oi-warning")"></i><span> @info.Name</span></div>
</div>
<div class="card-body">
<div class="row">
<div class="col-3 fw-bold">
Reg.nr.
</div>
<div class="col">
@info.VatNumber
</div>
</div>
<div class="row">
<div class="col-3 fw-bold">
Conavn
</div>
<div class="col">
@info.CoName
</div>
</div>
<div class="row">
<div class="col-3 fw-bold">
Adresse
</div>
<div class="col">
@info.Address
</div>
</div>
<div class="row">
<div class="col-3 fw-bold">
Postnr
</div>
<div class="col">
@info.ZipCode
</div>
</div>
<div class="row">
<div class="col-3 fw-bold">
Bynavn
</div>
<div class="col">
@info.City
</div>
</div>
</div>
</div>
}
}
</div>
}
else
{
<div>
<img class="spinner" src="/loader.gif" alt="Vent venligst..."/> Henter data...
</div>
}
</div>

View file

@ -0,0 +1,92 @@
// 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;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using Wonky.Client.HttpInterceptors;
using Wonky.Client.Services;
using Wonky.Entity.Models;
using Wonky.Entity.Requests;
namespace Wonky.Client.Components;
public partial class RegLookupAddress : IDisposable
{
private Query AdrQuery { get; set; } = new();
private EditContext AdrContext { get; set; }
private List<VirkRegInfo> _adrInfos { get; set; } = new();
private bool ShowAdrResult;
private bool AdrInvalid = true;
[Inject] public VirkRegistryService AdrQueryService { get; set; }
[Inject] public HttpInterceptorService Interceptor { get; set; }
protected override void OnInitialized()
{
ShowAdrResult = false;
AdrContext = new EditContext(AdrQuery);
AdrContext.OnFieldChanged += HandleAdrChanged;
AdrContext.OnValidationStateChanged += AdrValidationChanged;
Interceptor.RegisterEvent();
Interceptor.RegisterBeforeSendEvent();
}
private async Task FetchAddressData()
{
ShowAdrResult = true;
var query = new VirkParams
{
VatNumber = "",
HouseNumber = AdrQuery.HouseNumber,
StreetName = AdrQuery.StreetName,
ZipCode = AdrQuery.ZipCode
};
_adrInfos = await AdrQueryService.QueryVirkRegistry(query).ConfigureAwait(true);
}
private void HandleAdrChanged(object sender, FieldChangedEventArgs e)
{
AdrInvalid = !AdrContext.Validate();
StateHasChanged();
}
private void AdrValidationChanged(object sender, ValidationStateChangedEventArgs e)
{
AdrInvalid = true;
AdrContext.OnFieldChanged -= HandleAdrChanged;
AdrContext = new EditContext(AdrQuery);
AdrContext.OnFieldChanged += HandleAdrChanged;
AdrContext.NotifyValidationStateChanged();
}
public void Dispose()
{
Interceptor.DisposeEvent();
AdrContext.OnFieldChanged -= HandleAdrChanged;
AdrContext.OnValidationStateChanged -= AdrValidationChanged;
}
public class Query
{
[Required(ErrorMessage = "Vejnavn skal udfyldes", AllowEmptyStrings = false)]
public string StreetName { get; set; } = "";
[Required(ErrorMessage = "Husnummer skal udfyldes")]
public string HouseNumber { get; set; } = "";
[Required(ErrorMessage = "Postnummer skal udfyldes")]
public string ZipCode { get; set; } = "";
}
}

View file

@ -0,0 +1,11 @@
@media (min-width: 768px) and (max-width:991px){
.card-columns {
column-count: 3;
}
}
@media (min-width: 992px){
.card-columns {
column-count: 4;
}
}

View file

@ -0,0 +1,103 @@
@*
// 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]
//
*@
<EditForm EditContext="_regContext" OnValidSubmit="FetchRegData">
<DataAnnotationsValidator />
<div class="row mb-2">
<div class="col">
<InputText id="cvrLookup" class="form-control" placeholder="reg.nr. eks. 26991765"
@bind-Value="VatNumber" required />
<ValidationMessage For="@(() => VatNumber)"></ValidationMessage>
</div>
<div class="col">
<button class="btn btn-success" type="submit" autocomplete="off" >Vis</button>
</div>
</div>
</EditForm>
<div style="@(_showVatResult ? "" : "display:none;")">
@if (_vatInfos.Any())
{
<div class="row mb-3">
@foreach (var info in _vatInfos)
{
@if(info.Name == "INGEN DATA")
{
<div class="card mx-3 mb-3 col-sm-12 col-md-6 col-lg-4" style="width: 30rem;">
<div class="card-header">@info.Name</div>
</div>
}
else
{
<div class=" card mx-3 mb-3 col-sm-12 col-md-6 col-lg-4 @(info.States[^1].State == "NORMAL" ? "border-success" : "border-warning")" style="width: 30rem;">
<div class="card-header @(info.States[^1].State == "NORMAL" ? "bg-success text-white" : "bg-light")">
<div class="card-title"><i class="@(info.States[^1].State == "NORMAL" ? "oi oi-check" : "oi oi-warning")"></i><span> @info.Name</span></div>
</div>
<div class="card-body">
<div class="row">
<div class="col-3 fw-bold">
Reg.nr.
</div>
<div class="col">
@info.VatNumber
</div>
</div>
<div class="row">
<div class="col-3 fw-bold">
Conavn
</div>
<div class="col">
@info.CoName
</div>
</div>
<div class="row">
<div class="col-3 fw-bold">
Adresse
</div>
<div class="col">
@info.Address
</div>
</div>
<div class="row">
<div class="col-3 fw-bold">
Postnr
</div>
<div class="col">
@info.ZipCode
</div>
</div>
<div class="row">
<div class="col-3 fw-bold">
Bynavn
</div>
<div class="col">
@info.City
</div>
</div>
</div>
</div>
}
}
</div>
}
else
{
<div>
<img class="spinner" src="/loader.gif" alt="Vent venligst..."/> Henter data...
</div>
}
</div>

View file

@ -0,0 +1,82 @@
// 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;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using Wonky.Client.HttpInterceptors;
using Wonky.Client.Services;
using Wonky.Entity.Models;
using Wonky.Entity.Requests;
namespace Wonky.Client.Components;
public partial class RegLookupVatNo : IDisposable
{
private EditContext _regContext { get; set; }
private List<VirkRegInfo> _vatInfos { get; set; } = new();
private bool _showVatResult = true;
private bool _regInvalid = true;
[Required] private string VatNumber { get; set; } = "";
[Inject] private VirkRegistryService RegQueryService { get; set; }
[Inject] private HttpInterceptorService Interceptor { get; set; }
protected override void OnInitialized()
{
_showVatResult = false;
_regContext = new EditContext(VatNumber);
_regContext.OnFieldChanged += HandleRegChanged;
Interceptor.RegisterEvent();
Interceptor.RegisterBeforeSendEvent();
}
private void HandleRegChanged(object sender, FieldChangedEventArgs e)
{
_regInvalid = !_regContext.Validate();
StateHasChanged();
}
private async Task FetchRegData()
{
_showVatResult = true;
var query = new VirkParams
{
VatNumber = VatNumber,
HouseNumber = "",
StreetName = "",
ZipCode = ""
};
_vatInfos = await RegQueryService.QueryVirkRegistry(query).ConfigureAwait(true);
}
private void RegValidationChanged(object sender, ValidationStateChangedEventArgs e)
{
_vatInfos.Clear();
_regInvalid = true;
_regContext.OnFieldChanged -= HandleRegChanged;
_regContext = new EditContext(VatNumber);
_regContext.OnFieldChanged += HandleRegChanged;
_regContext.NotifyValidationStateChanged();
}
public void Dispose()
{
Interceptor.DisposeEvent();
_regContext.OnFieldChanged -= HandleRegChanged;
_regContext.OnValidationStateChanged -= RegValidationChanged;
}
}

View file

@ -0,0 +1,29 @@
@*
// 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]
//
*@
<div class="row">
<div class="col">
@if (string.IsNullOrEmpty(VatNumber))
{
<i class="text-primary oi oi- oi-question-mark"></i>
}
else
{
<i class="@(CurrentRegState == "NORMAL" ? "text-success oi oi-check" : "text-warning oi oi-warning" )"></i>
}
</div>
</div>

View file

@ -0,0 +1,46 @@
// 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 Microsoft.AspNetCore.Components;
using Wonky.Client.Services;
using Wonky.Entity.Models;
using Wonky.Entity.Requests;
namespace Wonky.Client.Components;
public partial class RegStateVatNumber
{
[Inject] public VirkRegistryService VirkRegistryService { get; set; }
[Parameter] public string VatNumber { get; set; } = "";
private VirkRegInfo VirkRegInfo { get; set; } = new();
private readonly VirkParams _virkParams = new();
private string CurrentRegState = "UKENDT";
protected override async Task OnParametersSetAsync()
{
_virkParams.VatNumber = VatNumber;
if (!string.IsNullOrEmpty(VatNumber))
{
var result = await VirkRegistryService.QueryVirkRegistry(_virkParams);
VirkRegInfo = result.Any() ? result[0] : new VirkRegInfo();
if (VirkRegInfo.States.Any())
CurrentRegState = VirkRegInfo.States[^1].State;
}
}
}

View file

@ -0,0 +1 @@


View file

@ -0,0 +1,28 @@
@*
// 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]
//
*@
<div class="group-filter">
<select class="form-control" @onchange="ApplyGroupFilter">
<option value="-1">standard</option>
<option value="1">Lim/Sealer/Rep</option>
<option value="2">Maling/Primer</option>
<option value="3">Smøremidler</option>
<option value="4">Polish/Cleaner</option>
<option value="5">Tape</option>
<option value="6">Diverse</option>
</select>
</div>

View file

@ -0,0 +1,30 @@
// 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 Microsoft.AspNetCore.Components;
namespace Wonky.Client.Components;
public partial class SalesItemGroupFilter
{
[Parameter] public EventCallback<string> OnGroupFilterChanged { get; set; }
private async Task ApplyGroupFilter(ChangeEventArgs eventArgs)
{
if (eventArgs?.Value?.ToString() == "-1")
return;
await OnGroupFilterChanged.InvokeAsync(eventArgs?.Value?.ToString());
}
}

View file

@ -0,0 +1,3 @@
.group-field {
margin-bottom: 10px;
}

View file

@ -0,0 +1,25 @@
@*
// 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]
//
*@
<div class="search-field">
<select class="form-control" @onchange="ApplySearchField">
<option value="-1">standard</option>
<option value="name" selected>Navn</option>
<option value="sku">Varenr</option>
<option value="shortName">Fork</option>
</select>
</div>

View file

@ -0,0 +1,30 @@
// 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 Microsoft.AspNetCore.Components;
namespace Wonky.Client.Components;
public partial class SalesItemSearchField
{
[Parameter] public EventCallback<string> OnSearchFieldChanged { get; set; }
private async Task ApplySearchField(ChangeEventArgs eventArgs)
{
if (eventArgs?.Value?.ToString() == "-1")
return;
await OnSearchFieldChanged.InvokeAsync(eventArgs?.Value?.ToString());
}
}

View file

@ -0,0 +1,3 @@
.search-field {
margin-bottom: 10px;
}

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]
//
*@
<section>
<select class="form-control" @onchange="ApplySort">
<option value="-1">standard</option>
<option value="itemName">Varenavn</option>
<option value="sku">Varenr</option>
</select>
</section>

View file

@ -0,0 +1,31 @@
// 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 Microsoft.AspNetCore.Components;
namespace Wonky.Client.Components;
public partial class SalesItemSort
{
[Parameter]
public EventCallback<string> OnSortFieldChanged { get; set; }
private async Task ApplySort(ChangeEventArgs eventArgs)
{
if (eventArgs?.Value?.ToString() == "-1")
return;
await OnSortFieldChanged.InvokeAsync(eventArgs?.Value?.ToString());
}
}

View file

@ -0,0 +1,61 @@
@*
// 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]
//
*@
@if (SalesItems.Any())
{
<table class="table table-hover table-striped justify-content-center">
<thead>
<tr>
<th scope="col" style="width: 50%;">Navn</th>
<th scope="col" style="width: 30%;" class="text-nowrap">Varenr</th>
<th scope="col" style="width: 20%">Stk / Pris</th>
</tr>
</thead>
<tbody>
@foreach (var salesItem in SalesItems)
{
<tr>
<td>
@salesItem.ItemName
</td>
<td>
@salesItem.ItemNumber
</td>
<td>
<ul class="list-group">
@foreach (var rate in salesItem.Rates)
{
<li class="list-group-item d-flex justify-content-between align-items-end">
<div class="px-2">@rate.Quantity</div>
<div class="text-end">@rate.Rate</div>
@if (PoDraftAccount != "")
{
<button class="btn btn-info" @onclick="AddToDraft">Læg til</button>
}
</li>
}
</ul>
</td>
</tr>
}
</tbody>
</table>
}
else
{
<div><img class="spinner" src="loader.gif" alt="Vent venligst..."/> Henter data...</div>
}

View file

@ -0,0 +1,31 @@
// 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 Blazored.Toast.Services;
using Microsoft.AspNetCore.Components;
using Wonky.Entity.DTO;
namespace Wonky.Client.Components;
public partial class SalesItemTable
{
[Parameter] public List<SalesItemDto> SalesItems { get; set; } = new();
[Parameter] public string PoDraftAccount { get; set; } = "";
[Inject] private IToastService ToastService { get; set; }
private void AddToDraft()
{
ToastService.ShowInfo("TODO: læg til ordre kladde");
}
}

View file

@ -0,0 +1,3 @@
.product-img {
width: 80px;
}

View file

@ -0,0 +1,22 @@
@*
// 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]
//
*@
<div class="search-input">
<input type="text" class="form-control" placeholder="Tekst ..."
@bind-value="@SearchTerm" @bind-value:event="oninput"
@onkeyup="SearchChanged"/>
</div>

View file

@ -0,0 +1,44 @@
// 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.Timers;
using Microsoft.AspNetCore.Components;
using Timer = System.Timers.Timer;
namespace Wonky.Client.Components
{
public partial class SearchPhrase
{
private Timer _timer = new();
public string SearchTerm { get; set; } = "";
[Parameter] public EventCallback<string> OnSearchChanged { get; set; }
private void SearchChanged()
{
_timer = new Timer(1000);
_timer.Elapsed += OnTimerElapsed;
_timer.AutoReset = false;
_timer.Enabled = true;
}
private void OnTimerElapsed(object? sender, ElapsedEventArgs e)
{
OnSearchChanged.InvokeAsync(SearchTerm);
_timer.Enabled = false;
_timer.Dispose();
}
}
}

View file

@ -0,0 +1,3 @@
.search-input {
margin-bottom: 10px;
}

View file

@ -0,0 +1,56 @@
using System.Security.Claims;
using System.Text.Json;
namespace Wonky.Client.Features;
public class JwtParser
{
public static IEnumerable<Claim> ParseClaimsFromJwt(string jwt)
{
var claims = new List<Claim>();
var payload = jwt.Split('.')[1];
var jsonBytes = ParseBase64WithoutPadding(payload);
var keyValuePairs = JsonSerializer
.Deserialize<Dictionary<string, object>>(jsonBytes);
ExtractRolesFromJwt(claims, keyValuePairs);
claims.AddRange(keyValuePairs!
.Select(kvp => new Claim(kvp.Key, kvp.Value.ToString())));
return claims;
}
private static void ExtractRolesFromJwt(List<Claim> claims,
Dictionary<string, object>? keyValuePairs)
{
keyValuePairs.TryGetValue(ClaimTypes.Role, out object roles);
if (roles == null) return;
var parsedRoles = roles.ToString().Trim()
.TrimStart('[').TrimEnd(']').Split(',');
if (parsedRoles.Length > 1)
{
claims.AddRange(parsedRoles
.Select(parsedRole => new Claim(ClaimTypes.Role, parsedRole.Trim('"'))));
}
else
{
claims.Add(new Claim(ClaimTypes.Role, parsedRoles[0]));
}
keyValuePairs.Remove(ClaimTypes.Role);
}
private static byte[] ParseBase64WithoutPadding(string base64)
{
switch (base64.Length % 4)
{
case 2: base64 += "=="; break;
case 3: base64 += "="; break;
}
return Convert.FromBase64String(base64);
}
}

View file

@ -0,0 +1,31 @@
// 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.Client.Features;
public class PagingLink
{
public string Text { get; set; }
public int Page { get; set; }
public bool Enabled { get; set; }
public bool Active { get; set; }
public PagingLink(int page, bool enabled, string text)
{
Page = page;
Enabled = enabled;
Text = text;
}
}

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]
//
using Wonky.Entity.Requests;
namespace Wonky.Client.Features;
public class PagingResponse<T> where T : class
{
public List<T>? Items { get; set; }
public MetaData? MetaData { get; set; }
}

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.Client.Helpers;
public static class Utils
{
public static int GetHashFromNow()
{
return DateTime.Now.ToFileTimeUtc().GetHashCode();
}
}

View file

@ -0,0 +1,109 @@
// 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.Net;
using System.Net.Http.Headers;
using Blazored.Toast.Services;
using Microsoft.AspNetCore.Components;
using Toolbelt.Blazor;
using Wonky.Client.Services;
namespace Wonky.Client.HttpInterceptors
{
public class HttpInterceptorService
{
private readonly HttpClientInterceptor _interceptor;
private readonly NavigationManager _navigation;
private readonly IToastService _toast;
private readonly RefreshTokenService _refreshTokenService;
private ILogger<HttpInterceptorService> _logger;
public HttpInterceptorService(HttpClientInterceptor interceptor,
NavigationManager navigation, IToastService toast,
RefreshTokenService refreshTokenService, ILogger<HttpInterceptorService> logger)
{
_interceptor = interceptor;
_navigation = navigation;
_toast = toast;
_refreshTokenService = refreshTokenService;
_logger = logger;
}
public void RegisterEvent()
{
_interceptor.AfterSend += AfterSend;
}
public void RegisterBeforeSendEvent()
{
_interceptor.BeforeSendAsync += InterceptBeforeSendAsync;
}
public void DisposeEvent()
{
_interceptor.AfterSend -= AfterSend;
_interceptor.BeforeSendAsync -= InterceptBeforeSendAsync;
}
public async Task InterceptBeforeSendAsync(object sender, HttpClientInterceptorEventArgs e)
{
var absolutePath = e.Request.RequestUri.AbsolutePath;
if (!absolutePath.Contains("token"))
{
// call TryRefreshToken
var token = await _refreshTokenService.TryRefreshToken();
if (!string.IsNullOrEmpty(token))
{
// set new token
e.Request.Headers.Authorization = new AuthenticationHeaderValue("bearer", token);
}
}
}
public void AfterSend (object sender, HttpClientInterceptorEventArgs e)
{
if (e.Response == null || e.Response.IsSuccessStatusCode)
return;
string? message;
var currDoc = _navigation.ToBaseRelativePath(_navigation.Uri);
switch (e.Response.StatusCode)
{
case HttpStatusCode.NotFound:
_navigation.NavigateTo("/404");
message = "404 - Page not found.";
break;
case HttpStatusCode.BadRequest:
_navigation.NavigateTo($"/login/{currDoc}");
message = "Verifikation nødvendig ...";
_toast.ShowInfo(message);
break;
case HttpStatusCode.Unauthorized:
_navigation.NavigateTo($"/login/{currDoc}");
message = "Verifikation nødvendig ...";
_toast.ShowInfo(message);
break;
default: _navigation.NavigateTo("/500");
message = "500 - Internal server error";
break;
}
throw new HttpResponseException(message);
}
}
}

View file

@ -0,0 +1,40 @@
// 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.Runtime.Serialization;
namespace Wonky.Client.HttpInterceptors
{
[Serializable]
public class HttpResponseException : Exception
{
public HttpResponseException()
{
}
public HttpResponseException(string message)
: base(message)
{
}
public HttpResponseException(string message, Exception innerException)
: base(message, innerException)
{
}
public HttpResponseException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
}
}

View file

@ -0,0 +1,110 @@
// 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.Net.Http.Json;
using System.Text.Json;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Options;
using Wonky.Client.Features;
using Wonky.Entity.Configuration;
using Wonky.Entity.DTO;
using Wonky.Entity.Requests;
#pragma warning disable CS8601
namespace Wonky.Client.HttpRepository;
public class CompanyHttpRepository : ICompanyHttpRepository
{
private readonly JsonSerializerOptions _options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
private readonly NavigationManager _navigation;
private ILogger<CompanyHttpRepository> _logger;
private readonly HttpClient _client;
private readonly ApiConfig _apiConfig;
public CompanyHttpRepository(HttpClient client,
ILogger<CompanyHttpRepository> logger,
NavigationManager navigation, IOptions<ApiConfig> apiConfig)
{
_client = client;
_logger = logger;
_navigation = navigation;
_apiConfig = apiConfig.Value;
}
public async Task<PagingResponse<CompanyDto>> GetCompanies(PagingParams pagingParameters)
{
var queryString = new Dictionary<string, string>
{
["pageNumber"] = pagingParameters.PageNumber.ToString(),
["pageSize"] = pagingParameters.PageSize.ToString(),
["searchTerm"] = string.IsNullOrEmpty(pagingParameters.SearchTerm) ? "" : pagingParameters.SearchTerm,
["orderBy"] = string.IsNullOrEmpty(pagingParameters.OrderBy) ? "" : pagingParameters.OrderBy,
["searchColumn"] = string.IsNullOrEmpty(pagingParameters.SearchColumn) ? "" : pagingParameters.SearchColumn
};
var response = await _client
.GetAsync(QueryHelpers.AddQueryString($"{_apiConfig.CrmCompanies}", queryString));
var content = await response.Content.ReadAsStringAsync();
var pagingResponse = new PagingResponse<CompanyDto>
{
Items = JsonSerializer.Deserialize<List<CompanyDto>>(content, _options),
MetaData = JsonSerializer.Deserialize<MetaData>(
response.Headers.GetValues("X-Pagination").First(), _options)
};
return pagingResponse;
}
public async Task<CompanyDto> GetCompanyByAccount(string accountNumber)
{
var company = await _client.GetFromJsonAsync<CompanyDto>(
$"{_apiConfig.CrmCompanies}/account/{accountNumber}");
return company ?? new CompanyDto();
}
public async Task<CompanyDto> GetCompanyById(string companyId)
{
var company = await _client.GetFromJsonAsync<CompanyDto>(
$"{_apiConfig.CrmCompanies}/id/{companyId}");
return company ?? new CompanyDto();
}
public async Task<string> CreateCompany(CompanyDto companyDto)
{
var response = await _client.PostAsJsonAsync(
$"{_apiConfig.CrmCompanies}", companyDto);
var content = await response.Content.ReadAsStringAsync();
var result = JsonSerializer.Deserialize<CompanyDto>(content);
return result.CompanyId;
}
public async Task UpdateCompany(CompanyDto companyDto)
{
await _client.PutAsJsonAsync(
$"{_apiConfig.CrmCompanies}/{companyDto.CompanyId}", companyDto);
}
public async Task DeleteCompany(string companyId)
{
await _client.DeleteAsync(
$"{_apiConfig.CrmCompanies}/{companyId}");
}
}

View file

@ -0,0 +1,30 @@
// 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 Wonky.Client.Features;
using Wonky.Entity.DTO;
using Wonky.Entity.Requests;
namespace Wonky.Client.HttpRepository;
public interface ICompanyHttpRepository
{
Task<PagingResponse<CompanyDto>> GetCompanies(PagingParams pagingParameters);
Task<CompanyDto> GetCompanyByAccount(string accountNumber);
Task<CompanyDto> GetCompanyById(string companyId);
Task<string> CreateCompany(CompanyDto companyDto);
Task UpdateCompany(CompanyDto companyDto);
Task DeleteCompany(string companyId);
}

View file

@ -0,0 +1,29 @@
// 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 Wonky.Client.Features;
using Wonky.Entity.DTO;
using Wonky.Entity.Requests;
namespace Wonky.Client.HttpRepository;
public interface IKrvProductHttpRepository
{
Task<PagingResponse<KrvProductDto>> GetProducts(PagingParams pagingParameters);
Task<KrvProductDto> GetProduct(string productId);
Task CreateProduct(KrvProductDto product);
Task<string> UploadImage(MultipartFormDataContent content, string productId);
Task UpdateProduct(KrvProductDto product);
}

View file

@ -0,0 +1,29 @@
// 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 Wonky.Client.Features;
using Wonky.Entity.DTO;
using Wonky.Entity.Requests;
namespace Wonky.Client.HttpRepository;
public interface IKrvVariantHttpRepository
{
Task<PagingResponse<KrvVariantDto>> GetVariants(PagingParams pagingParameters);
Task<KrvVariantDto> GetVariant(string variantId);
Task CreateVariant(KrvVariantDto variantDto);
Task<string> UploadImage(MultipartFormDataContent content, string variantId);
Task UpdateVariant(KrvVariantDto variant);
}

View file

@ -0,0 +1,26 @@
// 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 Wonky.Client.Features;
using Wonky.Entity.DTO;
using Wonky.Entity.Requests;
namespace Wonky.Client.HttpRepository;
public interface ISalesItemHttpRepository
{
Task<PagingResponse<SalesItemDto>> GetSalesItems(PagingParams pagingParameters);
Task<SalesItemDto> GetSalesItem(string id);
}

View file

@ -0,0 +1,108 @@
// 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.Net.Http.Json;
using System.Text.Json;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Options;
using Wonky.Client.Features;
using Wonky.Entity.Configuration;
using Wonky.Entity.DTO;
using Wonky.Entity.Requests;
namespace Wonky.Client.HttpRepository;
public class KrvProductHttpRepository : IKrvProductHttpRepository
{
private readonly JsonSerializerOptions? _options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
private readonly NavigationManager _navigation;
private ILogger<KrvProductHttpRepository> _logger;
private readonly HttpClient _client;
private readonly ApiConfig _apiConfig;
public KrvProductHttpRepository(HttpClient client,
ILogger<KrvProductHttpRepository> logger,
NavigationManager navigation, IOptions<ApiConfig> configuration)
{
_client = client;
_logger = logger;
_navigation = navigation;
_apiConfig = configuration.Value;
}
public async Task<PagingResponse<KrvProductDto>> GetProducts(PagingParams pagingParameters)
{
var queryString = new Dictionary<string, string>
{
["pageNumber"] = pagingParameters.PageNumber.ToString(),
["pageSize"] = pagingParameters.PageSize.ToString(),
["searchTerm"] = string.IsNullOrEmpty(pagingParameters.SearchTerm) ? "" : pagingParameters.SearchTerm,
["orderBy"] = string.IsNullOrEmpty(pagingParameters.OrderBy) ? "" : pagingParameters.OrderBy
};
var response = await _client
.GetAsync(QueryHelpers.AddQueryString($"{_apiConfig.KrvProducts}", queryString))
;
var content = await response.Content
.ReadAsStringAsync()
;
var pagingResponse = new PagingResponse<KrvProductDto>
{
Items = JsonSerializer.Deserialize<List<KrvProductDto>>(content, _options),
MetaData = JsonSerializer.Deserialize<MetaData>(
response.Headers.GetValues("X-Pagination").First(), _options)
};
return pagingResponse;
}
public async Task<KrvProductDto> GetProduct(string productId)
{
var product = await _client
.GetFromJsonAsync<KrvProductDto>($"{_apiConfig.KrvProducts}/get/id({productId})")
;
return product ?? new KrvProductDto();
}
public async Task CreateProduct(KrvProductDto productDto)
{
await _client
.PostAsJsonAsync($"{_apiConfig.KrvProducts}", productDto)
;
}
public async Task<string> UploadImage(MultipartFormDataContent content, string productId)
{
var postResult = await _client
.PostAsync($"{_apiConfig.ImageUpload}/products/id({productId})/image", content)
;
var postContent = await postResult.Content.ReadAsStringAsync();
return postContent;
}
public async Task UpdateProduct(KrvProductDto product)
{
Console.WriteLine(product.ProductId);
await _client.PutAsJsonAsync($"{_apiConfig.KrvProducts}/put/id({product.ProductId})", product);
}
}

View file

@ -0,0 +1,112 @@
// 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.Net.Http.Json;
using System.Text.Json;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Options;
using Wonky.Client.Features;
using Wonky.Entity.Configuration;
using Wonky.Entity.DTO;
using Wonky.Entity.Requests;
namespace Wonky.Client.HttpRepository;
public class KrvVariantHttpRepository : IKrvVariantHttpRepository
{
private readonly JsonSerializerOptions _options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
private readonly NavigationManager _navigation;
private ILogger<KrvVariantHttpRepository> _logger;
private readonly HttpClient _client;
private readonly ApiConfig _apiConfig;
public KrvVariantHttpRepository(HttpClient client,
ILogger<KrvVariantHttpRepository> logger,
NavigationManager navigation, IOptions<ApiConfig> configuration)
{
_client = client;
_logger = logger;
_navigation = navigation;
_apiConfig = configuration.Value;
}
public async Task<PagingResponse<KrvVariantDto>> GetVariants(PagingParams pagingParameters)
{
var queryString = new Dictionary<string, string>
{
["pageNumber"] = pagingParameters.PageNumber.ToString(),
["pageSize"] = pagingParameters.PageSize.ToString(),
["searchTerm"] = string.IsNullOrEmpty(pagingParameters.SearchTerm) ? "" : pagingParameters.SearchTerm,
["orderBy"] = string.IsNullOrEmpty(pagingParameters.OrderBy) ? "" : pagingParameters.OrderBy
};
var response = await _client
.GetAsync(QueryHelpers.AddQueryString($"{_apiConfig.KrvVariants}", queryString))
;
var content = await response.Content
.ReadAsStringAsync()
;
var pagingResponse = new PagingResponse<KrvVariantDto>
{
Items = JsonSerializer.Deserialize<List<KrvVariantDto>>(content, _options),
MetaData = JsonSerializer.Deserialize<MetaData>(
response.Headers.GetValues("X-Pagination").First(), _options)
};
return pagingResponse;
}
public async Task<KrvVariantDto> GetVariant(string variantId)
{
var variant = await _client
.GetFromJsonAsync<KrvVariantDto>($"{_apiConfig.KrvVariants}/get/id({variantId})")
;
return variant ?? new KrvVariantDto();
}
public async Task CreateVariant(KrvVariantDto variantDto)
{
await _client
.PostAsJsonAsync($"v2/", variantDto)
;
}
public async Task<string> UploadImage(MultipartFormDataContent content, string variantId)
{
Console.WriteLine($" Repo -> UploadImage -> {variantId}");
var postResult = await _client
.PostAsync($"{_apiConfig.ImageUpload}/variants/id({variantId})/image", content)
;
var postContent = await postResult.Content.ReadAsStringAsync();
Console.WriteLine(postContent);
return postContent;
}
public async Task UpdateVariant(KrvVariantDto variant)
{
Console.WriteLine(variant.VariantId);
await _client.PutAsJsonAsync($"{_apiConfig.KrvVariants}/put/id({variant.VariantId})", variant);
}
}

View file

@ -0,0 +1,79 @@
// 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.Net.Http.Json;
using System.Text.Json;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Options;
using Wonky.Client.Features;
using Wonky.Entity.Configuration;
using Wonky.Entity.DTO;
using Wonky.Entity.Requests;
namespace Wonky.Client.HttpRepository;
public class SalesItemHttpRepository : ISalesItemHttpRepository
{
private readonly JsonSerializerOptions _options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
private readonly NavigationManager _navigation;
private ILogger<SalesItemHttpRepository> _logger;
private readonly HttpClient _client;
private readonly ApiConfig _apiConfig;
public SalesItemHttpRepository(HttpClient client,
ILogger<SalesItemHttpRepository> logger,
NavigationManager navigation, IOptions<ApiConfig> configuration)
{
_client = client;
_logger = logger;
_navigation = navigation;
_apiConfig = configuration.Value;
}
public async Task<PagingResponse<SalesItemDto>> GetSalesItems(PagingParams pagingParameters)
{
var queryString = new Dictionary<string, string>
{
["pageNumber"] = pagingParameters.PageNumber.ToString(),
["pageSize"] = pagingParameters.PageSize.ToString(),
["searchTerm"] = string.IsNullOrEmpty(pagingParameters.SearchTerm) ? "" : pagingParameters.SearchTerm,
["orderBy"] = string.IsNullOrEmpty(pagingParameters.OrderBy) ? "" : pagingParameters.OrderBy
};
var response = await _client
.GetAsync(QueryHelpers.AddQueryString($"{_apiConfig.PriceCatalog}", queryString));
var content = await response.Content.ReadAsStringAsync();
var pagingResponse = new PagingResponse<SalesItemDto>
{
Items = JsonSerializer.Deserialize<List<SalesItemDto>>(content, _options),
MetaData = JsonSerializer.Deserialize<MetaData>(
response.Headers.GetValues("X-Pagination").First(), _options)
};
return pagingResponse;
}
public async Task<SalesItemDto> GetSalesItem(string id)
{
var salesItem = await _client
.GetFromJsonAsync<SalesItemDto>($"{_apiConfig.PriceCatalog}/{id}");
return salesItem ?? new SalesItemDto();
}
}

View file

@ -0,0 +1,49 @@
// 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;
using Wonky.Entity.DTO;
namespace Wonky.Client.Models
{
public class PurchaseOrder
{
public int ActivityId { get; set; }
public string CrmCompanyKey { get; set; } = "";
[Required(ErrorMessage = "Sælger skal udfyldes")] public string SalesRep { get; set; } = "";
// From company row
[Required(ErrorMessage = "Konto skal udfyldes")] public string Account { get; set; } = "";
[Required(ErrorMessage = "Moms nummer skal udfyldes")] public string VatNumber { get; set; } = "";
[Required(ErrorMessage = "Navn skal udfyldes")] public string Name { get; set; } = "";
public string Address { get; set; } = "";
public string Address2 { get; set; } = "";
[Required(ErrorMessage = "Bynavn skal udfyldes")] public string City { get; set; }= "";
[Required(ErrorMessage = "Postnummer skal udfyldes")] public string ZipCode { get; set; } = "";
public string Phone { get; set; } = "";
public string EMail { get; set; } = "";
// Form entries
public string ReferenceNumber { get; set; } = "";
[Required(ErrorMessage = "Indkøber skal udfyldes")] public string YourRef { get; set; } = "";
public string OurRef { get; set; } = "";
[MaxLength(255, ErrorMessage = "Du kan højst bruge 255 tegn")] public string OrderMessage { get; set; } = "";
// From company or form entry
public string DlvName { get; set; } = "";
public string DlvAddress1 { get; set; } = "";
public string DlvAddress2 { get; set; } = "";
public string DlvZipCode { get; set; } = "";
public string DlvCity { get; set; } = "";
public List<CrmActivityLine> Lines { get; set; } = new();
}
}

View file

@ -0,0 +1,28 @@
// 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.Client.Models;
public class PurchaseOrderLine
{
public int ActivityLineId { get; set; }
public int ActivityId { get; set; }
public string Sku { get; set; } = "";
public string Text { get; set; } = "";
public int Qty { get; set; }
public decimal Price { get; set; }
public decimal Discount { get; set; }
public decimal LineAmount { get; set; }
public int LineNumber { get; set; }
}

View file

@ -0,0 +1,26 @@
// 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.Client.Models
{
public class Quote
{
public int QuoteId { get; set; }
public string CompanyId { get; set; } = "";
public string Name { get; set; } = "";
public string EMail { get; set; } = "";
public List<QuoteItem> Items { get; set; } = new();
}
}

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.Client.Models;
public class QuoteItem
{
public string Sku { get; set; } = "";
public string Text { get; set; } = "";
public int Qty { get; set; }
public decimal Price { get; set; }
}

View file

@ -0,0 +1,6 @@
@page "/About"
<h3>Hvad er Wonky Online</h3>
Wonky Online er Innotec Danmarks egen udviklede ordresystem.
<AppVersion />

View file

@ -0,0 +1,10 @@
@page "/activites"
@using Client.V1.Components;
<h3>Salgs Aktivitet</h3>
<div class="row">
<div class="col">
<ActivityTable ActivityList="Activities" />
</div>
</div>

View file

@ -0,0 +1,16 @@
using System.Diagnostics;
using Microsoft.AspNetCore.Components;
namespace Wonky.Client.Pages;
public partial class ActivityList
{
public List<Activity> Activities { get; set; } = new();
[Inject] public ActivityDbContext DbContext { get; set; }
protected override async Task OnInitializedAsync()
{
Activities = await DbContext.GetAllActivities();
}
}

View file

@ -0,0 +1,23 @@
@*
// 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]
//
*@
@page "/CompanyActivity"
<h3>CompanyActivity</h3>
@code {
}

View file

@ -0,0 +1,146 @@
@*
// 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]
//
*@
@page "/create-company"
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components
@attribute [Authorize(Roles = "Adviser")]
<h2>Opret firma</h2>
<div class="row">
<div class="col-sm-12">
@if(_virkRegInfo.VatNumber != string.Empty)
{
foreach (var state in _virkRegInfo.States)
{
<div class="alert @(state.State == "INAKTIV" ? "alert-danger" : "alert-info")" role="alert">
<table class="table table-striped">
<tr>
<th scope="row">Status</th>
<td colspan="2"><strong>@state.State</strong></td>
</tr>
<tr>
<th scope="row">Opdateret</th>
<td colspan="2">@state.LastUpdate</td>
</tr>
<tr>
<th scope="row">Periode</th>
<th scope="row">Start</th>
<td>@state.TimeFrame.StartDate</td>
</tr>
<tr>
<th scope="row">Periode</th>
<th scope="row">Slut</th>
<td>@state.TimeFrame.EndDate</td>
</tr>
</table>
</div>
}
}
</div>
<div class="col-sm-12">
<EditForm EditContext="_cvrContext" OnValidSubmit="GetCvrDataFromVat">
<DataAnnotationsValidator />
<div class="form-group row mb-2">
<label for="cvrLookup" class="col-md-2 col-form-label">Cvr</label>
<div class="col">
<InputText id="cvrLookup" class="form-control" placeholder="CVR nummer" @bind-Value="VatToLookup"/>
</div>
<div class="col">
<button type="submit" class="btn btn-success btn-lg" disabled="@_cvrInvalid">Hent oplysninger</button>
</div>
</div>
</EditForm>
</div>
</div>
@* <EditForm Model="_company" OnValidSubmit="Create" class="card card-body bg-light mt-5"> *@
<EditForm EditContext="_editContext" OnValidSubmit="Create" class="card card-body bg-light mt-5">
<DataAnnotationsValidator />
@* <ValidationSummary /> *@
<InputText type="hidden" id="salesRepId" @bind-Value="_companyDto.SalesRepId"/>
<div class="form-group row mb-2">
<label for="name" class="col-md-2 col-form-label">Firmanavn</label>
<div class="col-md-10">
<InputText id="name" class="form-control" @bind-Value="_companyDto.Name"/>
<ValidationMessage For="@(() => _companyDto.Name)"></ValidationMessage>
</div>
</div>
<div class="form-group row mb-2">
<label for="address1" class="col-md-2 col-form-label">Adresse</label>
<div class="col-md-10">
<InputText id="address1" class="form-control" @bind-Value="_companyDto.Address1"/>
</div>
</div>
<div class="form-group row mb-2">
<label for="address2" class="col-md-2 col-form-label">Adresse</label>
<div class="col-md-10">
<InputText id="address2" class="form-control" @bind-Value="_companyDto.Address2"/>
</div>
</div>
<div class="form-group row mb-2">
<label for="zipCode" class="col-md-2 col-form-label">Postnr</label>
<div class="col-md-10">
<InputText id="zipCode" class="form-control" @bind-Value="_companyDto.ZipCode"/>
<ValidationMessage For="@(() => _companyDto.ZipCode)"></ValidationMessage>
</div>
</div>
<div class="form-group row mb-2">
<label for="city" class="col-md-2 col-form-label">Bynavn</label>
<div class="col-md-10">
<InputText id="city" class="form-control" @bind-Value="_companyDto.City"/>
<ValidationMessage For="@(() => _companyDto.City)"></ValidationMessage>
</div>
</div>
<div class="form-group row mb-2">
<label for="vatNumber" class="col-md-2 col-form-label">CVR/ORG</label>
<div class="col-md-10">
<InputText id="vatNumber" class="form-control" @bind-Value="_companyDto.VatNumber"/>
<ValidationMessage For="@(() => _companyDto.VatNumber)"></ValidationMessage>
</div>
</div>
<div class="form-group row mb-2">
<label for="phone" class="col-md-2 col-form-label">Telefon nummer</label>
<div class="col-md-10">
<InputText id="phone" class="form-control" @bind-Value="_companyDto.Phone"/>
</div>
</div>
<div class="form-group row mb-2">
<label for="mobile" class="col-md-2 col-form-label">Mobil nummer</label>
<div class="col-md-10">
<InputText id="mobile" class="form-control" @bind-Value="_companyDto.Mobile"/>
</div>
</div>
<div class="form-group row mb-2">
<label for="email" class="col-md-2 col-form-label">Email</label>
<div class="col-md-10">
<InputText id="email" class="form-control" @bind-Value="_companyDto.Email"/>
</div>
</div>
<div class="form-group row mb-2">
<label for="attention" class="col-md-2 col-form-label">Attention</label>
<div class="col-md-10">
<InputText id="attention" class="form-control" @bind-Value="_companyDto.Attention"/>
</div>
</div>
<div class="row mb-2">
<div class="col-md-12 text-right">
<button type="submit" class="btn btn-success" disabled="@_formInvalid">Opret</button>
</div>
</div>
</EditForm>

View file

@ -0,0 +1,127 @@
// 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;
using Blazored.LocalStorage;
using Blazored.Toast.Services;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using Wonky.Client.HttpInterceptors;
using Wonky.Client.HttpRepository;
using Wonky.Client.Services;
using Wonky.Entity.DTO;
using Wonky.Entity.Models;
using Wonky.Entity.Requests;
namespace Wonky.Client.Pages
{
public partial class CompanyCreate : IDisposable
{
private CompanyDto _companyDto = new();
private VirkRegInfo _virkRegInfo = new();
private EditContext _editContext;
private bool _formInvalid = true;
private EditContext _cvrContext;
private bool _cvrInvalid = true;
private VirkParams _virkParams = new();
[Required] public string VatToLookup { get; set; } = "";
[Inject] public ICompanyHttpRepository CompanyRepo { get; set; }
[Inject] public HttpInterceptorService Interceptor { get; set; }
[Inject] public IToastService ToastService { get; set; }
[Inject] public ILogger<CompanyCreate> Logger { get; set; }
[Inject] public VirkRegistryService VirkRegistryService { get; set; }
[Inject] public ILocalStorageService StorageService { get; set; }
[Inject] public NavigationManager Navigation { get; set; }
protected override async Task OnInitializedAsync()
{
_editContext = new EditContext(_companyDto);
_editContext.OnFieldChanged += HandleFieldChanged;
_cvrContext = new EditContext(VatToLookup);
_cvrContext.OnFieldChanged += HandleCvrChanged;
_cvrContext.OnValidationStateChanged += CvrValidationChanged;
var ux = await StorageService.GetItemAsync<UserInfoDto>("_ux");
_companyDto.SalesRepId = ux.Id;
Interceptor.RegisterEvent();
Interceptor.RegisterBeforeSendEvent();
}
private async Task GetCvrDataFromVat()
{
var result = await VirkRegistryService.QueryVirkRegistry(new VirkParams {VatNumber = VatToLookup}).ConfigureAwait(true);
if (!result.Any())
{
ToastService.ShowError($"Firma med CVR '{VatToLookup}' findes ikke.");
return;
}
ToastService.ShowSuccess($"Data for '{VatToLookup}' er hentet.");
_virkRegInfo = result[0];
_companyDto.Name = _virkRegInfo.Name;
_companyDto.Address1 = _virkRegInfo.CoName;
_companyDto.Address2 = _virkRegInfo.Address;
_companyDto.ZipCode = _virkRegInfo.ZipCode;
_companyDto.City = _virkRegInfo.City;
_companyDto.VatNumber = _virkRegInfo.VatNumber;
}
private async Task Create()
{
var newId = await CompanyRepo.CreateCompany(_companyDto);
ToastService.ShowSuccess($"Godt så! '{_companyDto.Name}' er oprettet i CRM.");
Navigation.NavigateTo($"/company/{newId}");
}
private void HandleCvrChanged(object sender, FieldChangedEventArgs e)
{
_cvrInvalid = !_cvrContext.Validate();
StateHasChanged();
}
private void CvrValidationChanged(object sender, ValidationStateChangedEventArgs e)
{
_cvrInvalid = true;
_cvrContext.OnFieldChanged -= HandleCvrChanged;
_cvrContext = new EditContext(VatToLookup);
_cvrContext.OnFieldChanged += HandleCvrChanged;
_cvrContext.OnValidationStateChanged -= CvrValidationChanged;
}
private void HandleFieldChanged(object sender, FieldChangedEventArgs e)
{
_formInvalid = !_editContext.Validate();
StateHasChanged();
}
private void ValidationChanged(object sender, ValidationStateChangedEventArgs e)
{
_formInvalid = true;
_editContext.OnFieldChanged -= HandleFieldChanged;
_editContext = new EditContext(_companyDto);
_editContext.OnFieldChanged += HandleFieldChanged;
_editContext.OnValidationStateChanged -= ValidationChanged;
}
public void Dispose()
{
Interceptor.DisposeEvent();
_editContext.OnFieldChanged -= HandleFieldChanged;
_editContext.OnValidationStateChanged -= ValidationChanged;
}
}
}

View file

@ -0,0 +1,23 @@
@*
// 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]
//
*@
@page "/CompanyInfo"
<h3>CompanyInfo</h3>
@code {
}

View file

@ -0,0 +1,23 @@
@*
// 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]
//
*@
@page "/CompanyKApv"
<h3>CompanyKApv</h3>
@code {
}

View file

@ -0,0 +1,53 @@
@*
// 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]
//
*@
@page "/companies"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Roles = "Adviser")]
<div class="row">
<div class="col">
<CompanySearchField OnFilterChanged="FilterChanged" />
</div>
<div class="col">
<SearchPhrase OnSearchChanged="SearchChanged"/>
</div>
<div class="col">
<CompanySort OnSortChanged="SortChanged"/>
</div>
<div class="col">
</div>
<div class="col">
<a class="btn btn-success mb-1" href="/create-company">Nyt firma</a>
</div>
</div>
<div class="row">
<div class="col-md-8">
<Pagination MetaData="MetaData" Spread="2" SelectedPage="SelectedPage"></Pagination>
</div>
<div class="col-md-2">
<PageSizeDropDown SelectedPageSize="SetPageSize" />
</div>
<div class="col-md-2">
</div>
</div>
<div class="row">
<div class="col">
<CompanyTable Companies="Companies" OnDelete="DeleteCompany"></CompanyTable>
</div>
</div>

View file

@ -0,0 +1,94 @@
// 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 Microsoft.AspNetCore.Components;
using Wonky.Client.HttpInterceptors;
using Wonky.Client.HttpRepository;
using Wonky.Entity.DTO;
using Wonky.Entity.Requests;
namespace Wonky.Client.Pages
{
public partial class CompanyList : IDisposable
{
public List<CompanyDto>? Companies { get; set; } = new();
public MetaData? MetaData { get; set; } = new();
private PagingParams _paging = new();
[Inject]
public ICompanyHttpRepository CompanyRepo { get; set; }
[Inject]
public HttpInterceptorService Interceptor { get; set; }
protected override async Task OnInitializedAsync()
{
Interceptor.RegisterEvent();
Interceptor.RegisterBeforeSendEvent();
await GetCompanies();
}
private async Task SelectedPage(int page)
{
_paging.PageNumber = page;
await GetCompanies();
}
private async Task GetCompanies()
{
var pagingResponse = await CompanyRepo.GetCompanies(_paging);
Companies = pagingResponse.Items;
MetaData = pagingResponse.MetaData;
}
private async Task FilterChanged(string? searchColumn)
{
_paging.SearchColumn = searchColumn;
_paging.PageNumber = 1;
await GetCompanies();
}
private async Task SetPageSize(int pageSize)
{
_paging.PageSize = pageSize;
_paging.PageNumber = 1;
await GetCompanies();
}
private async Task SearchChanged(string? searchTerm)
{
_paging.PageNumber = 1;
_paging.SearchTerm = searchTerm;
await GetCompanies();
}
private async Task SortChanged(string? orderBy)
{
_paging.OrderBy = orderBy;
await GetCompanies();
}
private async Task DeleteCompany(string companyId)
{
await CompanyRepo.DeleteCompany(companyId);
if (_paging.PageNumber > 1 && Companies.Count == 1)
_paging.PageNumber--;
await GetCompanies();
}
public void Dispose() => Interceptor.DisposeEvent();
}
}

View file

@ -0,0 +1,23 @@
@*
// 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]
//
*@
@page "/CompanyProducts"
<h3>CompanyProducts</h3>
@code {
}

View file

@ -0,0 +1,127 @@
@*
// 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]
//
*@
@page "/update-company/{account}"
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components
@attribute [Authorize(Roles = "Adviser")]
@if (_companyDto != null)
{
<div class="card">
<div class="card-header">
<h5>
@_companyDto.Name
</h5>
<span>@_companyDto.CompanyId</span>
</div>
@if (!string.IsNullOrEmpty(_companyDto.VatNumber))
{
<div class="card-body">
<RegInfocompany VatNumber="@_companyDto.VatNumber" />
</div>
}
<div class="card-body">
@* <EditForm Model="_company" OnValidSubmit="Create" class="card card-body bg-light mt-5"> *@
<EditForm EditContext="_editContext" OnValidSubmit="Update" class="card card-body bg-light mt-5">
<DataAnnotationsValidator/>
@* <ValidationSummary /> *@
<div class="form-group row mb-2">
<label for="name" class="col-md-2 col-form-label">Firmanavn</label>
<div class="col-md-10">
<InputText id="name" class="form-control" @bind-Value="_companyDto.Name"/>
<ValidationMessage For="@(() => _companyDto.Name)"></ValidationMessage>
</div>
</div>
<div class="form-group row mb-2">
<label for="address1" class="col-md-2 col-form-label">Adresse</label>
<div class="col-md-10">
<InputText id="address1" class="form-control" @bind-Value="_companyDto.Address1"/>
</div>
</div>
<div class="form-group row mb-2">
<label for="address2" class="col-md-2 col-form-label">Adresse</label>
<div class="col-md-10">
<InputText id="address2" class="form-control" @bind-Value="_companyDto.Address2"/>
</div>
</div>
<div class="form-group row mb-2">
<label for="zipCode" class="col-md-2 col-form-label">Postnr</label>
<div class="col-md-10">
<InputText id="zipCode" class="form-control" @bind-Value="_companyDto.ZipCode"/>
<ValidationMessage For="@(() => _companyDto.ZipCode)"></ValidationMessage>
</div>
</div>
<div class="form-group row mb-2">
<label for="city" class="col-md-2 col-form-label">Bynavn</label>
<div class="col-md-10">
<InputText id="city" class="form-control" @bind-Value="_companyDto.City"/>
<ValidationMessage For="@(() => _companyDto.City)"></ValidationMessage>
</div>
</div>
<div class="form-group row mb-2">
<label for="vatNumber" class="col-md-2 col-form-label">CVR/ORG</label>
<div class="col-md-10">
<InputText id="vatNumber" class="form-control" @bind-Value="_companyDto.VatNumber"/>
<ValidationMessage For="@(() => _companyDto.VatNumber)"></ValidationMessage>
</div>
</div>
<div class="form-group row mb-2">
<label for="phone" class="col-md-2 col-form-label">Telefon nummer</label>
<div class="col-md-10">
<InputText id="phone" class="form-control" @bind-Value="_companyDto.Phone"/>
</div>
</div>
<div class="form-group row mb-2">
<label for="mobile" class="col-md-2 col-form-label">Mobil nummer</label>
<div class="col-md-10">
<InputText id="mobile" class="form-control" @bind-Value="_companyDto.Mobile"/>
</div>
</div>
<div class="form-group row mb-2">
<label for="email" class="col-md-2 col-form-label">Email</label>
<div class="col-md-10">
<InputText id="email" class="form-control" @bind-Value="_companyDto.Email"/>
</div>
</div>
<div class="form-group row mb-2">
<label for="attention" class="col-md-2 col-form-label">Attention</label>
<div class="col-md-10">
<InputText id="attention" class="form-control" @bind-Value="_companyDto.Attention"/>
</div>
</div>
<div class="row mb-2">
<div class="col-md-12 text-right">
<button type="submit" class="btn btn-success" disabled="@_formInvalid">Send ændringer</button>
</div>
</div>
</EditForm>
</div>
<div class="card-footer">
<div class="row align-content-end">
<div class="col align-items-end">
<a class="btn btn-primary" href="/companies">Tilbage</a>
</div>
</div>
</div>
</div>
}
else
{
<div><img class="spinner" src="loader.gif" alt="Vent venligst..."/> Henter data...</div>
}

View file

@ -0,0 +1,65 @@
// 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 Blazored.Toast.Services;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using Wonky.Client.HttpInterceptors;
using Wonky.Client.HttpRepository;
using Wonky.Entity.DTO;
namespace Wonky.Client.Pages;
public partial class CompanyUpdate : IDisposable
{
private CompanyDto _companyDto;
private EditContext _editContext;
private bool _formInvalid = true;
[Inject] public ICompanyHttpRepository CompanyRepo { get; set; }
[Inject] public HttpInterceptorService Interceptor { get; set; }
[Inject] public IToastService ToastService { get; set; }
[Inject] public ILogger<CompanyCreate> Logger { get; set; }
[Inject] public NavigationManager Navigation { get; set; }
[Parameter] public string Account { get; set; } = null!;
protected override async Task OnInitializedAsync()
{
_companyDto = await CompanyRepo.GetCompanyByAccount(Account);
_editContext = new EditContext(_companyDto);
_editContext.OnFieldChanged += HandleFieldChanged!;
Interceptor.RegisterEvent();
Interceptor.RegisterBeforeSendEvent();
}
private async Task Update()
{
await CompanyRepo.UpdateCompany(_companyDto);
ToastService.ShowSuccess($"Godt så. Firma '{_companyDto!.Name}' er opdateret.");
Navigation.NavigateTo($"/company/{_companyDto.CompanyId}");
}
private void HandleFieldChanged(object sender, FieldChangedEventArgs e)
{
_formInvalid = !_editContext!.Validate();
StateHasChanged();
}
public void Dispose()
{
Interceptor.DisposeEvent();
_editContext.OnFieldChanged -= HandleFieldChanged!;
}
}

View file

@ -0,0 +1,96 @@
@*
// 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]
//
*@
@page "/company/account/{account}"
@page "/company/{companyId}"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Roles = "Adviser")]
<div class="card">
<div class="card-header">
<div class="row">
<div class="col">
<RegStateVatNumber VatNumber="@CompanyDto.VatNumber"/>
</div>
<div class="col">
@CompanyDto.Name
</div>
</div>
</div>
<div class="card-body">
<div class="row">
<div class="col">
<a class="btn btn-info" href="/company/@CompanyDto.Account/offer">Tilbud</a>
<a class="btn btn-info" href="#">Ordre</a>
<a class="btn btn-info" href="#">Faktura</a>
<a class="btn btn-info" href="#">Produkter</a>
</div>
</div>
</div>
<div class="card-body">
<table class="table table-striped table-bordered">
<tbody>
<tr>
<th scope="col">CVR</th>
<th scope="col">Telefon</th>
<th scope="col">Email</th>
</tr>
<tr>
<td>@CompanyDto.VatNumber</td>
<td>@CompanyDto.Phone</td>
<td>@CompanyDto.Email</td>
</tr>
<tr>
<th scope="row">Navn</th>
<td colspan="2">@CompanyDto.Name</td>
</tr>
<tr>
<th scope="row">Adresse</th>
<td colspan="2">@CompanyDto.Address1</td>
</tr>
<tr>
<th scope="row">Adresse</th>
<td colspan="2">@CompanyDto.Address2</td>
</tr>
<tr>
<th scope="row">Post By</th>
<td colspan="2">@CompanyDto.ZipCode @CompanyDto.City</td>
</tr>
<tr>
<th scope="col">Interval</th>
<th scope="col">Sidste besøg</th>
<th scope="col">Næste besøg</th>
</tr>
<tr>
<td>@CompanyDto.Interval</td>
<td>@($"{CompanyDto.LastVisitDate:dd-MM-yyyy}")</td>
<td>@($"{CompanyDto.NextVisitDate:dd-MM-yyyy}")</td>
</tr>
</tbody>
</table>
</div>
<div class="card-footer">
<div class="row">
<div class="col">
<a href="/update-company/@CompanyDto.Account" class="btn btn-primary">Rediger</a>
</div>
<div class="col align-content-end">
<a href="/companies" class="btn btn-primary">Tilbage</a>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,61 @@
// 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 Microsoft.AspNetCore.Components;
using Wonky.Client.HttpInterceptors;
using Wonky.Client.HttpRepository;
using Wonky.Entity.DTO;
namespace Wonky.Client.Pages;
public partial class CompanyView : IDisposable
{
private CompanyDto CompanyDto { get; set; } = new ();
[Inject]
public ICompanyHttpRepository CompanyRepo { get; set; }
[Inject]
public HttpInterceptorService Interceptor { get; set; }
[Parameter] public string Account { get; set; } = "";
[Parameter] public string CompanyId { get; set; } = "";
protected override async Task OnInitializedAsync()
{
Interceptor.RegisterEvent();
Interceptor.RegisterBeforeSendEvent();
if (!string.IsNullOrWhiteSpace(Account))
{
CompanyDto = await CompanyRepo.GetCompanyByAccount(Account);
}
else
{
if (!string.IsNullOrWhiteSpace(CompanyId))
{
CompanyDto = await CompanyRepo.GetCompanyById(CompanyId);
}
}
}
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
Interceptor!.DisposeEvent();
}
}

View file

@ -0,0 +1,25 @@
@*
// 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]
//
*@
@page "/"
@page "/index"
@inject IWebAssemblyHostEnvironment _hostEnvironment
<Home Title="Hej!"></Home>
@code{
}

View file

@ -0,0 +1,14 @@
@page "/krv-product/{productId}"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Roles = "Admin")]
<div class="card">
<div class="card-header">
<h1>@Product.TradingName</h1>
</div>
<div class="card-body">
<img class="image-preview" src="@Product.PictureLink" alt="@Product.TradingName"/>
</div>
<div class="card-footer">
<a href="/krvProducts" class="btn btn-success">Tilbage</a>
</div>
</div>

View file

@ -0,0 +1,36 @@
using Microsoft.AspNetCore.Components;
using Wonky.Client.HttpInterceptors;
using Wonky.Client.HttpRepository;
using Wonky.Entity.DTO;
namespace Wonky.Client.Pages.KrvAdmin;
public partial class KrvProduct : IDisposable
{
private KrvProductDto Product { get; set; } = new ();
[Inject]
public IKrvProductHttpRepository ProductRepo { get; set; }
[Inject]
public HttpInterceptorService Interceptor { get; set; }
[Parameter]
public string ProductId { get; set; } = "";
protected override async Task OnInitializedAsync()
{
Interceptor.RegisterEvent();
Interceptor.RegisterBeforeSendEvent();
Product = await ProductRepo.GetProduct(ProductId);
}
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
Interceptor.DisposeEvent();
}
}

View file

@ -0,0 +1,10 @@
/* product image preview */
.image-name {
margin-left: 10px;
}
.image-preview {
width: auto;
max-width: 200px;
height: 100px;
margin-top: 15px;
}

View file

@ -0,0 +1,35 @@
@page "/krv-products"
@using Client.V1.Components
@using Inno.Entities.RequestFeatures
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Roles = "Admin")]
<div class="row">
<div class="col-md-4">
<Search OnSearchChanged="SearchChanged"></Search>
</div>
<div class="col-md-4">
<SortKrvProducts OnSortChanged="SortChanged" />
</div>
<div class="col-md-2">
</div>
<div class="col-md-2">
@* <a class="btn btn-success mb-1" href="/createCompany">Nyt firma</a> *@
</div>
</div>
<div class="row">
<div class="col-md-8">
<Pagination MetaData="MetaData" Spread="2" SelectedPage="SelectedPage"></Pagination>
</div>
<div class="col-md-2">
<PageSizeDropDown SelectedPageSize="SetPageSize" />
</div>
<div class="col-md-2">
</div>
</div>
<div class="row">
<div class="col">
<KrvProductTable KrvProducts="KrvProducts"></KrvProductTable>
</div>
</div>

View file

@ -0,0 +1,64 @@
using Microsoft.AspNetCore.Components;
using Wonky.Client.HttpInterceptors;
using Wonky.Client.HttpRepository;
using Wonky.Entity.DTO;
using Wonky.Entity.Requests;
namespace Wonky.Client.Pages.KrvAdmin;
public partial class KrvProductList : IDisposable
{
public List<KrvProductDto> KrvProducts { get; set; } = new();
public MetaData? MetaData { get; set; } = new();
private PagingParams _paging = new();
[Inject]
public IKrvProductHttpRepository ProductRepo { get; set; }
[Inject]
public HttpInterceptorService Interceptor { get; set; }
protected override async Task OnInitializedAsync()
{
Interceptor.RegisterEvent();
Interceptor.RegisterBeforeSendEvent();
await GetKrvProducts();
}
private async Task SelectedPage(int page)
{
_paging.PageNumber = page;
await GetKrvProducts();
}
private async Task GetKrvProducts()
{
var pagingResponse = await ProductRepo.GetProducts(_paging);
KrvProducts = pagingResponse.Items;
MetaData = pagingResponse.MetaData;
}
private async Task SetPageSize(int pageSize)
{
_paging.PageSize = pageSize;
_paging.PageNumber = 1;
await GetKrvProducts();
}
private async Task SearchChanged(string? searchTerm)
{
_paging.PageNumber = 1;
_paging.SearchTerm = searchTerm;
await GetKrvProducts();
}
private async Task SortChanged(string? orderBy)
{
_paging.OrderBy = orderBy;
await GetKrvProducts();
}
public void Dispose() => Interceptor.DisposeEvent();
}

Some files were not shown because too many files have changed in this diff Show more