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.Services
|
||||
@using System.IO.Compression;
|
||||
@using Microsoft.EntityFrameworkCore;
|
||||
@inject ScriptService ScriptService
|
||||
@inject ModalService ModalService
|
||||
@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%">
|
||||
<SpaceItem>
|
||||
|
@ -85,7 +22,7 @@
|
|||
<ActionColumn Title="">
|
||||
<Space Style="display: flex; justify-content: end">
|
||||
<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?">
|
||||
<Button Icon="@IconType.Outline.Close" Type="@ButtonType.Text" Danger />
|
||||
|
@ -115,59 +52,44 @@
|
|||
[Parameter] public Guid GameId { get; set; }
|
||||
[Parameter] public Guid RedistributableId { 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; }
|
||||
|
||||
Script Script;
|
||||
ICollection<Script> Scripts { get; set; } = new List<Script>();
|
||||
|
||||
bool ModalVisible = false;
|
||||
|
||||
IEnumerable<Snippet> Snippets { get; set; }
|
||||
StandaloneCodeEditor? Editor;
|
||||
RegToPowerShell RegToPowerShell;
|
||||
|
||||
private StandaloneEditorConstructionOptions EditorConstructionOptions(StandaloneCodeEditor editor)
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
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,
|
||||
Language = "powershell",
|
||||
Value = Script.Contents,
|
||||
Theme = "vs-dark",
|
||||
Title = scriptId == null ? "Add Script" : "Edit Script",
|
||||
Maximizable = false,
|
||||
DefaultMaximized = true,
|
||||
Closable = true,
|
||||
OkText = "Save"
|
||||
};
|
||||
}
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
if (Scripts == null)
|
||||
Scripts = new List<Script>();
|
||||
var options = new ScriptEditorOptions()
|
||||
{
|
||||
ScriptId = scriptId ?? default,
|
||||
AllowedTypes = AllowedTypes,
|
||||
ArchiveId = ArchiveId,
|
||||
GameId = GameId,
|
||||
RedistributableId = RedistributableId
|
||||
};
|
||||
|
||||
Snippets = ScriptService.GetSnippets();
|
||||
var modalRef = await ModalService.CreateModalAsync<ScriptEditorDialog, ScriptEditorOptions, Script>(modalOptions, options);
|
||||
|
||||
if (Script == null)
|
||||
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;
|
||||
modalRef.OnOk = async (script) =>
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
@ -179,81 +101,4 @@
|
|||
|
||||
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 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 data-panel="Archives">
|
||||
|
|
Loading…
Reference in New Issue