LANCommander/LANCommander.Server/UI/Components/ScriptEditorDialog.razor

229 lines
7.1 KiB
Text

@using LANCommander.SDK.Enums
@inherits FeedbackComponent<ScriptEditorOptions, Script>
@inject ScriptService ScriptService
@inject ArchiveService ArchiveService
@inject ServerService ServerService
@inject ModalService ModalService
@inject IMessageService MessageService
@inject ILogger<ScriptEditorDialog> Logger
<Form @ref="@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 (_archive != null)
{
<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>
@if (Options.GameId.HasValue && Options.GameId != Guid.Empty && IsDebuggable)
{
<Tooltip Title="Debug">
<Button Icon="@IconType.Outline.CaretRight" Type="@ButtonType.Text" OnClick="() => _console.DebugPackagingScript(Options.GameId.Value)" />
</Tooltip>
}
</FormItem>
<FormItem>
<MonacoCodeEditor @ref="Editor" @bind-Value="context.Contents" Id="@($"editor-{Id}")" ConstructionOptions="EditorConstructionOptions" OnSave="Save" />
</FormItem>
<FormItem Label="Name" Required Rules=@(new[] { new FormValidationRule { Required = true } })>
<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>
<PowerShellConsole @ref="_console" />
</Form>
<RegToPowerShell @ref="RegToPowerShell" OnParsed="(text) => InsertText(text)" />
@code {
Guid Id = Guid.NewGuid();
Form<Script> Form;
MonacoCodeEditor? Editor;
RegToPowerShell RegToPowerShell;
PowerShellConsole _console;
IEnumerable<Snippet> Snippets { get; set; }
Archive? _archive;
StandaloneEditorConstructionOptions EditorConstructionOptions(StandaloneCodeEditor editor)
{
return new StandaloneEditorConstructionOptions
{
AutomaticLayout = true,
Language = "powershell",
Value = Script.Contents,
Theme = "vs-dark",
};
}
Script Script = new();
bool IsDebuggable =>
Script.Type == ScriptType.Package;
protected override async Task OnInitializedAsync()
{
if (Options.ScriptId != Guid.Empty)
Script = await ScriptService.GetAsync(Options.ScriptId);
else if (Options.GameId != Guid.Empty)
{
Script = new Script
{
GameId = Options.GameId
};
_archive = await ArchiveService.GetLatestArchiveAsync(a => a.GameId == Options.GameId);
}
else if (Options.RedistributableId != Guid.Empty)
{
Script = new Script()
{
RedistributableId = Options.RedistributableId
};
_archive = await ArchiveService.GetLatestArchiveAsync(a => a.RedistributableId == Options.RedistributableId);
}
else if (Options.ServerId != Guid.Empty)
{
Script = new Script()
{
ServerId = Options.ServerId
};
var server = await ServerService.GetAsync(Options.ServerId.Value);
_archive = await ArchiveService.GetLatestArchiveAsync(a => a.GameId == server.GameId);
}
Snippets = ScriptService.GetSnippets();
}
public override async Task OnFeedbackOkAsync(ModalClosingEventArgs args)
{
var success = await Save();
if (success)
await base.OkCancelRefWithResult!.OnOk(Script);
else
args.Reject();
}
async Task<bool> Save()
{
try
{
if (Form.Validate())
{
if (Script.Id == Guid.Empty)
Script = await ScriptService.AddAsync(Script);
else
Script = await ScriptService.UpdateAsync(Script);
MessageService.Success("Script saved!");
return true;
}
return false;
}
catch (Exception ex)
{
MessageService.Error("Script could not be saved!");
Logger.LogError(ex, "Script could not be saved!");
return false;
}
}
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 = _archive?.Id ?? Guid.Empty,
Select = true,
Multiple = false
};
var modalRef = await ModalService.CreateModalAsync<FilePickerDialog, FilePickerOptions, IEnumerable<IFileManagerEntry>>(modalOptions, browserOptions);
modalRef.OnOk = (results) =>
{
var path = results.FirstOrDefault().Path;
InsertText($"$InstallDirectory\\{path.Replace('/', '\\')}");
StateHasChanged();
return Task.CompletedTask;
};
}
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);
}
async Task InsertSnippet(Snippet snippet)
{
await InsertText(snippet.Content);
}
}