diff --git a/src/Artemis.UI/Screens/Workshop/Entries/Details/EntryInfoView.axaml b/src/Artemis.UI/Screens/Workshop/Entries/Details/EntryInfoView.axaml
index 94b2e1688..449639c4e 100644
--- a/src/Artemis.UI/Screens/Workshop/Entries/Details/EntryInfoView.axaml
+++ b/src/Artemis.UI/Screens/Workshop/Entries/Details/EntryInfoView.axaml
@@ -15,7 +15,7 @@
-
-
+
+
+
+
+
-
+
diff --git a/src/Artemis.UI/Screens/Workshop/Entries/Details/EntryInfoViewModel.cs b/src/Artemis.UI/Screens/Workshop/Entries/Details/EntryInfoViewModel.cs
index 6cf02efb1..6700f0bd3 100644
--- a/src/Artemis.UI/Screens/Workshop/Entries/Details/EntryInfoViewModel.cs
+++ b/src/Artemis.UI/Screens/Workshop/Entries/Details/EntryInfoViewModel.cs
@@ -25,7 +25,7 @@ public partial class EntryInfoViewModel : ActivatableViewModelBase
[Notify] private DateTimeOffset? _updatedAt;
[Notify] private bool _canBeManaged;
- public EntryInfoViewModel(IRouter router, INotificationService notificationService, IWorkshopService workshopService)
+ public EntryInfoViewModel(IRouter router, INotificationService notificationService, IWorkshopService workshopService, IAuthenticationService authenticationService)
{
_router = router;
_notificationService = notificationService;
@@ -38,8 +38,12 @@ public partial class EntryInfoViewModel : ActivatableViewModelBase
.Subscribe(_ => CanBeManaged = Entry != null && Entry.EntryType != EntryType.Profile && workshopService.GetInstalledEntry(Entry.Id) != null)
.DisposeWith(d);
});
+
+ IsAdministrator = authenticationService.GetRoles().Contains("Administrator");
}
-
+
+ public bool IsAdministrator { get; }
+
public void SetEntry(IEntryDetails? entry)
{
Entry = entry;
@@ -55,6 +59,14 @@ public partial class EntryInfoViewModel : ActivatableViewModelBase
await Shared.UI.Clipboard.SetTextAsync($"{WorkshopConstants.WORKSHOP_URL}/entries/{Entry.Id}/{StringUtilities.UrlFriendly(Entry.Name)}");
_notificationService.CreateNotification().WithTitle("Copied share link to clipboard.").Show();
}
+
+ public async Task GoToEdit()
+ {
+ if (Entry == null)
+ return;
+
+ await _router.Navigate($"workshop/library/submissions/{Entry.Id}");
+ }
public async Task GoToManage()
{
diff --git a/src/Artemis.UI/Screens/Workshop/Entries/Details/EntrySpecificationsView.axaml b/src/Artemis.UI/Screens/Workshop/Entries/Details/EntrySpecificationsView.axaml
index 16a0b4b5a..dda4ba091 100644
--- a/src/Artemis.UI/Screens/Workshop/Entries/Details/EntrySpecificationsView.axaml
+++ b/src/Artemis.UI/Screens/Workshop/Entries/Details/EntrySpecificationsView.axaml
@@ -63,6 +63,8 @@
+
+ Download by default (admin only)
diff --git a/src/Artemis.UI/Screens/Workshop/Entries/Details/EntrySpecificationsViewModel.cs b/src/Artemis.UI/Screens/Workshop/Entries/Details/EntrySpecificationsViewModel.cs
index 041af76cc..bea16889d 100644
--- a/src/Artemis.UI/Screens/Workshop/Entries/Details/EntrySpecificationsViewModel.cs
+++ b/src/Artemis.UI/Screens/Workshop/Entries/Details/EntrySpecificationsViewModel.cs
@@ -11,6 +11,7 @@ using Artemis.UI.Screens.Workshop.Categories;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Services;
using Artemis.WebClient.Workshop;
+using Artemis.WebClient.Workshop.Services;
using Avalonia.Media.Imaging;
using AvaloniaEdit.Document;
using DynamicData;
@@ -34,10 +35,11 @@ public partial class EntrySpecificationsViewModel : ValidatableViewModelBase
[Notify] private string _name = string.Empty;
[Notify] private string _summary = string.Empty;
[Notify] private string _description = string.Empty;
+ [Notify] private bool _isDefault;
[Notify] private Bitmap? _iconBitmap;
[Notify(Setter.Private)] private bool _iconChanged;
- public EntrySpecificationsViewModel(IWorkshopClient workshopClient, IWindowService windowService)
+ public EntrySpecificationsViewModel(IWorkshopClient workshopClient, IWindowService windowService, IAuthenticationService authenticationService)
{
_workshopClient = workshopClient;
_windowService = windowService;
@@ -65,8 +67,9 @@ public partial class EntrySpecificationsViewModel : ValidatableViewModelBase
_descriptionValid = descriptionRule.ValidationChanged.Select(c => c.IsValid).ToProperty(this, vm => vm.DescriptionValid);
this.WhenActivatedAsync(async _ => await PopulateCategories());
+ IsAdministrator = authenticationService.GetRoles().Contains("Administrator");
}
-
+
public ReactiveCommand SelectIcon { get; }
public ObservableCollection Categories { get; } = new();
@@ -76,7 +79,8 @@ public partial class EntrySpecificationsViewModel : ValidatableViewModelBase
public bool CategoriesValid => _categoriesValid.Value ;
public bool IconValid => _iconValid.Value;
public bool DescriptionValid => _descriptionValid.Value;
-
+ public bool IsAdministrator { get; }
+
public List PreselectedCategories { get; set; } = new();
private async Task ExecuteSelectIcon()
diff --git a/src/Artemis.UI/Screens/Workshop/Entries/List/EntryListItemView.axaml b/src/Artemis.UI/Screens/Workshop/Entries/List/EntryListItemView.axaml
index cae7a1934..af26a3da1 100644
--- a/src/Artemis.UI/Screens/Workshop/Entries/List/EntryListItemView.axaml
+++ b/src/Artemis.UI/Screens/Workshop/Entries/List/EntryListItemView.axaml
@@ -79,7 +79,7 @@
-
+
diff --git a/src/Artemis.UI/Screens/Workshop/Library/SubmissionDetailsViewModel.cs b/src/Artemis.UI/Screens/Workshop/Library/SubmissionDetailsViewModel.cs
index 7829b7261..da3216050 100644
--- a/src/Artemis.UI/Screens/Workshop/Library/SubmissionDetailsViewModel.cs
+++ b/src/Artemis.UI/Screens/Workshop/Library/SubmissionDetailsViewModel.cs
@@ -59,7 +59,7 @@ public partial class SubmissionDetailsViewModel : RoutableScreen
DiscardChanges = ReactiveCommand.CreateFromTask(ExecuteDiscardChanges, this.WhenAnyValue(vm => vm.HasChanges));
SaveChanges = ReactiveCommand.CreateFromTask(ExecuteSaveChanges, this.WhenAnyValue(vm => vm.HasChanges));
}
-
+
public ObservableCollection Images { get; } = new();
public ReactiveCommand AddImage { get; }
public ReactiveCommand SaveChanges { get; }
@@ -105,6 +105,7 @@ public partial class SubmissionDetailsViewModel : RoutableScreen
specificationsViewModel.Name = Entry.Name;
specificationsViewModel.Summary = Entry.Summary;
specificationsViewModel.Description = Entry.Description;
+ specificationsViewModel.IsDefault = Entry.IsDefault;
specificationsViewModel.PreselectedCategories = Entry.Categories.Select(c => c.Id).ToList();
specificationsViewModel.Tags.Clear();
@@ -169,6 +170,7 @@ public partial class SubmissionDetailsViewModel : RoutableScreen
HasChanges = EntrySpecificationsViewModel.Name != Entry.Name ||
EntrySpecificationsViewModel.Description != Entry.Description ||
EntrySpecificationsViewModel.Summary != Entry.Summary ||
+ EntrySpecificationsViewModel.IsDefault != Entry.IsDefault ||
EntrySpecificationsViewModel.IconChanged ||
!tags.SequenceEqual(Entry.Tags.Select(t => t.Name).OrderBy(t => t)) ||
!categories.SequenceEqual(Entry.Categories.Select(c => c.Id).OrderBy(c => c)) ||
@@ -192,6 +194,7 @@ public partial class SubmissionDetailsViewModel : RoutableScreen
Name = EntrySpecificationsViewModel.Name,
Summary = EntrySpecificationsViewModel.Summary,
Description = EntrySpecificationsViewModel.Description,
+ IsDefault = EntrySpecificationsViewModel.IsDefault,
Categories = EntrySpecificationsViewModel.SelectedCategories,
Tags = EntrySpecificationsViewModel.Tags
};
@@ -233,7 +236,7 @@ public partial class SubmissionDetailsViewModel : RoutableScreen
HasChanges = false;
await _router.Reload();
}
-
+
private async Task ExecuteAddImage(CancellationToken arg)
{
string[]? result = await _windowService.CreateOpenFileDialog().WithAllowMultiple().HavingFilter(f => f.WithBitmaps()).ShowAsync();
diff --git a/src/Artemis.UI/Screens/Workshop/Library/Tabs/SubmissionsTabItemView.axaml b/src/Artemis.UI/Screens/Workshop/Library/Tabs/SubmissionsTabItemView.axaml
index b45a8d3e8..822f24c71 100644
--- a/src/Artemis.UI/Screens/Workshop/Library/Tabs/SubmissionsTabItemView.axaml
+++ b/src/Artemis.UI/Screens/Workshop/Library/Tabs/SubmissionsTabItemView.axaml
@@ -67,7 +67,7 @@
-
+
diff --git a/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Models/SubmissionWizardState.cs b/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Models/SubmissionWizardState.cs
index aaf688ef6..5e6927690 100644
--- a/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Models/SubmissionWizardState.cs
+++ b/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Models/SubmissionWizardState.cs
@@ -32,6 +32,7 @@ public class SubmissionWizardState : IDisposable
public Stream? Icon { get; set; }
public string Summary { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
+ public bool IsDefault { get; set; }
public List Categories { get; set; } = new();
public List Tags { get; set; } = new();
diff --git a/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/ChangelogStepViewModel.cs b/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/ChangelogStepViewModel.cs
index e2e97795f..e84d4a69a 100644
--- a/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/ChangelogStepViewModel.cs
+++ b/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/ChangelogStepViewModel.cs
@@ -1,3 +1,4 @@
+using System.ComponentModel.DataAnnotations;
using System.Reactive.Disposables;
using Artemis.UI.Screens.Workshop.SubmissionWizard.Steps.Layout;
using Artemis.UI.Screens.Workshop.SubmissionWizard.Steps.Plugin;
@@ -10,7 +11,7 @@ namespace Artemis.UI.Screens.Workshop.SubmissionWizard.Steps;
public partial class ChangelogStepViewModel : SubmissionViewModel
{
- [Notify] private string? _changelog;
+ [Notify] private string _changelog = string.Empty;
public ChangelogStepViewModel()
{
@@ -18,7 +19,7 @@ public partial class ChangelogStepViewModel : SubmissionViewModel
Continue = ReactiveCommand.Create(ExecuteContinue);
ContinueText = "Submit";
- this.WhenActivated((CompositeDisposable _) => Changelog = State.Changelog);
+ this.WhenActivated((CompositeDisposable _) => Changelog = State.Changelog ?? string.Empty);
}
private void ExecuteContinue()
@@ -29,7 +30,7 @@ public partial class ChangelogStepViewModel : SubmissionViewModel
private void ExecuteGoBack()
{
- State.Changelog = Changelog;
+ State.Changelog = string.IsNullOrWhiteSpace(Changelog) ? null : Changelog;
if (State.EntryType == EntryType.Layout)
State.ChangeScreen();
else if (State.EntryType == EntryType.Plugin)
diff --git a/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/SpecificationsStepViewModel.cs b/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/SpecificationsStepViewModel.cs
index 678aea918..01a5c19fc 100644
--- a/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/SpecificationsStepViewModel.cs
+++ b/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/SpecificationsStepViewModel.cs
@@ -65,6 +65,7 @@ public partial class SpecificationsStepViewModel : SubmissionViewModel
viewModel.Name = State.Name;
viewModel.Summary = State.Summary;
viewModel.Description = State.Description;
+ viewModel.IsDefault = State.IsDefault;
// Tags
viewModel.Tags.Clear();
@@ -93,6 +94,7 @@ public partial class SpecificationsStepViewModel : SubmissionViewModel
State.Name = EntrySpecificationsViewModel.Name;
State.Summary = EntrySpecificationsViewModel.Summary;
State.Description = EntrySpecificationsViewModel.Description;
+ State.IsDefault = EntrySpecificationsViewModel.IsDefault;
// Categories and tasks
State.Categories = EntrySpecificationsViewModel.Categories.Where(c => c.IsSelected).Select(c => c.Id).ToList();
diff --git a/src/Artemis.WebClient.Workshop/Queries/Fragments.graphql b/src/Artemis.WebClient.Workshop/Queries/Fragments.graphql
index cf0c3c779..a1f8eb669 100644
--- a/src/Artemis.WebClient.Workshop/Queries/Fragments.graphql
+++ b/src/Artemis.WebClient.Workshop/Queries/Fragments.graphql
@@ -26,6 +26,10 @@ fragment submittedEntry on Entry {
entryType
downloads
createdAt
+ isDefault
+ latestRelease {
+ ...release
+ }
}
fragment entrySummary on Entry {
@@ -38,6 +42,9 @@ fragment entrySummary on Entry {
downloads
createdAt
latestReleaseId
+ latestRelease {
+ ...release
+ }
categories {
...category
}
diff --git a/src/Artemis.WebClient.Workshop/Services/AuthenticationService.cs b/src/Artemis.WebClient.Workshop/Services/AuthenticationService.cs
index 9c0dc6d7b..7e7e76f47 100644
--- a/src/Artemis.WebClient.Workshop/Services/AuthenticationService.cs
+++ b/src/Artemis.WebClient.Workshop/Services/AuthenticationService.cs
@@ -283,6 +283,12 @@ internal class AuthenticationService : CorePropertyChanged, IAuthenticationServi
return emailVerified?.Value.ToLower() == "true";
}
+ ///
+ public List GetRoles()
+ {
+ return Claims.Where(c => c.Type == JwtClaimTypes.Role).Select(c => c.Value).ToList();
+ }
+
private async Task InternalAutoLogin(bool force = false)
{
if (!force && _isLoggedInSubject.Value)
diff --git a/src/Artemis.WebClient.Workshop/Services/Interfaces/IAuthenticationService.cs b/src/Artemis.WebClient.Workshop/Services/Interfaces/IAuthenticationService.cs
index 5d8f908b3..66e1392be 100644
--- a/src/Artemis.WebClient.Workshop/Services/Interfaces/IAuthenticationService.cs
+++ b/src/Artemis.WebClient.Workshop/Services/Interfaces/IAuthenticationService.cs
@@ -15,4 +15,5 @@ public interface IAuthenticationService : IProtectedArtemisService
Task Login(CancellationToken cancellationToken);
Task Logout();
bool GetIsEmailVerified();
+ List GetRoles();
}
\ No newline at end of file