Spliit the script editor into its own dialog separate from the table. Only pass IDs between game, editor, and dialog for better performance.
parent
875b7b7caa
commit
8cc97f9bdb
|
@ -4,75 +4,12 @@
|
||||||
@using LANCommander.Models
|
@using LANCommander.Models
|
||||||
@using LANCommander.Services
|
@using LANCommander.Services
|
||||||
@using System.IO.Compression;
|
@using System.IO.Compression;
|
||||||
|
@using Microsoft.EntityFrameworkCore;
|
||||||
@inject ScriptService ScriptService
|
@inject ScriptService ScriptService
|
||||||
@inject ModalService ModalService
|
@inject ModalService ModalService
|
||||||
@inject IMessageService MessageService
|
@inject IMessageService MessageService
|
||||||
|
|
||||||
@{
|
|
||||||
RenderFragment Footer =
|
|
||||||
@<Template>
|
|
||||||
<Button OnClick="Save" Disabled="@(String.IsNullOrWhiteSpace(Script.Name))" Type="@ButtonType.Primary">Save</Button>
|
|
||||||
<Button OnClick="Close">Close</Button>
|
|
||||||
</Template>;
|
|
||||||
}
|
|
||||||
|
|
||||||
<Modal Visible="ModalVisible" Footer="@Footer" Title="@(Script == null ? "Add Script" : "Edit Script")" OkText="@("Save")" Maximizable="false" DefaultMaximized="true" Closable="true" OnCancel="Close">
|
|
||||||
<Form Model="@Script" Layout="@FormLayout.Vertical">
|
|
||||||
<FormItem>
|
|
||||||
@foreach (var group in Snippets.Select(s => s.Group).Distinct())
|
|
||||||
{
|
|
||||||
<Dropdown>
|
|
||||||
<Overlay>
|
|
||||||
<Menu>
|
|
||||||
@foreach (var snippet in Snippets.Where(s => s.Group == group))
|
|
||||||
{
|
|
||||||
<MenuItem OnClick="() => InsertSnippet(snippet)">
|
|
||||||
@snippet.Name
|
|
||||||
</MenuItem>
|
|
||||||
}
|
|
||||||
</Menu>
|
|
||||||
</Overlay>
|
|
||||||
|
|
||||||
<ChildContent>
|
|
||||||
<Button Type="@ButtonType.Primary">@group</Button>
|
|
||||||
</ChildContent>
|
|
||||||
</Dropdown>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (ArchiveId != Guid.Empty)
|
|
||||||
{
|
|
||||||
<Button Icon="@IconType.Outline.FolderOpen" OnClick="BrowseForPath" Type="@ButtonType.Text">Browse</Button>
|
|
||||||
}
|
|
||||||
|
|
||||||
<Button Icon="@IconType.Outline.Build" OnClick="() => RegToPowerShell.Open()" Type="@ButtonType.Text">Import .reg</Button>
|
|
||||||
</FormItem>
|
|
||||||
|
|
||||||
<FormItem>
|
|
||||||
<StandaloneCodeEditor @ref="Editor" Id="editor" ConstructionOptions="EditorConstructionOptions" />
|
|
||||||
</FormItem>
|
|
||||||
|
|
||||||
<FormItem Label="Name">
|
|
||||||
<Input @bind-Value="@context.Name" />
|
|
||||||
</FormItem>
|
|
||||||
|
|
||||||
<FormItem Label="Type">
|
|
||||||
<Select @bind-Value="context.Type" TItem="ScriptType" TItemValue="ScriptType" DataSource="Enum.GetValues<ScriptType>().Where(st => AllowedTypes == null || AllowedTypes.Contains(st))">
|
|
||||||
<LabelTemplate Context="Value">@Value.GetDisplayName()</LabelTemplate>
|
|
||||||
<ItemTemplate Context="Value">@Value.GetDisplayName()</ItemTemplate>
|
|
||||||
</Select>
|
|
||||||
</FormItem>
|
|
||||||
|
|
||||||
<FormItem>
|
|
||||||
<Checkbox @bind-Checked="context.RequiresAdmin">Requires Admin</Checkbox>
|
|
||||||
</FormItem>
|
|
||||||
|
|
||||||
<FormItem Label="Description">
|
|
||||||
<TextArea @bind-Value="context.Description" MaxLength=500 ShowCount />
|
|
||||||
</FormItem>
|
|
||||||
</Form>
|
|
||||||
</Modal>
|
|
||||||
|
|
||||||
<RegToPowerShell @ref="RegToPowerShell" OnParsed="(text) => InsertText(text)" />
|
|
||||||
|
|
||||||
<Space Direction="DirectionVHType.Vertical" Size="@("large")" Style="width: 100%">
|
<Space Direction="DirectionVHType.Vertical" Size="@("large")" Style="width: 100%">
|
||||||
<SpaceItem>
|
<SpaceItem>
|
||||||
|
@ -85,7 +22,7 @@
|
||||||
<ActionColumn Title="">
|
<ActionColumn Title="">
|
||||||
<Space Style="display: flex; justify-content: end">
|
<Space Style="display: flex; justify-content: end">
|
||||||
<SpaceItem>
|
<SpaceItem>
|
||||||
<Button OnClick="() => Edit(context)" Icon="@IconType.Outline.Edit" Type="@ButtonType.Text" />
|
<Button OnClick="() => Edit(context.Id)" Icon="@IconType.Outline.Edit" Type="@ButtonType.Text" />
|
||||||
|
|
||||||
<Popconfirm OnConfirm="() => Delete(context)" Title="Are you sure you want to delete this script?">
|
<Popconfirm OnConfirm="() => Delete(context)" Title="Are you sure you want to delete this script?">
|
||||||
<Button Icon="@IconType.Outline.Close" Type="@ButtonType.Text" Danger />
|
<Button Icon="@IconType.Outline.Close" Type="@ButtonType.Text" Danger />
|
||||||
|
@ -115,59 +52,44 @@
|
||||||
[Parameter] public Guid GameId { get; set; }
|
[Parameter] public Guid GameId { get; set; }
|
||||||
[Parameter] public Guid RedistributableId { get; set; }
|
[Parameter] public Guid RedistributableId { get; set; }
|
||||||
[Parameter] public Guid ArchiveId { get; set; }
|
[Parameter] public Guid ArchiveId { get; set; }
|
||||||
[Parameter] public ICollection<Script> Scripts { get; set; }
|
|
||||||
[Parameter] public EventCallback<ICollection<Script>> ScriptsChanged { get; set; }
|
|
||||||
[Parameter] public IEnumerable<ScriptType> AllowedTypes { get; set; }
|
[Parameter] public IEnumerable<ScriptType> AllowedTypes { get; set; }
|
||||||
|
|
||||||
Script Script;
|
ICollection<Script> Scripts { get; set; } = new List<Script>();
|
||||||
|
|
||||||
bool ModalVisible = false;
|
protected override async Task OnParametersSetAsync()
|
||||||
|
|
||||||
IEnumerable<Snippet> Snippets { get; set; }
|
|
||||||
StandaloneCodeEditor? Editor;
|
|
||||||
RegToPowerShell RegToPowerShell;
|
|
||||||
|
|
||||||
private StandaloneEditorConstructionOptions EditorConstructionOptions(StandaloneCodeEditor editor)
|
|
||||||
{
|
{
|
||||||
return new StandaloneEditorConstructionOptions
|
if (GameId != Guid.Empty)
|
||||||
|
Scripts = await ScriptService.Get(s => s.GameId == GameId).ToListAsync();
|
||||||
|
else if (RedistributableId != Guid.Empty)
|
||||||
|
Scripts = await ScriptService.Get(s => s.RedistributableId == RedistributableId).ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void Edit(Guid? scriptId = null)
|
||||||
|
{
|
||||||
|
var modalOptions = new ModalOptions()
|
||||||
{
|
{
|
||||||
AutomaticLayout = true,
|
Title = scriptId == null ? "Add Script" : "Edit Script",
|
||||||
Language = "powershell",
|
Maximizable = false,
|
||||||
Value = Script.Contents,
|
DefaultMaximized = true,
|
||||||
Theme = "vs-dark",
|
Closable = true,
|
||||||
|
OkText = "Save"
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
var options = new ScriptEditorOptions()
|
||||||
{
|
{
|
||||||
if (Scripts == null)
|
ScriptId = scriptId ?? default,
|
||||||
Scripts = new List<Script>();
|
AllowedTypes = AllowedTypes,
|
||||||
|
ArchiveId = ArchiveId,
|
||||||
|
GameId = GameId,
|
||||||
|
RedistributableId = RedistributableId
|
||||||
|
};
|
||||||
|
|
||||||
Snippets = ScriptService.GetSnippets();
|
var modalRef = await ModalService.CreateModalAsync<ScriptEditorDialog, ScriptEditorOptions, Script>(modalOptions, options);
|
||||||
|
|
||||||
if (Script == null)
|
modalRef.OnOk = async (script) =>
|
||||||
Script = new Script();
|
{
|
||||||
}
|
|
||||||
|
};
|
||||||
private async void Edit(Script script = null)
|
|
||||||
{
|
|
||||||
if (script == null) {
|
|
||||||
if (GameId != Guid.Empty)
|
|
||||||
Script = new Script() { GameId = GameId };
|
|
||||||
|
|
||||||
if (RedistributableId != Guid.Empty)
|
|
||||||
Script = new Script() { RedistributableId = RedistributableId };
|
|
||||||
|
|
||||||
if (Editor != null)
|
|
||||||
await Editor.SetValue("");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
Script = script;
|
|
||||||
|
|
||||||
if (Editor != null && Script != null)
|
|
||||||
await Editor.SetValue(Script.Contents);
|
|
||||||
|
|
||||||
ModalVisible = true;
|
|
||||||
|
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
@ -179,81 +101,4 @@
|
||||||
|
|
||||||
await MessageService.Success("Script deleted!");
|
await MessageService.Success("Script deleted!");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Close()
|
|
||||||
{
|
|
||||||
ModalVisible = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task Save()
|
|
||||||
{
|
|
||||||
var value = await Editor.GetValue();
|
|
||||||
|
|
||||||
Script.Contents = value;
|
|
||||||
|
|
||||||
if (Script.Id == Guid.Empty)
|
|
||||||
Script = await ScriptService.Add(Script);
|
|
||||||
else
|
|
||||||
Script = await ScriptService.Update(Script);
|
|
||||||
|
|
||||||
Close();
|
|
||||||
|
|
||||||
StateHasChanged();
|
|
||||||
|
|
||||||
await MessageService.Success("Script saved!");
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task InsertText(string text)
|
|
||||||
{
|
|
||||||
var line = await Editor.GetPosition();
|
|
||||||
var range = new BlazorMonaco.Range(line.LineNumber, 1, line.LineNumber, 1);
|
|
||||||
|
|
||||||
var currentSelections = await Editor.GetSelections();
|
|
||||||
|
|
||||||
await Editor.ExecuteEdits("ScriptEditor", new List<IdentifiedSingleEditOperation>()
|
|
||||||
{
|
|
||||||
new IdentifiedSingleEditOperation
|
|
||||||
{
|
|
||||||
Range = range,
|
|
||||||
Text = text,
|
|
||||||
ForceMoveMarkers = true
|
|
||||||
}
|
|
||||||
}, currentSelections);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task InsertSnippet(Snippet snippet)
|
|
||||||
{
|
|
||||||
await InsertText(snippet.Content);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void BrowseForPath()
|
|
||||||
{
|
|
||||||
var modalOptions = new ModalOptions()
|
|
||||||
{
|
|
||||||
Title = "Choose Reference",
|
|
||||||
Maximizable = false,
|
|
||||||
DefaultMaximized = true,
|
|
||||||
Closable = true,
|
|
||||||
OkText = "Insert File Path"
|
|
||||||
};
|
|
||||||
|
|
||||||
var browserOptions = new FilePickerOptions()
|
|
||||||
{
|
|
||||||
ArchiveId = ArchiveId,
|
|
||||||
Select = true,
|
|
||||||
Multiple = false
|
|
||||||
};
|
|
||||||
|
|
||||||
var modalRef = await ModalService.CreateModalAsync<FilePickerDialog, FilePickerOptions, IEnumerable<IFileManagerEntry>>(modalOptions, browserOptions);
|
|
||||||
|
|
||||||
modalRef.OnOk = (results) =>
|
|
||||||
{
|
|
||||||
var path = results.FirstOrDefault().Path;
|
|
||||||
|
|
||||||
InsertText($"$InstallDir\\{path.Replace('/', '\\')}");
|
|
||||||
|
|
||||||
StateHasChanged();
|
|
||||||
return Task.CompletedTask;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,176 @@
|
||||||
|
@using LANCommander.Components.FileManagerComponents;
|
||||||
|
@using LANCommander.Extensions;
|
||||||
|
@using LANCommander.Data.Enums;
|
||||||
|
@using LANCommander.Models;
|
||||||
|
@inherits FeedbackComponent<ScriptEditorOptions, Script>
|
||||||
|
@inject ScriptService ScriptService
|
||||||
|
@inject ModalService ModalService
|
||||||
|
@inject IMessageService MessageService
|
||||||
|
|
||||||
|
<Form Model="@Script" Layout="@FormLayout.Vertical">
|
||||||
|
<FormItem>
|
||||||
|
@foreach (var group in Snippets.Select(s => s.Group).Distinct())
|
||||||
|
{
|
||||||
|
<Dropdown>
|
||||||
|
<Overlay>
|
||||||
|
<Menu>
|
||||||
|
@foreach (var snippet in Snippets.Where(s => s.Group == group))
|
||||||
|
{
|
||||||
|
<MenuItem OnClick="() => InsertSnippet(snippet)">
|
||||||
|
@snippet.Name
|
||||||
|
</MenuItem>
|
||||||
|
}
|
||||||
|
</Menu>
|
||||||
|
</Overlay>
|
||||||
|
|
||||||
|
<ChildContent>
|
||||||
|
<Button Type="@ButtonType.Primary">@group</Button>
|
||||||
|
</ChildContent>
|
||||||
|
</Dropdown>
|
||||||
|
}
|
||||||
|
|
||||||
|
@if (Options.ArchiveId != Guid.Empty)
|
||||||
|
{
|
||||||
|
<Button Icon="@IconType.Outline.FolderOpen" OnClick="BrowseForPath" Type="@ButtonType.Text">Browse</Button>
|
||||||
|
}
|
||||||
|
|
||||||
|
<Button Icon="@IconType.Outline.Build" OnClick="() => RegToPowerShell.Open()" Type="@ButtonType.Text">Import .reg</Button>
|
||||||
|
</FormItem>
|
||||||
|
|
||||||
|
<FormItem>
|
||||||
|
<StandaloneCodeEditor @ref="Editor" Id="@("editor-" + Id.ToString())" ConstructionOptions="EditorConstructionOptions" />
|
||||||
|
</FormItem>
|
||||||
|
|
||||||
|
<FormItem Label="Name">
|
||||||
|
<Input @bind-Value="@context.Name" />
|
||||||
|
</FormItem>
|
||||||
|
|
||||||
|
<FormItem Label="Type">
|
||||||
|
<Select @bind-Value="context.Type" TItem="ScriptType" TItemValue="ScriptType" DataSource="Enum.GetValues<ScriptType>().Where(st => Options.AllowedTypes == null || Options.AllowedTypes.Contains(st))">
|
||||||
|
<LabelTemplate Context="Value">@Value.GetDisplayName()</LabelTemplate>
|
||||||
|
<ItemTemplate Context="Value">@Value.GetDisplayName()</ItemTemplate>
|
||||||
|
</Select>
|
||||||
|
</FormItem>
|
||||||
|
|
||||||
|
<FormItem>
|
||||||
|
<Checkbox @bind-Checked="context.RequiresAdmin">Requires Admin</Checkbox>
|
||||||
|
</FormItem>
|
||||||
|
|
||||||
|
<FormItem Label="Description">
|
||||||
|
<TextArea @bind-Value="context.Description" MaxLength=500 ShowCount />
|
||||||
|
</FormItem>
|
||||||
|
</Form>
|
||||||
|
|
||||||
|
<RegToPowerShell @ref="RegToPowerShell" OnParsed="(text) => InsertText(text)" />
|
||||||
|
|
||||||
|
@code {
|
||||||
|
Guid Id = Guid.NewGuid();
|
||||||
|
Script Script;
|
||||||
|
StandaloneCodeEditor? Editor;
|
||||||
|
RegToPowerShell RegToPowerShell;
|
||||||
|
IEnumerable<Snippet> Snippets { get; set; }
|
||||||
|
|
||||||
|
private StandaloneEditorConstructionOptions EditorConstructionOptions(StandaloneCodeEditor editor)
|
||||||
|
{
|
||||||
|
return new StandaloneEditorConstructionOptions
|
||||||
|
{
|
||||||
|
AutomaticLayout = true,
|
||||||
|
Language = "powershell",
|
||||||
|
Value = Script.Contents,
|
||||||
|
Theme = "vs-dark",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
if (Options.ScriptId != Guid.Empty)
|
||||||
|
Script = await ScriptService.Get(Options.ScriptId);
|
||||||
|
|
||||||
|
Snippets = ScriptService.GetSnippets();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task OnFeedbackOkAsync(ModalClosingEventArgs args)
|
||||||
|
{
|
||||||
|
await Save();
|
||||||
|
|
||||||
|
Editor.Dispose();
|
||||||
|
|
||||||
|
await base.OkCancelRefWithResult!.OnOk(Script);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task CancelAsync(ModalClosingEventArgs args)
|
||||||
|
{
|
||||||
|
Editor.Dispose();
|
||||||
|
|
||||||
|
await base.CancelAsync(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void BrowseForPath()
|
||||||
|
{
|
||||||
|
|
||||||
|
var modalOptions = new ModalOptions()
|
||||||
|
{
|
||||||
|
Title = "Choose Reference",
|
||||||
|
Maximizable = false,
|
||||||
|
DefaultMaximized = true,
|
||||||
|
Closable = true,
|
||||||
|
OkText = "Insert File Path"
|
||||||
|
};
|
||||||
|
|
||||||
|
var browserOptions = new FilePickerOptions()
|
||||||
|
{
|
||||||
|
ArchiveId = Options.ArchiveId,
|
||||||
|
Select = true,
|
||||||
|
Multiple = false
|
||||||
|
};
|
||||||
|
|
||||||
|
var modalRef = await ModalService.CreateModalAsync<FilePickerDialog, FilePickerOptions, IEnumerable<IFileManagerEntry>>(modalOptions, browserOptions);
|
||||||
|
|
||||||
|
modalRef.OnOk = (results) =>
|
||||||
|
{
|
||||||
|
var path = results.FirstOrDefault().Path;
|
||||||
|
|
||||||
|
InsertText($"$InstallDir\\{path.Replace('/', '\\')}");
|
||||||
|
|
||||||
|
StateHasChanged();
|
||||||
|
return Task.CompletedTask;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task InsertText(string text)
|
||||||
|
{
|
||||||
|
var line = await Editor.GetPosition();
|
||||||
|
var range = new BlazorMonaco.Range(line.LineNumber, 1, line.LineNumber, 1);
|
||||||
|
|
||||||
|
var currentSelections = await Editor.GetSelections();
|
||||||
|
|
||||||
|
await Editor.ExecuteEdits("ScriptEditor", new List<IdentifiedSingleEditOperation>()
|
||||||
|
{
|
||||||
|
new IdentifiedSingleEditOperation
|
||||||
|
{
|
||||||
|
Range = range,
|
||||||
|
Text = text,
|
||||||
|
ForceMoveMarkers = true
|
||||||
|
}
|
||||||
|
}, currentSelections);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task InsertSnippet(Snippet snippet)
|
||||||
|
{
|
||||||
|
await InsertText(snippet.Content);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task Save()
|
||||||
|
{
|
||||||
|
var value = await Editor.GetValue();
|
||||||
|
|
||||||
|
Script.Contents = value;
|
||||||
|
|
||||||
|
if (Script.Id == Guid.Empty)
|
||||||
|
Script = await ScriptService.Add(Script);
|
||||||
|
else
|
||||||
|
Script = await ScriptService.Update(Script);
|
||||||
|
|
||||||
|
await MessageService.Success("Script saved!");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
using LANCommander.Data.Enums;
|
||||||
|
|
||||||
|
namespace LANCommander.Models
|
||||||
|
{
|
||||||
|
public class ScriptEditorOptions
|
||||||
|
{
|
||||||
|
public Guid ScriptId { get; set; }
|
||||||
|
public Guid GameId { get; set; }
|
||||||
|
public Guid RedistributableId { get; set; }
|
||||||
|
public Guid ArchiveId { get; set; }
|
||||||
|
public IEnumerable<ScriptType> AllowedTypes { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -128,7 +128,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div data-panel="Scripts">
|
<div data-panel="Scripts">
|
||||||
<ScriptEditor @bind-Scripts="Game.Scripts" GameId="Game.Id" ArchiveId="@LatestArchiveId" AllowedTypes="new ScriptType[] { ScriptType.Install, ScriptType.Uninstall, ScriptType.NameChange, ScriptType.KeyChange }" />
|
<ScriptEditor GameId="Game.Id" ArchiveId="@LatestArchiveId" AllowedTypes="new ScriptType[] { ScriptType.Install, ScriptType.Uninstall, ScriptType.NameChange, ScriptType.KeyChange }" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div data-panel="Archives">
|
<div data-panel="Archives">
|
||||||
|
|
Loading…
Reference in New Issue