Skip to content

Commit

Permalink
Add support for HTML Input forms in output cells (#3673)
Browse files Browse the repository at this point in the history
* misc. code cleanup

* add support for multiple inputs using output cell HTML forms

* contract updates

* support stored values in input forms
  • Loading branch information
jonsequitur authored Sep 25, 2024
1 parent 7a872ca commit 24f5fba
Show file tree
Hide file tree
Showing 41 changed files with 1,209 additions and 327 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,13 @@ Microsoft.DotNet.Interactive.Commands
public class ImportDocument : KernelCommand, System.IEquatable<KernelCommand>
.ctor(System.String filePath, System.String targetKernelName = null)
public System.String FilePath { get;}
public class InputDescription
.ctor(System.String name, System.String prompt = null)
public System.String Name { get;}
public System.String Prompt { get;}
public System.String SaveAs { get; set;}
public System.String TypeHint { get; set;}
public System.String GetPropertyNameForJsonSerialization()
public abstract class KernelCommand, System.IEquatable<KernelCommand>
public System.Uri DestinationUri { get; set;}
public Microsoft.DotNet.Interactive.KernelCommandInvocation Handler { get; set;}
Expand Down Expand Up @@ -396,11 +403,15 @@ Microsoft.DotNet.Interactive.Commands
public class RequestHoverText : LanguageServiceCommand, System.IEquatable<KernelCommand>
.ctor(System.String code, Microsoft.DotNet.Interactive.LinePosition linePosition, System.String targetKernelName = null)
public class RequestInput : KernelCommand, System.IEquatable<KernelCommand>
.ctor(System.String prompt, System.String targetKernelName = null, System.String inputTypeHint = null)
.ctor(System.String prompt, System.String inputTypeHint = null)
public System.String InputTypeHint { get; set;}
public System.Boolean IsPassword { get;}
public System.String ParameterName { get; set;}
public System.String Prompt { get;}
public System.String SaveAs { get; set;}
public class RequestInputs : KernelCommand, System.IEquatable<KernelCommand>
.ctor()
public System.Collections.Generic.List<InputDescription> Inputs { get; set;}
public class RequestKernelInfo : KernelCommand, System.IEquatable<KernelCommand>
.ctor(System.String targetKernelName = null)
.ctor(System.Uri destinationUri)
Expand Down Expand Up @@ -464,6 +475,7 @@ Microsoft.DotNet.Interactive.Connection
public static KernelCommandAndEventReceiver FromNamedPipe(System.IO.Pipes.PipeStream stream)
public static KernelCommandAndEventReceiver FromObservable(System.IObservable<System.String> messages)
public static KernelCommandAndEventReceiver FromTextReader(System.IO.TextReader reader)
.ctor(ReadCommandOrEventAsync readCommandOrEvent)
.ctor(ReadCommandOrEvent readCommandOrEvent)
public System.Void Dispose()
public System.IDisposable Subscribe(System.IObserver<CommandOrEvent> observer)
Expand Down Expand Up @@ -518,6 +530,11 @@ Microsoft.DotNet.Interactive.Connection
public System.IAsyncResult BeginInvoke(System.Threading.CancellationToken cancellationToken, System.AsyncCallback callback, System.Object object)
public CommandOrEvent EndInvoke(System.IAsyncResult result)
public CommandOrEvent Invoke(System.Threading.CancellationToken cancellationToken = null)
public delegate ReadCommandOrEventAsync : System.MulticastDelegate, System.ICloneable, System.Runtime.Serialization.ISerializable
.ctor(System.Object object, System.IntPtr method)
public System.IAsyncResult BeginInvoke(System.Threading.CancellationToken cancellationToken, System.AsyncCallback callback, System.Object object)
public System.Threading.Tasks.Task<CommandOrEvent> EndInvoke(System.IAsyncResult result)
public System.Threading.Tasks.Task<CommandOrEvent> Invoke(System.Threading.CancellationToken cancellationToken = null)
public static class Serializer
public static System.Text.Json.JsonSerializerOptions JsonSerializerOptions { get;}
public static CommandOrEvent DeserializeCommandOrEvent(System.String json)
Expand Down Expand Up @@ -622,6 +639,9 @@ Microsoft.DotNet.Interactive.Events
public class InputProduced : KernelEvent
.ctor(System.String value, Microsoft.DotNet.Interactive.Commands.RequestInput command)
public System.String Value { get;}
public class InputsProduced : KernelEvent
.ctor(System.Collections.Generic.Dictionary<System.String,System.String> values, Microsoft.DotNet.Interactive.Commands.RequestInputs command)
public System.Collections.Generic.Dictionary<System.String,System.String> Values { get;}
public enum InsertTextFormat : System.Enum, System.IComparable, System.IConvertible, System.IFormattable, System.ISpanFormattable
PlainText=1
Snippet=2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
<FixtureTestSelector>
<FixtureName>Microsoft.DotNet.Interactive.ExtensionLab.Tests.DataFrameTypeGeneratorTests</FixtureName>
</FixtureTestSelector>
<FixtureTestSelector>
<FixtureName>Microsoft.DotNet.Interactive.ExtensionLab.Tests.InspectTests</FixtureName>
</FixtureTestSelector>
</IgnoredTests>
</Settings>
</ProjectConfiguration>
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,24 @@
<FixtureTestSelector>
<FixtureName>Microsoft.DotNet.Interactive.PowerShell.Tests.SecretManagerTests</FixtureName>
</FixtureTestSelector>
<NamedTestSelector>
<TestName>Microsoft.DotNet.Interactive.PowerShell.Tests.PowerShellKernelTests.GetCorrectProfilePaths</TestName>
</NamedTestSelector>
<NamedTestSelector>
<TestName>Microsoft.DotNet.Interactive.PowerShell.Tests.PowerShellKernelTests.PowerShell_get_history_should_work</TestName>
</NamedTestSelector>
<NamedTestSelector>
<TestName>Microsoft.DotNet.Interactive.PowerShell.Tests.PowerShellKernelTests.PowerShell_progress_sends_updated_display_values</TestName>
</NamedTestSelector>
<NamedTestSelector>
<TestName>Microsoft.DotNet.Interactive.PowerShell.Tests.PowerShellKernelTests.PowerShell_token_variables_work</TestName>
</NamedTestSelector>
<NamedTestSelector>
<TestName>Microsoft.DotNet.Interactive.PowerShell.Tests.PowerShellKernelTests.TryGetVariable_unwraps_PowerShell_object("$x = New-Object -TypeName System.IO.FileInfo -ArgumentList c:\\temp\\some.txt", "System.IO.FileInfo")</TestName>
</NamedTestSelector>
<NamedTestSelector>
<TestName>Microsoft.DotNet.Interactive.PowerShell.Tests.PowerShellKernelTests.When_code_produces_errors_then_the_command_fails</TestName>
</NamedTestSelector>
</IgnoredTests>
</Settings>
</ProjectConfiguration>
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using System;

namespace Microsoft.DotNet.Interactive.PowerShell;
using System.Diagnostics.CodeAnalysis;

public class SecretManager
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
Expand Down Expand Up @@ -111,13 +111,13 @@ public async Task When_receiver_is_disposed_then_no_further_reads_occur()

for (int i = 0; i < 2; i++)
{
_messageQueue.Add(new CommandOrEvent(new SubmitCode("")));
_messageQueue.Add(new CommandOrEvent(new SubmitCode(i.ToString())));
}

using var receiver = new KernelCommandAndEventReceiver(t =>
var receiver = new KernelCommandAndEventReceiver(t =>
{
var commandOrEvent = _messageQueue.Take(t);
readCount++;
var commandOrEvent = _messageQueue.Take(t);
return commandOrEvent;
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
"token": "the-token",
"commandType": "RequestInput",
"command": {
"parameterName": null,
"prompt": "provide answer",
"isPassword": true,
"type": "password",
"saveAs": null,
"targetKernelName": "vscode",
"type": "password",
"targetKernelName": null,
"originUri": null,
"destinationUri": null
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"token": "the-token",
"commandType": "RequestInputs",
"command": {
"inputs": [
{
"name": "value",
"prompt": "Please enter a value.",
"saveAs": "the-password",
"type": "password"
}
],
"targetKernelName": null,
"originUri": null,
"destinationUri": null
},
"routingSlip": [
"kernel://somelocation/kernelName?tag=arrived",
"kernel://somelocation/kernelName"
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@
"token": "the-token",
"commandType": "RequestInput",
"command": {
"parameterName": "filePath",
"prompt": "What is the path to the log file?",
"isPassword": false,
"saveAs": "the-file",
"type": "file",
"saveAs": null,
"targetKernelName": "vscode",
"targetKernelName": null,
"originUri": null,
"destinationUri": null
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"event": {
"values": {
"value": "tops3kr1tstuff"
}
},
"eventType": "InputsProduced",
"command": {
"token": "the-token",
"commandType": "RequestInputs",
"command": {
"inputs": [
{
"name": "value",
"prompt": "Please enter a value.",
"saveAs": "the-password",
"type": "password"
}
],
"targetKernelName": null,
"originUri": null,
"destinationUri": null
},
"routingSlip": [
"kernel://somelocation/kernelName?tag=arrived",
"kernel://somelocation/kernelName"
]
},
"routingSlip": [
"kernel://somelocation/kernelName"
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,20 @@ IEnumerable<KernelCommand> commands()

yield return new RequestHoverText("document-contents", new LinePosition(1, 2));

yield return new RequestInput(prompt: "provide answer", inputTypeHint: "password");

yield return new RequestInputs
{
Inputs =
[
new InputDescription("value", "Please enter a value.")
{
TypeHint = "password",
SaveAs = "the-password"
}
]
};

yield return new RequestSignatureHelp("sig-help-contents", new LinePosition(1, 2));

yield return new SendEditableCode("someKernelName", "code");
Expand Down Expand Up @@ -230,8 +244,6 @@ IEnumerable<KernelCommand> commands()

yield return new RequestValue("a", mimeType: HtmlFormatter.MimeType, targetKernelName: "csharp");

yield return new RequestInput(prompt: "provide answer", inputTypeHint: "password", targetKernelName: "vscode");

yield return new SendValue(
"name",
"formatted value",
Expand Down Expand Up @@ -364,8 +376,7 @@ [new FormattedValue(PlainTextFormatter.MimeType, diagnostic.ToString())],
OriginUri = new("kernel://pid-1234/csharp")
});

yield return new KernelReady(new[]
{
yield return new KernelReady([
new KernelInfo("javascript", aliases: new[] { "js" })
{
LanguageName = "JavaScript",
Expand All @@ -389,7 +400,7 @@ [new FormattedValue(PlainTextFormatter.MimeType, diagnostic.ToString())],
new KernelCommandInfo(nameof(SubmitCode))
}
}
});
]);

yield return new PackageAdded(
new ResolvedPackageReference(
Expand Down Expand Up @@ -454,7 +465,25 @@ [new FormattedValue(PlainTextFormatter.MimeType, diagnostic.ToString())],
"<span>raw value</span>"),
new RequestValue("a", mimeType: HtmlFormatter.MimeType, targetKernelName: "csharp"));

yield return new InputProduced("user input", new RequestInput(prompt: "What is the path to the log file?", inputTypeHint: "file", targetKernelName: "vscode"));
yield return new InputProduced("user input", new RequestInput(prompt: "What is the path to the log file?", inputTypeHint: "file")
{
ParameterName = "filePath",
SaveAs = "the-file"
});

yield return new InputsProduced(
new Dictionary<string, string> { ["value"] = "tops3kr1tstuff" },
new RequestInputs
{
Inputs =
[
new InputDescription("value", "Please enter a value.")
{
TypeHint = "password",
SaveAs = "the-password"
}
]
});
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,21 @@ var x = 123; // with some intervening code
<NamedTestSelector>
<TestName>Microsoft.DotNet.Interactive.Tests.Connection.SerializationTests.Event_contract_has_not_been_broken</TestName>
</NamedTestSelector>
<FixtureTestSelector>
<FixtureName>Microsoft.DotNet.Interactive.Tests.RequestInputTests</FixtureName>
</FixtureTestSelector>
<NamedTestSelector>
<TestName>Microsoft.DotNet.Interactive.Tests.RequestInputTests.When_a_saved_value_is_used_then_the_user_is_notified</TestName>
</NamedTestSelector>
<NamedTestSelector>
<TestName>Microsoft.DotNet.Interactive.Tests.RequestInputTests.When_a_value_is_saved_then_the_user_is_notified</TestName>
</NamedTestSelector>
<NamedTestSelector>
<TestName>Microsoft.DotNet.Interactive.Tests.RequestInputTests.When_Save_is_specified_then_subsequent_requests_reuse_the_saved_value</TestName>
</NamedTestSelector>
<NamedTestSelector>
<TestName>Microsoft.DotNet.Interactive.Tests.MultipleInputsWithinMagicCommandsTests.Previously_stored_values_are_used_to_prepopulate_input_fields</TestName>
</NamedTestSelector>
<NamedTestSelector>
<TestName>Microsoft.DotNet.Interactive.Tests.MultipleInputsWithinMagicCommandsTests.Input_field_values_can_be_stored_using_SecretManager</TestName>
</NamedTestSelector>
</IgnoredTests>
</Settings>
</ProjectConfiguration>
Loading

0 comments on commit 24f5fba

Please sign in to comment.