Skip to content

Commit e0ecff9

Browse files
authored
Merge pull request #436 from serverlessworkflow/feat-dashboard-copy-to-clipboard
Added copy to clipboard button to the Dashboard's editors
2 parents 0dee5c3 + 5444b48 commit e0ecff9

File tree

8 files changed

+102
-8
lines changed

8 files changed

+102
-8
lines changed

src/dashboard/Synapse.Dashboard/Components/DocumentDetails/DocumentDetails.razor

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,12 @@
4343
}
4444
else
4545
{
46-
<div class="d-flex justify-content-end mb-2">
46+
<div class="d-flex justify-content-between mb-2">
47+
<div>
48+
<Button Outline="true" Color="ButtonColor.Primary" Size="ButtonSize.Small" @onclick="Store.OnCopyToClipboard" TooltipTitle="Copy to clipboard">
49+
<Icon Name="IconName.Clipboard" />
50+
</Button>
51+
</div>
4752
<PreferredLanguageSelector PreferedLanguageChange="Store.ToggleTextBasedEditorLanguageAsync" />
4853
</div>
4954
<StandaloneCodeEditor @ref="Store.TextEditor"

src/dashboard/Synapse.Dashboard/Components/DocumentDetails/Store.cs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,15 @@ namespace Synapse.Dashboard.Components.DocumentDetailsStateManagement;
2525
/// <param name="monacoEditorHelper">The service used ease Monaco Editor interactions</param>
2626
/// <param name="jsonSerializer">The service used to serialize and deserialize JSON</param>
2727
/// <param name="yamlSerializer">The service used to serialize and deserialize YAML</param>
28+
/// <param name="toastService">The service used display toast messages</param>
2829
public class DocumentDetailsStore(
2930
ILogger<DocumentDetailsStore> logger,
3031
ISynapseApiClient apiClient,
3132
IJSRuntime jsRuntime,
3233
IMonacoEditorHelper monacoEditorHelper,
3334
IJsonSerializer jsonSerializer,
34-
IYamlSerializer yamlSerializer
35+
IYamlSerializer yamlSerializer,
36+
ToastService toastService
3537
)
3638
: ComponentStore<DocumentDetailsState>(new())
3739
{
@@ -69,6 +71,11 @@ IYamlSerializer yamlSerializer
6971
/// </summary>
7072
protected IYamlSerializer YamlSerializer { get; } = yamlSerializer;
7173

74+
/// <summary>
75+
/// Gets the service used display toast messages
76+
/// </summary>
77+
protected ToastService ToastService { get; } = toastService;
78+
7279
/// <summary>
7380
/// The <see cref="BlazorMonaco.Editor.StandaloneEditorConstructionOptions"/> provider function
7481
/// </summary>
@@ -352,6 +359,27 @@ async Task SetTextEditorValueAsync()
352359
}
353360
}
354361
}
362+
363+
/// <summary>
364+
/// Copies to content of the Monaco editor to the clipboard
365+
/// </summary>
366+
/// <returns>A awaitable task</returns>
367+
public async Task OnCopyToClipboard()
368+
{
369+
if (this.TextEditor == null) return;
370+
var text = await this.TextEditor.GetValue();
371+
if (string.IsNullOrWhiteSpace(text)) return;
372+
try
373+
{
374+
await this.JSRuntime.InvokeVoidAsync("navigator.clipboard.writeText", text);
375+
this.ToastService.Notify(new(ToastType.Success, "Definition copied to the clipboard!"));
376+
}
377+
catch (Exception ex)
378+
{
379+
this.ToastService.Notify(new(ToastType.Danger, "Failed to copy the definition to the clipboard."));
380+
this.Logger.LogError("Unable to copy to clipboard: {exception}", ex.ToString());
381+
}
382+
}
355383
#endregion
356384

357385
/// <inheritdoc/>

src/dashboard/Synapse.Dashboard/Components/MonacoEditor/MonacoEditor.razor

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,12 @@
1818
@using Synapse.Dashboard.Components.MonacoEditorStateManagement
1919
@inherits StatefulComponent<MonacoEditor, MonacoEditorStore, MonacoEditorState>
2020

21-
<div class="d-flex justify-content-end mb-2">
21+
<div class="d-flex justify-content-between mb-2">
22+
<div>
23+
<Button Outline="true" Color="ButtonColor.Primary" Size="ButtonSize.Small" @onclick="Store.OnCopyToClipboard" TooltipTitle="Copy to clipboard">
24+
<Icon Name="IconName.Clipboard" />
25+
</Button>
26+
</div>
2227
<PreferredLanguageSelector PreferedLanguageChange="Store.ToggleTextBasedEditorLanguageAsync" />
2328
</div>
2429
<StandaloneCodeEditor @ref="Store.TextEditor"

src/dashboard/Synapse.Dashboard/Components/MonacoEditor/MonacoEditorHelper.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,13 @@ public Func<StandaloneCodeEditor, StandaloneEditorConstructionOptions> GetStanda
3636
ReadOnly = readOnly,
3737
Value = value,
3838
TabSize = 2,
39+
FormatOnPaste = true,
40+
FormatOnType = true,
3941
QuickSuggestions = new QuickSuggestionsOptions
4042
{
4143
Other = "true",
42-
Strings = "true"
44+
Strings = "true",
45+
Comments = "fasle"
4346
}
4447
};
4548
}

src/dashboard/Synapse.Dashboard/Components/MonacoEditor/Store.cs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ namespace Synapse.Dashboard.Components.MonacoEditorStateManagement;
2525
/// <param name="monacoEditorHelper">The service used ease Monaco Editor interactions</param>
2626
/// <param name="jsonSerializer">The service used to serialize and deserialize JSON</param>
2727
/// <param name="yamlSerializer">The service used to serialize and deserialize YAML</param>
28-
public class MonacoEditorStore(ILogger<MonacoEditorStore> logger, ISynapseApiClient apiClient, IJSRuntime jsRuntime, IMonacoEditorHelper monacoEditorHelper, IJsonSerializer jsonSerializer, IYamlSerializer yamlSerializer)
28+
/// <param name="toastService">The service used display toast messages</param>
29+
public class MonacoEditorStore(ILogger<MonacoEditorStore> logger, ISynapseApiClient apiClient, IJSRuntime jsRuntime, IMonacoEditorHelper monacoEditorHelper, IJsonSerializer jsonSerializer, IYamlSerializer yamlSerializer, ToastService toastService)
2930
: ComponentStore<MonacoEditorState>(new())
3031
{
3132

@@ -62,6 +63,11 @@ public class MonacoEditorStore(ILogger<MonacoEditorStore> logger, ISynapseApiCli
6263
/// </summary>
6364
protected IYamlSerializer YamlSerializer { get; } = yamlSerializer;
6465

66+
/// <summary>
67+
/// Gets the service used display toast messages
68+
/// </summary>
69+
protected ToastService ToastService { get; } = toastService;
70+
6571
/// <summary>
6672
/// The <see cref="BlazorMonaco.Editor.StandaloneEditorConstructionOptions"/> provider function
6773
/// </summary>
@@ -271,6 +277,27 @@ async Task SetTextEditorValueAsync()
271277
await this.TextEditor.SetValue(document);
272278
}
273279
}
280+
281+
/// <summary>
282+
/// Copies to content of the Monaco editor to the clipboard
283+
/// </summary>
284+
/// <returns>A awaitable task</returns>
285+
public async Task OnCopyToClipboard()
286+
{
287+
if (this.TextEditor == null) return;
288+
var text = await this.TextEditor.GetValue();
289+
if (string.IsNullOrWhiteSpace(text)) return;
290+
try
291+
{
292+
await this.JSRuntime.InvokeVoidAsync("navigator.clipboard.writeText", text);
293+
this.ToastService.Notify(new(ToastType.Success, "Definition copied to the clipboard!"));
294+
}
295+
catch (Exception ex)
296+
{
297+
this.ToastService.Notify(new(ToastType.Danger, "Failed to copy the definition to the clipboard."));
298+
this.Logger.LogError("Unable to copy to clipboard: {exception}", ex.ToString());
299+
}
300+
}
274301
#endregion
275302

276303
/// <inheritdoc/>

src/dashboard/Synapse.Dashboard/Components/ResourceEditor/ResourceEditor.razor

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,16 @@
2020
@inherits StatefulComponent<ResourceEditor<TResource>, ResourceEditorStore<TResource>, ResourceEditorState<TResource>>
2121
@inject IMonacoEditorHelper MonacoEditorHelper
2222
@inject IJSRuntime JSRuntime
23+
@inject ToastService ToastService
2324

2425
<div class="container-fluid d-flex flex-grow flex-column">
2526
<div class="row flex-grow">
26-
<div class="d-flex justify-content-end mb-2">
27+
<div class="d-flex justify-content-between mb-2">
28+
<div>
29+
<Button Outline="true" Color="ButtonColor.Primary" Size="ButtonSize.Small" @onclick="OnCopyToClipboard" TooltipTitle="Copy to clipboard">
30+
<Icon Name="IconName.Clipboard" />
31+
</Button>
32+
</div>
2733
<PreferredLanguageSelector PreferedLanguageChange="ToggleTextBasedEditorLanguageAsync" />
2834
</div>
2935
<StandaloneCodeEditor @ref="textBasedEditor"
@@ -237,6 +243,27 @@
237243
}
238244
}
239245

246+
247+
/// <summary>
248+
/// Copies to content of the Monaco editor to the clipboard
249+
/// </summary>
250+
/// <returns>A awaitable task</returns>
251+
public async Task OnCopyToClipboard()
252+
{
253+
if (this.textBasedEditor == null) return;
254+
var text = await this.textBasedEditor.GetValue();
255+
if (string.IsNullOrWhiteSpace(text)) return;
256+
try
257+
{
258+
await this.JSRuntime.InvokeVoidAsync("navigator.clipboard.writeText", text);
259+
this.ToastService.Notify(new(ToastType.Success, "Definition copied to the clipboard!"));
260+
}
261+
catch (Exception ex)
262+
{
263+
this.ToastService.Notify(new(ToastType.Danger, "Failed to copy the definition to the clipboard."));
264+
}
265+
}
266+
240267
private bool disposed;
241268
/// <summary>
242269
/// Disposes of the component

src/dashboard/Synapse.Dashboard/Pages/Functions/Create/View.razor

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ else
9191
string? version;
9292
string? chosenName;
9393
string? nameInputValue;
94-
string? namespaceSelectValue;
9594
bool loading;
9695
bool saving;
9796
ProblemDetails? problemDetails = null;

src/dashboard/Synapse.Dashboard/Pages/Workflows/Create/State.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public record CreateWorkflowViewState
4444
{
4545
Document = new()
4646
{
47-
Dsl = "1.0.0-alpha3",
47+
Dsl = "1.0.0-alpha5",
4848
Namespace = Neuroglia.Data.Infrastructure.ResourceOriented.Namespace.DefaultNamespaceName,
4949
Name = "new-workflow",
5050
Version = "0.1.0"

0 commit comments

Comments
 (0)