This commit is contained in:
Thomas Peterson 2024-11-19 20:16:45 +01:00
parent e002a7458c
commit a873f39c86
28 changed files with 329 additions and 72 deletions

View File

@ -0,0 +1 @@
PSCHelpdesk

View File

@ -11,8 +11,16 @@
</component>
<component name="ChangeListManager">
<list default="true" id="95257dc5-08bd-4c50-8726-85956b3c2c92" name="Changes" comment="">
<change beforePath="$PROJECT_DIR$/.idea/.idea.PSCHelpdesk/.idea/.name" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/.idea.PSCHelpdesk/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.PSCHelpdesk/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/FastBill/Api/Customers.cs" beforeDir="false" afterPath="$PROJECT_DIR$/FastBill/Api/Customers.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/FastBill/FastBill.csproj" beforeDir="false" afterPath="$PROJECT_DIR$/FastBill/FastBill.csproj" afterDir="false" />
<change beforePath="$PROJECT_DIR$/FastBill/Models/Customer.cs" beforeDir="false" afterPath="$PROJECT_DIR$/FastBill/Models/Customer.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/FastBill/Models/Settings.cs" beforeDir="false" afterPath="$PROJECT_DIR$/FastBill/Models/Settings.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/FastBill/Services/CustomerService.cs" beforeDir="false" afterPath="$PROJECT_DIR$/FastBill/Services/CustomerService.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/FastBill/ViewModels/CustomerViewModel.cs" beforeDir="false" afterPath="$PROJECT_DIR$/FastBill/ViewModels/CustomerViewModel.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/FastBill/Views/CustomerView.axaml" beforeDir="false" afterPath="$PROJECT_DIR$/FastBill/Views/CustomerView.axaml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/HetznerServer/Models/Server.cs" beforeDir="false" afterPath="$PROJECT_DIR$/HetznerServer/Models/Server.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/HetznerServer/Models/ServerSetting.cs" beforeDir="false" afterPath="$PROJECT_DIR$/HetznerServer/Models/ServerSetting.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/HetznerServer/Service/ServerService.cs" beforeDir="false" afterPath="$PROJECT_DIR$/HetznerServer/Service/ServerService.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/HetznerServer/Views/ServerDetailView.axaml" beforeDir="false" afterPath="$PROJECT_DIR$/HetznerServer/Views/ServerDetailView.axaml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/_dist/hetzner/HetznerServer.dll" beforeDir="false" afterPath="$PROJECT_DIR$/_dist/hetzner/HetznerServer.dll" afterDir="false" />
@ -71,40 +79,40 @@
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">{
&quot;keyToString&quot;: {
&quot;.NET Project.PSCHelpdesk.Desktop ohne plugin.executor&quot;: &quot;Run&quot;,
&quot;.NET Project.PSCHelpdesk.Desktop.executor&quot;: &quot;Run&quot;,
&quot;Publish to folder.Build HetznerServer Plugin Debug.executor&quot;: &quot;Run&quot;,
&quot;Publish to folder.Copy Fastbill.executor&quot;: &quot;Run&quot;,
&quot;Publish to folder.Copy Hetzner Target.executor&quot;: &quot;Run&quot;,
&quot;Publish to folder.Copy Hetzner.executor&quot;: &quot;Run&quot;,
&quot;Publish to folder.Copy NextCloud Target.executor&quot;: &quot;Run&quot;,
&quot;Publish to folder.Copy NextCloud.executor&quot;: &quot;Run&quot;,
&quot;Publish to folder.Copy PrinshopCreator.executor&quot;: &quot;Run&quot;,
&quot;Publish to folder.Publish HetznerServer to folder.executor&quot;: &quot;Run&quot;,
&quot;Publish to folder.Publish NextCloud to folder.executor&quot;: &quot;Run&quot;,
&quot;Publish to folder.Publish Nextcloud to folder.executor&quot;: &quot;Run&quot;,
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
&quot;RunOnceActivity.git.unshallow&quot;: &quot;true&quot;,
&quot;XThreadsFramesViewSplitterKey&quot;: &quot;0.4427131&quot;,
&quot;git-widget-placeholder&quot;: &quot;master&quot;,
&quot;ignore.virus.scanning.warn.message&quot;: &quot;true&quot;,
&quot;last_opened_file_path&quot;: &quot;/home/thomas/RiderProjects/PSCHelpdesk/PSCHelpdesk/PSCHelpdesk.Desktop/bin/Debug/net9.0/plugins&quot;,
&quot;node.js.detected.package.eslint&quot;: &quot;true&quot;,
&quot;node.js.detected.package.tslint&quot;: &quot;true&quot;,
&quot;node.js.selected.package.eslint&quot;: &quot;(autodetect)&quot;,
&quot;node.js.selected.package.tslint&quot;: &quot;(autodetect)&quot;,
&quot;nodejs_package_manager_path&quot;: &quot;npm&quot;,
&quot;settings.editor.selected.configurable&quot;: &quot;preferences.pluginManager&quot;,
&quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
".NET Project.PSCHelpdesk.Desktop ohne plugin.executor": "Run",
".NET Project.PSCHelpdesk.Desktop.executor": "Run",
"Publish to folder.Build HetznerServer Plugin Debug.executor": "Run",
"Publish to folder.Copy Fastbill.executor": "Run",
"Publish to folder.Copy Hetzner Target.executor": "Run",
"Publish to folder.Copy Hetzner.executor": "Run",
"Publish to folder.Copy NextCloud Target.executor": "Run",
"Publish to folder.Copy NextCloud.executor": "Run",
"Publish to folder.Copy PrinshopCreator.executor": "Run",
"Publish to folder.Publish HetznerServer to folder.executor": "Run",
"Publish to folder.Publish NextCloud to folder.executor": "Run",
"Publish to folder.Publish Nextcloud to folder.executor": "Run",
"RunOnceActivity.ShowReadmeOnStart": "true",
"RunOnceActivity.git.unshallow": "true",
"XThreadsFramesViewSplitterKey": "0.4427131",
"git-widget-placeholder": "master",
"ignore.virus.scanning.warn.message": "true",
"last_opened_file_path": "/home/thomas/RiderProjects/PSCHelpdesk/PSCHelpdesk/PSCHelpdesk.Desktop/bin/Debug/net9.0/plugins",
"node.js.detected.package.eslint": "true",
"node.js.detected.package.tslint": "true",
"node.js.selected.package.eslint": "(autodetect)",
"node.js.selected.package.tslint": "(autodetect)",
"nodejs_package_manager_path": "npm",
"settings.editor.selected.configurable": "preferences.pluginManager",
"vue.rearranger.settings.migration": "true"
},
&quot;keyToStringList&quot;: {
&quot;com.intellij.ide.scratch.ScratchImplUtil$2/New Scratch File&quot;: [
&quot;Shell Script&quot;
"keyToStringList": {
"com.intellij.ide.scratch.ScratchImplUtil$2/New Scratch File": [
"Shell Script"
]
}
}</component>
}]]></component>
<component name="RunManager" selected=".NET Project.PSCHelpdesk.Desktop">
<configuration name="Copy Fastbill" type="DotNetFolderPublish" factoryName="Publish to folder">
<riderPublish configuration="Debug" platform="Any CPU" runtime="Portable" target_folder="$PROJECT_DIR$/_dist/fastbill" target_framework="net9.0" uuid_high="-7209100147811201171" uuid_low="-5152034027148450759" />
@ -204,6 +212,7 @@
<item itemvalue=".NET Project.PSCHelpdesk.Browser" />
<item itemvalue=".NET Project.PSCHelpdesk.Desktop" />
<item itemvalue=".NET Project.PSCHelpdesk.Desktop ohne plugin" />
<item itemvalue="Android.PSCHelpdesk.Android" />
<item itemvalue="iOS.PSCHelpdesk.iOS" />
<item itemvalue="Publish to folder.Copy NextCloud" />
<item itemvalue="Publish to folder.Copy Fastbill" />
@ -243,6 +252,7 @@
<workItem from="1731924310645" duration="5978000" />
<workItem from="1731934744692" duration="8712000" />
<workItem from="1731959435583" duration="1827000" />
<workItem from="1732006290483" duration="14905000" />
</task>
<servers />
</component>
@ -378,33 +388,12 @@
</properties>
<option name="timeStamp" value="204" />
</line-breakpoint>
<line-breakpoint enabled="true" type="DotNet Breakpoints">
<url>file://$PROJECT_DIR$/FastBill/Api/Customers.cs</url>
<line>18</line>
<properties documentPath="C:\Users\info\RiderProjects\pschelpdesk\FastBill\Api\Customers.cs" containingFunctionPresentation="Method 'SearchCustomer'">
<startOffsets>
<option value="702" />
</startOffsets>
<endOffsets>
<option value="758" />
</endOffsets>
</properties>
<option name="timeStamp" value="212" />
</line-breakpoint>
<line-breakpoint enabled="true" type="DotNet Breakpoints">
<url>file://$PROJECT_DIR$/FastBill/Api/Customers.cs</url>
<line>20</line>
<properties documentPath="C:\Users\info\RiderProjects\pschelpdesk\FastBill\Api\Customers.cs" containingFunctionPresentation="Method 'SearchCustomer'">
<startOffsets>
<option value="781" />
</startOffsets>
<endOffsets>
<option value="802" />
</endOffsets>
</properties>
<option name="timeStamp" value="213" />
</line-breakpoint>
</breakpoints>
</breakpoint-manager>
<pin-to-top-manager>
<pinned-members>
<PinnedItemInfo parentTag="Type#FastBill.Api.Response.SearchCustomer" memberName="Response" />
</pinned-members>
</pin-to-top-manager>
</component>
</project>

28
FastBill/Api/Contacts.cs Normal file
View File

@ -0,0 +1,28 @@
using FastBill.Api.Response;
using FastBill.Models;
using RestSharp;
using RestSharp.Authenticators;
using Contact = FastBill.Models.Contact;
namespace FastBill.Api;
public class Contacts
{
async public Task<List<Contact>> GetContacts(Settings settings, string customerId)
{
var customers = new List<Contact>();
var client = new RestClient("https://my.fastbill.com/");
var request = new RestRequest("api/1.0/api.php"){
Authenticator = new HttpBasicAuthenticator(settings.EMail, settings.ApiKey)
};
request.AddJsonBody(new { SERVICE = "contact.get", FILTER = new { CUSTOMER_ID = customerId } });
var response = await client.ExecuteAsync<GetContacts>(request);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
return response.Data.Response.Contacts;
}
return customers;
}
}

View File

@ -1,6 +1,8 @@
using FastBill.Models;
using FastBill.Api.Response;
using FastBill.Models;
using RestSharp;
using RestSharp.Authenticators;
using Customer = FastBill.Models.Customer;
namespace FastBill.Api;
@ -15,10 +17,10 @@ public class Customers
Authenticator = new HttpBasicAuthenticator(settings.EMail, settings.ApiKey)
};
request.AddJsonBody(new { SERVICE = "customer.get", FILTER = new { TERM = term } });
var response = await client.ExecuteAsync<List<Customer>>(request);
var response = await client.ExecuteAsync<SearchCustomer>(request);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
return response.Data;
return response.Data.Response.Customers;
}
return customers;

View File

@ -0,0 +1,6 @@
namespace FastBill.Api.Request;
public class GetContacts
{
public string Service = "";
}

View File

@ -0,0 +1,6 @@
namespace FastBill.Api.Request;
public class SearchCustomer
{
public string Service = "";
}

View File

@ -0,0 +1,9 @@
using System.Text.Json.Serialization;
namespace FastBill.Api.Response;
public class Contact
{
[JsonPropertyName("CONTACTS")]
public List<Models.Contact> Contacts { get; set; } = new List<Models.Contact>();
}

View File

@ -0,0 +1,6 @@
namespace FastBill.Api.Response;
public class Customer
{
public List<Models.Customer> Customers { get; set; } = new List<Models.Customer>();
}

View File

@ -0,0 +1,9 @@
namespace FastBill.Api.Response;
public class GetContacts
{
public Request.GetContacts Request { get; set; }
public Contact Response { get; set; }
}

View File

@ -0,0 +1,9 @@
namespace FastBill.Api.Response;
public class SearchCustomer
{
public Request.SearchCustomer Request { get; set; }
public Customer Response { get; set; }
}

View File

@ -16,4 +16,10 @@
<PackageReference Include="RestSharp" Version="112.1.0" />
</ItemGroup>
<ItemGroup>
<Reference Include="Avalonia.Controls.DataGrid">
<HintPath>..\..\..\.nuget\packages\avalonia.controls.datagrid\11.2.0\lib\net8.0\Avalonia.Controls.DataGrid.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

View File

@ -0,0 +1,29 @@
using System.Text.Json.Serialization;
namespace FastBill.Models;
public class Contact
{
[JsonPropertyName("CONTACT_ID")]
public string Id { get; set; }
[JsonPropertyName("CUSTOMER_TYPE")]
public string Type { get; set; }
[JsonPropertyName("ORGANIZATION")]
public string Company { get; set; }
[JsonPropertyName("FIRST_NAME")]
public string Firstname { get; set; }
[JsonPropertyName("LAST_NAME")]
public string Lastname { get; set; }
[JsonPropertyName("ADDRESS")]
public string Address { get; set; }
[JsonPropertyName("ZIPCODE")]
public string Zip { get; set; }
[JsonPropertyName("CITY")]
public string City { get; set; }
[JsonPropertyName("PHONE")]
public string Phone { get; set; }
[JsonPropertyName("MOBILE")]
public string Mobile { get; set; }
[JsonPropertyName("EMAIL")]
public string EMail { get; set; }
}

View File

@ -1,7 +1,35 @@
namespace FastBill.Models;
using System.Text.Json.Serialization;
namespace FastBill.Models;
public class Customer
{
public string CustomerNr { get; set; }
public string CustomerId { get; set; }
[JsonPropertyName("CUSTOMER_NUMBER")]
public string Nr { get; set; }
[JsonPropertyName("CUSTOMER_ID")]
public string Id { get; set; }
[JsonPropertyName("CUSTOMER_TYPE")]
public string Type { get; set; }
[JsonPropertyName("ORGANIZATION")]
public string Company { get; set; }
[JsonPropertyName("FIRST_NAME")]
public string Firstname { get; set; }
[JsonPropertyName("LAST_NAME")]
public string Lastname { get; set; }
[JsonPropertyName("ADDRESS")]
public string Address { get; set; }
[JsonPropertyName("ZIPCODE")]
public string Zip { get; set; }
[JsonPropertyName("CITY")]
public string City { get; set; }
[JsonPropertyName("PHONE")]
public string Phone { get; set; }
[JsonPropertyName("EMAIL")]
public string EMail { get; set; }
[JsonPropertyName("WEBSITE")]
public string Website { get; set; }
[JsonPropertyName("DOCUMENT_HISTORY_URL")]
public string DocumentsUrl { get; set; }
public List<Contact> Contacts { get; set; } = new List<Contact>();
}

View File

@ -4,4 +4,6 @@ public class Settings
{
public string EMail { get; set; } = string.Empty;
public string ApiKey { get; set; } = string.Empty;
public List<Customer> Customers { get; set; } = new List<Customer>();
}

View File

@ -9,11 +9,13 @@ public class CustomerService
{
private readonly SettingsManager? _settingsManager;
private readonly Api.Customers _customerApi;
private readonly Api.Contacts _contactApi;
public CustomerService()
{
_settingsManager = (SettingsManager)Ioc.Default.GetService<ISettingsManager>();
_customerApi = new Api.Customers();
_contactApi = new Api.Contacts();
}
public async Task<List<Customer>> SearchCustomer(string term)
@ -25,4 +27,14 @@ public class CustomerService
customers = await _customerApi.SearchCustomer(settings, term);
return customers;
}
public async Task<List<Contact>> GetContacts(string customerId)
{
var settings = new Settings();
_settingsManager.LoadPluginSettings("FastbillSettings", settings);
List<Contact> contacts = new List<Contact>();
contacts = await _contactApi.GetContacts(settings, customerId);
return contacts;
}
}

View File

@ -0,0 +1,8 @@
using PSCHelpdesk.Shared.ViewModels;
namespace FastBill.ViewModels;
public class CustomerDetailViewModel: ViewModelBase, IViewModelBase
{
}

View File

@ -1,5 +1,10 @@
using System.Reactive;
using CommunityToolkit.Mvvm.DependencyInjection;
using DynamicData;
using FastBill.Models;
using FastBill.Services;
using PSCHelpdesk.Shared.Service;
using PSCHelpdesk.Shared.Setting;
using PSCHelpdesk.Shared.ViewModels;
using ReactiveUI;
@ -9,13 +14,23 @@ public class CustomerViewModel: ViewModelBase, IViewModelBase
{
private string _term;
private List<Customer> _customers;
public string Term
{
get => _term;
set => SetAndRaisePropertyChanged(ref _term, value);
}
public List<Customer> Customers
{
get => _customers;
set => SetAndRaisePropertyChanged(ref _customers, value);
}
private CustomerService _customerService;
private readonly SettingsManager? _settingsManager;
public ReactiveCommand<Unit, Unit> SearchCustomer { get; }
@ -24,9 +39,28 @@ public class CustomerViewModel: ViewModelBase, IViewModelBase
Term = "";
_customerService = customerService;
SearchCustomer = ReactiveCommand.Create(searchTerm);
_settingsManager = (SettingsManager)Ioc.Default.GetService<ISettingsManager>();
}
async void searchTerm()
{
var list = await _customerService.SearchCustomer(Term);
Customers = await _customerService.SearchCustomer(Term);
var settings = new Settings();
_settingsManager.LoadPluginSettings("FastbillSettings", settings);
foreach (var customer in Customers)
{
customer.Contacts = await _customerService.GetContacts(customer.Id);
if (settings.Customers.Count(x => x.Id == customer.Id) > 0)
{
var index = settings.Customers.FindIndex(x => x.Id == customer.Id);
settings.Customers[index] = customer;
}
else
{
settings.Customers.Add(customer);
}
}
_settingsManager.SavePluginSettings("FastbillSettings", settings);
}
}

View File

@ -0,0 +1,8 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="FastBill.Views.CustomerDetailView">
Welcome to Avalonia!
</UserControl>

View File

@ -0,0 +1,13 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace FastBill.Views;
public partial class CustomerDetailView : UserControl
{
public CustomerDetailView()
{
InitializeComponent();
}
}

View File

@ -9,9 +9,47 @@
<Design.DataContext>
<vm:CustomerViewModel></vm:CustomerViewModel>
</Design.DataContext>
<StackPanel>
<TextBox Text="{Binding Term}"></TextBox>
<Grid ColumnDefinitions="*,4,*">
<Grid Grid.Column="0" Margin="20" RowDefinitions="Auto,*">
<StackPanel Grid.Row="0" Margin="0 0 0 5">
<TextBox Text="{Binding Term}" Margin="0 5"></TextBox>
<Button Content="Search" Command="{Binding SearchCustomer}"></Button>
</StackPanel>
<DataGrid Grid.Row="1" ItemsSource="{Binding Customers}"
AutoGenerateColumns="False" IsReadOnly="True"
GridLinesVisibility="All"
BorderThickness="1" BorderBrush="Gray"
x:Name="CustomerTable">
<DataGrid.Columns>
<DataGridTemplateColumn Width="*" Header="Id">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox
Text="{Binding Id}"
/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="*" Header="Nr">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox
Text="{Binding Nr}"
/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Width="*" Header="Company" Binding="{Binding Company}" />
<DataGridTextColumn Width="*" Header="Firstname" Binding="{Binding Firstname}" />
<DataGridTextColumn Width="*" Header="Lastname" Binding="{Binding Lastname}" />
</DataGrid.Columns>
</DataGrid>
</Grid>
<GridSplitter Grid.Column="1" Background="Black" ResizeDirection="Columns"/>
<StackPanel Grid.Column="2" Margin="5 0">
</StackPanel>
</Grid>
</UserControl>

View File

@ -46,6 +46,14 @@ public class Server : ReactiveObject
set => this.RaiseAndSetIfChanged(ref _fastBillId, value);
}
private string _fastBillNr;
public string FastBillNr
{
get => _fastBillNr;
set => this.RaiseAndSetIfChanged(ref _fastBillNr, value);
}
public string Status { get; set; }
private MaterialIconKind _isGoodIcon = MaterialIconKind.AlertCircleOutline;

View File

@ -5,11 +5,13 @@ public class ServerSetting
public long ServerId { get; set; }
public string PscApiKey { get; set; }
public string FastBillId { get; set; }
public string FastBillNr { get; set; }
public ServerSetting(long serverId, string pscApiKey, string fastBillId)
public ServerSetting(long serverId, string pscApiKey, string fastBillId, string fastBillNr)
{
ServerId = serverId;
PscApiKey = pscApiKey;
FastBillId = fastBillId;
FastBillNr = fastBillNr;
}
}

View File

@ -81,6 +81,7 @@ public class ServerService: IServerService
if (settings.ServerSettings.Count(e => e.ServerId == serv.ServerId) > 0)
{
serv.FastBillId = settings.ServerSettings.First(e => e.ServerId == serv.ServerId).FastBillId;
serv.FastBillNr = settings.ServerSettings.First(e => e.ServerId == serv.ServerId).FastBillNr;
serv.PscApiKey = settings.ServerSettings.First(e => e.ServerId == serv.ServerId).PscApiKey;
}
@ -261,10 +262,11 @@ public class ServerService: IServerService
{
settings.ServerSettings.First(e => e.ServerId == selectedServer.ServerId).FastBillId = selectedServer.FastBillId;
settings.ServerSettings.First(e => e.ServerId == selectedServer.ServerId).PscApiKey = selectedServer.PscApiKey;
settings.ServerSettings.First(e => e.ServerId == selectedServer.ServerId).FastBillNr = selectedServer.FastBillNr;
}
else
{
settings.ServerSettings.Add(new ServerSetting(selectedServer.ServerId, selectedServer.PscApiKey, selectedServer.FastBillId));
settings.ServerSettings.Add(new ServerSetting(selectedServer.ServerId, selectedServer.PscApiKey, selectedServer.FastBillId, selectedServer.FastBillNr));
}
_settingsManager.SavePluginSettings("HetznerSettings", settings);
}

View File

@ -67,6 +67,8 @@
<TextBox Text="{Binding SelectedServer.PscApiKey}"></TextBox>
<TextBlock Text="FastBill Id" Margin="0 5"></TextBlock>
<TextBox Text="{Binding SelectedServer.FastBillId}"></TextBox>
<TextBlock Text="FastBill Nr" Margin="0 5"></TextBlock>
<TextBox Text="{Binding SelectedServer.FastBillNr}"></TextBox>
<Button Content="Save" Command="{Binding SaveServerSettings}"></Button>
</StackPanel>
</TabItem>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.