LANCommander/LANCommander.Server/UI/Components/ScriptTextEditor.razor
Pat Hartl ca713f6d3f Rework .reg importing in script editor
Script editor now supports drag and drop for .ps1, .reg, and other text files. .ps1 files will be handled by replacing the contents of the text editor. .reg files will be converted to PowerShell commands and inserted into the script editor. Any other text file will be inserted as an escaped string.
2026-06-10 20:19:06 -05:00

147 lines
4.8 KiB
Text

@using LANCommander.SDK.Enums
@using LANCommander.Server.Extensions;
@using LANCommander.Server.Models;
@inject ModalService ModalService
@inject ScriptService ScriptService
<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 (ArchiveId != Guid.Empty)
{
<Button Icon="@IconType.Outline.FolderOpen" OnClick="BrowseForPath" Type="@ButtonType.Text">Browse</Button>
}
</FormItem>
<FormItem>
<MonacoCodeEditor @ref="Editor" @bind-Value="context.Contents" Id="@($"editor-{Id}")" ConstructionOptions="EditorConstructionOptions" OnSave="OnSave" ScriptType="@context.Type.ToString()" />
</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 => 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>
@code {
[Parameter] public Script Script { get; set; } = new();
[Parameter] public EventCallback<Script> ScriptChanged { get; set; }
[Parameter] public IEnumerable<ScriptType> AllowedTypes { get; set; }
[Parameter] public Guid ArchiveId { get; set; }
[Parameter] public EventCallback OnSave { get; set; }
Guid Id = Guid.NewGuid();
Form<Script> Form;
MonacoCodeEditor? Editor;
IEnumerable<Snippet> Snippets { get; set; }
StandaloneEditorConstructionOptions EditorConstructionOptions(StandaloneCodeEditor editor)
{
return new StandaloneEditorConstructionOptions
{
AutomaticLayout = true,
Language = "powershell",
Value = Script.Contents,
Theme = "vs-dark",
Minimap = new EditorMinimapOptions { Enabled = false },
BracketPairColorization = new BracketPairColorizationOptions { Enabled = true },
WordWrap = "on",
FixedOverflowWidgets = true,
};
}
protected override void OnInitialized()
{
Snippets = ScriptService.GetSnippets();
}
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($"$InstallDirectory\\{path.Replace('/', '\\')}");
StateHasChanged();
return Task.CompletedTask;
};
}
async Task InsertText(string text)
{
var selection = await Editor.GetSelection();
var range = new BlazorMonaco.Range(
selection.StartLineNumber, selection.StartColumn,
selection.EndLineNumber, selection.EndColumn);
await Editor.ExecuteEdits("ScriptEditor", new List<IdentifiedSingleEditOperation>()
{
new IdentifiedSingleEditOperation
{
Range = range,
Text = text,
ForceMoveMarkers = true
}
}, (List<BlazorMonaco.Selection>)null);
}
async Task InsertSnippet(Snippet snippet)
{
if (Editor != null)
await Editor.InsertSnippetAsync(snippet.Content);
}
}