diff --git a/.idea/.idea.PSCHelpdesk/.idea/avalonia.xml b/.idea/.idea.PSCHelpdesk/.idea/avalonia.xml
index fdb6bad..6588654 100644
--- a/.idea/.idea.PSCHelpdesk/.idea/avalonia.xml
+++ b/.idea/.idea.PSCHelpdesk/.idea/avalonia.xml
@@ -7,6 +7,10 @@
+
+
+
+
@@ -18,6 +22,7 @@
+
diff --git a/.idea/.idea.PSCHelpdesk/.idea/workspace.xml b/.idea/.idea.PSCHelpdesk/.idea/workspace.xml
index 275ea21..53ecc36 100644
--- a/.idea/.idea.PSCHelpdesk/.idea/workspace.xml
+++ b/.idea/.idea.PSCHelpdesk/.idea/workspace.xml
@@ -11,20 +11,25 @@
+
-
+
+
+
+
-
+
+
+
+
-
-
-
+
@@ -38,22 +43,21 @@
-
-
-
-
+
+
+
-
+
+
+
-
-
-
-
-
+
+
+
@@ -85,6 +89,8 @@
".NET Project.PSCHelpdesk.Desktop.executor": "Run",
"Publish to folder.Build HetznerServer Plugin Debug.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",
"XThreadsFramesViewSplitterKey": "0.4427131",
"git-widget-placeholder": "master",
@@ -100,7 +106,11 @@
}]]>
-
+
+
+
+
+
@@ -156,6 +166,7 @@
+
@@ -181,6 +192,7 @@
+
@@ -199,6 +211,8 @@
+
+
@@ -302,6 +316,71 @@
+
+ file://$APPLICATION_CONFIG_DIR$/resharper-host/SourcesCache/dd582eafcc7da4dc5ece1e7e4de37b1f271b42b4cea54a2aecfe3bda3fd2e5a/HyperlinkButton.cs
+ 80
+
+
+
+
+
+
+
+
+
+
+
+ file://$APPLICATION_CONFIG_DIR$/resharper-host/SourcesCache/dd582eafcc7da4dc5ece1e7e4de37b1f271b42b4cea54a2aecfe3bda3fd2e5a/HyperlinkButton.cs
+ 78
+
+
+
+
+
+
+
+
+
+
+
+ file://$APPLICATION_CONFIG_DIR$/resharper-host/SourcesCache/dd582eafcc7da4dc5ece1e7e4de37b1f271b42b4cea54a2aecfe3bda3fd2e5a/HyperlinkButton.cs
+ 60
+
+
+
+
+
+
+
+
+
+
+
+ file://$PROJECT_DIR$/HetznerServer/Views/ServerView.axaml.cs
+ 29
+
+
+
+
+
+
+
+
+
+
+
+ file://$PROJECT_DIR$/HetznerServer/Views/ServerView.axaml.cs
+ 28
+
+
+
+
+
+
+
+
+
+
diff --git a/HetznerServer/HetznerServer.cs b/HetznerServer/HetznerServer.cs
index cee8799..3ae9c8b 100644
--- a/HetznerServer/HetznerServer.cs
+++ b/HetznerServer/HetznerServer.cs
@@ -32,7 +32,7 @@ public class HetznerServer : Contract
var settingsService = Ioc.Default.GetRequiredService();
var hetznerSettings = new Shared.Setting.Item()
{
- Header = "HetznerSettings",
+ Header = "Hetzner",
CommandParameter = new HetznerSettingsViewModel()
};
settingsService.AddSetting(hetznerSettings);
diff --git a/HetznerServer/HetznerServer.csproj b/HetznerServer/HetznerServer.csproj
index 4727695..39e2215 100644
--- a/HetznerServer/HetznerServer.csproj
+++ b/HetznerServer/HetznerServer.csproj
@@ -36,6 +36,11 @@
+
+
+
+
+
diff --git a/HetznerServer/Models/Domain.cs b/HetznerServer/Models/Domain.cs
new file mode 100644
index 0000000..14fab85
--- /dev/null
+++ b/HetznerServer/Models/Domain.cs
@@ -0,0 +1,11 @@
+namespace PSCHelpdesk.Plugins.HetznerServer.Models;
+
+public class Domain
+{
+ public string Name { get; set; }
+
+ public Domain(String name)
+ {
+ this.Name = name;
+ }
+}
\ No newline at end of file
diff --git a/HetznerServer/Models/Server.cs b/HetznerServer/Models/Server.cs
index ea69f36..fcf4c8a 100644
--- a/HetznerServer/Models/Server.cs
+++ b/HetznerServer/Models/Server.cs
@@ -1,10 +1,11 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
+using ReactiveUI;
namespace PSCHelpdesk.Plugins.HetznerServer.Models;
-public class Server
+public class Server : ReactiveObject
{
public long Id { get; set; }
public string Name { get; set; }
@@ -23,5 +24,43 @@ public class Server
Status = status;
Ipv4 = ipv4;
Ipv6 = ipv6;
+ this.Domains = new List();
+ }
+
+ private List _domains;
+
+ public List Domains
+ {
+ get => _domains;
+ set => this.RaiseAndSetIfChanged(ref _domains, value);
+ }
+
+ private string _datum;
+
+ public string Datum
+ {
+ get => _datum;
+ set => this.RaiseAndSetIfChanged(ref _datum, value);
+ }
+
+ private float _release;
+
+ public float Release
+ {
+ get => _release;
+ set => this.RaiseAndSetIfChanged(ref _release, value);
+ }
+
+ private DateTime _backupLastModified;
+ public DateTime BackupLastModified {
+ get => _backupLastModified;
+ set => this.RaiseAndSetIfChanged(ref _backupLastModified, value);
+ }
+
+ private bool _hasBackup = false;
+
+ public bool HasBackup {
+ get => _hasBackup;
+ set => this.RaiseAndSetIfChanged(ref _hasBackup, value);
}
}
\ No newline at end of file
diff --git a/HetznerServer/Service/ServerService.cs b/HetznerServer/Service/ServerService.cs
index 94f702a..b3df68a 100644
--- a/HetznerServer/Service/ServerService.cs
+++ b/HetznerServer/Service/ServerService.cs
@@ -1,13 +1,17 @@
using System.Collections.ObjectModel;
+using System.Net.Http.Headers;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.DependencyInjection;
using DynamicData;
using DynamicData.Binding;
using HetznerCloudApi;
+using Newtonsoft.Json.Linq;
using PSCHelpdesk.Plugins.HetznerServer.Models;
using PSCHelpdesk.Shared.Service;
using PSCHelpdesk.Shared.Setting;
+using PSCHelpdesk.Shared.Tasks;
using ReactiveUI;
+using Renci.SshNet;
namespace PSCHelpdesk.Plugins.HetznerServer.Service;
@@ -17,19 +21,23 @@ public class ServerService: IServerService
private SettingsManager _settingsManager;
private readonly DispatcherTimer _reloadTimer = new DispatcherTimer();
private string _searchText = string.Empty;
+ private static readonly HttpClient httpClient = new HttpClient();
+ private ITaskManager _taskManager;
+ private readonly IToastManager? _toastManager;
+
public ServerService()
{
_settingsManager = (SettingsManager)Ioc.Default.GetService();
-
+ _taskManager = Ioc.Default.GetService();
+ _toastManager = (IToastManager)Ioc.Default.GetService();
this._reloadTimer.Tick += (sender, args) =>
{
- this.reloadServer();
+ this.reloadServerStatus();
};
- _reloadTimer.Interval = TimeSpan.FromMinutes(10);
+ _reloadTimer.Interval = TimeSpan.FromMinutes(2);
_reloadTimer.Start();
-
- Task.Run(async () => await this.reloadServer());
+ this.reloadServer();
}
private async Task reloadServer()
@@ -52,5 +60,89 @@ public class ServerService: IServerService
}
}
+ Task.Run(async () => await this.reloadServerStatus());
+ }
+
+ private async Task reloadServerStatus()
+ {
+ var uiDispatcher = Ioc.Default.GetService();
+
+ await uiDispatcher.InvokeAsync(() =>
+ {
+ _reloadTimer.Stop();
+ });
+ foreach (Server serv in SourceCache.Items)
+ {
+ var connectionInfo = new ConnectionInfo(serv.Ipv4,
+ "root",
+ new PrivateKeyAuthenticationMethod("root", new PrivateKeyFile(this._settingsManager.CoreSettings.PrivateSSHKeyPath)));
+ using (var client = new SshClient(connectionInfo))
+ {
+ try
+ {
+ client.Connect();
+ var command = client.RunCommand("borgmatic info --json");
+ if (command.ExitStatus == 0)
+ {
+ serv.HasBackup = true;
+ JArray borgMatic = JArray.Parse(command.Result);
+ await uiDispatcher.InvokeAsync(() =>
+ {
+ serv.BackupLastModified = DateTime.Parse(borgMatic[0]["repository"]["last_modified"].ToString());
+ });
+
+ }
+
+ command = client.RunCommand("docker inspect psc_web_1");
+ if (command.ExitStatus == 0)
+ {
+ JArray web = JArray.Parse(command.Result);
+ var webEnvArray = web[0]["Config"]["Env"];
+
+ foreach (String entry in webEnvArray)
+ {
+ var webExploded = entry.Split("=");
+ if (webExploded[0] == "LETSENCRYPT_HOST")
+ {
+ var webHosts = webExploded[1].Split(",");
+ serv.Domains.Clear();
+ foreach (String dom in webHosts)
+ {
+ serv.Domains.Add(new Domain(dom));
+ }
+
+ httpClient.DefaultRequestHeaders.Accept.Clear();
+ httpClient.DefaultRequestHeaders.Accept.Add(
+ new MediaTypeWithQualityHeaderValue("application/ld+json"));
+ httpClient.DefaultRequestHeaders.Add("User-Agent", "PSC Client");
+
+ var stringTask = httpClient.GetStringAsync("https://" + webHosts[0] + "/apps/api/system/version");
+
+ var msg = await stringTask;
+ JObject versionMSg = JObject.Parse(msg);
+
+ serv.Datum = versionMSg["datum"].ToString();
+ serv.Release = float.Parse(versionMSg["release"].ToString());
+
+
+ }
+ }
+ }
+
+ client.Disconnect();
+ _toastManager.DisplayNewToast("Server " + serv.Name + " finished");
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex.Message);
+ }
+ }
+
+ }
+
+ await uiDispatcher.InvokeAsync(() =>
+ {
+ this._reloadTimer.Start();
+ });
}
}
\ No newline at end of file
diff --git a/HetznerServer/ViewModels/ServerViewModel.cs b/HetznerServer/ViewModels/ServerViewModel.cs
index 80140af..f1d522a 100644
--- a/HetznerServer/ViewModels/ServerViewModel.cs
+++ b/HetznerServer/ViewModels/ServerViewModel.cs
@@ -36,7 +36,7 @@ public partial class ServerViewModel : ViewModelBase, IViewModelBase
ServerService.SourceCache.Connect()
// Sort Ascending on the OrderIndex property
.Sort(SortExpressionComparer.Ascending(t => t.Id))
- .Filter(x => x.Name.Contains(_searchText, StringComparison.OrdinalIgnoreCase))
+ .Filter(x => x.Name.Contains(_searchText, StringComparison.OrdinalIgnoreCase) || x.Domains.Count(d => d.Name.Contains(_searchText, StringComparison.OrdinalIgnoreCase)) > 0)
// Bind to our ReadOnlyObservableCollection
.Bind(out _server)
// Subscribe for changes
diff --git a/HetznerServer/Views/ServerView.axaml b/HetznerServer/Views/ServerView.axaml
index 3e069f9..0183ba8 100644
--- a/HetznerServer/Views/ServerView.axaml
+++ b/HetznerServer/Views/ServerView.axaml
@@ -19,7 +19,7 @@
DisplayMode="Inline"
PanePlacement="Right">
-
+
Suchtext
@@ -42,26 +42,23 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
@@ -92,10 +89,18 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/HetznerServer/Views/ServerView.axaml.cs b/HetznerServer/Views/ServerView.axaml.cs
index 183fbd3..907df3e 100644
--- a/HetznerServer/Views/ServerView.axaml.cs
+++ b/HetznerServer/Views/ServerView.axaml.cs
@@ -1,5 +1,7 @@
using Avalonia.Controls;
+using Avalonia.Input;
using Avalonia.Interactivity;
+using Avalonia.Threading;
using PSCHelpdesk.Plugins.HetznerServer.Models;
using PSCHelpdesk.Plugins.HetznerServer.ViewModels;
@@ -21,4 +23,16 @@ public partial class ServerView : UserControl
{
((ServerViewModel)DataContext).SCP(((Button)sender).DataContext as Server);
}
+
+ private void InputElement_OnDoubleTapped(object? sender, TappedEventArgs e)
+ {
+ Uri? uri = new Uri("https://" + ((TextBox)sender).Text);
+ if (uri is not null)
+ {
+ Dispatcher.UIThread.Post(async () =>
+ {
+ bool success = await TopLevel.GetTopLevel(this)!.Launcher.LaunchUriAsync(uri);
+ });
+ }
+ }
}
\ No newline at end of file
diff --git a/Nextcloud/Models/Settings.cs b/Nextcloud/Models/Settings.cs
new file mode 100644
index 0000000..458afef
--- /dev/null
+++ b/Nextcloud/Models/Settings.cs
@@ -0,0 +1,11 @@
+namespace PSCHelpdesk.Plugins.Nextcloud.Models;
+
+public class Settings
+{
+ public string ServerUrl { get; set; }
+
+ public Settings()
+ {
+ ServerUrl = "https://api.nextcloud.com";
+ }
+}
\ No newline at end of file
diff --git a/Nextcloud/Nextcloud.cs b/Nextcloud/Nextcloud.cs
new file mode 100644
index 0000000..ff7cd6b
--- /dev/null
+++ b/Nextcloud/Nextcloud.cs
@@ -0,0 +1,43 @@
+using CommunityToolkit.Mvvm.DependencyInjection;
+using Prise.Plugin;
+using PSCHelpdesk.Plugins.Nextcloud.ViewModels;
+using PSCHelpdesk.Plugins.Nextcloud.Views;
+using PSCHelpdesk.Shared.Menu;
+using PSCHelpdesk.Shared.Plugin;
+using PSCHelpdesk.Shared.Service;
+
+namespace PSCHelpdesk.Plugins.Nextcloud;
+
+[Plugin(PluginType = typeof(Contract))]
+public class Nextcloud : Contract
+{
+ public string GetName()
+ {
+ return "NextcloudPlugin";
+ }
+
+ public void Configure()
+ {
+ var menuService = Ioc.Default.GetRequiredService();
+ /*var serverTab = new Item()
+ {
+ Header = "Server",
+ CommandParameter = new ServerViewModel(new ServerService())
+ };
+ menuService.AddMenuItem(serverTab);
+ */
+ var settingsService = Ioc.Default.GetRequiredService();
+ var hetznerSettings = new Shared.Setting.Item()
+ {
+ Header = "Nextcloud",
+ CommandParameter = new NextcloudSettingsViewModel()
+ };
+ settingsService.AddSetting(hetznerSettings);
+ }
+
+ public List LoadViews()
+ {
+ return [typeof(NextcloudSettingsView)];
+ }
+
+}
\ No newline at end of file
diff --git a/Nextcloud/Nextcloud.csproj b/Nextcloud/Nextcloud.csproj
index fa0d0f4..2c070ff 100644
--- a/Nextcloud/Nextcloud.csproj
+++ b/Nextcloud/Nextcloud.csproj
@@ -8,14 +8,21 @@
-
-
-
-
+
+
+
+
+
-
+
+
+
+
+
+ ..\..\..\.nuget\packages\communitytoolkit.mvvm\8.3.2\lib\net8.0\CommunityToolkit.Mvvm.dll
+
diff --git a/Nextcloud/ViewModels/NextcloudSettingsViewModel.cs b/Nextcloud/ViewModels/NextcloudSettingsViewModel.cs
new file mode 100644
index 0000000..de5492d
--- /dev/null
+++ b/Nextcloud/ViewModels/NextcloudSettingsViewModel.cs
@@ -0,0 +1,27 @@
+using CommunityToolkit.Mvvm.DependencyInjection;
+using PSCHelpdesk.Plugins.Nextcloud.Models;
+using PSCHelpdesk.Shared.Service;
+using PSCHelpdesk.Shared.Setting;
+using PSCHelpdesk.Shared.ViewModels;
+
+namespace PSCHelpdesk.Plugins.Nextcloud.ViewModels;
+
+public class NextcloudSettingsViewModel: ViewModelBase, IViewModelBase
+{
+ private string _serverUrl;
+ public NextcloudSettingsViewModel()
+ {
+
+ var settingsManager = (SettingsManager)Ioc.Default.GetService();
+ var settings = new Settings();
+ settingsManager.LoadPluginSettings("NextcloudSettings", settings);
+
+ ServerUrl = settings.ServerUrl;
+ }
+
+ public string ServerUrl
+ {
+ get => _serverUrl;
+ set => SetAndRaisePropertyChanged(ref _serverUrl, value);
+ }
+}
\ No newline at end of file
diff --git a/Nextcloud/Views/NextcloudSettingsView.axaml b/Nextcloud/Views/NextcloudSettingsView.axaml
new file mode 100644
index 0000000..8ab14f6
--- /dev/null
+++ b/Nextcloud/Views/NextcloudSettingsView.axaml
@@ -0,0 +1,18 @@
+
+
+
+
+
+ Server Url
+
+
+
+
+
+
diff --git a/Nextcloud/Views/NextcloudSettingsView.axaml.cs b/Nextcloud/Views/NextcloudSettingsView.axaml.cs
new file mode 100644
index 0000000..a4aa4c6
--- /dev/null
+++ b/Nextcloud/Views/NextcloudSettingsView.axaml.cs
@@ -0,0 +1,31 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Interactivity;
+using Avalonia.Markup.Xaml;
+using CommunityToolkit.Mvvm.DependencyInjection;
+using PSCHelpdesk.Plugins.Nextcloud.Models;
+using PSCHelpdesk.Plugins.Nextcloud.ViewModels;
+using PSCHelpdesk.Shared.Service;
+using PSCHelpdesk.Shared.Setting;
+
+namespace PSCHelpdesk.Plugins.Nextcloud.Views;
+
+public partial class NextcloudSettingsView : UserControl
+{
+ private SettingsManager settingsManager;
+ private Settings settings;
+
+ public NextcloudSettingsView()
+ {
+ InitializeComponent();
+ settingsManager = (SettingsManager)Ioc.Default.GetService();
+ settings = new Settings();
+ settingsManager.LoadPluginSettings("NextcloudSettings", settings);
+ }
+
+ private void SaveSettings_OnClick(object? sender, RoutedEventArgs e)
+ {
+ settings.ServerUrl = ((NextcloudSettingsViewModel)this.DataContext).ServerUrl;
+ settingsManager.SavePluginSettings("NextcloudSettings", settings);
+ }
+}
\ No newline at end of file
diff --git a/PSCHelpdesk.sln.DotSettings.user b/PSCHelpdesk.sln.DotSettings.user
index 8244a1f..c48348e 100644
--- a/PSCHelpdesk.sln.DotSettings.user
+++ b/PSCHelpdesk.sln.DotSettings.user
@@ -5,6 +5,8 @@
ForceIncluded
ForceIncluded
ForceIncluded
+ ForceIncluded
+ ForceIncluded
ForceIncluded
ForceIncluded
ForceIncluded
@@ -19,6 +21,7 @@
ForceIncluded
ForceIncluded
ForceIncluded
+ ForceIncluded
ForceIncluded
ForceIncluded
ForceIncluded
@@ -30,10 +33,13 @@
ForceIncluded
ForceIncluded
ForceIncluded
+ ForceIncluded
+ ForceIncluded
ForceIncluded
ForceIncluded
ForceIncluded
ForceIncluded
+ ForceIncluded
ForceIncluded
ForceIncluded
ForceIncluded
diff --git a/PSCHelpdesk/PSCHelpdesk/App.axaml b/PSCHelpdesk/PSCHelpdesk/App.axaml
index eb3280f..bec75b6 100644
--- a/PSCHelpdesk/PSCHelpdesk/App.axaml
+++ b/PSCHelpdesk/PSCHelpdesk/App.axaml
@@ -10,8 +10,19 @@
-
-
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/PSCHelpdesk/PSCHelpdesk/Controls/ProgressRing.axaml b/PSCHelpdesk/PSCHelpdesk/Controls/ProgressRing.axaml
new file mode 100644
index 0000000..bb08fa1
--- /dev/null
+++ b/PSCHelpdesk/PSCHelpdesk/Controls/ProgressRing.axaml
@@ -0,0 +1,392 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/PSCHelpdesk/PSCHelpdesk/Controls/ProgressRing.axaml.cs b/PSCHelpdesk/PSCHelpdesk/Controls/ProgressRing.axaml.cs
new file mode 100644
index 0000000..9a10dcb
--- /dev/null
+++ b/PSCHelpdesk/PSCHelpdesk/Controls/ProgressRing.axaml.cs
@@ -0,0 +1,102 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Controls.Primitives;
+using System.Reactive.Disposables;
+using System.Reactive.Linq;
+
+namespace PSCHelpdesk.Controls
+{
+ ///
+ /// provides a Windows 10 styled circular loading animation.
+ ///
+ ///
+ /// Adapted from the MahApps Metro implementation at
+ /// https://github.com/MahApps/MahApps.Metro/blob/develop/src/MahApps.Metro/Controls/ProgressRing.cs.
+ ///
+ public class ProgressRing : TemplatedControl
+ {
+ public static readonly StyledProperty IsActiveProperty =
+ AvaloniaProperty.Register(
+ "IsActive",
+ inherits: true,
+ defaultValue: true);
+
+ public static readonly StyledProperty MaxSideLengthProperty =
+ AvaloniaProperty.Register(
+ "MaxSideLength",
+ inherits: true);
+
+ public static readonly StyledProperty EllipseDiameterProperty =
+ AvaloniaProperty.Register(
+ "EllipseDiameter",
+ inherits: true);
+
+ public static readonly StyledProperty EllipseOffsetProperty =
+ AvaloniaProperty.Register(
+ "EllipseOffset",
+ inherits: true);
+
+ public static readonly StyledProperty EllipseDiameterScaleProperty =
+ AvaloniaProperty.Register(
+ "EllipseDiameterScale",
+ inherits: true,
+ defaultValue: 1D);
+
+ private readonly CompositeDisposable disposables = new CompositeDisposable();
+
+ public ProgressRing()
+ {
+ this.GetObservable(Control.BoundsProperty).ForEachAsync((rect) =>
+ {
+ this.SetEllipseDiameter(rect.Width);
+ this.SetEllipseOffset(rect.Width);
+ this.SetMaxSideLength(rect.Width);
+ }).DisposeWith(this.disposables);
+ }
+
+ public double MaxSideLength
+ {
+ get => (double)this.GetValue(MaxSideLengthProperty);
+ private set => this.SetValue(MaxSideLengthProperty, value);
+ }
+
+ public double EllipseDiameter
+ {
+ get => (double)this.GetValue(EllipseDiameterProperty);
+ private set => this.SetValue(EllipseDiameterProperty, value);
+ }
+
+ public double EllipseDiameterScale
+ {
+ get => (double)this.GetValue(EllipseDiameterScaleProperty);
+ set => this.SetValue(EllipseDiameterScaleProperty, value);
+ }
+
+ public Thickness EllipseOffset
+ {
+ get => (Thickness)this.GetValue(EllipseOffsetProperty);
+ private set => this.SetValue(EllipseOffsetProperty, value);
+ }
+
+ public bool IsActive
+ {
+ get => (bool)this.GetValue(IsActiveProperty);
+ set => this.SetValue(IsActiveProperty, value);
+ }
+
+ private void SetMaxSideLength(double width)
+ {
+ this.MaxSideLength = width <= 20 ? 20 : width;
+ }
+
+ private void SetEllipseDiameter(double width)
+ {
+ this.EllipseDiameter = (width / 8) * this.EllipseDiameterScale;
+ }
+
+ private void SetEllipseOffset(double width)
+ {
+ this.EllipseOffset = new Thickness(0, width / 2, 0, 0);
+ }
+ }
+}
diff --git a/PSCHelpdesk/PSCHelpdesk/LightTheme.axaml b/PSCHelpdesk/PSCHelpdesk/LightTheme.axaml
new file mode 100644
index 0000000..27e8c66
--- /dev/null
+++ b/PSCHelpdesk/PSCHelpdesk/LightTheme.axaml
@@ -0,0 +1,54 @@
+
\ No newline at end of file
diff --git a/PSCHelpdesk/PSCHelpdesk/PSCHelpdesk.csproj b/PSCHelpdesk/PSCHelpdesk/PSCHelpdesk.csproj
index 8b26672..d564254 100644
--- a/PSCHelpdesk/PSCHelpdesk/PSCHelpdesk.csproj
+++ b/PSCHelpdesk/PSCHelpdesk/PSCHelpdesk.csproj
@@ -49,6 +49,6 @@
-
+
diff --git a/PSCHelpdesk/PSCHelpdesk/Services/PluginService.cs b/PSCHelpdesk/PSCHelpdesk/Services/PluginService.cs
index 1808dcc..a67e7bf 100644
--- a/PSCHelpdesk/PSCHelpdesk/Services/PluginService.cs
+++ b/PSCHelpdesk/PSCHelpdesk/Services/PluginService.cs
@@ -6,6 +6,7 @@ using Microsoft.Extensions.DependencyInjection;
using PSCHelpdesk.Shared.Menu;
using PSCHelpdesk.Shared.Plugin;
using PSCHelpdesk.Shared.Service;
+using PSCHelpdesk.Shared.Tasks;
namespace PSCHelpdesk.Services;
@@ -26,6 +27,7 @@ public class PluginService
{
this.scanPlugins();
this.LoadPlugin("HetznerServer");
+ this.LoadPlugin("Nextcloud");
}
public Dictionary GetPlugins()
{
@@ -65,6 +67,7 @@ public class PluginService
var menuService = Ioc.Default.GetRequiredService();
var settingsService = Ioc.Default.GetRequiredService();
var settingsManager = Ioc.Default.GetRequiredService();
+ var taskManager = Ioc.Default.GetRequiredService();
var testService = Ioc.Default.GetRequiredService();
var appService = Ioc.Default.GetService(typeof(AppService)) as AppService;
@@ -81,6 +84,7 @@ public class PluginService
.AddHostService(menuService)
.AddHostService(settingsService)
.AddHostService(settingsManager)
+ .AddHostService(taskManager)
.AddHostService(testService)
//.AddHostService(settingsService)
diff --git a/PSCHelpdesk/PSCHelpdesk/Startup.cs b/PSCHelpdesk/PSCHelpdesk/Startup.cs
index 52a5125..6c885d6 100644
--- a/PSCHelpdesk/PSCHelpdesk/Startup.cs
+++ b/PSCHelpdesk/PSCHelpdesk/Startup.cs
@@ -6,6 +6,10 @@ using PSCHelpdesk.Converter;
using PSCHelpdesk.Services;
using PSCHelpdesk.Shared.Service;
using PSCHelpdesk.Shared.Setting;
+using PSCHelpdesk.Shared.Tasks;
+using PSCHelpdesk.Tasks;
+using PSCHelpdesk.Toasts;
+using PSCHelpdesk.Toasts.Display;
using PSCHelpdesk.ViewModels;
namespace PSCHelpdesk;
@@ -17,6 +21,8 @@ class Startup
var menuService = new MenuService();
var settingsManager = new SettingsManager();
var settingsService = new SettingsService();
+ var taskManager = new TaskManager();
+ var toastManager = new ToastManager();
var te = new ServiceCollection()
.AddSingleton()
@@ -24,10 +30,12 @@ class Startup
.AddFactory(()=> new AvaloniaPluginResultConverter())
.AddSingleton()
.AddSingleton(settingsManager)
- .AddSingleton(menuService)
.AddSingleton(settingsService)
+ .AddSingleton(taskManager)
+ .AddSingleton(menuService)
.AddSingleton(new TestService())
.AddSingleton()
+ .AddSingleton(toastManager)
.AddTransient();
diff --git a/PSCHelpdesk/PSCHelpdesk/Tasks/TaskManager.cs b/PSCHelpdesk/PSCHelpdesk/Tasks/TaskManager.cs
new file mode 100644
index 0000000..537e014
--- /dev/null
+++ b/PSCHelpdesk/PSCHelpdesk/Tasks/TaskManager.cs
@@ -0,0 +1,146 @@
+using System;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+using CommunityToolkit.Mvvm.DependencyInjection;
+using PSCHelpdesk.Shared.Service;
+using PSCHelpdesk.Shared.Tasks;
+
+namespace PSCHelpdesk.Tasks
+{
+ ///
+ /// manages a collection of running s.
+ ///
+ public class TaskManager: ITaskManager
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public TaskManager()
+ {
+ this.RunningTasks = new ObservableCollection();
+ }
+
+ ///
+ /// Event that fires when the number of tasks that are currently executing changes.
+ ///
+ public event Action