mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-12 13:28:33 +00:00
Workshop - Finished initial plugin implementation
This commit is contained in:
parent
f2c8de1746
commit
cf10193bd2
@ -19,7 +19,10 @@
|
||||
Grid.RowSpan="3"
|
||||
VerticalAlignment="Top" />
|
||||
|
||||
<TextBlock Grid.Column="1" Grid.Row="0" Classes="h5 no-margin" Text="{CompiledBinding Plugin.Info.Name}" />
|
||||
<TextBlock Grid.Column="1" Grid.Row="0" Classes="no-margin">
|
||||
<Run Classes="h5" Text="{CompiledBinding Plugin.Info.Name}"/>
|
||||
<Run Classes="subtitle" Text="{CompiledBinding Plugin.Info.Version}"/>
|
||||
</TextBlock>
|
||||
|
||||
<ItemsControl Grid.Column="2" Grid.Row="0" IsVisible="{CompiledBinding Platforms.Count}" ItemsSource="{CompiledBinding Platforms}" HorizontalAlignment="Right">
|
||||
<ItemsControl.ItemsPanel>
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
using Artemis.UI.Shared.Extensions;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.Settings.Account;
|
||||
|
||||
@ -10,5 +12,6 @@ public partial class CreatePersonalAccessTokenView : ReactiveUserControl<CreateP
|
||||
public CreatePersonalAccessTokenView()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.WhenActivated(_ => this.ClearAllDataValidationErrors());
|
||||
}
|
||||
}
|
||||
@ -16,7 +16,7 @@ public partial class CreatePersonalAccessTokenViewModel : ContentDialogViewModel
|
||||
private readonly IUserManagementService _userManagementService;
|
||||
private readonly IWindowService _windowService;
|
||||
[Notify] private string _description = string.Empty;
|
||||
[Notify] private DateTime _expirationDate = DateTime.Today.AddDays(180);
|
||||
[Notify] private DateTime _expirationDate = DateTime.UtcNow.Date.AddDays(181);
|
||||
|
||||
public CreatePersonalAccessTokenViewModel(IUserManagementService userManagementService, IWindowService windowService)
|
||||
{
|
||||
@ -25,13 +25,13 @@ public partial class CreatePersonalAccessTokenViewModel : ContentDialogViewModel
|
||||
Submit = ReactiveCommand.CreateFromTask(ExecuteSubmit, ValidationContext.Valid);
|
||||
|
||||
this.ValidationRule(vm => vm.Description, e => e != null, "You must specify a description");
|
||||
this.ValidationRule(vm => vm.Description, e => e == null || e.Length >= 10, "You must specify a description of at least 10 characters");
|
||||
this.ValidationRule(vm => vm.Description, e => e == null || e.Length >= 5, "You must specify a description of at least 5 characters");
|
||||
this.ValidationRule(vm => vm.Description, e => e == null || e.Length <= 150, "You must specify a description of less than 150 characters");
|
||||
this.ValidationRule(vm => vm.ExpirationDate, e => e >= DateTime.Today.AddDays(1), "Expiration date must be at least 24 hours from now");
|
||||
this.ValidationRule(vm => vm.ExpirationDate, e => e >= DateTime.UtcNow.Date.AddDays(1), "Expiration date must be at least 24 hours from now");
|
||||
}
|
||||
|
||||
public DateTime StartDate => DateTime.Today.AddDays(1);
|
||||
public DateTime EndDate => DateTime.Today.AddDays(365);
|
||||
public DateTime StartDate => DateTime.UtcNow.Date.AddDays(1);
|
||||
public DateTime EndDate => DateTime.UtcNow.Date.AddDays(365);
|
||||
public ReactiveCommand<Unit, Unit> Submit { get; }
|
||||
|
||||
private async Task ExecuteSubmit(CancellationToken cts)
|
||||
|
||||
@ -15,31 +15,31 @@
|
||||
<converters:DateTimeConverter x:Key="DateTimeConverter" />
|
||||
</UserControl.Resources>
|
||||
<Panel>
|
||||
<!-- <StackPanel IsVisible="{CompiledBinding !IsLoggedIn^}" Margin="0 50 0 0"> -->
|
||||
<!-- <StackPanel.Styles> -->
|
||||
<!-- <Styles> -->
|
||||
<!-- <Style Selector="TextBlock"> -->
|
||||
<!-- <Setter Property="TextAlignment" Value="Center"></Setter> -->
|
||||
<!-- <Setter Property="TextWrapping" Value="Wrap"></Setter> -->
|
||||
<!-- </Style> -->
|
||||
<!-- </Styles> -->
|
||||
<!-- </StackPanel.Styles> -->
|
||||
<!-- <TextBlock Theme="{StaticResource TitleTextBlockStyle}">You are not logged in</TextBlock> -->
|
||||
<!-- <TextBlock> -->
|
||||
<!-- <Run>In order to manage your account you must be logged in.</Run> -->
|
||||
<!-- <LineBreak /> -->
|
||||
<!-- <Run>Creating an account is free and we'll not bother you with a newsletter or crap like that.</Run> -->
|
||||
<!-- </TextBlock> -->
|
||||
<!-- -->
|
||||
<!-- <Lottie Path="/Assets/Animations/login-pending.json" RepeatCount="1" Width="350" Height="350"></Lottie> -->
|
||||
<!-- -->
|
||||
<!-- <TextBlock> -->
|
||||
<!-- <Run>Click Log In below to (create an account) and log in.</Run> -->
|
||||
<!-- <LineBreak /> -->
|
||||
<!-- <Run>You'll also be able to log in with Google or Discord.</Run> -->
|
||||
<!-- </TextBlock> -->
|
||||
<!-- <Button HorizontalAlignment="Center" Command="{CompiledBinding Login}" Margin="0 25 0 0">Login</Button> -->
|
||||
<!-- </StackPanel> -->
|
||||
<StackPanel IsVisible="{CompiledBinding !IsLoggedIn^}" Margin="0 50 0 0">
|
||||
<StackPanel.Styles>
|
||||
<Styles>
|
||||
<Style Selector="TextBlock">
|
||||
<Setter Property="TextAlignment" Value="Center"></Setter>
|
||||
<Setter Property="TextWrapping" Value="Wrap"></Setter>
|
||||
</Style>
|
||||
</Styles>
|
||||
</StackPanel.Styles>
|
||||
<TextBlock Theme="{StaticResource TitleTextBlockStyle}">You are not logged in</TextBlock>
|
||||
<TextBlock>
|
||||
<Run>In order to manage your account you must be logged in.</Run>
|
||||
<LineBreak />
|
||||
<Run>Creating an account is free and we'll not bother you with a newsletter or crap like that.</Run>
|
||||
</TextBlock>
|
||||
|
||||
<Lottie Path="/Assets/Animations/login-pending.json" RepeatCount="1" Width="350" Height="350"></Lottie>
|
||||
|
||||
<TextBlock>
|
||||
<Run>Click Log In below to (create an account) and log in.</Run>
|
||||
<LineBreak />
|
||||
<Run>You'll also be able to log in with Google or Discord.</Run>
|
||||
</TextBlock>
|
||||
<Button HorizontalAlignment="Center" Command="{CompiledBinding Login}" Margin="0 25 0 0">Login</Button>
|
||||
</StackPanel>
|
||||
|
||||
<ScrollViewer IsVisible="{CompiledBinding IsLoggedIn^}" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Margin="15" MaxWidth="1000">
|
||||
@ -109,16 +109,26 @@
|
||||
</TextBlock>
|
||||
<Border Classes="card" VerticalAlignment="Stretch" Margin="0,0,5,0">
|
||||
<StackPanel>
|
||||
<Button HorizontalAlignment="Right" Command="{CompiledBinding GenerateToken}">Generate token</Button>
|
||||
<DockPanel Margin="0 0 0 10">
|
||||
<TextBlock VerticalAlignment="Center">
|
||||
Tokens be used to communicate with Artemis APIs without using a username and password
|
||||
</TextBlock>
|
||||
<Button HorizontalAlignment="Right" Command="{CompiledBinding GenerateToken}">Generate token</Button>
|
||||
</DockPanel>
|
||||
|
||||
<Grid ColumnDefinitions="2*,*,*,*" Margin="12 6">
|
||||
<TextBlock Grid.Column="0">Description</TextBlock>
|
||||
<TextBlock Grid.Column="1">Created at</TextBlock>
|
||||
<TextBlock Grid.Column="2" Grid.ColumnSpan="2">Expires at</TextBlock>
|
||||
</Grid>
|
||||
|
||||
<TextBlock IsVisible="{CompiledBinding !PersonalAccessTokens.Count}" TextAlignment="Center" Classes="subtitle" Margin="0 10">
|
||||
You have no active personal access tokens.
|
||||
</TextBlock>
|
||||
|
||||
<ItemsControl ItemsSource="{CompiledBinding PersonalAccessTokens}">
|
||||
<ItemsControl ItemsSource="{CompiledBinding PersonalAccessTokens}" IsVisible="{CompiledBinding PersonalAccessTokens.Count}">
|
||||
<ItemsControl.Styles>
|
||||
<Style Selector="ContentPresenter:nth-child(even) > Border">
|
||||
<Style Selector="ContentPresenter:nth-child(odd) > Border">
|
||||
<Setter Property="Background" Value="{StaticResource ControlStrokeColorOnAccentDefault}"></Setter>
|
||||
</Style>
|
||||
</ItemsControl.Styles>
|
||||
@ -130,8 +140,8 @@
|
||||
<TextBlock Grid.Column="1" VerticalAlignment="Center" Text="{CompiledBinding CreationTime, Converter={StaticResource DateTimeConverter}}" />
|
||||
<TextBlock Grid.Column="2" VerticalAlignment="Center" Text="{CompiledBinding Expiration, Converter={StaticResource DateTimeConverter}}" />
|
||||
<Button Grid.Column="3" HorizontalAlignment="Right"
|
||||
Classes="icon-button"
|
||||
Command="{Binding $parent[settings:AccountTabView].DataContext.DeleteToken}"
|
||||
Classes="icon-button"
|
||||
Command="{Binding $parent[settings:AccountTabView].DataContext.DeleteToken}"
|
||||
CommandParameter="{CompiledBinding}">
|
||||
<avalonia:MaterialIcon Kind="Trash" />
|
||||
</Button>
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
Command="{CompiledBinding ViewWorkshopPage}">
|
||||
<Grid ColumnDefinitions="Auto,*,*,*,Auto">
|
||||
<Grid ColumnDefinitions="Auto,2*,*,*,*,Auto">
|
||||
<Border Grid.Column="0"
|
||||
CornerRadius="6"
|
||||
VerticalAlignment="Center"
|
||||
@ -42,12 +42,13 @@
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock Grid.Column="2" VerticalAlignment="Center" Text="{CompiledBinding InstalledEntry.EntryType}"></TextBlock>
|
||||
<TextBlock Grid.Column="3" VerticalAlignment="Center">
|
||||
<TextBlock Grid.Column="3" VerticalAlignment="Center" Text="{CompiledBinding InstalledEntry.ReleaseVersion}"></TextBlock>
|
||||
<TextBlock Grid.Column="4" VerticalAlignment="Center">
|
||||
<Run>Installed</Run>
|
||||
<Run Text="{CompiledBinding InstalledEntry.InstalledAt, FallbackValue=01-01-1337, Mode=OneWay, Converter={StaticResource DateTimeConverter}}" />
|
||||
</TextBlock>
|
||||
|
||||
<StackPanel Grid.Column="4" VerticalAlignment="Center" Orientation="Horizontal" Spacing="6">
|
||||
<StackPanel Grid.Column="5" VerticalAlignment="Center" Orientation="Horizontal" Spacing="6">
|
||||
<Button Command="{CompiledBinding ViewLocal}">Open</Button>
|
||||
<Button Command="{CompiledBinding Uninstall}" Theme="{StaticResource TransparentButton}" Height="32">
|
||||
<avalonia:MaterialIcon Kind="Trash"/>
|
||||
|
||||
@ -63,6 +63,14 @@ public class PluginEntryInstallationHandler : IEntryInstallationHandler
|
||||
using ZipArchive archive = new(stream);
|
||||
archive.ExtractToDirectory(releaseDirectory.FullName);
|
||||
|
||||
// If there is already a version of the plugin installed, disable it
|
||||
if (installedEntry.TryGetMetadata("PluginId", out Guid pluginId))
|
||||
{
|
||||
Plugin? currentVersion = _pluginManagementService.GetAllPlugins().FirstOrDefault(p => p.Guid == pluginId);
|
||||
if (currentVersion != null)
|
||||
_pluginManagementService.UnloadPlugin(currentVersion);
|
||||
}
|
||||
|
||||
// Load the plugin, next time during startup this will happen automatically
|
||||
try
|
||||
{
|
||||
|
||||
@ -97,7 +97,7 @@ public class InstalledEntry
|
||||
/// <param name="value">The value to set.</param>
|
||||
public void SetMetadata(string key, object value)
|
||||
{
|
||||
_metadata.Add(key, value);
|
||||
_metadata[key] = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -118,7 +118,7 @@ public class InstalledEntry
|
||||
{
|
||||
return new DirectoryInfo(Path.Combine(Constants.WorkshopFolder, $"{EntryId}-{StringUtilities.UrlFriendly(Name)}"));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns the directory info of a release of this entry, where any files would be stored if applicable.
|
||||
/// </summary>
|
||||
|
||||
@ -3,7 +3,7 @@ namespace Artemis.WebClient.Workshop.Models;
|
||||
public class PersonalAccessToken
|
||||
{
|
||||
public string Key { get; init; }
|
||||
public DateTimeOffset CreationTime { get; init; }
|
||||
public DateTimeOffset? Expiration { get; init; }
|
||||
public DateTime CreationTime { get; init; }
|
||||
public DateTime? Expiration { get; init; }
|
||||
public string? Description { get; init; }
|
||||
}
|
||||
@ -10,7 +10,7 @@ public interface IUserManagementService : IProtectedArtemisService
|
||||
Task<ApiResult> ChangeEmailAddress(string emailAddress, CancellationToken cancellationToken);
|
||||
Task<ApiResult> ChangeAvatar(Stream avatar, CancellationToken cancellationToken);
|
||||
Task<ApiResult> RemoveAccount(CancellationToken cancellationToken);
|
||||
Task<string> CreatePersonAccessToken(string description, DateTimeOffset expirationDate, CancellationToken cancellationToken);
|
||||
Task<string> CreatePersonAccessToken(string description, DateTime expirationDate, CancellationToken cancellationToken);
|
||||
Task<ApiResult> DeletePersonAccessToken(PersonalAccessToken personalAccessToken, CancellationToken cancellationToken);
|
||||
Task<List<PersonalAccessToken>> GetPersonAccessTokens(CancellationToken cancellationToken);
|
||||
}
|
||||
@ -66,7 +66,7 @@ internal class UserManagementService : IUserManagementService
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<string> CreatePersonAccessToken(string description, DateTimeOffset expirationDate, CancellationToken cancellationToken)
|
||||
public async Task<string> CreatePersonAccessToken(string description, DateTime expirationDate, CancellationToken cancellationToken)
|
||||
{
|
||||
HttpClient client = _httpClientFactory.CreateClient(WorkshopConstants.IDENTITY_CLIENT_NAME);
|
||||
HttpResponseMessage response = await client.PostAsync("user/access-token", JsonContent.Create(new {Description = description, ExpirationDate = expirationDate}), cancellationToken);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user