/// <summary> /// Adds a JavaScript statement that should be executed when the value changes. /// </summary> /// <param name="statementGetter">A function that takes the value expression and returns a complete statement. Do not pass null.</param> public void AddJsModificationStatement(Func <string, string> statementGetter) { // This dependency on EwfPage should not exist. EwfPage.AssertPageTreeNotBuilt(); jsModificationStatements.Add(statementGetter); }
public override IReadOnlyCollection <ActionComponentSetup> GetGlobalNavActions() { var navButtonSetups = new List <ActionComponentSetup>(); if (CreateSystem.GetInfo().IsIdenticalToCurrent()) { return(navButtonSetups); } // This will hide itself because Contact Us requires a logged-in user, and the standard library test web site has no users. var contactPage = EnterpriseWebFramework.EnterpriseWebLibrary.WebSite.ContactSupport.GetInfo(EwfPage.Instance.InfoAsBaseType.GetUrl()); navButtonSetups.Add(new HyperlinkSetup(contactPage, contactPage.ResourceName)); navButtonSetups.Add( new ButtonSetup( "Test", behavior: new MenuButtonBehavior( new EwfButton( new StandardButtonStyle("Test method"), behavior: new PostBackBehavior( postBack: PostBack.CreateFull( id: "testMethod", firstModificationMethod: () => EwfPage.AddStatusMessage(StatusMessageType.Info, "Successful method execution.")))).ToCollection()))); return(navButtonSetups); }
/// <summary> /// Returns the JavaScript statements that should be executed when the value changes. Not available until after the page tree has been built. /// </summary> public string GetJsModificationStatements(string valueExpression) { EwfPage.AssertPageTreeBuilt(); return(jsModificationStatements.Aggregate( new StringBuilder(), (builder, statementGetter) => builder.Append(statementGetter(valueExpression)), i => i.ToString())); }
/// <summary> /// Adds the element ID. This can only be called once. /// </summary> public void AddId(string id) { EwfPage.AssertPageTreeNotBuilt(); if (this.id.Length > 0) { throw new ApplicationException("The ID was already added."); } this.id = id; }
/// <summary> /// Call this during ModifyData. /// </summary> // NOTE SJR: This needs to change: You can't see this comment unless you're scrolling through all of the methods. It's easy to not call this // even though the radio button for generating a new password and emailing it to the user is always there. public void SendEmailIfNecessary() { if (passwordToEmail == null) { return; } FormsAuthStatics.SendPassword(Email, passwordToEmail); EwfPage.AddStatusMessage(StatusMessageType.Info, "Password reset email sent."); }
void ControlTreeDataLoader.LoadData() { EwfPage.Instance.SetContentContainer(contentPlace); globalPlace.AddControlsReturnThis(getGlobalBlock()); entityAndTopTabPlace.AddControlsReturnThis(getEntityAndTopTabBlock()); if (entityUsesTabMode(TabMode.Vertical)) { setUpSideTabs(); } pageActionPlace.AddControlsReturnThis(getPageActionList()); contentFootCell.Attributes.Add("class", CssElementCreator.ContentFootCellCssClass); var contentFootBlock = getContentFootBlock(); if (contentFootBlock != null) { contentFootCell.Controls.AddAt(0, contentFootBlock); } var globalFootBlock = getGlobalFootBlock(); if (globalFootBlock != null) { globalFootPlace.AddControlsReturnThis(globalFootBlock); } BasicPage.Instance.Body.Attributes["class"] = CssElementCreator.BodyCssClass; if (!EwfUiStatics.AppProvider.BrowserWarningDisabled()) { if (AppRequestState.Instance.Browser.IsOldVersionOfMajorBrowser() && !StandardLibrarySessionState.Instance.HideBrowserWarningForRemainderOfSession) { EwfPage.AddStatusMessage( StatusMessageType.Warning, StringTools.ConcatenateWithDelimiter( " ", new[] { "We've detected that you are not using the latest version of your browser.", "While most features of this site will work, and you will be safe browsing here, we strongly recommend using the newest version of your browser in order to provide a better experience on this site and a safer experience throughout the Internet." }) + "<br/>" + NetTools.BuildBasicLink("Click here to get Firefox (it's free)", new ExternalResourceInfo("http://www.getfirefox.com").GetUrl(), true) + "<br />" + NetTools.BuildBasicLink( "Click here to get Chrome (it's free)", new ExternalResourceInfo("https://www.google.com/intl/en/chrome/browser/").GetUrl(), true) + "<br />" + NetTools.BuildBasicLink( "Click here to get the latest Internet Explorer (it's free)", new ExternalResourceInfo("http://www.beautyoftheweb.com/").GetUrl(), true)); } StandardLibrarySessionState.Instance.HideBrowserWarningForRemainderOfSession = true; } }
/// <summary> /// Creates a file collection manager. /// </summary> /// <param name="fileCollectionId"></param> /// <param name="displaySetup"></param> /// <param name="postBackIdBase">Do not pass null.</param> /// <param name="sortByName"></param> /// <param name="thumbnailResourceGetter">A function that takes a file ID and returns the corresponding thumbnail resource. Do not return null.</param> /// <param name="openedFileIds">The file IDs that should not be marked with a UI element drawing the user’s attention to the fact that they haven’t read it. /// All other files not in this collection will be marked. The collection can be null, and will result as nothing being shown as new.</param> /// <param name="unopenedFileOpenedNotifier">A method that executes when an unopened file is opened. Use to update the app’s database with an indication /// that the file has been seen by the user.</param> /// <param name="disableModifications">Pass true if there should be no way to upload or delete files.</param> /// <param name="uploadValidationMethod"></param> /// <param name="fileCreatedOrReplacedNotifier">A method that executes after a file is created or replaced.</param> /// <param name="filesDeletedNotifier">A method that executes after one or more files are deleted.</param> public BlobFileCollectionManager( int fileCollectionId, DisplaySetup displaySetup = null, string postBackIdBase = "", bool sortByName = false, Func <int, ResourceInfo> thumbnailResourceGetter = null, IEnumerable <int> openedFileIds = null, MarkFileAsReadMethod unopenedFileOpenedNotifier = null, bool disableModifications = false, Action <RsFile, Validator> uploadValidationMethod = null, NewFileNotificationMethod fileCreatedOrReplacedNotifier = null, Action filesDeletedNotifier = null) { postBackIdBase = PostBack.GetCompositeId("ewfFileCollection", postBackIdBase); var columnSetups = new List <EwfTableField>(); if (thumbnailResourceGetter != null) { columnSetups.Add(new EwfTableField(size: 10.ToPercentage())); } columnSetups.Add(new EwfTableField(classes: new ElementClass("ewfOverflowedCell"))); columnSetups.Add(new EwfTableField(size: 13.ToPercentage())); columnSetups.Add(new EwfTableField(size: 7.ToPercentage())); var table = EwfTable.Create( postBackIdBase: postBackIdBase, caption: "Files", selectedItemActions: disableModifications ? null : SelectedItemAction.CreateWithFullPostBackBehavior <int>( "Delete Selected Files", ids => { foreach (var i in ids) { BlobStorageStatics.SystemProvider.DeleteFile(i); } filesDeletedNotifier?.Invoke(); EwfPage.AddStatusMessage(StatusMessageType.Info, "Selected files deleted successfully."); }) .ToCollection(), fields: columnSetups); IReadOnlyCollection <BlobFile> files = BlobStorageStatics.SystemProvider.GetFilesLinkedToFileCollection(fileCollectionId); files = (sortByName ? files.OrderByName() : files.OrderByUploadedDateDescending()).Materialize(); foreach (var file in files) { addFileRow(postBackIdBase, thumbnailResourceGetter, openedFileIds, unopenedFileOpenedNotifier, table, file); } children = files.Any() || !disableModifications ? table.Concat( !disableModifications ?getUploadComponents( fileCollectionId, files, displaySetup, postBackIdBase, uploadValidationMethod, fileCreatedOrReplacedNotifier ) : Enumerable.Empty <FlowComponent>()) .Materialize() : Enumerable.Empty <FlowComponent>().Materialize(); }
private IReadOnlyCollection <FlowComponent> getUploadComponents( int fileCollectionId, IReadOnlyCollection <BlobFile> files, DisplaySetup displaySetup, string postBackIdBase, Action <RsFile, Validator> uploadValidationMethod, NewFileNotificationMethod fileCreatedOrReplacedNotifier) { RsFile file = null; var dm = PostBack.CreateFull( id: PostBack.GetCompositeId(postBackIdBase, "add"), firstModificationMethod: () => { if (file == null) { return; } var existingFile = files.SingleOrDefault(i => i.FileName == file.FileName); int newFileId; if (existingFile != null) { BlobStorageStatics.SystemProvider.UpdateFile( existingFile.FileId, file.FileName, file.Contents, BlobStorageStatics.GetContentTypeForPostedFile(file)); newFileId = existingFile.FileId; } else { newFileId = BlobStorageStatics.SystemProvider.InsertFile( fileCollectionId, file.FileName, file.Contents, BlobStorageStatics.GetContentTypeForPostedFile(file)); } fileCreatedOrReplacedNotifier?.Invoke(newFileId); EwfPage.AddStatusMessage(StatusMessageType.Info, "File uploaded successfully."); }); return(FormState.ExecuteWithDataModificationsAndDefaultAction( dm.ToCollection(), () => new StackList( new FileUpload( validationMethod: (postBackValue, validator) => { file = postBackValue; uploadValidationMethod?.Invoke(postBackValue, validator); }).ToFormItem() .ToListItem() .Append(new EwfButton(new StandardButtonStyle("Upload new file")).ToCollection().ToComponentListItem())).ToFormItem( setup: new FormItemSetup(displaySetup: displaySetup), label: "Select and upload a new file:".ToComponents()) .ToComponentCollection())); }
IReadOnlyCollection <ActionComponentSetup> UiEntitySetupBase.GetActions() => new ButtonSetup( "Delegate action", behavior: new PostBackBehavior( postBack: PostBack.CreateFull( id: "delegate", firstModificationMethod: () => EwfPage.AddStatusMessage(StatusMessageType.Info, "Did Something.")))).ToCollection <ActionComponentSetup>() .Append(new HyperlinkSetup(new ExternalResourceInfo("http://www.google.com").ToHyperlinkNewTabBehavior(), "Go to Google in new window")) .Append( new ButtonSetup( "Generate error", behavior: new PostBackBehavior( postBack: PostBack.CreateFull(id: "error", firstModificationMethod: () => { throw new ApplicationException(); })))) .Materialize();
private ControlList getUploadControlList() { var dm = PostBack.CreateFull(id: PostBack.GetCompositeId(postBackIdBase, "add")); RsFile file = null; var fi = FormItem.Create( "", new EwfFileUpload(), validationGetter: control => new EwfValidation( (pbv, validator) => { BlobFileOps.ValidateUploadedFile(validator, control, acceptableFileExtensions, ValidateImage, AcceptOnlyImages); file = control.GetPostBackValue(pbv); }, dm)); dm.AddModificationMethod( () => { if (file == null) { return; } var existingFile = files.SingleOrDefault(i => i.FileName == file.FileName); int newFileId; if (existingFile != null) { BlobFileOps.SystemProvider.UpdateFile(existingFile.FileId, file.FileName, file.Contents, BlobFileOps.GetContentTypeForPostedFile(file)); newFileId = existingFile.FileId; } else { newFileId = BlobFileOps.SystemProvider.InsertFile(fileCollectionId, file.FileName, file.Contents, BlobFileOps.GetContentTypeForPostedFile(file)); } if (NewFileNotificationMethod != null) { NewFileNotificationMethod(newFileId); } EwfPage.AddStatusMessage(StatusMessageType.Info, "File uploaded successfully."); }); return(ControlList.CreateWithControls( true, "Select and upload a new file:", fi.ToControl(), new PostBackButton(dm, new ButtonActionControlStyle("Upload new file"), false))); }
private static void addStatusMessageIfClockNotSynchronized(DataValue <string> utcOffset) { try { // IE uses a "UTC" suffix and Firefox uses a "GMT" suffix. For our purposes, they are the same thing. Ironically, Microsoft fails to parse the time // generated by its own product, so we convert it to be the same as the time Firefox gives, which parses fine. var clockDifference = DateTime.Parse(utcOffset.Value.Replace("UTC", "GMT")) - DateTime.Now; if (Math.Abs(clockDifference.TotalMinutes) > 5) { EwfPage.AddStatusMessage( StatusMessageType.Warning, Translation.YourClockIsWrong + " " + DateTime.Now.ToShortTimeString() + " " + (TimeZone.CurrentTimeZone.IsDaylightSavingTime(DateTime.Now) ? TimeZone.CurrentTimeZone.DaylightName : TimeZone.CurrentTimeZone.StandardName) + "."); } } catch {} // NOTE: Figure out why the date time field passed from javascript might be empty, and get rid of this catch }
private static void addStatusMessageIfClockNotSynchronized(DataValue <string> clientTime) { var clientParseResult = InstantPattern.ExtendedIso.Parse(clientTime.Value); if (!clientParseResult.Success) { throw new DataModificationException("Your browser did not submit the current time."); } var clockDifference = clientParseResult.GetValueOrThrow() - AppRequestState.RequestTime; if (Math.Abs(clockDifference.TotalMinutes) > 5) { var timeZone = DateTimeZoneProviders.Tzdb.GetSystemDefault(); EwfPage.AddStatusMessage( StatusMessageType.Warning, Translation.YourClockIsWrong + " " + AppRequestState.RequestTime.InZone(timeZone).ToDateTimeUnspecified().ToHourAndMinuteString() + " " + timeZone.GetZoneInterval(AppRequestState.RequestTime).Name + "."); } }
/// <summary> /// Call this from Application_Start in your Global.asax.cs file. Besides this call, there should be no other code in the method. /// </summary> /// <param name="globalInitializer">The system's global initializer. Do not pass null.</param> /// <param name="appInitializer">The application initializer, which performs web-site specific initialization and cleanup. If you have one of these you /// should name the class AppInitializer.</param> public static void InitStatics(SystemInitializer globalInitializer, SystemInitializer appInitializer = null) { // This is a hack to support data-access state in WCF services. var wcfDataAccessState = new ThreadLocal <DataAccessState>(() => new DataAccessState()); // Initialize system. var initTimeDataAccessState = new ThreadLocal <DataAccessState>(() => new DataAccessState()); try { GlobalInitializationOps.InitStatics( globalInitializer, Path.GetFileName(Path.GetDirectoryName(HttpRuntime.AppDomainAppPath)), false, mainDataAccessStateGetter: () => { return(EwfApp.Instance != null ? EwfApp.Instance.RequestState != null ? EwfApp.Instance.RequestState.DataAccessState : initTimeDataAccessState.Value : System.ServiceModel.OperationContext.Current != null ? wcfDataAccessState.Value : null); }); } catch { // Suppress all exceptions since there is no way to report them. return; } ewlInitialized = true; // Initialize web application. if (!GlobalInitializationOps.SecondaryInitFailed) { EwfApp.ExecuteWithBasicExceptionHandling( () => { EwfConfigurationStatics.Init(); GlobalConfiguration.Configure(WebApiStatics.ConfigureWebApi); // Prevent MiniProfiler JSON exceptions caused by pages with hundreds of database queries. MiniProfiler.Settings.MaxJsonResponseSize = int.MaxValue; var globalType = BuildManager.GetGlobalAsaxType().BaseType; if (!(globalType.Assembly.CreateInstance("EnterpriseWebLibrary.EnterpriseWebFramework." + globalType.Namespace + ".MetaLogicFactory") is AppMetaLogicFactory metaLogicFactory)) { throw new ApplicationException("Meta logic factory not found."); } EwfApp.Init(globalType, metaLogicFactory); EwfPage.Init( ModalBox.CreateBrowsingModalBox, () => { var cssInfos = new List <ResourceInfo>(); cssInfos.AddRange(EwfApp.MetaLogicFactory.CreateBasicCssInfos()); if (EwfUiStatics.AppMasterPage != null) { cssInfos.AddRange(EwfApp.MetaLogicFactory.CreateEwfUiCssInfos()); } cssInfos.AddRange(EwfApp.Instance.GetStyleSheets()); if (EwfUiStatics.AppMasterPage != null) { cssInfos.AddRange(EwfUiStatics.AppProvider.GetStyleSheets()); } return(cssInfos); }); CssPreprocessingStatics.Init(globalInitializer.GetType().Assembly, globalType.Assembly); HyperlinkBehaviorExtensionCreators.Init(ModalBox.GetBrowsingModalBoxOpenStatements); EwfUiStatics.Init(globalType); EwfInitializationOps.appInitializer = appInitializer; appInitializer?.InitStatics(); initTimeDataAccessState = null; EwfApp.FrameworkInitialized = true; }, false, false); } // If initialization failed, unload and restart the application after a reasonable delay. if (!EwfApp.FrameworkInitialized) { const int unloadDelay = 60000; // milliseconds initFailureUnloadTimer = new Timer( state => EwfApp.ExecuteWithBasicExceptionHandling( () => { if (ConfigurationStatics.IsDevelopmentInstallation) { return; } HttpRuntime.UnloadAppDomain(); // Restart the application by making a request. Idea from Rick Strahl: // http://weblog.west-wind.com/posts/2013/Oct/02/Use-IIS-Application-Initialization-for-keeping-ASPNET-Apps-alive. // // Disable server certificate validation so that this request gets through even for web sites that don't use a certificate that is trusted by // default. There is no security risk since we're not sending any sensitive information and we're not using the response. Tewl.Tools.NetTools.ExecuteWithResponse( IisConfigurationStatics.GetFirstBaseUrlForCurrentSite(false), response => {}, disableCertificateValidation: true); }, false, false), null, unloadDelay, Timeout.Infinite); } }
/// <summary> /// Returns a JavaScript function call getter that opens a Stripe Checkout modal window. If the window's submit button is clicked, the credit card is /// charged or otherwise used. Do not execute the getter before all controls have IDs. /// </summary> /// <param name="etherealControlParent">The control to which any necessary ethereal controls will be added.</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/checkout. Do not pass null.</param> /// <param name="description">See https://stripe.com/docs/checkout. Do not pass null.</param> /// <param name="amountInDollars">See https://stripe.com/docs/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 static Func <string> GetCreditCardCollectionJsFunctionCall( Control etherealControlParent, 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."); } EwfPage.Instance.ClientScript.RegisterClientScriptInclude( typeof(PaymentProcessingStatics), "Stripe Checkout", "https://checkout.stripe.com/v2/checkout.js"); if (amountInDollars.HasValue && amountInDollars.Value.DollarValueHasFractionalCents()) { throw new ApplicationException("Amount must not include fractional cents."); } ResourceInfo successDestination = null; var postBack = PostBack.CreateFull( id: PostBack.GetCompositeId("ewfCreditCardCollection", description), actionGetter: () => new PostBackAction(successDestination)); var token = new DataValue <string>(); Func <PostBackValueDictionary, string> tokenHiddenFieldValueGetter; // unused Func <string> tokenHiddenFieldClientIdGetter; EwfHiddenField.Create( etherealControlParent, "", postBackValue => token.Value = postBackValue, postBack, out tokenHiddenFieldValueGetter, out tokenHiddenFieldClientIdGetter); postBack.AddModificationMethod( () => { // 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."); } var apiKey = ConfigurationStatics.IsLiveInstallation ? liveSecretKey : testSecretKey; dynamic response = new StripeClient(apiKey).CreateCharge( amountInDollars.Value, "usd", new CreditCardToken(token.Value), description: description.Any() ? description : null); if (response.IsError) { if (response.error.type == "card_error") { throw new DataModificationException(response.error.message); } throw new ApplicationException("Stripe error: " + response); } try { var messageAndDestination = successHandler((string)response.id, amountInDollars.Value); if (messageAndDestination.Message.Any()) { EwfPage.AddStatusMessage(StatusMessageType.Info, messageAndDestination.Message); } successDestination = messageAndDestination.Destination; } catch (Exception e) { throw new ApplicationException("An exception occurred after a credit card was charged.", e); } }); EwfPage.Instance.AddPostBack(postBack); return(() => { var jsTokenHandler = "function( res ) { $( '#" + tokenHiddenFieldClientIdGetter() + "' ).val( res.id ); " + PostBackButton.GetPostBackScript(postBack, includeReturnFalse: false) + "; }"; return "StripeCheckout.open( { key: '" + (ConfigurationStatics.IsLiveInstallation ? livePublishableKey : testPublishableKey) + "', name: '" + name + "', description: '" + description + "', " + (amountInDollars.HasValue ? "amount: " + amountInDollars.Value * 100 + ", " : "") + "token: " + jsTokenHandler + ", email: '" + (prefilledEmailAddressOverride ?? (AppTools.User == null ? "" : AppTools.User.Email)) + "' } )"; }); }
/// <summary> /// Not available until after the page tree has been built. /// </summary> internal IEnumerable <string> GetClassNames() { EwfPage.AssertPageTreeBuilt(); return(from i in JsModificationStatementAdderAndInclusionPredicatePairsByClassName where i.Value == null || i.Value.Item2() select i.Key); }
public override List <ActionButtonSetup> GetGlobalNavActionControls() { var navButtonSetups = new List <ActionButtonSetup>(); // This will hide itself because Contact Us requires a logged-in user, and the standard library test web site has no users. navButtonSetups.Add( new ActionButtonSetup( "Contact us", new EwfLink( RedStapler.StandardLibrary.EnterpriseWebFramework.EnterpriseWebLibrary.WebSite.ContactUs.Page.GetInfo(EwfPage.Instance.InfoAsBaseType.GetUrl())))); var menu = EwfTable.Create(); menu.AddItem( () => new EwfTableItem( new EwfTableItemSetup( clickScript: ClickScript.CreatePostBackScript( PostBack.CreateFull(id: "testMethod", firstModificationMethod: () => EwfPage.AddStatusMessage(StatusMessageType.Info, "Successful method execution.")))), "Test method")); navButtonSetups.Add(new ActionButtonSetup("Test", new ToolTipButton(menu))); navButtonSetups.Add( new ActionButtonSetup( "Calendar", new EwfLink( CalendarDemo.GetInfo( new EntitySetup.OptionalParameterPackage(), new CalendarDemo.OptionalParameterPackage { ReturnUrl = EwfPage.Instance.InfoAsBaseType.GetUrl(), Date = DateTime.Now })))); return(navButtonSetups); }
public override List <ActionButtonSetup> GetGlobalNavActionControls() { var navButtonSetups = new List <ActionButtonSetup>(); if (CreateSystem.GetInfo().IsIdenticalToCurrent()) { return(navButtonSetups); } // This will hide itself because Contact Us requires a logged-in user, and the standard library test web site has no users. var contactPage = EnterpriseWebFramework.EnterpriseWebLibrary.WebSite.ContactSupport.GetInfo(EwfPage.Instance.InfoAsBaseType.GetUrl()); navButtonSetups.Add(new ActionButtonSetup(contactPage.ResourceName, new EwfLink(contactPage))); var menu = EwfTable.Create(); menu.AddItem( () => new EwfTableItem( new EwfTableItemSetup( clickScript: ClickScript.CreatePostBackScript( PostBack.CreateFull(id: "testMethod", firstModificationMethod: () => EwfPage.AddStatusMessage(StatusMessageType.Info, "Successful method execution.")))), "Test method")); navButtonSetups.Add(new ActionButtonSetup("Test", new ToolTipButton(menu))); return(navButtonSetups); }
/// <summary> /// Adds a JavaScript statement that should be executed when the value changes. /// </summary> /// <param name="statementGetter">A function that takes the value expression and returns a complete statement. Do not pass null.</param> public void AddJsModificationStatement(Func <string, string> statementGetter) { EwfPage.AssertPageTreeNotBuilt(); jsModificationStatements.Add(statementGetter); }
/// <summary> /// Returns credit-card-collection hidden fields and a JavaScript function call getter that opens a Stripe Checkout modal window. If the window's submit /// button is clicked, the credit card is charged or otherwise used. Do not execute the getter until after the page tree has been built. /// </summary> /// <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/checkout. Do not pass null.</param> /// <param name="description">See https://stripe.com/docs/checkout. Do not pass null.</param> /// <param name="amountInDollars">See https://stripe.com/docs/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 static Tuple <IReadOnlyCollection <EtherealComponentOrElement>, Func <string> > GetCreditCardCollectionHiddenFieldsAndJsFunctionCall( 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."); } EwfPage.Instance.ClientScript.RegisterClientScriptInclude(typeof(PaymentProcessingStatics), "Stripe Checkout", "https://checkout.stripe.com/checkout.js"); if (amountInDollars.HasValue && amountInDollars.Value.DollarValueHasFractionalCents()) { throw new ApplicationException("Amount must not include fractional cents."); } ResourceInfo successDestination = null; var postBack = PostBack.CreateFull( id: PostBack.GetCompositeId("ewfCreditCardCollection", description), actionGetter: () => new PostBackAction(successDestination)); var token = new DataValue <string>(); var hiddenFieldId = new HiddenFieldId(); List <EtherealComponentOrElement> hiddenFields = new List <EtherealComponentOrElement>(); FormState.ExecuteWithDataModificationsAndDefaultAction( postBack.ToCollection(), () => hiddenFields.Add(new EwfHiddenField("", (postBackValue, validator) => token.Value = postBackValue.Value, id: hiddenFieldId).PageComponent)); postBack.AddModificationMethod( () => { // 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()) { EwfPage.AddStatusMessage(StatusMessageType.Info, messageAndDestination.Message); } successDestination = messageAndDestination.Destination; } catch (Exception e) { throw new ApplicationException("An exception occurred after a credit card was charged.", e); } }); FormAction action = new PostBackFormAction(postBack); action.AddToPageIfNecessary(); return(Tuple.Create <IReadOnlyCollection <EtherealComponentOrElement>, Func <string> >( hiddenFields, () => { 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)) + "' } )"; })); }
void ControlTreeDataLoader.LoadData() { CssClass = CssClass.ConcatenateWithSpace("ewfStandardFileCollectionManager"); if (AppRequestState.Instance.Browser.IsInternetExplorer()) { base.Controls.Add( new HtmlGenericControl("p") { InnerText = "Because you are using Internet Explorer, clicking on a file below will result in a yellow warning bar appearing near the top of the browser. You will need to then click the warning bar and tell Internet Explorer you are sure you want to download the file." }); } var columnSetups = new List <ColumnSetup>(); if (ThumbnailResourceInfoCreator != null) { columnSetups.Add(new ColumnSetup { Width = Unit.Percentage(10) }); } columnSetups.Add(new ColumnSetup { CssClassOnAllCells = "ewfOverflowedCell" }); columnSetups.Add(new ColumnSetup { Width = Unit.Percentage(13) }); columnSetups.Add(new ColumnSetup { Width = Unit.Percentage(7) }); columnSetups.Add(new ColumnSetup { Width = Unit.Percentage(23), CssClassOnAllCells = "ewfRightAlignCell" }); var table = new DynamicTable(columnSetups.ToArray()) { Caption = Caption }; files = BlobFileOps.SystemProvider.GetFilesLinkedToFileCollection(fileCollectionId); files = (sortByName ? files.OrderByName() : files.OrderByUploadedDateDescending()).ToArray(); var deletePb = PostBack.CreateFull(id: PostBack.GetCompositeId(postBackIdBase, "delete")); var deleteModMethods = new List <Func <bool> >(); foreach (var file in files) { addFileRow(table, file, deletePb, deleteModMethods); } if (!ReadOnly) { table.AddRow( getUploadControlList().ToCell(new TableCellSetup(fieldSpan: ThumbnailResourceInfoCreator != null ? 3 : 2)), (files.Any() ? new PostBackButton(deletePb, new ButtonActionControlStyle("Delete Selected Files"), usesSubmitBehavior: false) : null).ToCell( new TableCellSetup(fieldSpan: 2, classes: "ewfRightAlignCell".ToSingleElementArray()))); } deletePb.AddModificationMethod( () => { if (deleteModMethods.Aggregate(false, (deletesOccurred, method) => method() || deletesOccurred)) { EwfPage.AddStatusMessage(StatusMessageType.Info, "Selected files deleted successfully."); } }); Controls.Add(table); if (ReadOnly && !files.Any()) { Visible = false; } }
/// <summary> /// Not available until after the page tree has been built. /// </summary> internal IEnumerable <string> GetClassNames() { EwfPage.AssertPageTreeBuilt(); return(from i in ConditionsByClassName where i.Value == null || i.Value.IsTrue select i.Key); }
/// <summary> /// Adds an element ID to this set. /// </summary> public void AddId(string id) { EwfPage.AssertPageTreeNotBuilt(); ids.Add(id); }
public List <ActionButtonSetup> CreateActionButtonSetups() { var actionButtonSetups = new List <ActionButtonSetup>(); actionButtonSetups.Add( new ActionButtonSetup( "Delegate action", new PostBackButton( PostBack.CreateFull(id: "delegate", firstModificationMethod: () => EwfPage.AddStatusMessage(StatusMessageType.Info, "Did Something."))))); actionButtonSetups.Add(new ActionButtonSetup("Go to Google", new EwfLink(new ExternalResourceInfo("http://www.google.com")))); actionButtonSetups.Add( new ActionButtonSetup( "Generate error", new PostBackButton(PostBack.CreateFull(id: "error", firstModificationMethod: () => { throw new ApplicationException(); })))); return(actionButtonSetups); }