11
11
// See the License for the specific language governing permissions and
12
12
// limitations under the License.
13
13
14
- using Json . Schema ;
15
14
using JsonCons . Utilities ;
16
15
using Neuroglia . Data ;
17
16
using Semver ;
18
17
using ServerlessWorkflow . Sdk . Models ;
19
18
using Synapse . Api . Client . Services ;
20
19
using Synapse . Dashboard . Components . ResourceEditorStateManagement ;
21
20
using Synapse . Resources ;
21
+ using System . Text . RegularExpressions ;
22
22
23
23
namespace Synapse . Dashboard . Pages . Workflows . Create ;
24
24
@@ -48,7 +48,8 @@ MonacoInterop monacoInterop
48
48
49
49
private TextModel ? _textModel = null ;
50
50
private string _textModelUri = string . Empty ;
51
- private bool _disposed ;
51
+ private bool _disposed = false ;
52
+ private bool _processingVersion = false ;
52
53
53
54
/// <summary>
54
55
/// Gets the service used to interact with the Synapse API
@@ -115,6 +116,10 @@ MonacoInterop monacoInterop
115
116
/// Gets an <see cref="IObservable{T}"/> used to observe changes to the state's <see cref="CreateWorkflowViewState.WorkflowDefinition"/> property
116
117
/// </summary>
117
118
public IObservable < WorkflowDefinition ? > WorkflowDefinition => this . Select ( state => state . WorkflowDefinition ) . DistinctUntilChanged ( ) ;
119
+ /// <summary>
120
+ /// Gets an <see cref="IObservable{T}"/> used to observe changes to the state's <see cref="CreateWorkflowViewState.WorkflowDefinitionText"/> property
121
+ /// </summary>
122
+ public IObservable < string ? > WorkflowDefinitionText => this . Select ( state => state . WorkflowDefinitionText ) . DistinctUntilChanged ( ) ;
118
123
119
124
/// <summary>
120
125
/// Gets an <see cref="IObservable{T}"/> used to observe changes to the state's <see cref="CreateWorkflowViewState.Loading"/> property
@@ -289,16 +294,17 @@ public async Task OnTextBasedEditorInitAsync()
289
294
/// <returns></returns>
290
295
public async Task SetTextBasedEditorLanguageAsync ( )
291
296
{
297
+ if ( this . TextEditor == null )
298
+ {
299
+ return ;
300
+ }
292
301
try
293
302
{
294
303
var language = this . MonacoEditorHelper . PreferredLanguage ;
295
- if ( this . TextEditor != null )
296
- {
297
- this . _textModel = await Global . GetModel ( this . JSRuntime , this . _textModelUri ) ;
298
- this . _textModel ??= await Global . CreateModel ( this . JSRuntime , "" , language , this . _textModelUri ) ;
299
- await Global . SetModelLanguage ( this . JSRuntime , this . _textModel , language ) ;
300
- await this . TextEditor ! . SetModel ( this . _textModel ) ;
301
- }
304
+ this . _textModel = await Global . GetModel ( this . JSRuntime , this . _textModelUri ) ;
305
+ this . _textModel ??= await Global . CreateModel ( this . JSRuntime , "" , language , this . _textModelUri ) ;
306
+ await Global . SetModelLanguage ( this . JSRuntime , this . _textModel , language ) ;
307
+ await this . TextEditor ! . SetModel ( this . _textModel ) ;
302
308
}
303
309
catch ( Exception ex )
304
310
{
@@ -314,20 +320,34 @@ public async Task SetTextBasedEditorLanguageAsync()
314
320
async Task SetTextEditorValueAsync ( )
315
321
{
316
322
var document = this . Get ( state => state . WorkflowDefinitionText ) ;
317
- if ( this . TextEditor != null && ! string . IsNullOrWhiteSpace ( document ) )
323
+ if ( this . TextEditor == null || string . IsNullOrWhiteSpace ( document ) )
318
324
{
319
- await this . TextEditor . SetValue ( document ) ;
320
- try
321
- {
322
- //await this.TextEditor.Trigger("", "editor.action.triggerSuggest");
323
- await this . TextEditor . Trigger ( "" , "editor.action.formatDocument" ) ;
324
- }
325
- catch ( Exception ex )
326
- {
327
- Console . WriteLine ( ex . ToString ( ) ) ;
328
- // todo: handle exception
329
- }
325
+ return ;
330
326
}
327
+ await this . TextEditor . SetValue ( document ) ;
328
+ try
329
+ {
330
+ await this . TextEditor . Trigger ( "" , "editor.action.formatDocument" ) ;
331
+ }
332
+ catch ( Exception ex )
333
+ {
334
+ Console . WriteLine ( ex . ToString ( ) ) ;
335
+ // todo: handle exception
336
+ }
337
+ }
338
+
339
+ /// <summary>
340
+ /// Handles text editor content changes
341
+ /// </summary>
342
+ /// <param name="e">The <see cref="ModelContentChangedEvent"/></param>
343
+ /// <returns>An awaitable task</returns>
344
+ public async Task OnDidChangeModelContent ( ModelContentChangedEvent e )
345
+ {
346
+ if ( this . TextEditor == null ) return ;
347
+ var document = await this . TextEditor . GetValue ( ) ;
348
+ this . Reduce ( state => state with {
349
+ WorkflowDefinitionText = document
350
+ } ) ;
331
351
}
332
352
333
353
/// <summary>
@@ -442,10 +462,6 @@ public override async Task InitializeAsync()
442
462
string document = "" ;
443
463
if ( definition != null )
444
464
{
445
- if ( definition . Document ? . Dsl != null )
446
- {
447
- await this . SetValidationSchema ( $ "v{ definition . Document . Dsl } ") ;
448
- }
449
465
document = this . MonacoEditorHelper . PreferredLanguage == PreferredLanguage . JSON ?
450
466
this . JsonSerializer . SerializeToText ( definition ) :
451
467
this . YamlSerializer . SerializeToText ( definition ) ;
@@ -464,6 +480,25 @@ public override async Task InitializeAsync()
464
480
{
465
481
await this . GetWorkflowDefinitionAsync ( workflow . ns , workflow . name ) ;
466
482
} , cancellationToken : this . CancellationTokenSource . Token ) ;
483
+ this . WorkflowDefinitionText . Where ( document => ! string . IsNullOrEmpty ( document ) ) . Throttle ( new ( 100 ) ) . SubscribeAsync ( async ( document ) => {
484
+ if ( string . IsNullOrWhiteSpace ( document ) )
485
+ {
486
+ return ;
487
+ }
488
+ var currentDslVersion = this . Get ( state => state . DslVersion ) ;
489
+ var versionExtractor = new Regex ( "'?\" ?(dsl|DSL)'?\" ?\\ s*:\\ s*'?\" ?([\\ w\\ .\\ -\\ +]*)'?\" ?" ) ;
490
+ var match = versionExtractor . Match ( document ) ;
491
+ if ( match == null )
492
+ {
493
+ return ;
494
+ }
495
+ var documentDslVersion = match . Groups [ 2 ] . Value ;
496
+ if ( documentDslVersion == currentDslVersion )
497
+ {
498
+ return ;
499
+ }
500
+ await this . SetValidationSchema ( "v" + documentDslVersion ) ;
501
+ } , cancellationToken : this . CancellationTokenSource . Token ) ;
467
502
await base . InitializeAsync ( ) ;
468
503
}
469
504
@@ -475,10 +510,34 @@ public override async Task InitializeAsync()
475
510
protected async Task SetValidationSchema ( string ? version = null )
476
511
{
477
512
version = version ?? await this . SpecificationSchemaManager . GetLatestVersion ( ) ;
478
- var schema = await this . SpecificationSchemaManager . GetSchema ( version ) ;
479
- var type = $ "create_{ typeof ( WorkflowDefinition ) . Name . ToLower ( ) } _{ version } ";
480
- await this . MonacoInterop . AddValidationSchemaAsync ( schema , $ "https://synapse.io/schemas/{ type } .json", $ "{ type } *") . ConfigureAwait ( false ) ;
481
- this . _textModelUri = this . MonacoEditorHelper . GetResourceUri ( type ) ;
513
+ var currentVersion = this . Get ( state => state . DslVersion ) ;
514
+ if ( currentVersion == version )
515
+ {
516
+ return ;
517
+ }
518
+ if ( this . _processingVersion )
519
+ {
520
+ return ;
521
+ }
522
+ this . SetProblemDetails ( null ) ;
523
+ this . _processingVersion = true ;
524
+ try
525
+ {
526
+ var schema = await this . SpecificationSchemaManager . GetSchema ( version ) ;
527
+ var type = $ "create_{ typeof ( WorkflowDefinition ) . Name . ToLower ( ) } _{ version } _schema";
528
+ await this . MonacoInterop . AddValidationSchemaAsync ( schema , $ "https://synapse.io/schemas/{ type } .json", $ "{ type } *") . ConfigureAwait ( false ) ;
529
+ this . _textModelUri = this . MonacoEditorHelper . GetResourceUri ( type ) ;
530
+ this . Reduce ( state => state with
531
+ {
532
+ DslVersion = version
533
+ } ) ;
534
+ }
535
+ catch ( Exception ex )
536
+ {
537
+ Console . WriteLine ( ex . ToString ( ) ) ;
538
+ this . SetProblemDetails ( new ProblemDetails ( new Uri ( "about:blank" ) , "Unable to set the validation schema" , 404 , $ "Unable to set the validation schema for the specification version '{ version } '. Make sure the version exists.") ) ;
539
+ }
540
+ this . _processingVersion = false ;
482
541
}
483
542
484
543
/// <summary>
0 commit comments