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); }
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)); }
protected override Task <UiFlowScreenModel> OnRefreshModelAsync(IUiFlowContextData contextData, UiFlowScreenModel originalScreenModel, IDictionary <string, object> stepViewCustomizations = null) { ThrowIfMustFail(contextData, ScreenLifecycleStage.RefreshingStepData); return(base.OnRefreshModelAsync(contextData, originalScreenModel, stepViewCustomizations)); }
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); }
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); }
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, }); }
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); }
//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); }
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); } }
protected virtual async Task <UiFlowScreenModel> OnRefreshModelAsync(IUiFlowContextData contextData, UiFlowScreenModel originalScreenModel, IDictionary <string, object> stepViewCustomizations = null) { return(originalScreenModel); }
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); } } }
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); } }
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)); }
protected override async Task <SampleComponentViewModelAsync> ResolveComponentDataAsync(SampleComponentInputAsync input, UiFlowScreenModel screenModel) { await Task.Delay(2500); return(await _viewModelBuilder.Resolve(input, screenModel)); }
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)); }
internal Assert(FlowScreenWithLifecycleAdapter <TFlowScreen> adapter, UiFlowScreenModel actual) { _adapter = adapter; _actual = actual; }
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 }; })); }
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)); }
/// <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))); }