webconfig
Main package containing all neccesarry functions
See Also
settings.aliases
for shorter UDAs
Examples
enum FavoriteFood
{
// enum UDAs require at least dmd 2.082.0
//dfmt off
@settingTranslation(null, "Fish") @settingTranslation("de", "Fisch") @settingTranslation("ja", "魚")
fish,
@settingTranslation(null, "Meat") @settingTranslation("de", "Fleisch") @settingTranslation("ja", "肉")
meat,
@settingTranslation(null, "Vegetables") @settingTranslation("de", "Gemüse") @settingTranslation("ja", "野菜")
vegetables,
@settingTranslation(null, "Fruits") @settingTranslation("de", "Obst") @settingTranslation("ja", "フルーツ")
fruit
//dfmt on
}
//dfmt off
enum Country
{
none, AF, AX, AL, DZ, AS, AD, AO, AI, AQ, AG, AR, AM, AW, AC, AU, AT, AZ, BS, BH, BD, BB, BY, BE, BZ, BJ, BM,
BT, BO, BA, BW, BR, IO, VG, BN, BG, BF, BI, KH, CM, CA, IC, CV, BQ, KY, CF, EA, TD, CL, CN, CX, CC, CO, KM,
CG, CD, CK, CR, CI, HR, CU, CW, CY, CZ, DK, DG, DJ, DM, DO, EC, EG, SV, GQ, ER, EE, ET, FK, FO, FJ, FI, FR,
GF, PF, TF, GA, GM, GE, DE, GH, GI, GR, GL, GD, GP, GU, GT, GG, GN, GW, GY, HT, HN, HK, HU, IS, IN, ID, IR,
IQ, IE, IM, IL, IT, JM, JP, JE, JO, KZ, KE, KI, XK, KW, KG, LA, LV, LB, LS, LR, LY, LI, LT, LU, MO, MK, MG,
MW, MY, MV, ML, MT, MH, MQ, MR, MU, YT, MX, FM, MD, MC, MN, ME, MS, MA, MZ, MM, NA, NR, NP, NL, NC, NZ, NI,
NE, NG, NU, NF, KP, MP, NO, OM, PK, PW, PS, PA, PG, PY, PE, PH, PN, PL, PT, PR, QA, RE, RO, RU, RW, WS, SM,
ST, SA, SN, RS, SC, SL, SG, SX, SK, SI, SB, SO, ZA, GS, KR, SS, ES, LK, BL, SH, KN, LC, MF, PM, VC, SD, SR,
SJ, SZ, SE, CH, SY, TW, TJ, TZ, TH, TL, TG, TK, TO, TT, TA, TN, TR, TM, TC, TV, UM, VI, UG, UA, AE, GB, US,
UY, UZ, VU, VA, VE, VN, WF, EH, YE, ZM, ZW
}
//dfmt on
enum SocialMedia
{
twitter = 1 << 0,
facebook = 1 << 1,
myspace = 1 << 2,
}
struct Config
{
@requiredSetting // Must be filled out
@nonAutomaticSetting // Don't auto sync when typing
@emailSetting @settingPlaceholder("you@example.com") string userEmail;
bool married;
@urlSetting @settingLength(64) string resourceURI;
// OR
@settingLength(64) URL myWebsite;
@multilineSetting @settingLength(1000) string aboutMe;
@rangeSetting @settingRange(0, 10) int rating;
@timeSetting string favoriteTimeOfDay;
// OR
TimeOfDay leastFavoriteTimeOfDay;
@weekSetting string bestWeekYouHad;
@monthSetting string firstMonthOfWork;
// Timezone-less
@datetimeLocalSetting string birthdayTimeAndDate;
// OR
DateTime myChildsBirthdayTimeAndDate;
@dateSetting string myMothersBirthday;
// OR
Date myFathersBirthday;
// inserts some html before some element
@settingHTML("<hr/><p>Some cooler information now follows.</p>")
@colorSetting @settingClass("wide") string favoriteColor;
@disabledSetting string someInformation = "Just a hint, nothing changable";
Country favoriteCountry;
@settingTranslation("de", "Lieblingsessen") // Translation of labels (only in translation contexts inside web interfaces)
@settingTranslation("ja", "好きな食べ物") // translations require at least vibe.d 0.8.1-alpha.3 to work
@optionsSetting FavoriteFood favoriteFood;
BitFlags!SocialMedia usedSocialMedia;
@settingTitle("If you don't have any you can still say 1 because you have yourself.") // Hover & validation text
@settingMin(1) int numberOfFriends;
@settingRange(0, 100) @settingStep(0.1) double englishSkillLevelPercentage;
@settingMax(10) ubyte orderedProductCount;
@settingLabel("Accept terms of service") @requiredSetting bool acceptTOS;
@settingPattern(`(ISBN\s+)?\d{3}-\d-\d{5}-\d{3}-\d`) string favoriteBookISBN;
@settingRows(8) string[] someStrings;
}
import vibe.vibe;
auto router = new URLRouter;
router.get("/style.css", serveStaticFile("styles/material.css"));
router.get("/", staticRedirect("/settings"));
enum html = `<html>
<head>
<title>Settings</title>
<meta charset="utf-8"/>
<link rel="stylesheet" href="/style.css"/>
<style>
body,html{background:#efefef;color:rgba(0,0,0,0.87);font-family:Roboto,"Segoe UI",sans-serif;}
.settings{background:white;border-radius:2px;padding:16px;margin:32px auto;box-shadow:0 2px 5px rgba(0,0,0,0.3);max-width:600px;}
</style>
</head>
<body>
<div class="settings">
<h2>Settings</h2>
%s
</div>
</body>
</html>`;
struct TranslationContext
{
import std.meta;
alias languages = AliasSeq!("en", "de", "ja");
}
Config settingsInstance; // You might fetch & save this per user, web-config only changes the struct
@translationContext!TranslationContext class SettingsInterface
{
@safe void getSettings(scope HTTPServerRequest req, scope HTTPServerResponse res)
{
string settings = renderSettings(settingsInstance);
res.writeBody(html.format(settings), "text/html");
}
@safe void postSettings(scope HTTPServerRequest req, scope HTTPServerResponse res)
{
// no-js & nonautomatic setting route
auto ret = req.processSettings(settingsInstance);
string settings = renderSettings(settingsInstance, ret);
if (ret)
{
// Something changed, you can save here
}
res.writeBody(html.format(settings), "text/html");
}
@path("/api/setting") @safe void postJsSettings(scope HTTPServerRequest req,
scope HTTPServerResponse res)
{
// js route called for each individual setting
if (req.processSettings(settingsInstance))
{
// Save settings
res.writeBody("", 204); // Send 200 or 204
}
else
res.writeBody("", HTTPStatus.badRequest);
}
}
router.registerWebInterface(new SettingsInterface);
auto httpSettings = new HTTPServerSettings;
httpSettings.port = 8080;
listenHTTP(httpSettings, router);
runApplication();
-
Declaration
@safe string
renderSettings
(T, InputGenerator = DefaultInputGenerator, string javascript = DefaultJavascriptCode)(Tvalue
, stringformAttributes
= "", stringaction
= "/settings", stringmethod
= "POST", stringjsAction
= "/api/setting");
@safe stringrenderSettings
(T, InputGenerator = DefaultInputGenerator, string javascript = DefaultJavascriptCode)(Tvalue
, ulongset
, stringformAttributes
= "", stringaction
= "/settings", stringmethod
= "POST", stringjsAction
= "/api/setting");Generates a HTML form for a configuration struct
T
with automatic instant updates using AJAX. The fields can be annotated with the various UDAs found in this module. (setting enums + structs)
Supported types:enum
(drop down lists or radio box lists),std.typecons.BitFlags
(checkbox lists),bool
(checkbox), string types (text, email, url, etc.), numeric types (number),std.datetime.DateTime
(datetime-local),std.datetime.Date
(date),std.datetime.TimeOfDay
(time),vibe.inet.URL
(url),string[]
(textarea taking each line)Parameters
T
the config struct type.
InputGenerator
the input generator to use.
javascript
the javascript code to embed including script tag.
T
value
an existing config
value
to prefill the inputs.ulong
set
a bitflag field which settings have been
set
properly. Any bitset
to 0 will show an error string for the given field. Defaults to all success.string
formAttributes
extra HTML to put into the form.
string
action
Path to the form submit HTTP endpoint.
string
method
Method to use for the submit HTTP endpoint. Also replaces {
method
} inside the javascript template.string
jsAction
Path to the javascript form submit HTTP endpoint. Replaces {
action
} inside the javascript template. If empty then no js will be emitted. -
Declaration
@safe string
renderSetting
(InputGenerator = DefaultInputGenerator, string name, Config)(ref Configconfig
, boolsuccess
= true);Generates a single input
-
Declaration
@safe ulong
processSettings
(T)(scope HTTPServerRequestreq
, ref Tconfig
, boolstrict
= false, boolpost
= true);
@safe boolprocessSetting
(string name, Config)(HTTPServerRequestreq
, ref Configconfig
, boolstrict
= false, boolpost
= true);Function processing user input and validating for correctness.
The following validations are done:
If the setting is adisabledSetting
, it will always skip this field.
If the setting has asettingPattern
, it will validate the raw value (no matter what type) against this regex.
If the setting is a number, std.conv.to will be used to try to convert it to a double and then it will be cast to the type after checking min/max/step.
If the setting is aBitFlags!T
every passed argument will be checked if it is contained inside the enumT
or when submitted via JS only the one specified argument will get validated and inverted if starting with!
If the setting is an enum the value will be checked if it is contained inside the enum.
Additionally if the setting is a floating point number and there hasn't been a min/max setup but it is arangeSetting
, the number will be finite.
Integral numbers will always be checked if finite & if no range is given they will be clamped.
Attributes for strings:
emailSetting
is validated usingstd.net.isemail.isEmail(CheckDns.no, EmailStatusCode.any)
urlSetting
is validated usingvibe.inet.url.URL
timeSetting
is checked against pattern00:00
+ checking if 0 <= hour < 24 && 0 <= minute < 60
weekSetting
is checked against pattern0{4,6}-W00
+ checking if 1 <= year <= 200000 && 1 <= week <= 52
monthSetting
is checked against pattern0{4,6}-00
+ checking if 1 <= year <= 200000 && 1 <= month <= 12
datetimeLocalSetting
is checked against pattern0000-00-00T00:00
+ passing intostd.datetime.SysTime.fromISOExtString
`
dateSetting
is checked against pattern0000-00-00
+ checking the date usingstd.datetime.Date
colorSetting
is checked against pattern#FFFFFF
Values using these attributes can be used without the need to validate the input.Parameters
bool
strict
if
false
, values will be fixed to conform to the input instead of discarding them. Currently only fixing numbers and string lengths and new lines in single line strings is implemented.Return Value
a bit array where each bit represents an input and is set to 1 if valid
-
Declaration
@safe bool
validateTimeString
(strings
);Validates
s
== pattern "00:00" -
Declaration
@safe bool
validateWeekString
(strings
);Validates
s
== pattern "0{4,6}-W00" -
Declaration
@safe bool
validateMonthString
(strings
);Validates
s
== pattern "0{4,6}-00" -
Declaration
@safe bool
validateDatetimeLocalString
(strings
);Validates
s
== pattern "0000-00-00T00:00" -
Declaration
@safe bool
validateDateString
(strings
);Validates
s
== pattern "0000-00-00" -
Declaration
@safe bool
validateColorString
(strings
);Validates
s
== pattern "#xxxxxx" -
Declaration
@safe string
makeHumanName
(stringidentifier
);Converts correctBookISBN_number to "Correct Book ISBN Number"
-
Declaration
struct
DefaultInputGenerator
;Controls how the input HTML is generated
-
Declaration
static @safe string
textfield
(stringname
, stringtype
, stringvalue
, stringraw
, boolsuccess
, string[]classes
);Called for single line input types
-
Declaration
static @safe string
textarea
(stringname
, stringvalue
, stringraw
, boolsuccess
, string[]classes
);Called for textareas
-
Declaration
static @safe string
checkbox
(stringname
, boolchecked
, stringraw
, boolsuccess
, string[]classes
);Called for boolean values
-
Declaration
string
dropdownList
(Enum, translations...)(stringname
, Enumvalue
, stringraw
, boolsuccess
, string[]classes
);Called for enums disabled as select (you need to iterate over the enum members)
-
Declaration
string
optionList
(Enum, translations...)(stringname
, Enumvalue
, stringraw
, boolsuccess
, string[]classes
);Called for enums displayed as list of radio boxes (you need to iterate over the enum members)
-
Declaration
string
checkboxList
(Enum, translations...)(stringname
, BitFlags!Enumvalue
, stringraw
, boolsuccess
, string[]classes
);Called for BitFlags displayed as list of checkboxes.
-
-
Declaration
enum
emailSetting
;Adds type="email" to string types
-
Declaration
enum
urlSetting
;Adds type="url" to string types
-
Declaration
enum
passwordSetting
;Adds type="password" to string types
-
Declaration
enum
multilineSetting
;Makes string types textareas
-
Declaration
enum
rangeSetting
;Adds type="range" to numeric types
-
Declaration
enum
timeSetting
;Adds type="time" to string types
-
Declaration
enum
weekSetting
;Adds type="week" to string types
-
Declaration
enum
monthSetting
;Adds type="month" to string types
-
Declaration
enum
datetimeLocalSetting
;Adds type="datetime-local" to string types
-
Declaration
enum
dateSetting
;Adds type="date" to string types
-
Declaration
enum
colorSetting
;Adds type="color" to string types
-
Declaration
enum
disabledSetting
;Adds disabled to any input
-
Declaration
enum
requiredSetting
;Adds required to any input
-
Declaration
enum
nonAutomaticSetting
;Disables automatic JS saving when changing the input
-
Declaration
enum
optionsSetting
;Changes a dropdown to a radio button list
-
Declaration
struct
settingMin
;Changes the min="" attribute for numerical values
-
Declaration
double
min
;
-
-
Declaration
struct
settingMax
;Changes the max="" attribute for numerical values
-
Declaration
double
max
;
-
-
Declaration
struct
settingStep
;Changes the step="" attribute for numerical values
-
Declaration
double
step
;
-
-
Declaration
struct
settingRange
; -
Declaration
struct
settingLength
; -
Declaration
struct
settingPattern
;Changes the pattern="regex" attribute
-
Declaration
string
regex
;
-
-
Declaration
struct
settingTitle
;Changes the title="" attribute for custom error messages & tooltips
-
Declaration
string
title
;
-
-
Declaration
struct
settingLabel
;Overrides the label of the input
-
Declaration
string
label
;
-
-
Declaration
struct
settingRows
;Sets the number of rows of a textarea
-
Declaration
int
count
;
-
-
Declaration
struct
settingTranslation
; -
Declaration
struct
enumTranslation
;Relables all enum member names for a language. Give
null
as first argument to change the default language-
Declaration
string
language
; -
Declaration
string[]
translations
;
-
-
Declaration
struct
settingHTML
;Inserts raw HTML code before an element.
-
Declaration
string
raw
;
-
-
Declaration
struct
settingClass
;Inserts raw CSS class name for an element.
-
Declaration
string
className
;
-
-
Declaration
struct
formTemplate
;Changes how the form HTML template looks
-
Declaration
string
code
;Contains the std.format formattable template
code
.
Arguments in order are: string action, string method, string formArguments, string html
html is last so you can embed it using %4$s without throwing an orphan arguments exception.
-
-
Declaration
struct
settingPlaceholder
;Sets the placeholder attribute for elements that support it
-
Declaration
string
placeholder
;
-
-
Declaration
enum string
DefaultJavascriptCode
;Contains a updateSetting(input) function which automatically sends changes to the server.