/// <summary> /// Creates a hidden field. /// </summary> /// <param name="value">Do not pass null.</param> /// <param name="id"></param> /// <param name="pageModificationValue"></param> /// <param name="validationMethod">The validation method. Pass null if you’re only using this control for page modification.</param> /// <param name="jsInitStatementGetter">A function that takes the field’s ID and returns the JavaScript statements that should be executed when the DOM is /// loaded. Do not return null.</param> public EwfHiddenField( string value, HiddenFieldId id = null, PageModificationValue <string> pageModificationValue = null, Action <PostBackValue <string>, Validator> validationMethod = null, Func <string, string> jsInitStatementGetter = null) { pageModificationValue = pageModificationValue ?? new PageModificationValue <string>(); var elementId = new ElementId(); var formValue = new FormValue <string>( () => value, () => elementId.Id, v => v, rawValue => rawValue != null ? PostBackValueValidationResult <string> .CreateValid(rawValue) : PostBackValueValidationResult <string> .CreateInvalid()); component = new ElementComponent( context => { elementId.AddId(context.Id); id?.AddId(context.Id); return(new ElementData( () => { var attributes = new List <Tuple <string, string> >(); attributes.Add(Tuple.Create("type", "hidden")); attributes.Add(Tuple.Create("name", context.Id)); attributes.Add(Tuple.Create("value", pageModificationValue.Value)); return new ElementLocalData( "input", focusDependentData: new ElementFocusDependentData( attributes: attributes, includeIdAttribute: id != null || pageModificationValue != null || jsInitStatementGetter != null, jsInitStatements: StringTools.ConcatenateWithDelimiter( " ", pageModificationValue != null ? "$( '#{0}' ).change( function() {{ {1} }} );".FormatWith( context.Id, pageModificationValue.GetJsModificationStatements("$( this ).val()")) : "", jsInitStatementGetter?.Invoke(context.Id) ?? ""))); })); }, formValue: formValue); formValue.AddPageModificationValue(pageModificationValue, v => v); if (validationMethod != null) { validation = formValue.CreateValidation(validationMethod); } }
/// <summary> /// Creates a modal credit-card collector that is implemented with Stripe Checkout. When the window’s submit button is clicked, the credit card is charged /// or otherwise used. /// </summary> /// <param name="jsOpenStatements">The JavaScript statement list that will open this credit-card collector.</param> /// <param name="testPublishableKey">Your test publishable API key. Will be used in non-live installations. Do not pass null.</param> /// <param name="livePublishableKey">Your live publishable API key. Will be used in live installations. Do not pass null.</param> /// <param name="name">See https://stripe.com/docs/legacy-checkout. Do not pass null.</param> /// <param name="description">See https://stripe.com/docs/legacy-checkout. Do not pass null.</param> /// <param name="amountInDollars">See https://stripe.com/docs/legacy-checkout, but note that this parameter is in dollars, not cents</param> /// <param name="testSecretKey">Your test secret API key. Will be used in non-live installations. Do not pass null.</param> /// <param name="liveSecretKey">Your live secret API key. Will be used in live installations. Do not pass null.</param> /// <param name="successHandler">A method that executes if the credit-card submission is successful. The first parameter is the charge ID and the second /// parameter is the amount of the charge, in dollars.</param> /// <param name="prefilledEmailAddressOverride">By default, the email will be prefilled with AppTools.User.Email if AppTools.User is not null. You can /// override this with either a specified email address (if user is paying on behalf of someone else) or the empty string (to force the user to type in the /// email address).</param> public CreditCardCollector( JsStatementList jsOpenStatements, string testPublishableKey, string livePublishableKey, string name, string description, decimal?amountInDollars, string testSecretKey, string liveSecretKey, Func <string, decimal, StatusMessageAndDestination> successHandler, string prefilledEmailAddressOverride = null) { if (!EwfApp.Instance.RequestIsSecure(HttpContext.Current.Request)) { throw new ApplicationException("Credit-card collection can only be done from secure pages."); } if (amountInDollars.HasValue && amountInDollars.Value.DollarValueHasFractionalCents()) { throw new ApplicationException("Amount must not include fractional cents."); } var token = new DataValue <string>(); ResourceInfo successDestination = null; var postBack = PostBack.CreateFull( id: PostBack.GetCompositeId("ewfCreditCardCollection", description), modificationMethod: () => { // We can add support later for customer creation, subscriptions, etc. as needs arise. if (!amountInDollars.HasValue) { throw new ApplicationException("Only simple charges are supported at this time."); } StripeCharge response; try { response = new StripeGateway(ConfigurationStatics.IsLiveInstallation ? liveSecretKey : testSecretKey).Post( new ChargeStripeCustomer { Amount = (int)(amountInDollars.Value * 100), Currency = "usd", Description = description.Any() ? description : null, Card = token.Value }); } catch (StripeException e) { if (e.Type == "card_error") { throw new DataModificationException(e.Message); } throw new ApplicationException("A credit-card charge failed.", e); } try { var messageAndDestination = successHandler(response.Id, amountInDollars.Value); if (messageAndDestination.Message.Any()) { PageBase.AddStatusMessage(StatusMessageType.Info, messageAndDestination.Message); } successDestination = messageAndDestination.Destination; } catch (Exception e) { throw new ApplicationException("An exception occurred after a credit card was charged.", e); } }, actionGetter: () => new PostBackAction(successDestination)); var hiddenFieldId = new HiddenFieldId(); var hiddenFields = new List <EtherealComponent>(); FormState.ExecuteWithDataModificationsAndDefaultAction( postBack.ToCollection(), () => hiddenFields.Add( new EwfHiddenField("", validationMethod: (postBackValue, validator) => token.Value = postBackValue.Value, id: hiddenFieldId).PageComponent)); FormAction action = new PostBackFormAction(postBack); childGetter = () => { stripeCheckoutIncludeSetter(); action.AddToPageIfNecessary(); jsOpenStatements.AddStatementGetter( () => { var jsTokenHandler = "function( token, args ) { " + hiddenFieldId.GetJsValueModificationStatements("token.id") + " " + action.GetJsStatements() + " }"; return("StripeCheckout.open( { key: '" + (ConfigurationStatics.IsLiveInstallation ? livePublishableKey : testPublishableKey) + "', token: " + jsTokenHandler + ", name: '" + name + "', description: '" + description + "', " + (amountInDollars.HasValue ? "amount: " + amountInDollars.Value * 100 + ", " : "") + "email: '" + (prefilledEmailAddressOverride ?? (AppTools.User == null ? "" : AppTools.User.Email)) + "' } );"); }); return(hiddenFields); }; }
/// <summary> /// Creates a change-value behavior. /// </summary> /// <param name="hiddenFieldId">Do not pass null.</param> /// <param name="value">Do not pass null.</param> public ChangeValueBehavior(HiddenFieldId hiddenFieldId, string value) { this.hiddenFieldId = hiddenFieldId; this.value = value; }
public BlobFileManager( int?fileCollectionId, bool requireUploadIfNoFile, Action <int> idSetter, out Action modificationMethod, BlobFileManagerSetup setup = null) { setup = setup ?? BlobFileManagerSetup.Create(); var file = fileCollectionId != null?BlobStorageStatics.GetFirstFileFromCollection(fileCollectionId.Value) : null; var components = new List <FlowComponent>(); if (file != null) { var download = new EwfButton( new StandardButtonStyle(Translation.DownloadExisting + " (" + file.FileName + ")", buttonSize: ButtonSize.ShrinkWrap), behavior: new PostBackBehavior( postBack: PostBack.CreateFull( id: PostBack.GetCompositeId("ewfFile", file.FileId.ToString()), actionGetter: () => { // Refresh the file here in case a new one was uploaded on the same post-back. return(new PostBackAction( new PageReloadBehavior( secondaryResponse: new SecondaryResponse( new BlobFileResponse(BlobStorageStatics.GetFirstFileFromCollection(fileCollectionId.Value).FileId, () => true), false)))); }))); components.Add(download); } else if (!setup.OmitNoExistingFileMessage) { components.Add(new GenericPhrasingContainer(Translation.NoExistingFile.ToComponents())); } RsFile uploadedFile = null; var fileUploadDisplayedPmv = new PageModificationValue <string>(); components.AddRange( new FileUpload( displaySetup: fileUploadDisplayedPmv.ToCondition(bool.TrueString.ToCollection()).ToDisplaySetup(), validationPredicate: setup.UploadValidationPredicate, validationErrorNotifier: setup.UploadValidationErrorNotifier, validationMethod: (postBackValue, validator) => { if (requireUploadIfNoFile && file == null && postBackValue == null) { validator.NoteErrorAndAddMessage(Translation.PleaseUploadAFile); setup.UploadValidationErrorNotifier?.Invoke(); return; } uploadedFile = postBackValue; setup.UploadValidationMethod?.Invoke(postBackValue, validator); }).ToFormItem() .ToComponentCollection()); var fileUploadDisplayedHiddenFieldId = new HiddenFieldId(); if (file != null) { components.Add( new EwfButton( new StandardButtonStyle(Translation.ClickHereToReplaceExistingFile, buttonSize: ButtonSize.ShrinkWrap), displaySetup: fileUploadDisplayedPmv.ToCondition(bool.FalseString.ToCollection()).ToDisplaySetup(), behavior: new ChangeValueBehavior(fileUploadDisplayedHiddenFieldId, bool.TrueString))); } children = new GenericFlowContainer( BlobManagementStatics.GetThumbnailControl(file, setup.ThumbnailResourceGetter) .Append <FlowComponent>(new StackList(from i in components select i.ToCollection().ToComponentListItem())) .Materialize(), displaySetup: setup.DisplaySetup, classes: setup.Classes, etherealContent: new EwfHiddenField((file == null).ToString(), id: fileUploadDisplayedHiddenFieldId, pageModificationValue: fileUploadDisplayedPmv) .PageComponent.ToCollection()).ToCollection(); modificationMethod = () => { if (fileCollectionId == null) { fileCollectionId = BlobStorageStatics.SystemProvider.InsertFileCollection(); } if (uploadedFile != null) { BlobStorageStatics.SystemProvider.DeleteFilesLinkedToFileCollection(fileCollectionId.Value); BlobStorageStatics.SystemProvider.InsertFile( fileCollectionId.Value, uploadedFile.FileName, uploadedFile.Contents, BlobStorageStatics.GetContentTypeForPostedFile(uploadedFile)); } idSetter(fileCollectionId.Value); }; }
/// <summary> /// BasicPage.master use only. /// </summary> public Section( DisplaySetup displaySetup, SectionStyle style, ElementClassSet classes, string heading, IReadOnlyCollection <FlowComponent> postHeadingComponents, IReadOnlyCollection <FlowComponent> content, bool?expanded, bool disableStatePersistence, IReadOnlyCollection <EtherealComponent> etherealContent) { children = new DisplayableElement( context => { var hiddenFieldId = new HiddenFieldId(); var expandedPmv = heading.Any() && expanded.HasValue && !disableStatePersistence ? new PageModificationValue <string>() : null; FlowComponent getHeadingButton() { var headingComponents = new DisplayableElement( headingContext => new DisplayableElementData( null, () => new DisplayableElementLocalData("h1"), classes: headingClass, children: heading.ToComponents())).Concat(postHeadingComponents ?? Enumerable.Empty <FlowComponent>()); return(expanded.HasValue ? // We cannot use EwfButton because we have flow content. ElementActivationBehavior.GetActivatableElement( "div", ElementClassSet.Empty, Enumerable.Empty <Tuple <string, string> >().Materialize(), ElementActivationBehavior.CreateButton( buttonBehavior: new CustomButtonBehavior( () => disableStatePersistence ? "$( '#{0}' ).toggleClass( '{1}', 200 );".FormatWith( context.Id, StringTools.ConcatenateWithDelimiter( " ", style == SectionStyle.Normal ? new[] { normalClosedClass.ClassName, normalExpandedClass.ClassName } : new[] { boxClosedClass.ClassName, boxExpandedClass.ClassName })) : hiddenFieldId.GetJsValueModificationStatements( "document.getElementById( '{0}' ).value === '{2}' ? '{1}' : '{2}'".FormatWith( hiddenFieldId.ElementId.Id, bool.FalseString, bool.TrueString)))), new GenericFlowContainer( new GenericPhrasingContainer("Click to Expand".ToComponents(), classes: closeClass).ToCollection() .Append(new GenericPhrasingContainer("Click to Close".ToComponents(), classes: expandClass)) .Concat(headingComponents) .Materialize(), classes: headingClass).ToCollection(), Enumerable.Empty <EtherealComponent>().Materialize()) : new GenericFlowContainer(new GenericFlowContainer(headingComponents.Materialize(), classes: headingClass).ToCollection())); } content = content ?? Enumerable.Empty <FlowComponent>().Materialize(); return(new DisplayableElementData( displaySetup, () => new DisplayableElementLocalData( "section", focusDependentData: new DisplayableElementFocusDependentData(includeIdAttribute: heading.Any() && expanded.HasValue && disableStatePersistence)), classes: allStylesBothStatesClass .Add( style == SectionStyle.Normal ? getSectionClasses(expanded, expandedPmv, normalClosedClass, normalExpandedClass) : getSectionClasses(expanded, expandedPmv, boxClosedClass, boxExpandedClass)) .Add(classes ?? ElementClassSet.Empty), children: (heading.Any() ? getHeadingButton().ToCollection() : Enumerable.Empty <FlowComponent>()).Concat( content.Any() ? new GenericFlowContainer(content, classes: contentClass).ToCollection() : Enumerable.Empty <FlowComponent>()) .Materialize(), etherealChildren: (expandedPmv != null ? new EwfHiddenField(expanded.Value.ToString(), id: hiddenFieldId, pageModificationValue: expandedPmv).PageComponent .ToCollection() : Enumerable.Empty <EtherealComponent>()).Concat(etherealContent ?? Enumerable.Empty <EtherealComponent>()) .Materialize())); }).ToCollection(); }