Example #1
0
        public async Task <UiFlowScreenModel> RefreshStepDataAsync(IUiFlowContextData contextData,
                                                                   UiFlowScreenModel originalScreenModel, IDictionary <string, object> stepViewCustomizations = null)
        {
            TraceBegin(nameof(RefreshStepDataAsync), contextData);

            var result = originalScreenModel;

            if (!_stepDataLoaded)
            {
                await _syncLock.AsyncCriticalSection(async() =>
                {
                    if (!_stepDataLoaded)
                    {
                        LifecycleStage  = ScreenLifecycleStage.RefreshingStepData;
                        _stepDataLoaded = true;

                        var onRefreshStepDataAsync =
                            await OnRefreshModelAsync(contextData, originalScreenModel, stepViewCustomizations);
                        await OnScreenLoadCompletedAsync(contextData);
                        result         = onRefreshStepDataAsync;
                        LifecycleStage = ScreenLifecycleStage.RefreshStepDataCompleted;
                    }
                }
                                                     );
            }
            TraceEnd(nameof(RefreshStepDataAsync), contextData);

            return(result);
        }
Example #2
0
        public async Task <IActionResult> Index()
        {
            var debuggerModel = new DebuggerModel();

            try
            {
                var contextData = await _repository.GetLastSnapshot();

                if (contextData != null)
                {
                    UiFlowScreenModel screenModel = contextData.GetCurrentStepData <UiFlowScreenModel>();
                    string            flowHandler = screenModel.FlowHandler;
                    while (screenModel.Metadata.ContainedFlowHandler != null)
                    {
                        contextData = await _repository.Get(screenModel.Metadata.ContainedFlowHandler);

                        screenModel = contextData.GetCurrentStepData <UiFlowScreenModel>();
                        flowHandler = screenModel.FlowHandler;
                    }


                    debuggerModel.FlowHandler = flowHandler;
                }
            }
            catch (Exception ex)
            {
                debuggerModel.Error = $"Possible cause: You need to refresh the page once you have the application with a flow rendered {Environment.NewLine}{ex}";
            }



            return(View(debuggerModel));
        }
Example #3
0
 protected override Task <UiFlowScreenModel> OnRefreshModelAsync(IUiFlowContextData contextData,
                                                                 UiFlowScreenModel originalScreenModel,
                                                                 IDictionary <string, object> stepViewCustomizations = null)
 {
     ThrowIfMustFail(contextData, ScreenLifecycleStage.RefreshingStepData);
     return(base.OnRefreshModelAsync(contextData, originalScreenModel, stepViewCustomizations));
 }
Example #4
0
        protected override async Task <UiFlowScreenModel> OnRefreshModelAsync(IUiFlowContextData contextData,
                                                                              UiFlowScreenModel originalScreenModel, IDictionary <string, object> stepViewCustomizations = null)
        {
            var result = Map(contextData.GetStepData <InputScreen.ScreenModel>(ModelTesterFlowStep.InputScreen),
                             contextData.GetCurrentStepData <ScreenModel>());

            return(result);
        }
Example #5
0
 public async Task <SampleComponentViewModelAsync> Resolve(SampleComponentInputAsync componentInput,
                                                           UiFlowScreenModel screenModelContainingTheComponent)
 {
     return(new SampleComponentViewModelAsync
     {
         Value = componentInput.InputParameter,
         DataFromRestoredScreenModel = screenModelContainingTheComponent.FlowScreenName
     });
 }
        public async Task <TResult> Execute(CurrentViewRequest <TResult> input)
        {
            TResult result;
            var     flow = await _flows.GetByFlowHandler(input.FlowHandler);

            if (flow == null)
            {
                return(await input.BuildResultOnFlowNotFound());
            }
            var stepData = await flow.GetCurrentStepData(input.FlowHandler, input.ViewParameters);

            UiFlowScreenModel actualStepData = null;

            //TODO: is component view property
            if (!input.ResolveAsComponentOnly)
            {
                actualStepData = await InitializeNewContainedFlows(stepData, input.ViewParameters);
            }

            if (actualStepData is ExitReturnToCaller)
            {
                result = await input.OnCallbackCallerFlow(((ExitReturnToCaller)actualStepData));
            }
            else if (actualStepData != null && stepData.FlowHandler != actualStepData.FlowHandler)
            {
                result = await input.BuildResultOnRequestRedirectTo(actualStepData.FlowHandler);
            }
            else
            {
                if (input.OnAddModelError != null)
                {
                    foreach (var error in stepData.Errors)
                    {
                        input.OnAddModelError(error.MemberName, error.ErrorMessage);
                    }
                }

                result = await input.OnBuildView(new CurrentViewRequest <TResult> .BuildViewInput
                {
                    BuildPartial = stepData.Metadata.IsContainedInController() ||
                                   (await _contextRepository.Get(input.FlowHandler)).IsInContainer(),
                    ScreenModel = stepData,
                    ViewName    = flow.CurrentState.ViewName,
                    FlowType    = flow.FlowTypeId
                });
            }
            if (!input.ResolveAsComponentOnly)
            {
                await _contextRepository.Flush();
            }

            return(result);
        }
        public static UiFlowScreenModel AddStepData(this UiFlowContextData ctx, string flowScreenName, bool setCurrentStepData = false)
        {
            var userData = new UiFlowScreenModel();

            userData.Metadata.FlowHandler    = ctx.FlowHandler;
            userData.Metadata.FlowScreenName = flowScreenName;
            ctx.SetStepData(flowScreenName, userData);
            if (setCurrentStepData)
            {
                ctx.CurrentScreenStep = flowScreenName;
            }
            return(userData);
        }
        private object ResolveStepDataView(UiFlowScreenModel src)
        {
            var result        = (IDictionary <string, object>)(src.ToExpandoObject());
            var exclude       = new[] { nameof(UiFlowScreenModel.DontValidateEvents), nameof(UiFlowScreenModel.Errors) };
            var propertyNames = typeof(UiFlowScreenModel).GetPropertiesFast().Union(typeof(InitialFlowScreenModel).GetPropertiesFast()).Select(x => x.Name).Where(x => !exclude.Contains(x));

            foreach (var propertyName in propertyNames)
            {
                result.RemoveIfExists(propertyName);
            }

            return(result);
        }
Example #9
0
 public FlowResultResolverRequest <TResult> ToFlowResolverRequest(UiFlowScreenModel model)
 {
     return(new FlowResultResolverRequest <TResult>
     {
         ScreenModel = model ?? Model,
         OnExecuteEvent = this.OnExecuteEvent,
         OnExecuteRedirection = OnExecuteRedirection,
         OnExecuteUnauthorized = OnExecuteUnauthorized,
         OnRedirectToCurrent = OnRedirectToCurrent,
         OnNewContainedScreen = OnNewContainedScreen,
         OnStartNewFlow = OnStartNewFlow,
         OnRedirectToRoot = OnRedirectToRoot,
     });
 }
Example #10
0
        protected override async Task <UiFlowScreenModel> OnRefreshModelAsync(IUiFlowContextData contextData,
                                                                              UiFlowScreenModel originalScreenModel, IDictionary <string, object> stepViewCustomizations = null)
        {
            var result = (StepCScreenScreenModel)originalScreenModel;


            result.FlowInputData = contextData.GetStepData <FlowInitializer.StartScreenModel>(ScreenName.PreStart).SampleParameter;
            result.InitialValue  = contextData
                                   .GetStepData <InitialScreen.InitialScreenScreenModel>(GreenFlowScreenName.Step0Screen).StepValue1;
            result.StepAValue = contextData
                                .GetStepData <StepAScreen.StepAScreenScreenModel>(GreenFlowScreenName.StepAScreen)
                                ?.StepAValue1;
            result.StepBValue = contextData
                                .GetStepData <StepBScreen.StepBScreenScreenModel>(GreenFlowScreenName.StepBScreen)
                                ?.StepBValue1;
            return(result);
        }
        protected virtual async Task <IActionResult> OnInvokeDeferredAsync(string componentId, TComponentInput input,
                                                                           UiFlowScreenModel screenModel, Func <string, object, IActionResult> viewBuilder)
        {
            if (!(PlatformSettings.IsDeferredComponentLoadEnabled && DeferComponentLoad))
            {
                return(new BadRequestResult());
            }
            if (input == null)
            {
                input = new TComponentInput();
            }

            ComponentId = componentId;
            var data = await ResolveComponentDataAsync(input, screenModel);

            data.ScreenModel = screenModel;
            data.ComponentId = componentId;
            return(viewBuilder(ViewName, data));
        }
        async Task <UiFlowScreenModel> InitializeNewContainedFlows(UiFlowScreenModel sData,
                                                                   IDictionary <string, object> stepViewCustomizations)
        {
            var refresh = false;

            var stepMetaData = sData.Metadata;

            while (stepMetaData.ContainedFlowType != null && stepMetaData.ContainedFlowHandler != null)
            {
                var ctx = await _contextRepository.Get(stepMetaData.ContainedFlowHandler);

                stepMetaData = ctx.GetCurrentStepData <UiFlowScreenModel>().Metadata;
                refresh      = true;
            }

            while (stepMetaData.ContainedFlowType != null && stepMetaData.ContainedFlowHandler == null)
            {
                var c            = _flows.GetByFlowType((await _contextRepository.Get(sData.FlowHandler)).FlowType);
                var uiFlowScreen = await c.GetCurrentScreen(sData.FlowHandler);

                var containedFlowStartInfo = await uiFlowScreen.ResolveContainedFlowStartInfo(c.CurrentState.ContextData, stepViewCustomizations);

                var f = _flows.GetByFlowType(stepMetaData.ContainedFlowType);
                sData = await f.StartNew(sData.FlowHandler, containedFlowStartInfo);

                if (sData is ExitReturnToCaller)
                {
                    return(sData);
                }
                stepMetaData = sData.Metadata;
                refresh      = true;
            }

            if (refresh)
            {
                var uiFlowContextData = (await _contextRepository.GetRootContainerContext(sData.FlowHandler));
                var flow = await _flows.GetByFlowHandler(uiFlowContextData.FlowHandler);

                sData = await flow.GetCurrentStepData(uiFlowContextData.FlowHandler, stepViewCustomizations);
            }

            return(sData);
        }
Example #13
0
        //TODO: THIS SHOULD BE THE COMMAND CONCERN AND ENCAPSULATED IN IT
        private async Task <IActionResult> RecordAndResolve(UiFlowScreenModel sourceStep)
        {
            IActionResult result = null;
            var           form   = HttpContext.Request.Form;

            if (!form.ContainsKey(FlowFormKey))
            {
                result = BadRequest();
            }
            else
            {
                var currentToken = form[FlowFormKey].ToString();

                var lastToken = await _store.GetAsync(LastProcessedTokenKey);

                if (lastToken == currentToken)
                {
                    var ctx = await _contextRepository.GetCurrentSnapshot(sourceStep.FlowHandler);

                    var uiFlowStepData = ctx.GetCurrentStepData <UiFlowScreenModel>();
                    while (uiFlowStepData == null)
                    {
                        await Task.Delay(100);

                        ctx = await _contextRepository.GetCurrentSnapshot(sourceStep.FlowHandler);

                        uiFlowStepData = ctx.GetCurrentStepData <UiFlowScreenModel>();
                    }

                    var request = new FlowResultResolverRequest <IActionResult>
                    {
                        ScreenModel = uiFlowStepData
                    };
                    AddDefaultCallbackHandlers(request);
                    result = await _resultResolver.Execute(request);
                }

                await _store.SetAsync(LastProcessedTokenKey, currentToken);
            }

            return(result);
        }
Example #14
0
        protected override async Task <UiFlowScreenModel> OnRefreshModelAsync(IUiFlowContextData contextData,
                                                                              UiFlowScreenModel originalScreenModel, IDictionary <string, object> stepViewCustomizations = null)
        {
            var result = (StepCScreenScreenModel)originalScreenModel;


            if (stepViewCustomizations != null)
            {
                result = (StepCScreenScreenModel)originalScreenModel.CloneDeep();
                result.SetFlowCustomizableValue(stepViewCustomizations, x => x.CustomizableViewDataSample);
            }
            result.FlowInputData = contextData.GetStepData <FlowInitializer.StartScreenModel>(ScreenName.PreStart).GreenFlowData;
            result.InitialValue  = contextData
                                   .GetStepData <InitialScreen.InitialScreenScreenModel>(BlueFlowScreenName.Step0Screen).StepValue1;
            result.StepAValue = contextData
                                .GetStepData <StepAScreen.StepAScreenScreenModel>(BlueFlowScreenName.FillDataStep_StepAScreen)
                                ?.StepAValue1;
            result.StepBValue = contextData
                                .GetStepData <StepBScreen.StepBScreenScreenModel>(BlueFlowScreenName.FillDataStep_StepBScreen)
                                ?.StepBValue1;
            return(result);
        }
        private async Task <IViewComponentResult> ResolveLoaderResultAsync(TComponentInput input,
                                                                           UiFlowScreenModel uiFlowScreenModel)
        {
            if (input == null)
            {
                throw new ArgumentNullException(nameof(input));
            }

            var loaderContent = Template.Value
                                .Replace("[[componentId]]", ComponentId)
                                .Replace("[[loadingPlaceholder]]", _loadingViewContent.Value)
                                .Replace("[[urlPlaceholder]]", await ResolveUrl());

            return(new HtmlContentViewComponentResult(new HtmlString(loaderContent)));

            async Task <string> ResolveUrl()
            {
                var avoidBaseProps = typeof(TComponentModel).GetPropertiesFast(
                    BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public |
                    BindingFlags.GetProperty | BindingFlags.SetProperty, p => p.DeclaringType != typeof(TComponentModel),
                    $"InheritedOf_{typeof(TComponentModel).FullName}")
                                     .Select(x => x.Name);
                var val = await HttpContext.EncryptedActionUrl(
                    nameof(DeferredComponentPartialsController.Resolve)
                    , typeof(DeferredComponentPartialsController).GetNameWithoutSuffix()
                    , new
                {
                    HandlerType = GetType().FullName,
                    FlowHandler = uiFlowScreenModel.FlowHandler,
                    ComponentId = ComponentId
                }
                    .MergeObjects(input
                                  .ToExpandoObject(avoidBaseProps.ToArray()))
                    );

                return(val);
            }
        }
Example #16
0
 protected virtual async Task <UiFlowScreenModel> OnRefreshModelAsync(IUiFlowContextData contextData,
                                                                      UiFlowScreenModel originalScreenModel,
                                                                      IDictionary <string, object> stepViewCustomizations = null)
 {
     return(originalScreenModel);
 }
Example #17
0
        public async Task <IActionResult> OnEvent([FromForm(Name = SharedSymbol.FlowEventFormFieldName)]
                                                  string trigger, [FromForm] UiFlowScreenModel model)
        {
            using (_profiler.Profile(nameof(UiFlowController), nameof(OnEvent)))
            {
                IActionResult result;
                Logger.Trace(() => $"Starting - {nameof(OnEvent)} --> trigger:{trigger} model:{model} ");
                if (model == null)
                {
                    return(BadRequest("model not specified"));
                }

                try
                {
                    var alreadyProcessedResult = await RecordAndResolve(model);

                    if (alreadyProcessedResult != null)
                    {
                        return(alreadyProcessedResult);
                    }
                }
                catch (Exception ex)
                {
                    Logger.Warn(() => ex.ToString());
                }

                result = await this.HandleActionAsync(async() =>
                {
                    ModelState.Clear();

                    var triggerEventOnView = new TriggerEventOnView <IActionResult>
                    {
                        Event = trigger,
                        Model = model,

                        OnExecuteValidation = ValidateStepModel
                    };
                    AddDefaultCallbackHandlers(triggerEventOnView);
                    return(await _flowExecuteEvent.Execute(triggerEventOnView));
                });

                Logger.Trace(() => $"Completed - {nameof(OnEvent)} --> trigger:{trigger} model:{model} ");
                return(result);
            }

            IEnumerable <UiFlowUserInputError> ValidateStepModel(UiFlowScreenModel stepModel)
            {
                ModelState.Clear();
                TryValidateModel(stepModel);
                return(GetValidationErrorsAsFlowErrors());

                IEnumerable <UiFlowUserInputError> GetValidationErrorsAsFlowErrors()
                {
                    var errors = new List <UiFlowUserInputError>();

                    foreach (var itemName in ModelState.Where(x =>
                                                              x.Value.ValidationState == ModelValidationState.Invalid))
                    {
                        var itemNameKey = itemName.Key;
                        errors.AddRange(itemName.Value.Errors
                                        .Where(x => !errors.Any(y =>
                                                                y.MemberName == itemNameKey && x.ErrorMessage == y.ErrorMessage)).Select(x =>
                                                                                                                                         new UiFlowUserInputError
                        {
                            ErrorMessage = x.ErrorMessage, MemberName = itemNameKey
                        }));
                    }

                    return(errors);
                }
            }
        }
Example #18
0
        public async Task Process(FlowActionTagHelper target, IHtmlHelper htmlHelper, TagHelperContext context,
                                  TagHelperOutput output)
        {
            var content = (await output.GetChildContentAsync()).GetContent();

            IHtmlContent htmlContent;

            var attrsObject = (object)context.AllAttributes
                              .Where(x => !FlowActionTagHelper.DesignerOnlySymbols.Any(att => att.Equals(x.Name, StringComparison.InvariantCultureIgnoreCase)))
                              .ToDictionary(x => x.Name, x => x.Value).ToExpandoObject();

            if (target.Type == FlowActionTagHelper.FlowActionType.StartFlow)
            {
                var containerViewModel = await LocateContainer();

                htmlContent = await htmlHelper.DisplayFlowLinkAsync2(containerViewModel, content, target.FlowName,
                                                                     target.FlowParameters, attrsObject);
            }
            else if (target.Type == FlowActionTagHelper.FlowActionType.ReloadStepWithChanges)
            {
                var uiFlowScreenModel = htmlHelper.ViewData.Model is FlowComponentViewModel model
                                        ? (UiFlowScreenModel)model.ScreenModel
                                        : (UiFlowScreenModel)htmlHelper.ViewData.Model;
                htmlContent = await htmlHelper.UiFlowActionLinkToCurrentStepAsync(uiFlowScreenModel,
                                                                                  target.FlowParameters, content, attrsObject);
            }
            else
            {
                throw new ArgumentOutOfRangeException();
            }
            output.TagName = null;
            output.Content.SetHtmlContent(htmlContent);
            async Task <UiFlowScreenModel> LocateContainer()
            {
                UiFlowScreenModel result = null;
                var currentHandler       = (htmlHelper.ViewData.Model as UiFlowScreenModel)?.FlowHandler ??
                                           (htmlHelper.ViewData.Model as FlowComponentViewModel)?.ScreenModel?.FlowHandler;

                switch (target.FlowLocation)
                {
                case FlowActionTagHelper.StartFlowLocation.NotRelevantToThis:
                case  FlowActionTagHelper.StartFlowLocation.NotContained:
                    break;

                case FlowActionTagHelper.StartFlowLocation.SameContainerAsMe:
                    if (currentHandler != null)
                    {
                        var ctx = await _contextRepository.Get(currentHandler);

                        if (ctx.ContainerFlowHandler != null)
                        {
                            ctx = await _contextRepository.Get(ctx.ContainerFlowHandler);

                            result = ctx.GetCurrentStepData <UiFlowScreenModel>();
                        }
                    }

                    break;

                case FlowActionTagHelper.StartFlowLocation.ContainedInMe:
                    if (currentHandler != null)
                    {
                        var ctx = await _contextRepository.Get(currentHandler);

                        result = ctx.GetCurrentStepData <UiFlowScreenModel>();
                    }

                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                return(result);
            }
        }
Example #19
0
        protected virtual async Task <IViewComponentResult> OnInvokeAsync(TComponentInput input, UiFlowScreenModel screenModel)
        {
            IViewComponentResult result;

            if (input == null)
            {
                input = new TComponentInput();
            }
            if (!(PlatformSettings?.IsDeferredComponentLoadEnabled ?? false) || !DeferComponentLoad)
            {
                var data = await ResolveComponentDataAsync(input, screenModel);

                data.ScreenModel = screenModel;
                data.ComponentId = $"flow_component{Guid.NewGuid()}";
                result           = await ResolveResultAsync(data);
            }
            else
            {
                result = await ResolveLoaderResultAsync(input, screenModel);
            }
            return(result);
        }
        public async Task <IActionResult> OnEvent([FromForm(Name = SharedSymbol.FlowEventFormFieldName)] string trigger, [FromForm] UiFlowScreenModel model)
        {
            if (trigger == null)
            {
                throw new ArgumentNullException(nameof(trigger));
            }
            var result = BuildResult(new object[] { trigger, model });

            return(Ok(result));
        }
Example #21
0
        protected override async Task <SampleComponentViewModelAsync> ResolveComponentDataAsync(SampleComponentInputAsync input, UiFlowScreenModel screenModel)
        {
            await Task.Delay(2500);

            return(await _viewModelBuilder.Resolve(input, screenModel));
        }
Example #22
0
        protected override async Task <UiFlowScreenModel> OnRefreshModelAsync(IUiFlowContextData contextData, UiFlowScreenModel originalScreenModel,
                                                                              IDictionary <string, object> stepViewCustomizations = null)
        {
            await SetTitle(contextData, (Number2ContainerScreenModel)originalScreenModel);

            return(originalScreenModel);
        }
 public async Task <ViewModel> Resolve(InputComponentInput componentInput, UiFlowScreenModel screenModelContainingTheComponent)
 {
     return(new ViewModel
     {
         StringValue = componentInput.InputParameter
     });
 }
 protected override async Task <ViewModel> ResolveComponentDataAsync(InputComponentInput input, UiFlowScreenModel screenModel)
 {
     return(await _viewModelBuilder.Resolve(input, screenModel));
 }
Example #25
0
 internal Assert(FlowScreenWithLifecycleAdapter <TFlowScreen> adapter,
                 UiFlowScreenModel actual)
 {
     _adapter = adapter;
     _actual  = actual;
 }
Example #26
0
            public async Task <SampleComponentViewModel> Resolve(SampleComponentInput componentInput, UiFlowScreenModel screenModelContainingTheComponent)
            {
                await Task.Yield();

                return(await Task.Run(async() =>
                {
                    await Task.Yield();
                    Thread.Sleep(new Random().Next(1, 5000));
                    await Task.Yield();
                    return new SampleComponentViewModel
                    {
                        Value = componentInput.InputParameter
                    };
                }));
            }
Example #27
0
 public async Task <IViewComponentResult> InvokeAsync(TComponentInput input, UiFlowScreenModel screenModel)
 {
     return(await OnInvokeAsync(input, screenModel));
 }
 protected virtual Task <ScreenEvent> OnResolveInitializationEventToTrigger(ScreenEvent defaultEventToTriggerAfter,
                                                                            UiFlowScreenModel screenModel)
 {
     return(Task.FromResult(defaultEventToTriggerAfter));
 }
Example #29
0
 /// <summary>
 /// Resolves the component model
 /// </summary>
 /// <param name="input"></param>
 /// <param name="screenModel"></param>
 /// <returns></returns>
 protected abstract Task <TComponentModel> ResolveComponentDataAsync(TComponentInput input,
                                                                     UiFlowScreenModel screenModel);
        public async Task <IActionResult> Process([FromForm] TViewModel viewModel, [FromForm] string trigger, UiFlowScreenModel viewData, string flowType = null)
        {
            _flowController.ControllerContext = this.ControllerContext;

            await _flowController.OnEvent(trigger, viewData);

            if (flowType != null)
            {
                viewModel.SetContainedFlow(_flowsRegistry.GetByName(flowType, true).Name);
            }
            return(RedirectToAction(nameof(Index), await viewModel.ToValidRouteValueAsync(ControllerContext.HttpContext)));
        }