Skip to content

Commit 3364827

Browse files
authored
feat: add ability to save requests and toggle ui elements (#2095)
1 parent 33ad2ec commit 3364827

26 files changed

+1301
-185
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"Projects": [
3+
{
4+
"Name": "Amazon.Lambda.TestTool",
5+
"Type": "Minor",
6+
"ChangelogMessages": [
7+
"Add the ability to save requests and hide UI elements"
8+
]
9+
}
10+
]
11+
}

Tools/LambdaTestTool-v2/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ dotnet lambda-test-tool start \
133133
| `--api-gateway-emulator-port` | Port for API Gateway | API Gateway Mode |
134134
| `--api-gateway-emulator-mode` | API Gateway mode (Rest/HttpV1/HttpV2) | API Gateway Mode |
135135
| `--no-launch-window` | Disable auto-launching web interface | Optional |
136+
| `--config-storage-path` | Path for saving settings and requests | Optional |
136137

137138

138139
## API Gateway Configuration
@@ -333,3 +334,11 @@ Expected response:
333334
```
334335
8
335336
```
337+
338+
## Saving Lambda Requests
339+
340+
The Test Tool provides users with the ability to save Lambda requests for quick access. Saved requests will be listed in a drop down above the request input area.
341+
342+
In order to enable saving requests, you will need to provide a storage path during the test tool startup.
343+
344+
You can use the command line argument `--config-storage-path <absolute-path>` to specify the storage path.

Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Commands/Settings/RunCommandSettings.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using Amazon.Lambda.TestTool.Models;
55
using Spectre.Console.Cli;
66
using System.ComponentModel;
7+
using ValidationResult = Spectre.Console.ValidationResult;
78

89
namespace Amazon.Lambda.TestTool.Commands.Settings;
910

@@ -61,4 +62,29 @@ public sealed class RunCommandSettings : CommandSettings
6162
[CommandOption("--sqs-eventsource-config <CONFIG>")]
6263
[Description("The configuration for the SQS event source. The format of the config is a comma delimited key pairs. For example \"QueueUrl=<queue-url>,FunctionName=<function-name>,VisibilityTimeout=100\". Possible keys are: BatchSize, DisableMessageDelete, FunctionName, LambdaRuntimeApi, Profile, QueueUrl, Region, VisibilityTimeout")]
6364
public string? SQSEventSourceConfig { get; set; }
65+
66+
/// <summary>
67+
/// The absolute path used to save global settings and saved requests. You will need to specify a path in order to enable saving global settings and requests.
68+
/// </summary>
69+
[CommandOption("--config-storage-path <CONFIG-STORAGE-PATH>")]
70+
[Description("The absolute path used to save global settings and saved requests. You will need to specify a path in order to enable saving global settings and requests.")]
71+
public string? ConfigStoragePath { get; set; }
72+
73+
/// <summary>
74+
/// Validate that <see cref="ConfigStoragePath"/> is an absolute path.
75+
/// </summary>
76+
public override ValidationResult Validate()
77+
{
78+
if (string.IsNullOrEmpty(ConfigStoragePath))
79+
return ValidationResult.Success();
80+
81+
if (!Path.IsPathFullyQualified(ConfigStoragePath))
82+
{
83+
ConfigStoragePath = Path.Combine(Environment.CurrentDirectory, ConfigStoragePath);
84+
}
85+
86+
return !Path.IsPathFullyQualified(ConfigStoragePath)
87+
? ValidationResult.Error("'Config storage path' must be an absolute path.")
88+
: ValidationResult.Success();
89+
}
6490
}

Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Components/Pages/Home.razor

Lines changed: 61 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
@page "/"
22

33
@using Amazon.Lambda.TestTool.Models
4-
@using Amazon.Lambda.TestTool.SampleRequests
5-
@using Amazon.Lambda.TestTool.Services
64
@using Amazon.Lambda.TestTool.Utilities
75

86
<PageTitle>Lambda Function Tester</PageTitle>
@@ -43,27 +41,39 @@ else
4341
<div class="row">
4442
<div class="col-lg-6 gap-2 d-flex flex-column mt-1 mb-3">
4543
<div class="form-group d-flex">
46-
<h4>Queue Event</h4>
47-
<button class="btn btn-primary btn-sm ms-auto rounded-pill px-4 fw-bold d-flex align-items-center gap-1" @onclick="OnAddEventClick">
48-
<i class="bi bi-play-fill"></i>
49-
Invoke
50-
</button>
44+
<h4 class="m-0">Queue Event</h4>
45+
<div class="d-flex gap-2 ms-auto">
46+
@if (!string.IsNullOrEmpty(LambdaOptions.Value.ConfigStoragePath))
47+
{
48+
<button type="button" data-bs-toggle="modal" data-bs-target="#manageSavedRequestsModal" class="btn @(ThemeService.CurrentTheme.Equals("dark")? "btn-dark" : "btn-light") btn-sm rounded-circle fs-5 p-0 px-2 fw-bold d-flex align-items-center" @onclick="async () => await ShowManagedSavedRequestsDialog()">
49+
<i class="bi bi-sliders"></i>
50+
</button>
51+
<button type="button" data-bs-toggle="modal" data-bs-target="#saveRequestModal" class="btn @(string.IsNullOrEmpty(_editorContent) ? "btn-disabled" : "btn-secondary") btn-sm rounded-pill px-4 fw-bold d-flex align-items-center gap-2" disabled="@(string.IsNullOrEmpty(_editorContent))" @onclick="async () => await ShowSaveEventDialog()">
52+
<i class="bi bi-floppy-fill"></i>
53+
Save
54+
</button>
55+
}
56+
<button class="btn btn-primary btn-sm rounded-pill px-4 fw-bold d-flex align-items-center gap-1" @onclick="OnAddEventClick">
57+
<i class="bi bi-play-fill"></i>
58+
Invoke
59+
</button>
60+
</div>
5161
</div>
52-
<div class="form-floating">
62+
<div class="form-floating @(GlobalSettingsService.CurrentSettings.ShowRequestsList ? "" : "d-none")">
5363
<select class="form-select" id="sample-requests" @bind="SelectedSampleRequestName">
5464
<option value="@NoSampleSelectedId">Select a request</option>
55-
@if (@SampleRequests.ContainsKey(SampleRequestManager.SavedRequestGroup))
65+
@if (@SampleRequests.ContainsKey(Constants.SavedRequestGroup))
5666
{
57-
<optgroup id="saved-select-request-group" label="@SampleRequestManager.SavedRequestGroup">
58-
@foreach (var request in SampleRequests[SampleRequestManager.SavedRequestGroup])
67+
<optgroup id="saved-select-request-group" label="@Constants.SavedRequestGroup">
68+
@foreach (var request in SampleRequests[Constants.SavedRequestGroup])
5969
{
6070
<option value="@request.Filename">@request.Name</option>
6171
}
6272
</optgroup>
6373
}
6474
@foreach (var group in SampleRequests.Keys)
6575
{
66-
@if (!string.Equals(group, SampleRequestManager.SavedRequestGroup))
76+
@if (!string.Equals(group, Constants.SavedRequestGroup))
6777
{
6878
<optgroup label="@group">
6979
@foreach (var request in SampleRequests[group])
@@ -90,6 +100,7 @@ else
90100
Id="function-payload"
91101
@ref="_editor"
92102
ConstructionOptions="EditorConstructionOptions"
103+
OnDidChangeModelContent="HandleModelContentChanged"
93104
CssClass="@($"rounded-4 overflow-hidden border {(!string.IsNullOrEmpty(_errorMessage) ? "border-danger border-2" : "")}")"/>
94105
@if (!string.IsNullOrEmpty(_errorMessage))
95106
{
@@ -263,13 +274,15 @@ else
263274
}
264275

265276
<EventDialog @ref="_eventDialog"/>
277+
<SaveRequestDialog @ref="_saveRequestDialog" OnSaveRequest="OnSaveRequest" />
278+
<ManageSavedRequestsDialog @ref="_manageSavedRequestsDialog" Callback="ReloadSampleRequests" />
266279

267280
<div class="offcanvas offcanvas-end" tabindex="-1" id="switchFunctionOffCanvas">
268281
<nav class="navbar navbar-expand-lg bd-navbar sticky-top bg-body-tertiary">
269282
<div class="container-fluid">
270283
<a class="navbar-brand py-0 me-4 d-flex align-items-center gap-3" href="/">
271-
<img src="aws.svg" width="42" height="42" class="align-text-top logo-light-mode"/>
272-
<img src="aws-light.svg" width="42" height="42" class="align-text-top logo-dark-mode"/>
284+
<img src="aws.svg" alt="AWS Logo" width="42" height="42" class="align-text-top logo-light-mode"/>
285+
<img src="aws-light.svg" alt="AWS Light Logo" width="42" height="42" class="align-text-top logo-dark-mode"/>
273286
Lambda Test Tool
274287
</a>
275288
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
@@ -289,3 +302,37 @@ else
289302
</div>
290303
</div>
291304
</div>
305+
306+
<div class="toast-container position-fixed top-0 end-0 p-3">
307+
<div id="liveToast" class="toast align-items-center text-bg-success border-0" role="alert" aria-live="assertive" aria-atomic="true">
308+
<div class="d-flex">
309+
<div class="toast-body">
310+
@_toastMessage
311+
</div>
312+
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
313+
</div>
314+
</div>
315+
</div>
316+
317+
<script>
318+
window.liveToast = {
319+
show: () => {
320+
const toastElement = document.getElementById('liveToast')
321+
if (toastElement) {
322+
const toastInstance = bootstrap.Toast.getOrCreateInstance(toastElement)
323+
if (toastInstance){
324+
toastInstance.show();
325+
}
326+
}
327+
},
328+
hide: () => {
329+
const toastElement = document.getElementById('liveToast')
330+
if (toastElement) {
331+
const toastInstance = bootstrap.Toast.getOrCreateInstance(toastElement)
332+
if (toastInstance){
333+
toastInstance.hide();
334+
}
335+
}
336+
}
337+
};
338+
</script>

0 commit comments

Comments
 (0)