protected override PageContent getContent() { if (Password.Any()) { return(new UiPageContent( pageLoadPostBack: PostBack.CreateFull( modificationMethod: () => logIn(HideWarnings), actionGetter: () => new PostBackAction(new ExternalResource(ReturnUrl)))).Add(new Paragraph("Please wait.".ToComponents()))); } return(FormState.ExecuteWithDataModificationsAndDefaultAction( PostBack.CreateFull(modificationMethod: () => logIn(false), actionGetter: () => new PostBackAction(new ExternalResource(ReturnUrl))) .ToCollection(), () => new UiPageContent(contentFootActions: new ButtonSetup("Log In").ToCollection()).Add( FormItemList.CreateStack( items: new TextControl( "", true, setup: TextControlSetup.CreateObscured(), validationMethod: (postBackValue, validator) => { // NOTE: Using a single password here is a hack. The real solution is being able to use System Manager credentials, which is a goal. var passwordMatch = postBackValue == ConfigurationStatics.SystemGeneralProvider.IntermediateLogInPassword; if (!passwordMatch) { validator.NoteErrorAndAddMessage("Incorrect password."); } }).ToFormItem(label: "Enter your password for this non-live installation".ToComponents()) .ToCollection())))); }
/// <summary> /// Creates a duration control. /// </summary> /// <param name="value"></param> /// <param name="allowEmpty"></param> /// <param name="setup">The setup object for the duration control.</param> /// <param name="validationMethod">The validation method. Pass null if you’re only using this control for page modification.</param> public DurationControl(TimeSpan?value, bool allowEmpty, DurationControlSetup setup = null, Action <TimeSpan?, Validator> validationMethod = null) { setup = setup ?? DurationControlSetup.Create(); var textControl = new TextControl( value.HasValue ? Math.Floor(value.Value.TotalHours).ToString("0000") + ":" + value.Value.Minutes.ToString("00") : "", allowEmpty, setup: setup.IsReadOnly ? TextControlSetup.CreateReadOnly(validationPredicate: setup.ValidationPredicate, validationErrorNotifier: setup.ValidationErrorNotifier) : TextControlSetup.Create( placeholder: "h:m", action: new SpecifiedValue <FormAction>(setup.Action), valueChangedAction: setup.ValueChangedAction, pageModificationValue: setup.PageModificationValue, validationPredicate: setup.ValidationPredicate, validationErrorNotifier: setup.ValidationErrorNotifier), validationMethod: validationMethod == null ? (Action <string, Validator>)null : (postBackValue, validator) => { if (tooLongOrInvalidCharacters(postBackValue)) { validator.NoteErrorAndAddMessage("Please enter a valid duration."); setup.ValidationErrorNotifier?.Invoke(); return; } var errorHandler = new ValidationErrorHandler("duration"); var validatedValue = validator.GetNullableTimeSpan(errorHandler, parseTimeSpan(postBackValue), allowEmpty); if (errorHandler.LastResult != ErrorCondition.NoError) { setup.ValidationErrorNotifier?.Invoke(); return; } validationMethod(validatedValue, validator); }); Labeler = textControl.Labeler; PageComponent = new CustomPhrasingComponent( new DisplayableElement( context => new DisplayableElementData( setup.DisplaySetup, () => new DisplayableElementLocalData( "span", focusDependentData: new DisplayableElementFocusDependentData( includeIdAttribute: true, jsInitStatements: "{0}.blur( function() {{ {1} }} ).keypress( function( e ) {{ {2} }} ).focus( function() {{ {3} }} ).mouseup( function( e ) {{ {4} }} );" .FormatWith( getTextControlExpression(context.Id), "ApplyTimeSpanFormat( this );", "if( !NumericalOnly( e, this ) ) e.preventDefault();", "this.value = this.value.replace( ':', '' ); this.select();", "e.preventDefault();"))), classes: elementClass.Add(setup.Classes ?? ElementClassSet.Empty), children: textControl.PageComponent.ToCollection())).ToCollection()); Validation = textControl.Validation; }
/// <summary> /// Creates a text control. /// </summary> /// <param name="setup">The setup object for the control. Do not pass null.</param> /// <param name="validationMethod">A function that validates the value entered by the user and returns a result. Do not pass null.</param> public static NavFormControl CreateText(NavFormControlSetup setup, Func <string, NavFormControlValidationResult> validationMethod) => new NavFormControl( setup, validationResultHandler => { return(new TextControl( "", false, setup: setup.AutoCompleteResource != null ? TextControlSetup.CreateAutoComplete(setup.AutoCompleteResource, placeholder: setup.Placeholder, triggersActionWhenItemSelected: true) : TextControlSetup.Create(placeholder: setup.Placeholder), validationMethod: (postBackValue, validator) => validationResultHandler(validationMethod(postBackValue), validator))); });
/// <summary> /// Creates a text control. /// </summary> /// <param name="value">Do not pass null.</param> /// <param name="allowEmpty"></param> /// <param name="setup">The setup object for the text control.</param> /// <param name="maxLength">The maximum number of characters a user can input.</param> /// <param name="validationMethod">The validation method. Pass null if you’re only using this control for page modification.</param> public TextControl( string value, bool allowEmpty, TextControlSetup setup = null, int?maxLength = null, Action <string, Validator> validationMethod = null) { setup = setup ?? TextControlSetup.Create(); (Labeler, PageComponent, Validation) = setup.LabelerAndComponentAndValidationGetter( value, allowEmpty, null, maxLength, (postBackValue, validator) => postBackValue, validationMethod); }
protected override PageContent getContent() { var body = new DataValue <string>(); return(FormState.ExecuteWithDataModificationsAndDefaultAction( PostBack.CreateFull( modificationMethod: () => { var message = new EmailMessage { Subject = "Support request from {0} in {1}".FormatWith( AppTools.User.FriendlyName.Any() ? AppTools.User.FriendlyName : AppTools.User.Email, ConfigurationStatics.SystemDisplayName), BodyHtml = body.Value.GetTextAsEncodedHtml() }; message.ReplyToAddresses.Add(new EmailAddress(AppTools.User.Email, AppTools.User.FriendlyName)); message.ToAddresses.AddRange(EmailStatics.GetAdministratorEmailAddresses()); EmailStatics.SendEmailWithDefaultFromAddress(message); AddStatusMessage(StatusMessageType.Info, "Your message has been sent."); }, actionGetter: () => new PostBackAction(new ExternalResource(ReturnUrl))) .ToCollection(), () => new UiPageContent(contentFootActions: new ButtonSetup("Send Message").ToCollection()) .Add(new Paragraph("You may report any problems, make suggestions, or ask for help here.".ToComponents())) .Add( FormItemList.CreateStack( items: new EmailAddress(AppTools.User.Email, AppTools.User.FriendlyName).ToMailAddress() .ToString() .ToComponents() .ToFormItem(label: "From".ToComponents()) .Append( "{0} ({1} for this system)".FormatWith( StringTools.GetEnglishListPhrase(EmailStatics.GetAdministratorEmailAddresses().Select(i => i.DisplayName), true), "support contacts".ToQuantity(EmailStatics.GetAdministratorEmailAddresses().Count(), showQuantityAs: ShowQuantityAs.None)) .ToComponents() .ToFormItem(label: "To".ToComponents())) .Append( body.ToTextControl(false, setup: TextControlSetup.Create(numberOfRows: 10), value: "").ToFormItem(label: "Message".ToComponents())) .Materialize())))); }
private NumericTextControlSetup(TextControlSetup textControlSetup, Action validationErrorNotifier) { TextControlSetup = textControlSetup; ValidationErrorNotifier = validationErrorNotifier; }
private UrlControlSetup(TextControlSetup textControlSetup) { TextControlSetup = textControlSetup; }
private TelephoneNumberControlSetup(TextControlSetup textControlSetup) { TextControlSetup = textControlSetup; }
/// <summary> /// Creates a date-and-time control. /// </summary> /// <param name="value"></param> /// <param name="allowEmpty"></param> /// <param name="setup">The setup object for the date-and-time control.</param> /// <param name="minValue">The earliest acceptable date.</param> /// <param name="maxValue">The latest acceptable date.</param> /// <param name="validationMethod">The validation method. Pass null if you’re only using this control for page modification.</param> public DateAndTimeControl( LocalDateTime?value, bool allowEmpty, DateAndTimeControlSetup setup = null, LocalDate?minValue = null, LocalDate?maxValue = null, Action <LocalDateTime?, Validator> validationMethod = null) { setup = setup ?? DateAndTimeControlSetup.Create(); var textControl = new TextControl( value.HasValue ? value.Value.ToDateTimeUnspecified().ToMonthDayYearString() + " " + value.Value.ToDateTimeUnspecified().ToHourAndMinuteString() : "", allowEmpty, setup: setup.IsReadOnly ? TextControlSetup.CreateReadOnly(validationPredicate: setup.ValidationPredicate, validationErrorNotifier: setup.ValidationErrorNotifier) : TextControlSetup.Create( autoFillTokens: setup.AutoFillTokens, action: new SpecifiedValue <FormAction>(setup.Action), valueChangedAction: setup.ValueChangedAction, pageModificationValue: setup.PageModificationValue, validationPredicate: setup.ValidationPredicate, validationErrorNotifier: setup.ValidationErrorNotifier), validationMethod: validationMethod == null ? (Action <string, Validator>)null : (postBackValue, validator) => { var errorHandler = new ValidationErrorHandler("date and time"); var validatedValue = validator.GetNullableDateTime( errorHandler, postBackValue.ToUpper(), TewlContrib.DateTimeTools.MonthDayYearFormats.Select(i => i + " " + TewlContrib.DateTimeTools.HourAndMinuteFormat).ToArray(), allowEmpty, minValue?.ToDateTimeUnspecified() ?? DateTime.MinValue, maxValue?.PlusDays(1).ToDateTimeUnspecified() ?? DateTime.MaxValue); if (errorHandler.LastResult != ErrorCondition.NoError) { setup.ValidationErrorNotifier?.Invoke(); return; } validationMethod( validatedValue.HasValue ? (LocalDateTime?)LocalDateTime.FromDateTime(validatedValue.Value) : null, validator); }); Labeler = textControl.Labeler; PageComponent = new CustomPhrasingComponent( new DisplayableElement( context => new DisplayableElementData( setup.DisplaySetup, () => new DisplayableElementLocalData( "span", focusDependentData: new DisplayableElementFocusDependentData( includeIdAttribute: true, jsInitStatements: "{0}.datetimepicker( {{ {1} }} );".FormatWith( getTextControlExpression(context.Id), StringTools.ConcatenateWithDelimiter( ", ", minValue.HasValue ? "minDate: {0}".FormatWith("new Date( {0}, {1} - 1, {2} )".FormatWith(minValue.Value.Year, minValue.Value.Month, minValue.Value.Day)) : "", maxValue.HasValue ? "maxDate: {0}".FormatWith("new Date( {0}, {1} - 1, {2} )".FormatWith(maxValue.Value.Year, maxValue.Value.Month, maxValue.Value.Day)) : "", "timeFormat: 'h:mmt'", "stepMinute: {0}".FormatWith(setup.MinuteInterval.Value))))), classes: elementClass.Add(setup.Classes ?? ElementClassSet.Empty), children: textControl.PageComponent.ToCollection() .Concat( setup.IsReadOnly ? Enumerable.Empty <PhrasingComponent>() : new EwfButton( new CustomButtonStyle( children: new GenericPhrasingContainer( new FontAwesomeIcon("fa-calendar-o", "fa-stack-2x").ToCollection() .Append(new FontAwesomeIcon("fa-clock-o", "fa-stack-1x")) .Materialize(), classes: new ElementClass("fa-stack")).ToCollection()), behavior: new CustomButtonBehavior(() => "{0}.datetimepicker( 'show' );".FormatWith(getTextControlExpression(context.Id))), classes: new ElementClass("icon")).ToCollection()) .Materialize())).ToCollection()); Validation = textControl.Validation; }
/// <summary> /// Creates a simple HTML editor. /// </summary> /// <param name="value">Do not pass null.</param> /// <param name="allowEmpty"></param> /// <param name="validationMethod">The validation method. Do not pass null.</param> /// <param name="setup">The setup object for the HTML editor.</param> /// <param name="maxLength"></param> public WysiwygHtmlEditor( string value, bool allowEmpty, Action <string, Validator> validationMethod, WysiwygHtmlEditorSetup setup = null, int?maxLength = null) { setup = setup ?? new WysiwygHtmlEditorSetup(); var id = new ElementId(); FormValue <string> formValue = null; formValue = new FormValue <string>( () => value, () => setup.IsReadOnly ? "" : id.Id, v => v, rawValue => { if (rawValue == null) { return(PostBackValueValidationResult <string> .CreateInvalid()); } // This hack prevents the NewLine that CKEditor seems to always add to the end of the textarea from causing // ValueChangedOnPostBack to always return true. if (rawValue.EndsWith(Environment.NewLine) && rawValue.Remove(rawValue.Length - Environment.NewLine.Length) == formValue.GetDurableValue()) { rawValue = formValue.GetDurableValue(); } return(PostBackValueValidationResult <string> .CreateValid(rawValue)); }); var modificationValue = new PageModificationValue <string>(); PageComponent = new ElementComponent( context => { var displaySetup = setup.DisplaySetup ?? new DisplaySetup(true); displaySetup.AddJsShowStatements(getJsShowStatements(context.Id, false, setup.CkEditorConfiguration)); displaySetup.AddJsHideStatements("CKEDITOR.instances.{0}.destroy(); $( '#{0}' ).css( 'display', 'none' );".FormatWith(context.Id)); return(new ElementData( () => { var attributes = new List <ElementAttribute>(); if (setup.IsReadOnly) { attributes.Add(new ElementAttribute("disabled")); } else { attributes.Add(new ElementAttribute("name", context.Id)); } if (!displaySetup.ComponentsDisplayed) { attributes.Add(new ElementAttribute("style", "display: none")); } return new ElementLocalData( "textarea", new FocusabilityCondition(!setup.IsReadOnly), isFocused => new ElementFocusDependentData( attributes: attributes, includeIdAttribute: true, jsInitStatements: displaySetup.ComponentsDisplayed ? getJsShowStatements(context.Id, isFocused, setup.CkEditorConfiguration) : "")); }, clientSideIdReferences: id.ToCollection(), children: new TextNode(() => TextControlSetup.GetTextareaValue(modificationValue.Value)).ToCollection())); }, formValue: formValue); formValue.AddPageModificationValue(modificationValue, v => v); Validation = formValue.CreateValidation( (postBackValue, validator) => { if (setup.ValidationPredicate != null && !setup.ValidationPredicate(postBackValue.ChangedOnPostBack)) { return; } var errorHandler = new ValidationErrorHandler("HTML"); var validatedValue = maxLength.HasValue ? validator.GetString(errorHandler, postBackValue.Value, allowEmpty, maxLength.Value) : validator.GetString(errorHandler, postBackValue.Value, allowEmpty); if (errorHandler.LastResult != ErrorCondition.NoError) { setup.ValidationErrorNotifier?.Invoke(); return; } validationMethod(validatedValue, validator); }); }
private EmailAddressControlSetup(TextControlSetup textControlSetup) { TextControlSetup = textControlSetup; }
/// <summary> /// Creates a time control. /// </summary> /// <param name="value"></param> /// <param name="allowEmpty"></param> /// <param name="setup">The setup object for the time control.</param> /// <param name="minValue">The earliest allowed time.</param> /// <param name="maxValue">The latest allowed time. This can be earlier than <paramref name="minValue"/> to create a range spanning midnight.</param> /// <param name="minuteInterval">Allows the user to select values only in the given increments. Be aware that other values can still be sent from the /// browser via a crafted request.</param> /// <param name="validationMethod">The validation method. Pass null if you’re only using this control for page modification.</param> public TimeControl( LocalTime?value, bool allowEmpty, TimeControlSetup setup = null, LocalTime?minValue = null, LocalTime?maxValue = null, int minuteInterval = 15, Action <LocalTime?, Validator> validationMethod = null) { setup = setup ?? TimeControlSetup.Create(); minValue = minValue ?? LocalTime.Midnight; if (minuteInterval < 30) { var textControl = new TextControl( value.HasValue ? new TimeSpan(value.Value.TickOfDay).ToTimeOfDayHourAndMinuteString() : "", allowEmpty, setup: setup.IsReadOnly ? TextControlSetup.CreateReadOnly(validationPredicate: setup.ValidationPredicate, validationErrorNotifier: setup.ValidationErrorNotifier) : TextControlSetup.Create( autoFillTokens: setup.AutoFillTokens, action: new SpecifiedValue <FormAction>(setup.Action), valueChangedAction: setup.ValueChangedAction, pageModificationValue: setup.PageModificationValue, validationPredicate: setup.ValidationPredicate, validationErrorNotifier: setup.ValidationErrorNotifier), validationMethod: validationMethod == null ? (Action <string, Validator>)null : (postBackValue, validator) => { var errorHandler = new ValidationErrorHandler("time"); var validatedValue = validator.GetNullableTimeOfDayTimeSpan( errorHandler, postBackValue.ToUpper(), TewlContrib.DateTimeTools.HourAndMinuteFormat.ToCollection().ToArray(), allowEmpty) .ToNewUnderlyingValue(v => LocalTime.FromTicksSinceMidnight(v.Ticks)); if (errorHandler.LastResult != ErrorCondition.NoError) { setup.ValidationErrorNotifier?.Invoke(); return; } var wrap = maxValue < minValue.Value; if (!wrap ? validatedValue < minValue.Value || validatedValue > maxValue : validatedValue < minValue.Value && validatedValue > maxValue) { validator.NoteErrorAndAddMessage("The time is too early or too late."); setup.ValidationErrorNotifier?.Invoke(); return; } validationMethod(validatedValue, validator); }); Labeler = textControl.Labeler; PageComponent = new DisplayableElement( context => new DisplayableElementData( setup.DisplaySetup, () => new DisplayableElementLocalData( "div", focusDependentData: new DisplayableElementFocusDependentData( includeIdAttribute: true, jsInitStatements: "{0}.timepicker( {{ {1} }} );".FormatWith( getTextControlExpression(context.Id), StringTools.ConcatenateWithDelimiter( ", ", "timeFormat: 'h:mmt'", "stepMinute: {0}".FormatWith(minuteInterval), "showButtonPanel: false")))), classes: elementClass.Add(setup.Classes ?? ElementClassSet.Empty), children: textControl.PageComponent.ToCollection() .Concat( setup.IsReadOnly ? Enumerable.Empty <PhrasingComponent>() : new EwfButton( new CustomButtonStyle(children: new FontAwesomeIcon("fa-clock-o").ToCollection()), behavior: new CustomButtonBehavior(() => "{0}.timepicker( 'show' );".FormatWith(getTextControlExpression(context.Id))), classes: new ElementClass("icon")).ToCollection()) .Materialize())); Validation = textControl.Validation; } else { var items = from time in getTimes(minValue.Value, maxValue, minuteInterval) let timeSpan = new TimeSpan(time.TickOfDay) select SelectListItem.Create <LocalTime?>(time, timeSpan.ToTimeOfDayHourAndMinuteString()); var selectList = SelectList.CreateDropDown( setup.IsReadOnly ? DropDownSetup.CreateReadOnly( items, placeholderText: "", validationPredicate: setup.ValidationPredicate, validationErrorNotifier: setup.ValidationErrorNotifier) : DropDownSetup.Create( items, placeholderText: "", autoFillTokens: setup.AutoFillTokens, action: new SpecifiedValue <FormAction>(setup.Action), selectionChangedAction: setup.ValueChangedAction, validationPredicate: setup.ValidationPredicate, validationErrorNotifier: setup.ValidationErrorNotifier), value, placeholderIsValid: allowEmpty, validationMethod: validationMethod); Labeler = selectList.Labeler; PageComponent = new GenericFlowContainer( selectList.PageComponent.ToCollection(), displaySetup: setup.DisplaySetup, classes: elementClass.Add(setup.Classes ?? ElementClassSet.Empty)); Validation = selectList.Validation; } }