diff --git a/.idea/.idea.PSCHelpdesk/.idea/.name b/.idea/.idea.PSCHelpdesk/.idea/.name new file mode 100644 index 0000000..6f7d947 --- /dev/null +++ b/.idea/.idea.PSCHelpdesk/.idea/.name @@ -0,0 +1 @@ +PSCHelpdesk \ No newline at end of file diff --git a/.idea/.idea.PSCHelpdesk/.idea/workspace.xml b/.idea/.idea.PSCHelpdesk/.idea/workspace.xml index 53ecc36..28b72a8 100644 --- a/.idea/.idea.PSCHelpdesk/.idea/workspace.xml +++ b/.idea/.idea.PSCHelpdesk/.idea/workspace.xml @@ -11,25 +11,23 @@ - - - - - - + + + + + + + + - - - - - - + + + - - - + - - - + + @@ -59,7 +55,7 @@ - + @@ -94,6 +90,7 @@ "RunOnceActivity.ShowReadmeOnStart": "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", @@ -150,7 +147,7 @@ - @@ -319,40 +318,19 @@ 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 - - - - - - + @@ -381,6 +359,71 @@ + + file://$PROJECT_DIR$/Nextcloud/Views/NextcloudSettingsView.axaml.cs + 49 + + + + + + + + + file://$PROJECT_DIR$/HetznerServer/HetznerServer.cs + 23 + + + + + + + + + file://$PROJECT_DIR$/Nextcloud/Nextcloud.cs + 21 + + + + + + + + + file://$PROJECT_DIR$/HetznerServer/HetznerServer.cs + 24 + + + + + + + + + file://$PROJECT_DIR$/Vendor/Prise/AssemblyScanning/DefaultAssemblyScanner.cs + 26 + + + + + + + diff --git a/HetznerServer/HetznerServer.csproj b/HetznerServer/HetznerServer.csproj index 39e2215..9899c34 100644 --- a/HetznerServer/HetznerServer.csproj +++ b/HetznerServer/HetznerServer.csproj @@ -13,6 +13,9 @@ + + + @@ -34,8 +37,6 @@ - - diff --git a/HetznerServer/Service/ServerService.cs b/HetznerServer/Service/ServerService.cs index b3df68a..3023339 100644 --- a/HetznerServer/Service/ServerService.cs +++ b/HetznerServer/Service/ServerService.cs @@ -34,7 +34,7 @@ public class ServerService: IServerService { this.reloadServerStatus(); }; - _reloadTimer.Interval = TimeSpan.FromMinutes(2); + _reloadTimer.Interval = TimeSpan.FromMinutes(10); _reloadTimer.Start(); this.reloadServer(); diff --git a/Nextcloud/Api/Notes.cs b/Nextcloud/Api/Notes.cs new file mode 100644 index 0000000..83fbbc2 --- /dev/null +++ b/Nextcloud/Api/Notes.cs @@ -0,0 +1,30 @@ +using CommunityToolkit.Mvvm.DependencyInjection; +using PSCHelpdesk.Plugins.Nextcloud.Models; +using RestSharp; +using RestSharp.Authenticators; + +namespace PSCHelpdesk.Plugins.Nextcloud.Api; + +public class Notes +{ + public Notes() + { + } + + async public Task> GetNotes(Settings settings) + { + var notes = new List(); + + var client = new RestClient(settings.ServerUrl); + var request = new RestRequest("index.php/apps/notes/api/v1/notes"); + request.Authenticator = new HttpBasicAuthenticator(settings.Username, settings.AppPassword); + + var response = await client.ExecuteAsync>(request); + if (response.StatusCode == System.Net.HttpStatusCode.OK) + { + return response.Data; + } + + return notes; + } +} \ No newline at end of file diff --git a/Nextcloud/Models/Note.cs b/Nextcloud/Models/Note.cs new file mode 100644 index 0000000..ebb0fe0 --- /dev/null +++ b/Nextcloud/Models/Note.cs @@ -0,0 +1,12 @@ +namespace PSCHelpdesk.Plugins.Nextcloud.Models; + +public class Note +{ + public long Id { get; set; } + + public string Content { get; set; } + + public string Title { get; set; } + + public string etag { get; set; } +} \ No newline at end of file diff --git a/Nextcloud/Models/Settings.cs b/Nextcloud/Models/Settings.cs index 458afef..0bb452d 100644 --- a/Nextcloud/Models/Settings.cs +++ b/Nextcloud/Models/Settings.cs @@ -3,9 +3,13 @@ namespace PSCHelpdesk.Plugins.Nextcloud.Models; public class Settings { public string ServerUrl { get; set; } + public string Username { get; set; } + public string AppPassword { get; set; } public Settings() { ServerUrl = "https://api.nextcloud.com"; + Username = ""; + AppPassword = ""; } } \ No newline at end of file diff --git a/Nextcloud/Nextcloud.cs b/Nextcloud/Nextcloud.cs index ff7cd6b..d0c2f38 100644 --- a/Nextcloud/Nextcloud.cs +++ b/Nextcloud/Nextcloud.cs @@ -1,5 +1,6 @@ using CommunityToolkit.Mvvm.DependencyInjection; using Prise.Plugin; +using PSCHelpdesk.Plugins.Nextcloud.Services; using PSCHelpdesk.Plugins.Nextcloud.ViewModels; using PSCHelpdesk.Plugins.Nextcloud.Views; using PSCHelpdesk.Shared.Menu; @@ -19,13 +20,12 @@ public class Nextcloud : Contract public void Configure() { var menuService = Ioc.Default.GetRequiredService(); - /*var serverTab = new Item() + var notesTab = new Item() { - Header = "Server", - CommandParameter = new ServerViewModel(new ServerService()) + Header = "Notes", + CommandParameter = new NotesViewModel(new NotesService()) }; - menuService.AddMenuItem(serverTab); - */ + menuService.AddMenuItem(notesTab); var settingsService = Ioc.Default.GetRequiredService(); var hetznerSettings = new Shared.Setting.Item() { @@ -37,7 +37,7 @@ public class Nextcloud : Contract public List LoadViews() { - return [typeof(NextcloudSettingsView)]; + return [typeof(NextcloudSettingsView), typeof(NotesView)]; } } \ No newline at end of file diff --git a/Nextcloud/Nextcloud.csproj b/Nextcloud/Nextcloud.csproj index 2c070ff..55c4e45 100644 --- a/Nextcloud/Nextcloud.csproj +++ b/Nextcloud/Nextcloud.csproj @@ -12,11 +12,13 @@ - + + + diff --git a/Nextcloud/Services/NotesService.cs b/Nextcloud/Services/NotesService.cs new file mode 100644 index 0000000..8c97556 --- /dev/null +++ b/Nextcloud/Services/NotesService.cs @@ -0,0 +1,44 @@ +using Avalonia.Threading; +using CommunityToolkit.Mvvm.DependencyInjection; +using PSCHelpdesk.Plugins.Nextcloud.Models; +using PSCHelpdesk.Shared.Service; +using PSCHelpdesk.Shared.Setting; + +namespace PSCHelpdesk.Plugins.Nextcloud.Services; + +public class NotesService +{ + public List Notes; + private Api.Notes _notes; + private readonly IToastManager? _toastManager; + private SettingsManager _settingsManager; + public EventHandler OnNotesChanged; + private DispatcherTimer _timer; + public NotesService() + { + Notes = new List(); + _settingsManager = (SettingsManager)Ioc.Default.GetService(); + _toastManager = (IToastManager)Ioc.Default.GetService(); + _notes = new Api.Notes(); + + _timer = new DispatcherTimer(); + _timer.Interval = TimeSpan.FromMinutes(10); + _timer.Tick += async (_, _) => LoadNotes(); + _timer.Start(); + } + + public async Task LoadNotes() + { + var settings = new Settings(); + _settingsManager.LoadPluginSettings("NextcloudSettings", settings); + + if (settings.AppPassword != "") + { + _toastManager.DisplayNewToast("Reload Notes started"); + Notes = await _notes.GetNotes(settings); + _toastManager.DisplayNewToast("Reload Notes finshed"); + this.OnNotesChanged.Invoke(null, EventArgs.Empty); + } + } + +} \ No newline at end of file diff --git a/Nextcloud/ViewModels/NextcloudSettingsViewModel.cs b/Nextcloud/ViewModels/NextcloudSettingsViewModel.cs index de5492d..d87f5b6 100644 --- a/Nextcloud/ViewModels/NextcloudSettingsViewModel.cs +++ b/Nextcloud/ViewModels/NextcloudSettingsViewModel.cs @@ -9,6 +9,8 @@ namespace PSCHelpdesk.Plugins.Nextcloud.ViewModels; public class NextcloudSettingsViewModel: ViewModelBase, IViewModelBase { private string _serverUrl; + private string _userName; + private string _appPassword; public NextcloudSettingsViewModel() { @@ -17,6 +19,8 @@ public class NextcloudSettingsViewModel: ViewModelBase, IViewModelBase settingsManager.LoadPluginSettings("NextcloudSettings", settings); ServerUrl = settings.ServerUrl; + Username = settings.Username; + AppPassword = settings.AppPassword; } public string ServerUrl @@ -24,4 +28,14 @@ public class NextcloudSettingsViewModel: ViewModelBase, IViewModelBase get => _serverUrl; set => SetAndRaisePropertyChanged(ref _serverUrl, value); } + public string Username + { + get => _userName; + set => SetAndRaisePropertyChanged(ref _userName, value); + } + public string AppPassword + { + get => _appPassword; + set => SetAndRaisePropertyChanged(ref _appPassword, value); + } } \ No newline at end of file diff --git a/Nextcloud/ViewModels/NotesViewModel.cs b/Nextcloud/ViewModels/NotesViewModel.cs index 2c0313c..2ef9bef 100644 --- a/Nextcloud/ViewModels/NotesViewModel.cs +++ b/Nextcloud/ViewModels/NotesViewModel.cs @@ -1,13 +1,62 @@ +using System.Windows.Input; using Avalonia.Controls; +using Avalonia.Threading; +using CommunityToolkit.Mvvm.DependencyInjection; +using CommunityToolkit.Mvvm.Input; +using PSCHelpdesk.Plugins.Nextcloud.Models; +using PSCHelpdesk.Plugins.Nextcloud.Services; using PSCHelpdesk.Plugins.Nextcloud.Views; +using PSCHelpdesk.Shared.Service; using PSCHelpdesk.Shared.ViewModels; +using ReactiveUI; namespace PSCHelpdesk.Plugins.Nextcloud.ViewModels; -public class NotesViewModel: ViewModelBase +public partial class NotesViewModel: ViewModelBase, IViewModelBase { - public UserControl GetViewControl() + public ICommand SelectNote { get; } + + private List _notes; + public List Notes { - return new NotesView(); + get => _notes; + set => this.SetAndRaisePropertyChanged(ref _notes, value); + } + + private Note _selectedNote; + public Note SelectedNote + { + get => _selectedNote; + set => this.SetAndRaisePropertyChanged(ref _selectedNote, value); + } + + private NotesService _notesService; + + + public NotesViewModel(NotesService notesService) + { + SelectedNote = new Note(); + Notes = new List(); + _notesService = notesService; + _notesService.OnNotesChanged += (sender, args) => this.reloadNotes(); + _notesService.LoadNotes(); + SelectNote = ReactiveCommand.Create((Note note) => + { + selectNote(note); + }); + } + + private void reloadNotes() + { + Notes = _notesService.Notes; + } + + private async void selectNote(Note note) + { + var uiDispatcher = Ioc.Default.GetService(); + await uiDispatcher.InvokeAsync(() => + { + SelectedNote = note; + }); } } \ No newline at end of file diff --git a/Nextcloud/Views/NextcloudSettingsView.axaml b/Nextcloud/Views/NextcloudSettingsView.axaml index 8ab14f6..ec7e436 100644 --- a/Nextcloud/Views/NextcloudSettingsView.axaml +++ b/Nextcloud/Views/NextcloudSettingsView.axaml @@ -12,6 +12,15 @@ Server Url + + + + UserName + + + + App Password + diff --git a/Nextcloud/Views/NextcloudSettingsView.axaml.cs b/Nextcloud/Views/NextcloudSettingsView.axaml.cs index a4aa4c6..4c63971 100644 --- a/Nextcloud/Views/NextcloudSettingsView.axaml.cs +++ b/Nextcloud/Views/NextcloudSettingsView.axaml.cs @@ -1,8 +1,11 @@ +using System.Net.Http.Headers; using Avalonia; using Avalonia.Controls; using Avalonia.Interactivity; using Avalonia.Markup.Xaml; +using Avalonia.Threading; using CommunityToolkit.Mvvm.DependencyInjection; +using Newtonsoft.Json.Linq; using PSCHelpdesk.Plugins.Nextcloud.Models; using PSCHelpdesk.Plugins.Nextcloud.ViewModels; using PSCHelpdesk.Shared.Service; @@ -14,6 +17,7 @@ public partial class NextcloudSettingsView : UserControl { private SettingsManager settingsManager; private Settings settings; + private static readonly HttpClient httpClient = new HttpClient(); public NextcloudSettingsView() { @@ -26,6 +30,56 @@ public partial class NextcloudSettingsView : UserControl private void SaveSettings_OnClick(object? sender, RoutedEventArgs e) { settings.ServerUrl = ((NextcloudSettingsViewModel)this.DataContext).ServerUrl; + settings.Username = ((NextcloudSettingsViewModel)this.DataContext).Username; + settings.AppPassword = ((NextcloudSettingsViewModel)this.DataContext).AppPassword; settingsManager.SavePluginSettings("NextcloudSettings", settings); } + + private async void Button_OnClick(object? sender, RoutedEventArgs e) + { + httpClient.DefaultRequestHeaders.Accept.Clear(); + httpClient.DefaultRequestHeaders.Accept.Add( + new MediaTypeWithQualityHeaderValue("application/ld+json")); + httpClient.DefaultRequestHeaders.Add("User-Agent", "PSC Client"); + + var stringTask = httpClient.PostAsync(settings.ServerUrl + "/index.php/login/v2", new MultipartContent()); + + var msg = await stringTask; + JObject response = JObject.Parse(msg.Content.ReadAsStringAsync().Result); + Uri? uri = new Uri(response["login"].ToString()); + if (uri is not null) + { + Dispatcher.UIThread.Post(async () => + { + bool success = await TopLevel.GetTopLevel(this)!.Launcher.LaunchUriAsync(uri); + }); + } + + httpClient.DefaultRequestHeaders.Accept.Clear(); + httpClient.DefaultRequestHeaders.Accept.Add( + new MediaTypeWithQualityHeaderValue("application/ld+json")); + httpClient.DefaultRequestHeaders.Add("User-Agent", "PSC Client"); + + while (true) + { + + var pollLink = httpClient.PostAsync( + response["poll"]["endpoint"].ToString(), + new FormUrlEncodedContent(new []{new KeyValuePair("token", response["poll"]["token"].ToString())})); + + var resultPoll = await pollLink; + if (resultPoll.IsSuccessStatusCode) + { + JObject responsePoll = JObject.Parse(resultPoll.Content.ReadAsStringAsync().Result); + settings.Username = responsePoll["loginName"].ToString(); + settings.AppPassword = responsePoll["appPassword"].ToString(); + ((NextcloudSettingsViewModel)this.DataContext).Username = settings.Username; + ((NextcloudSettingsViewModel)this.DataContext).AppPassword = settings.AppPassword; + break; + } + + Thread.Sleep(1000); + } + + } } \ No newline at end of file diff --git a/Nextcloud/Views/NotesView.axaml b/Nextcloud/Views/NotesView.axaml index 7bb9020..166dce0 100644 --- a/Nextcloud/Views/NotesView.axaml +++ b/Nextcloud/Views/NotesView.axaml @@ -2,7 +2,30 @@ 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" + xmlns:vm="clr-namespace:PSCHelpdesk.Plugins.Nextcloud.ViewModels" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" - x:Class="PSCHelpdesk.Plugins.Nextcloud.Views.NotesView"> - Welcome to Avalonia! + x:Class="PSCHelpdesk.Plugins.Nextcloud.Views.NotesView" + x:DataType="vm:NotesViewModel"> + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Nextcloud/Views/NotesView.axaml.cs b/Nextcloud/Views/NotesView.axaml.cs index 797a6c0..30d4ed6 100644 --- a/Nextcloud/Views/NotesView.axaml.cs +++ b/Nextcloud/Views/NotesView.axaml.cs @@ -1,4 +1,6 @@ using Avalonia.Controls; +using Avalonia.Input; +using PSCHelpdesk.Plugins.Nextcloud.ViewModels; namespace PSCHelpdesk.Plugins.Nextcloud.Views; public partial class NotesView : UserControl @@ -7,4 +9,9 @@ public partial class NotesView : UserControl { InitializeComponent(); } + + private void InputElement_OnTapped(object? sender, TappedEventArgs e) + { + //((NotesViewModel)DataContext).SelectNote(sender); + } } \ No newline at end of file diff --git a/PSCHelpdesk.sln.DotSettings.user b/PSCHelpdesk.sln.DotSettings.user index c48348e..40fec4b 100644 --- a/PSCHelpdesk.sln.DotSettings.user +++ b/PSCHelpdesk.sln.DotSettings.user @@ -23,10 +23,12 @@ ForceIncluded ForceIncluded ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded @@ -76,11 +78,11 @@ </AssemblyExplorer> True True - True - True + + True - True - True + + diff --git a/PSCHelpdesk/PSCHelpdesk/PSCHelpdesk.csproj b/PSCHelpdesk/PSCHelpdesk/PSCHelpdesk.csproj index d564254..e398f03 100644 --- a/PSCHelpdesk/PSCHelpdesk/PSCHelpdesk.csproj +++ b/PSCHelpdesk/PSCHelpdesk/PSCHelpdesk.csproj @@ -21,12 +21,13 @@ - - + + + diff --git a/PSCHelpdesk/PSCHelpdesk/Services/PluginService.cs b/PSCHelpdesk/PSCHelpdesk/Services/PluginService.cs index a67e7bf..cf07469 100644 --- a/PSCHelpdesk/PSCHelpdesk/Services/PluginService.cs +++ b/PSCHelpdesk/PSCHelpdesk/Services/PluginService.cs @@ -25,8 +25,8 @@ public class PluginService public PluginService() { - this.scanPlugins(); - this.LoadPlugin("HetznerServer"); + //this.scanPlugins(); + //this.LoadPlugin("HetznerServer"); this.LoadPlugin("Nextcloud"); } public Dictionary GetPlugins() diff --git a/PSCHelpdesk/PSCHelpdesk/Views/MainWindow.axaml.cs b/PSCHelpdesk/PSCHelpdesk/Views/MainWindow.axaml.cs index 852e4e2..a96aaaf 100644 --- a/PSCHelpdesk/PSCHelpdesk/Views/MainWindow.axaml.cs +++ b/PSCHelpdesk/PSCHelpdesk/Views/MainWindow.axaml.cs @@ -22,8 +22,8 @@ public partial class MainWindow : Window SettingsWindow settings = new SettingsWindow { DataContext = new SettingsViewModel(), - Width = 500, - Height = 400 + Width = 800, + Height = 600 }; settings.Show(); } diff --git a/Vendor/Prise/AssemblyScanning/DefaultAssemblyScanner.cs b/Vendor/Prise/AssemblyScanning/DefaultAssemblyScanner.cs index 415c8a2..1b24522 100644 --- a/Vendor/Prise/AssemblyScanning/DefaultAssemblyScanner.cs +++ b/Vendor/Prise/AssemblyScanning/DefaultAssemblyScanner.cs @@ -44,6 +44,7 @@ namespace Prise.AssemblyScanning { foreach (var implementation in GetImplementationsOfTypeFromAssembly(typeToScan, assemblyFilePath)) if (implementation != null) + { results.Add(new AssemblyScanResult { ContractType = typeToScan, @@ -51,6 +52,8 @@ namespace Prise.AssemblyScanning AssemblyPath = Path.GetDirectoryName(assemblyFilePath), PluginType = implementation }); + Console.WriteLine($"Scanning File {assemblyFilePath}"); + } } }