public async Task <IActionResult> Edit(string sourcename, string localId)
        {
            if (!await _authorizationService.AuthorizeAsync(User, OrchardCore.Workflows.Snippets.Permissions.ManageWorkflowSnippets))
            {
                return(Forbid());
            }

            var newLocalId          = string.IsNullOrWhiteSpace(localId) ? Guid.NewGuid().ToString() : localId;
            var availableActivities = _activityLibrary.ListActivities();

            var shortcodeTemplatesDocument = await _workflowSnippetsManager.GetWorkflowSnippetsDocumentAsync();

            if (!shortcodeTemplatesDocument.WorkflowSnippets.ContainsKey(sourcename))
            {
                return(RedirectToAction("EditProperties", new { sourcename = sourcename }));
            }

            var workflowSnippet = shortcodeTemplatesDocument.WorkflowSnippets[sourcename];

            var workflowType = workflowSnippet.WorkFlowType;

            if (workflowType == null)
            {
                return(NotFound());
            }

            //populate properties from source object
            workflowType.Name      = sourcename;
            workflowType.IsEnabled = workflowSnippet.IsEnabled;

            var workflow        = _workflowManager.NewWorkflow(workflowType);
            var workflowContext = await _workflowManager.CreateWorkflowExecutionContextAsync(workflowType, workflow);

            var activityContexts = await Task.WhenAll(workflowType.Activities.Select(x => _workflowManager.CreateActivityExecutionContextAsync(x, x.Properties)));

            // var workflowCount = await _session.QueryIndex<WorkflowIndex>(x => x.WorkflowTypeId == workflowType.WorkflowTypeId).CountAsync();


            var activityThumbnailShapes = new List <dynamic>();
            var index = 0;

            foreach (var activity in availableActivities)
            {
                activityThumbnailShapes.Add(await BuildActivityDisplay(activity, index++, sourcename, newLocalId, "Thumbnail"));
            }

            var activityDesignShapes = new List <dynamic>();

            index = 0;

            foreach (var activityContext in activityContexts)
            {
                activityDesignShapes.Add(await BuildActivityDisplay(activityContext, index++, sourcename, newLocalId, "Design"));
            }

            var activitiesDataQuery = activityContexts.Select(x => new
            {
                Id       = x.ActivityRecord.ActivityId,
                X        = x.ActivityRecord.X,
                Y        = x.ActivityRecord.Y,
                Name     = x.ActivityRecord.Name,
                IsStart  = x.ActivityRecord.IsStart,
                IsEvent  = x.Activity.IsEvent(),
                Outcomes = x.Activity.GetPossibleOutcomes(workflowContext, x).ToArray()
            });
            var workflowTypeData = new
            {
                Id          = sourcename,
                Name        = workflowType.Name,
                IsEnabled   = workflowType.IsEnabled,
                Activities  = activitiesDataQuery.ToArray(),
                Transitions = workflowType.Transitions
            };

            var wfVewModel = new WorkflowTypeViewModel
            {
                WorkflowType     = workflowType,
                WorkflowTypeJson = JsonConvert.SerializeObject(workflowTypeData, Formatting.None, new JsonSerializerSettings {
                    ContractResolver = new CamelCasePropertyNamesContractResolver()
                }),
                ActivityThumbnailShapes = activityThumbnailShapes,
                ActivityDesignShapes    = activityDesignShapes,
                ActivityCategories      = _activityLibrary.ListCategories().ToList(),
                LocalId        = newLocalId,
                LoadLocalState = !string.IsNullOrWhiteSpace(localId),
                //  WorkflowCount = workflowCount
            };

            var model = new WorkflowSnippetViewModel
            {
                Name = sourcename,
                WorkflowTypeViewModel = wfVewModel,
                //Content = template.Content,
                // WorkflowType = workflowType,
                Description = workflowSnippet.Description,
                // Categories = template.Categories
            };

            return(View(model));
        }
        public async Task <IActionResult> Edit(string sourcename, WorkflowSnippetViewModel model, string submit)
        {
            if (!await _authorizationService.AuthorizeAsync(User, OrchardCore.Workflows.Snippets.Permissions.ManageWorkflowSnippets))
            {
                return(Forbid());
            }

            var shortcodeTemplatesDocument = await _workflowSnippetsManager.LoadWorkflowSnippetsDocumentAsync();

            if (!shortcodeTemplatesDocument.WorkflowSnippets.ContainsKey(sourcename))
            {
                return(NotFound());
            }
            var workflowSnippet = shortcodeTemplatesDocument.WorkflowSnippets[sourcename];

            var workflowType = workflowSnippet.WorkFlowType;


            dynamic state                   = JObject.Parse(model.WorkflowTypeViewModel.State);
            var     currentActivities       = workflowType.Activities.ToDictionary(x => x.ActivityId);
            var     postedActivities        = ((IEnumerable <dynamic>)state.activities).ToDictionary(x => (string)x.id);
            var     removedActivityIdsQuery =
                from activityId in currentActivities.Keys
                where !postedActivities.ContainsKey(activityId)
                select activityId;
            var removedActivityIds = removedActivityIdsQuery.ToList();

            // Remove any orphans (activities deleted on the client).
            foreach (var activityId in removedActivityIds)
            {
                var activityToRemove = currentActivities[activityId];
                workflowType.Activities.Remove(activityToRemove);
                currentActivities.Remove(activityId);
            }

            // Update activities.
            foreach (var activityState in state.activities)
            {
                var activity = currentActivities[(string)activityState.id];
                activity.X       = activityState.x;
                activity.Y       = activityState.y;
                activity.IsStart = activityState.isStart;
            }

            // Update transitions.
            workflowType.Transitions.Clear();
            foreach (var transitionState in state.transitions)
            {
                workflowType.Transitions.Add(new Transition
                {
                    SourceActivityId      = transitionState.sourceActivityId,
                    DestinationActivityId = transitionState.destinationActivityId,
                    SourceOutcomeName     = transitionState.sourceOutcomeName
                });
            }

            await _workflowSnippetsManager.RemoveWorkflowSnippetAsync(sourcename);

            await _workflowSnippetsManager.UpdateShortcodeTemplateAsync(sourcename, workflowSnippet);

            _notifier.Success(H["Snippet has been saved."]);

            if (submit != "SaveAndContinue")
            {
                return(RedirectToAction(nameof(Index)));
            }
            else
            {
                return(RedirectToAction(nameof(Edit), new { sourcename = sourcename }));
            }
        }
        public async Task <IActionResult> EditProperties(WorkflowSnippetViewModel viewModel, string sourcename)
        {
            if (!await _authorizationService.AuthorizeAsync(User, OrchardCore.Workflows.Snippets.Permissions.ManageWorkflowSnippets))
            {
                return(Forbid());
            }

            if (!ModelState.IsValid)
            {
                return(View(viewModel));
            }

            var isNew           = string.IsNullOrEmpty(sourcename);
            var workflowSnippet = default(WorkflowSnippet);

            if (isNew)
            {
                if (String.IsNullOrWhiteSpace(viewModel.Name))
                {
                    ModelState.AddModelError(nameof(WorkflowSnippetViewModel.Name), S["The name is mandatory."]);
                }
                else
                {
                    var shortcodeTemplatesDocument = await _workflowSnippetsManager.GetWorkflowSnippetsDocumentAsync();

                    if (shortcodeTemplatesDocument.WorkflowSnippets.ContainsKey(viewModel.Name))
                    {
                        ModelState.AddModelError(nameof(WorkflowSnippetViewModel.Name), S["A snippet with the same name already exists."]);
                    }
                }

                if (!ModelState.IsValid)
                {
                    // If we got this far, something failed, redisplay form
                    return(View(viewModel));
                }

                workflowSnippet = new WorkflowSnippet
                {
                    Description = viewModel.Description,
                    IsEnabled   = viewModel.IsEnabled,
                    Categories  = JsonConvert.DeserializeObject <string[]>(viewModel.SelectedCategories),
                };
                await _workflowSnippetsManager.UpdateShortcodeTemplateAsync(viewModel.Name, workflowSnippet);
            }
            else
            {
                var shortcodeTemplatesDocument = await _workflowSnippetsManager.GetWorkflowSnippetsDocumentAsync();

                if (!shortcodeTemplatesDocument.WorkflowSnippets.ContainsKey(sourcename))
                {
                    return(NotFound());
                }
                workflowSnippet = shortcodeTemplatesDocument.WorkflowSnippets[sourcename];

                workflowSnippet.Description = viewModel.Description?.Trim();
                workflowSnippet.Categories  = JsonConvert.DeserializeObject <string[]>(viewModel.SelectedCategories);
                workflowSnippet.IsEnabled   = viewModel.IsEnabled;

                await _workflowSnippetsManager.RemoveWorkflowSnippetAsync(sourcename);

                await _workflowSnippetsManager.UpdateShortcodeTemplateAsync(viewModel.Name, workflowSnippet);
            }


            return(isNew
                        ? RedirectToAction("Edit", new { sourcename = viewModel.Name })
                        :   RedirectToAction("Index"));
        }