This commit is contained in:
fenris 2026-09-30 08:38:52 +02:00
parent 51c684c896
commit 3ec357ea8f
31 changed files with 1391 additions and 195 deletions

View file

@ -28,7 +28,8 @@
"title": "Vertragskontonummer",
"description": "Die 10-stellige Vertragskontonummer finden Sie auf Ihrer Abrechnung."
}
}
},
"title": "Allgemeine Angaben"
},
"operator_address": {
"type": "object",

View file

@ -2,23 +2,31 @@
"type": "group",
"members": {
"active": {
"type": "checkbox",
"label": "aktiv"
"ioc": {
"type": "checkbox",
"label": "aktiv"
}
},
"name": {
"type": "text",
"label": "Name"
"ioc": {
"type": "text",
"label": "Name"
}
},
"ranks": {
"type": "list",
"element": {
"type": "number"
},
"label": "Rang"
"ioc": {
"type": "list",
"element": {
"type": "number"
},
"label": "Rang"
}
},
"color": {
"type": "color",
"label": "Farbe"
"ioc": {
"type": "color",
"label": "Farbe"
}
}
}
}

View file

@ -1 +1,9 @@
type int = number;
type float = number;
type type_handler<type_value> = (
(type_value)
=>
void
);

51
source/logic/conf.ts Normal file
View file

@ -0,0 +1,51 @@
namespace formgen.conf
{
/**
*/
export type type_data = {
zerez : {
fake : boolean;
base_url : string;
token_url : string;
scope : string;
client_id : string;
client_secret : string;
};
};
/**
*/
var _data : (null | type_data) = null;
/**
*/
export async function initialize(
path : string
) : Promise<void>
{
const content : string = await formgen.helpers.file.read_text(path);
const data : type_data = (formgen.helpers.json.decode(content) as type_data);
_data = data;
}
/**
* @todo sanitize
*/
export function get(
) : type_data
{
if (_data === null)
{
throw (new Error("not initialized"));
}
else
{
return _data;
}
}
}

View file

@ -16,7 +16,7 @@ namespace formgen
/**
*/
private input : formgen.input.interface_input<type_value>;
private input : formgen.ioc.interface_ioc<type_value>;
/**
@ -27,7 +27,7 @@ namespace formgen
/**
*/
public constructor(
input : formgen.input.interface_input<type_value>,
input : formgen.ioc.interface_ioc<type_value>,
actions : Array<type_action>
)
{

View file

@ -11,4 +11,29 @@ namespace formgen.helpers.json
return JSON.parse(json);
}
/**
* @todo handle errors
*/
export function encode(
value : unknown,
{
"formatted": formatted = false,
}
:
{
formatted ?: boolean;
}
=
{
}
) : string
{
return JSON.stringify(
value,
undefined,
(formatted ? " " : undefined)
);
}
}

View file

@ -178,7 +178,7 @@ namespace formgen.helpers.json_schema
export type type_root = (
{
/**
* @see hhttps://json-schema.org/understanding-json-schema/keywords#dollardefs
* @see https://json-schema.org/understanding-json-schema/keywords#dollardefs
*/
$defs : Map<string, type_schema>;
}

View file

@ -0,0 +1,263 @@
namespace formgen.helpers.zerez
{
/**
*/
type type_credentials = {
base_url : string;
token_url : string;
scope : string;
client_id : string;
client_secret : string;
};
/**
*/
var _credentials : type_credentials;
/**
*/
var _token : (null | string) = null;
/**
* @todo set to false/remove
*/
var _fake : boolean = false;
async function get_token(
) : Promise<string>
{
if (_fake)
{
_token = "fake";
return _token;
}
else
{
/**
* this does not work due to CORS restrictions on the zerez server; to solve this, a proxy/backend is be required
*/
if (_token === null)
{
_token = await (
fetch(
_credentials.token_url,
{
"method": "POST",
"headers": {
"Content-Type": "application/x-www-form-urlencoded",
"User-Agent": "Guzzle/4.0 curl/7.21.4 PHP/5.5.7",
},
"body": (
(new URLSearchParams(
{
"grant_type": "client_credentials",
"client_id": _credentials.client_id,
"client_secret": _credentials.client_secret,
"scope": _credentials.scope,
}
))
.toString()
),
}
)
.then(
x => x.json()
)
.then(
x => x["access_token"]
)
.catch(
(error) => Promise.resolve(null)
)
);
if (_token === null)
{
throw (new Error("could not fetch token"));
}
else
{
return _token;
}
}
else
{
return _token;
}
}
}
/**
*/
export async function get_unit(
id : string
) : Promise<any>
{
const bearer : string = await get_token();
if (_fake)
{
return {
"deep_link": "https:\/\/www.zerez.net\/units\/6314260b-364a-4d53-368d-08dd4b5a9353",
"unit_zerez_code": "ZE-EYVQ-5OEX-0001",
"model_number": "ASN-12TL-G2",
"model_name": "ASN-12TL-G2",
"replaced_by_zerez_code": "",
"maximum_active_power_kw": 13.2,
"maximum_apparent_power_kva": 13.3,
"rated_active_power_kw": 12,
"rated_apparent_power_kva": 12,
"maximum_active_power_at_0_9_pf_kw": null,
"rated_voltage_v": 400,
"rated_current_a": 17.3,
"peak_short_circuit_current_a": 50,
"initial_short_circuit_alternating_current_a": 19.1,
"worst_case_operation_scenario_value": 0.74,
"net_feed_in_details": "Three-Phase",
"flicker_system_coefficient_at_30_cu": 2.3,
"flicker_system_coefficient_at_50_cu": 2.3,
"flicker_system_coefficient_at_70_cu": 2.3,
"flicker_system_coefficient_at_85_cu": 2.3,
"max_switch_operations_operation1_n10": null,
"max_number_of_operations_operation1_n120": null,
"voltage_variation_factor_at_operation1_30_kwv": null,
"voltage_variation_factor_at_operation1_50_kwv": null,
"voltage_variation_factor_at_operation1_70_kwv": null,
"voltage_variation_factor_at_operation1_85_kwv": null,
"flicker_step_factor_at_operation1_30_kfv": null,
"flicker_step_factor_at_operation1_50_kfv": null,
"flicker_step_factor_at_operation1_70_kfv": null,
"flicker_step_factor_at_operation1_85_kfv": null,
"max_switch_operations_operation2_n10": null,
"max_number_of_operations_operation2_n120": null,
"voltage_variation_factor_at_operation2_30_kwv": null,
"voltage_variation_factor_at_operation2_50_kwv": null,
"voltage_variation_factor_at_operation2_70_kwv": null,
"voltage_variation_factor_at_operation2_85_kwv": null,
"flicker_step_factor_at_operation2_30_kfv": null,
"flicker_step_factor_at_operation2_50_kfv": null,
"flicker_step_factor_at_operation2_70_kfv": null,
"flicker_step_factor_at_operation2_85_kfv": null,
"max_no_of_switching_operations_operation3_n10": null,
"max_no_of_switching_operations_operation3_n120": null,
"voltage_variation_factor_operation3_30_kuf": null,
"voltage_variation_factor_operation3_50_kuf": null,
"voltage_variation_factor_operation3_70_kuf": null,
"voltage_variation_factor_operation3_85_kuf": null,
"flicker_step_factor_operation3_30_kff": null,
"flicker_step_factor_operation3_50_kff": null,
"flicker_step_factor_operation3_70_kff": null,
"flicker_step_factor_operation3_85_kff": null,
"fast_voltage_change_turn_on_without_specifications": 0.07,
"fast_voltage_change_worst_case_during_generator_stage_switching": 0,
"fast_voltage_change_turn_on_at_rated_conditions": 0.07,
"fast_voltage_change_turn_off_at_rated_power": 0.74,
"min_active_power_range_kW": null,
"max_active_power_range_kW": null,
"min_apparent_power_range_kW": null,
"max_apparent_power_range_kW": null,
"has_switching_operation_1": null,
"has_switching_operation_2": null,
"has_switching_operation_3": null,
"matrix_type": null,
"effective_impedance_reference_point": null,
"temporary_minimum_performance": null,
"date_of_latest_change": "2025-02-26T13:16:37.2828973",
"certificate": {
"deep_link": "https:\/\/www.zerez.net\/certificates\/11f20238-f3ee-475f-a52e-0005575c8f06",
"certificate_number": "4479823053419",
"zerez_id": "ZE-EYVQ-5OEX",
"certificate_type": "",
"replaced_by": "",
"certificate_holder": "Ningbo AUX Solar Technology Co., Ltd.",
"certificate_authority": "T\u00dcV NORD CERT GmbH",
"certificate_norms": [
{
"name": "VDE-AR-N 4105"
}
],
"certificate_validity_status": "Valid \/ Ongoing",
"certificate_issue_date": "2024-11-01T03:17:16.873",
"validity_start_date": null,
"restrictions": "restricted",
"software_environment_version_number": "",
"norms": [
"VDE-AR-N 4105:2018-11"
],
"validity_end_date": null,
"validation_status": "Ongoing Feedback Process",
"category": "Inverter",
"primary_energy_source": "Photovoltaic",
"certificate_files": [
{
"certificate_file_name": "RDPVP0705524B03_E4E5.pdf",
"certificate_file_type": "Cover Sheet",
"certificate_file_description": null,
"certificate_file_storage_location": "\/api\/PublicDownload\/F9565FEDFFF684AD065562A198EF3077.A177478D7D94FCA2FBB486A4B8430B91C91C9B1858261B57B51513DB79BE22D8E74C1917BE5DAD731C45CBC7C9567C62469E3FDEBC000BEACF372411668ADC74EC94218BA4F1858E2C161B7D7DE8893CB52072ABCD63A8012E25C4945DC16475A3FB5498052816FFAEA8A5CBC554A586F5715F4C61DCB455F4E13F9E96763A2B1E8B86414AF98F987B0FED8E4F3B80CA78147CBF02E30BEA7D976776A0DD153399D42E078E7BE0413511EE44F5A5E5E08D7C154B5CC9FEEF8C50F63BDD60453CF7C49AF438621DFFB80BD573BFD8DE4B0FDD1F21E003F595AC8790C0EAEA2F925BF85466CE17142258E42A7C716AC7C9AD24C1A694A114C83BB4AC861DB8C7967BDF5172B71154669B6C4A83ACEFF75BBECB52BA36B885B6DAC3B215E3009E7BD3A5D26481FA24F392B58B0E5FDB01C0632E686964B2BF0556667B18BFB07DF78797FCFC6FFCB19AD785FBB038CA3A500E89E57BDEDE8BFA64F58AE921D89DF80911006448B9A93583C670CCCE0F81C6A18D977EDF62CC640016C7FFE9DA8719DA370F599A9FA51298DBE70FB6A18EF7BD0155625B1A361EB4080F1EBC2DC545987023A9C7EBB83CDC569D4FB3328CC21741D9648A321468DC101037C1D3426DF753E31C15DB29FEC50D3288A4148C1CFC8A217714A8D4B998D172E588D6A94345CF986EFCA32D85C159016CEA79F03DE1F2E90424567B949CA3BFEB78830E4591CBC5A521FA636483866106C19187AF1812D3014B253707E1E484749E7C4F4EEC70E1530C35076A708C12E2A775A47AD73544FD9B68A7DFC8BE33B02EF4987C",
"expiration": "2026-09-29T20:25:43.0561735Z"
},
{
"certificate_file_name": "RDPVP0705524B03_E7.pdf",
"certificate_file_type": "Perturbations Test Report",
"certificate_file_description": null,
"certificate_file_storage_location": "\/api\/PublicDownload\/74EB90CE7416C2085FEE1A996C19F753.5514D632B01CC208B2D1E24EA97950F06F903B12E646F387362D1D32B6753390CDCE5B369973965A275D9EDB5DDEA57E743743E7E1F45C2B23A9D085AECBF2ED627939D75E2747F75665705DEF68A5A325452271B91FB922AD6B96B91C45AE80A142E84ED08658E1FB1D456A5DBDDE3073D3184A80579973D62DE7B035E7B3AFA462449E3DF3FA528078401EC92E7F9C0762D9AA138D0EDFB39D944C15ABF949A2C1ED8C60E37719A63805F3BF16720A7FC304819A5223D58A4DF56FB0A8EA1032D20041C603723DDD09177134E6F413D74FBD519490F2B7DD1B7D72C70E9E652EF1450C314F25343A325886EC55087ED33B98AF335DCACD7E0E8BC40E62CCD9AE9BA5375A772C3A0C2E8B2E21C98297AD66EF46EF28934B4EF16BEBE2D91D01C3CDBBBCB33F65C70253C732550BEAC84F55ACF5BC4BC6B006C87D96319E89DB6FDE4F5774E3B711BB10A23FF66B8BBAAEC09E541AD8A8324CECE399F53283A82079F73CF13E75CD3CB0AE6FFF90C49912C26F8AC3CD3E909E1DFA39B80B009F8187EC723830F55F4AF554A4C3416DADD3E71CA8F132EBFC9F335015BFD8DF78C2357AC4D784B8A26983EF202819921C28E6D7C16D46F8D047E771927691F25EAF8AA9735993B2D6C87E792F5156014F448295CF6C725F7ADF7ACFA17D9DDCC19A4C772BFC3816817E37A8F180F98FAF13BB84831EB9419A47EF5A21B56F92C0747341BCADD2AA399AB23FAAA945C4AF2F84A4EABED27364487E940F6DF44E2E569826DAE6BFE2D3892525308615886E561AACD9A5D44F816443A145EA9B6DF3",
"expiration": "2026-09-29T20:25:43.0562281Z"
}
],
"date_of_latest_change": "2025-02-26T13:16:36.7226181"
}
};
}
else
{
return (
fetch(
formgen.helpers.string.coin(
"{{base_url}}/api/v1/units/{{id}}",
{
"base_url": _credentials.base_url,
"id": id,
}
),
{
"headers": {
"Authorization": ("Bearer " + bearer),
"Accept": "application/json",
// "Content-Type": "application/json",
}
}
)
.then(
x => x.json()
)
);
}
}
/**
*/
export async function initialize(
credentials : type_credentials,
{
"fake": fake = false,
}
:
{
fake ?: boolean;
}
=
{
}
) : Promise<void>
{
_credentials = credentials;
_fake = fake;
await get_token();
}
}

View file

@ -1,20 +1,90 @@
namespace formgen.input
namespace formgen.ioc
{
/**
*/
export type type_description = (
{
type : "checkbox";
label ?: (null | string);
}
|
{
type : "number";
label ?: (null | string);
}
|
{
type : "text";
label ?: (null | string);
}
|
{
type : "color";
label ?: (null | string);
}
|
{
type : "select";
options : Array<
{
value : string;
label : (null | string);
}
>;
label ?: (null | string);
}
|
{
type : "list";
element : type_description;
label ?: (null | string);
}
|
{
type : "group";
members : Record<
string,
{
ioc : type_description;
required ?: boolean;
}
>;
label ?: (null | string);
}
|
{
type : "sum";
items : Array<
{
ioc : type_description;
kind ?: (null | string);
label ?: (null | string);
}
>;
label ?: (null | string);
}
|
{
type : "zerez";
}
);
/**
*/
export function from_raw(
raw : any
) : interface_input<unknown>
raw : type_description
) : interface_ioc<unknown>
{
switch (raw.type)
{
case "checkbox":
{
return (
new class_input_checkbox(
new class_ioc_checkbox(
{
"label": formgen.helpers.map.read<(null | string)>(raw, "label", null),
"label": (raw.label ?? null),
}
)
);
@ -23,9 +93,9 @@ namespace formgen.input
case "number":
{
return (
new class_input_number(
new class_ioc_number(
{
"label": formgen.helpers.map.read<(null | string)>(raw, "label", null),
"label": (raw.label ?? null),
}
)
);
@ -34,9 +104,9 @@ namespace formgen.input
case "text":
{
return (
new class_input_text(
new class_ioc_text(
{
"label": formgen.helpers.map.read<(null | string)>(raw, "label", null),
"label": (raw.label ?? null),
}
)
);
@ -45,9 +115,9 @@ namespace formgen.input
case "color":
{
return (
new class_input_color(
new class_ioc_color(
{
"label": formgen.helpers.map.read<(null | string)>(raw, "label", null),
"label": (raw.label ?? null),
}
)
);
@ -56,18 +126,18 @@ namespace formgen.input
case "select":
{
return (
new class_input_select(
new class_ioc_select(
(
raw.options
.map(
(option_raw : Record<string, any>) => ({
"value": option_raw["value"],
"label": (formgen.helpers.map.read<(null | string)>(option_raw, "label", null) ?? String(option_raw["value"])),
(option_raw) => ({
"value": option_raw.value,
"label": (option_raw.label ?? String(option_raw.value)),
})
)
),
{
"label": formgen.helpers.map.read<(null | string)>(raw, "label", null),
"label": (raw.label ?? null),
}
)
);
@ -75,10 +145,10 @@ namespace formgen.input
case "list":
{
return (
new class_input_list(
new class_ioc_list(
() => from_raw(raw.element),
{
"label": formgen.helpers.map.read<(null | string)>(raw, "label", null),
"label": (raw.label ?? null),
}
)
);
@ -87,17 +157,54 @@ namespace formgen.input
case "group":
{
return (
new class_input_group(
new class_ioc_group(
formgen.helpers.list.transform(
formgen.helpers.map.to_pairs(raw.members),
(pair) => ({
"name": pair.key,
"input": from_raw(pair.value),
"marked": (pair.value["required"] ?? false),
"ioc": from_raw(pair.value.ioc),
"marked": (pair.value.required ?? false),
})
),
{
"label": formgen.helpers.map.read<(null | string)>(raw, "label", null),
"label": (raw.label ?? null),
}
)
);
break;
}
case "sum":
{
return (
new class_ioc_sum(
formgen.helpers.list.transform(
raw.items,
(raw_item) => ({
"ioc": from_raw(raw_item.ioc),
"kind": raw_item.kind,
"label": raw_item.label,
})
),
{
"label": (raw.label ?? null),
}
)
);
break;
}
case "zerez":
{
return (
new class_ioc_zerez(
/**
* @todo outsource?
*/
async (id) => {
const data_raw : any = await formgen.helpers.zerez.get_unit(id);
return {
"manufacturer": data_raw["certificate"]["certificate_holder"],
"power": data_raw["maximum_active_power_kw"],
};
}
)
);
@ -105,7 +212,7 @@ namespace formgen.input
}
default:
{
throw (new Error("unhandled type: " + raw.type));
throw (new Error("unhandled type " + String(raw)));
break;
}
}
@ -132,7 +239,7 @@ namespace formgen.input
=
{
}
) : interface_input<unknown>
) : interface_ioc<unknown>
{
const schema_adjusted : formgen.helpers.json_schema.type_schema = (() => {
if (! ("$ref" in json_schema))
@ -186,7 +293,7 @@ namespace formgen.input
if ("enum" in schema_adjusted)
{
return (
new class_input_select<any>(
new class_ioc_select<any>(
schema_adjusted.enum.map(
(value, index) => (
{
@ -209,7 +316,7 @@ namespace formgen.input
case "null":
{
return (
new class_input_empty(
new class_ioc_empty(
)
);
break;
@ -217,7 +324,7 @@ namespace formgen.input
case "boolean":
{
return (
new class_input_checkbox(
new class_ioc_checkbox(
{
"label": (schema_adjusted.title ?? fallback_label ?? null),
"hint": (schema_adjusted.description ?? null),
@ -236,7 +343,7 @@ namespace formgen.input
case "integer":
{
return (
new class_input_number(
new class_ioc_number(
{
"label": (schema_adjusted.title ?? fallback_label ?? null),
"hint": (schema_adjusted.description ?? null),
@ -255,7 +362,7 @@ namespace formgen.input
case "number":
{
return (
new class_input_number(
new class_ioc_number(
{
"label": (schema_adjusted.title ?? fallback_label ?? null),
"hint": (schema_adjusted.description ?? null),
@ -279,7 +386,7 @@ namespace formgen.input
case "date":
{
return (
new class_input_date(
new class_ioc_date(
{
"label": (schema_adjusted.title ?? fallback_label ?? null),
"hint": (schema_adjusted.description ?? null),
@ -291,7 +398,7 @@ namespace formgen.input
case "time":
{
return (
new class_input_time(
new class_ioc_time(
{
"label": (schema_adjusted.title ?? fallback_label ?? null),
"hint": (schema_adjusted.description ?? null),
@ -306,7 +413,7 @@ namespace formgen.input
* @todo warning
*/
return (
new class_input_text(
new class_ioc_text(
{
"label": (schema_adjusted.title ?? fallback_label ?? null),
"hint": (schema_adjusted.description ?? null),
@ -320,7 +427,7 @@ namespace formgen.input
else
{
return (
new class_input_text(
new class_ioc_text(
{
"label": (schema_adjusted.title ?? fallback_label ?? null),
"hint": (schema_adjusted.description ?? null),
@ -339,7 +446,7 @@ namespace formgen.input
else
{
return (
new class_input_list(
new class_ioc_list(
() => from_json_schema_inner(
defs,
root,
@ -363,17 +470,25 @@ namespace formgen.input
*/
case "object":
{
if ("properties" in schema_adjusted)
if (
("properties" in schema_adjusted)
&&
! (
("additionalProperties" in schema_adjusted)
&&
(schema_adjusted["additionalProperties"] !== false)
)
)
{
return (
new class_input_group(
new class_ioc_group(
formgen.helpers.list.transform(
formgen.helpers.map.to_pairs<
formgen.helpers.json_schema.type_schema
>(schema_adjusted.properties as Record<string, formgen.helpers.json_schema.type_schema>),
(pair : {key : string, value : formgen.helpers.json_schema.type_schema;}) => ({
"name": pair.key,
"input": from_json_schema_inner(
"ioc": from_json_schema_inner(
defs,
root,
pair.value,
@ -391,6 +506,36 @@ namespace formgen.input
)
);
}
else if (
! ("properties" in schema_adjusted)
&&
(
("additionalProperties" in schema_adjusted)
&&
(schema_adjusted["additionalProperties"] !== false)
)
)
{
return (
new class_ioc_map<unknown>(
() => from_json_schema_inner(
defs,
root,
(schema_adjusted.additionalProperties as formgen.helpers.json_schema.type_schema),
{
/**
* @todo
*/
"fallback_label": null,
"map_unhandled_refs_to_empty": map_unhandled_refs_to_empty,
}
),
{
"label": (schema_adjusted.title ?? fallback_label ?? null),
}
)
);
}
else
{
throw (new Error("unhandled object situation"));
@ -411,13 +556,13 @@ namespace formgen.input
else if ("oneOf" in schema_adjusted)
{
return (
new class_input_sum(
formgen.helpers.list.transform<int, {input : interface_input<any>;}>(
new class_ioc_sum(
formgen.helpers.list.transform<int, {ioc : interface_ioc<any>;}>(
formgen.helpers.list.sequence(schema_adjusted.oneOf.length),
(index) => {
const sub_schema : formgen.helpers.json_schema.type_schema = schema_adjusted.oneOf[index];
return {
"input": from_json_schema_inner(
"ioc": from_json_schema_inner(
defs,
root,
sub_schema,
@ -438,13 +583,13 @@ namespace formgen.input
else if ("anyOf" in schema_adjusted)
{
return (
new class_input_sum(
formgen.helpers.list.transform<int, {input : interface_input<any>;}>(
new class_ioc_sum(
formgen.helpers.list.transform<int, {ioc : interface_ioc<any>;}>(
formgen.helpers.list.sequence(schema_adjusted.anyOf.length),
(index) => {
const sub_schema : formgen.helpers.json_schema.type_schema = schema_adjusted.anyOf[index];
return {
"input": from_json_schema_inner(
"ioc": from_json_schema_inner(
defs,
root,
sub_schema,
@ -487,7 +632,7 @@ namespace formgen.input
=
{
}
) : interface_input<unknown>
) : interface_ioc<unknown>
{
let defs : Map<string, formgen.helpers.json_schema.type_schema> = new Map<string, formgen.helpers.json_schema.type_schema>();
if ("$defs" in root)

View file

@ -1,9 +1,9 @@
namespace formgen.input
namespace formgen.ioc
{
/**
*/
export interface interface_input<type_value>
export interface interface_ioc<type_value>
{
/**
@ -27,6 +27,14 @@ namespace formgen.input
read(
) : Promise<type_value>
;
/**
*/
listen(
handler : type_handler<type_value>
) : void
;
}

View file

@ -0,0 +1,54 @@
namespace formgen.ioc
{
/**
*/
export class trait_notification<type_value>
{
/**
*/
private handlers : Array<type_handler<type_value>>;
/**
*/
public constructor(
handlers : Array<type_handler<type_value>>
)
{
this.handlers = handlers;
}
/**
*/
public listen(
handler : type_handler<type_value>
) : void
{
this.handlers.push(handler);
}
/**
*/
public async notify(
value : type_value
) : Promise<void>
{
return (
Promise.all<void>(
this.handlers.map(
handler => handler(value)
)
)
.then(
() => Promise.resolve<void>(undefined)
)
);
}
}
}

View file

@ -1,9 +1,9 @@
namespace formgen.input
namespace formgen.ioc
{
/**
*/
export class class_input_checkbox implements interface_input<boolean>
export class class_ioc_checkbox implements interface_ioc<boolean>
{
/**
@ -26,6 +26,11 @@ namespace formgen.input
private element_input : (null | Element);
/**
*/
private notification : trait_notification<boolean>;
/**
*/
public constructor(
@ -33,22 +38,25 @@ namespace formgen.input
"additional_classes": additional_classes = [],
"label": label = null,
"hint": hint = null,
"handlers": handlers = [],
}
:
{
additional_classes ?: Array<string>,
label ?: (null | string);
hint ?: (null | string);
handlers ?: Array<type_handler<boolean>>;
}
=
{
}
)
{
this.additional_classes = ["formgen-input-checkbox"].concat(additional_classes);
this.additional_classes = ["formgen-ioc-checkbox"].concat(additional_classes);
this.label = label;
this.hint = hint;
this.element_input = null;
this.notification = new trait_notification(handlers);
}
@ -62,7 +70,7 @@ namespace formgen.input
const id : string = formgen.helpers.string.generate();
const element_container : Element = document.createElement("div");
element_container.classList.add("formgen-input");
element_container.classList.add("formgen-ioc");
for (const class_ of this.additional_classes)
{
element_container.classList.add(class_);
@ -91,6 +99,13 @@ namespace formgen.input
element_input.setAttribute("type", "checkbox");
element_input.setAttribute("id", id);
element_container.appendChild(element_input);
element_input.addEventListener(
"change",
async () => {
const value = await this.read();
await this.notification.notify(value);
}
);
this.element_input = element_input;
}
target.appendChild(element_container);
@ -120,6 +135,17 @@ namespace formgen.input
return Promise.resolve<void>(undefined);
}
/**
* [implementation]
*/
public listen(
handler : type_handler<boolean>
) : void
{
this.notification.listen(handler);
}
}
}

View file

@ -1,10 +1,10 @@
namespace formgen.input
namespace formgen.ioc
{
/**
* @todo dedicated color type
*/
export class class_input_color extends class_input_simple<string>
export class class_ioc_color extends class_ioc_simple<string>
{
/**
@ -33,7 +33,7 @@ namespace formgen.input
{
"label": label,
"hint": hint,
"additional_classes": ["formgen-input-color"].concat(additional_classes),
"additional_classes": ["formgen-ioc-color"].concat(additional_classes),
}
);
}

View file

@ -1,10 +1,10 @@
namespace formgen.input
namespace formgen.ioc
{
/**
* @todo dedicated date type
*/
export class class_input_date extends class_input_simple<string>
export class class_ioc_date extends class_ioc_simple<string>
{
/**
@ -33,7 +33,7 @@ namespace formgen.input
{
"label": label,
"hint": hint,
"additional_classes": ["formgen-input-date"].concat(additional_classes),
"additional_classes": ["formgen-ioc-date"].concat(additional_classes),
}
);
}

View file

@ -1,9 +1,9 @@
namespace formgen.input
namespace formgen.ioc
{
/**
*/
export class class_input_empty implements interface_input<null>
export class class_ioc_empty implements interface_ioc<null>
{
/**
@ -45,6 +45,16 @@ namespace formgen.input
return Promise.resolve<void>(undefined);
}
/**
* [implementation]
*/
public listen(
) : void
{
// do nothing
}
}
}

View file

@ -1,18 +1,18 @@
namespace formgen.input
namespace formgen.ioc
{
/**
*/
type type_field<type_value> = {
name : string;
input : interface_input<type_value>;
ioc : interface_ioc<type_value>;
marked : boolean;
};
/**
*/
export class class_input_group implements interface_input<Record<string, any>>
export class class_ioc_group implements interface_ioc<Record<string, any>>
{
/**
@ -24,6 +24,11 @@ namespace formgen.input
*/
private label : (null | string);
/**
*/
private notification : trait_notification<Record<string, any>>;
/**
*/
@ -31,10 +36,12 @@ namespace formgen.input
fields : Array<type_field<any>>,
{
"label": label = null,
"handlers": handlers = [],
}
:
{
label ?: (null | string);
handlers ?: Array<type_handler<Record<string, any>>>;
}
=
{
@ -43,6 +50,7 @@ namespace formgen.input
{
this.fields = fields;
this.label = label;
this.notification = new trait_notification(handlers);
}
@ -54,8 +62,8 @@ namespace formgen.input
) : Promise<void>
{
const element_container : Element = document.createElement("div");
element_container.classList.add("formgen-input");
element_container.classList.add("formgen-input-group");
element_container.classList.add("formgen-ioc");
element_container.classList.add("formgen-ioc-group");
// label
{
if (this.label === null)
@ -72,14 +80,20 @@ namespace formgen.input
// fields
{
const element_fields : Element = document.createElement("div");
element_fields.classList.add("formgen-input-group-fields");
element_fields.classList.add("formgen-ioc-group-fields");
for (const field of this.fields)
{
const element_field : Element = document.createElement("div");
element_field.classList.add("formgen-input-group-field");
element_field.classList.toggle("formgen-input-group-field-marked", field.marked);
element_field.classList.add("formgen-ioc-group-field");
element_field.classList.toggle("formgen-ioc-group-field-marked", field.marked);
element_field.setAttribute("rel", field.name);
await field.input.setup(element_field);
await field.ioc.setup(element_field);
field.ioc.listen(
async () => {
const value : Record<string, any> = await this.read();
await this.notification.notify(value);
}
);
element_fields.appendChild(element_field);
}
element_container.appendChild(element_fields);
@ -98,7 +112,7 @@ namespace formgen.input
let result : Record<string, any> = {};
for (const field of this.fields)
{
result[field.name] = await field.input.read();
result[field.name] = await field.ioc.read();
}
return result;
}
@ -107,11 +121,24 @@ namespace formgen.input
/**
* [implementation]
*/
public write(
public async write(
value : Record<string, any>
) : Promise<void>
{
return Promise.reject(new Error("not implemented"));
for (const field of this.fields)
{
await field.ioc.write(value[field.name]);
}
}
/**
*/
public listen(
handler : type_handler<Record<string, any>>
) : void
{
this.notification.listen(handler);
}
}

View file

@ -1,23 +1,23 @@
namespace formgen.input
namespace formgen.ioc
{
/**
*/
type type_entry<type_element> = {
id : string;
input : interface_input<type_element>;
input : interface_ioc<type_element>;
element : Element;
};
/**
*/
export class class_input_list<type_element> implements interface_input<Array<type_element>>
export class class_ioc_list<type_element> implements interface_ioc<Array<type_element>>
{
/**
*/
private element_input_factory : (() => interface_input<type_element>);
private element_input_factory : (() => interface_ioc<type_element>);
/**
@ -35,16 +35,23 @@ namespace formgen.input
private entries : Array<type_entry<type_element>>;
/**
*/
private notification : trait_notification<Array<type_element>>;
/**
*/
public constructor(
element_input_factory : (() => interface_input<type_element>),
element_input_factory : (() => interface_ioc<type_element>),
{
"label": label = null,
"handlers": handlers = [],
}
:
{
label ?: (null | string);
handlers ?: Array<type_handler<Array<type_element>>>;
}
=
{
@ -55,6 +62,7 @@ namespace formgen.input
this.label = label;
this.element_entries = null;
this.entries = [];
this.notification = new trait_notification(handlers);
}
@ -76,15 +84,15 @@ namespace formgen.input
) : Promise<void>
{
const id : string = formgen.helpers.string.generate();
const input : interface_input<type_element> = this.element_input_factory();
const input : interface_ioc<type_element> = this.element_input_factory();
const element_entry : Element = document.createElement("div");
element_entry.classList.add("formgen-input-list-entry");
element_entry.classList.add("formgen-ioc-list-entry");
element_entry.setAttribute("rel", id);
// remover
{
const element_remover : Element = document.createElement("button");
element_remover.classList.add("formgen-input-list-action");
element_remover.classList.add("formgen-input-list-acrion-remove");
element_remover.classList.add("formgen-ioc-list-action");
element_remover.classList.add("formgen-ioc-list-acrion-remove");
element_remover.innerHTML = "&dash;";
element_remover.addEventListener(
"click",
@ -98,8 +106,14 @@ namespace formgen.input
// input
{
const element_input : Element = document.createElement("div");
element_input.classList.add("formgen-input-list-entry-input");
element_input.classList.add("formgen-ioc-list-entry-input");
await input.setup(element_input);
input.listen(
async () => {
const value : Array<type_element> = await this.read();
await this.notification.notify(value);
}
);
element_entry.appendChild(element_input);
}
this.entries.push(
@ -121,8 +135,8 @@ namespace formgen.input
) : Promise<void>
{
const element_container : Element = document.createElement("div");
element_container.classList.add("formgen-input");
element_container.classList.add("formgen-input-list");
element_container.classList.add("formgen-ioc");
element_container.classList.add("formgen-ioc-list");
{
// label
{
@ -140,15 +154,15 @@ namespace formgen.input
// entries
{
const element_entries : Element = document.createElement("div");
element_entries.classList.add("formgen-input-list-entries");
element_entries.classList.add("formgen-ioc-list-entries");
element_container.appendChild(element_entries);
this.element_entries = element_entries;
}
// adder
{
const element_adder_button : Element = document.createElement("button");
element_adder_button.classList.add("formgen-input-list-action");
element_adder_button.classList.add("formgen-input-list-action-add");
element_adder_button.classList.add("formgen-ioc-list-action");
element_adder_button.classList.add("formgen-ioc-list-action-add");
element_adder_button.textContent = "+";
element_adder_button.addEventListener(
"click",
@ -188,6 +202,16 @@ namespace formgen.input
{
return Promise.reject(new Error("not implemented"));
}
/**
*/
public listen(
handler : type_handler<Array<type_element>>
) : void
{
this.notification.listen(handler);
}
}

87
source/logic/ioc/map.ts Normal file
View file

@ -0,0 +1,87 @@
namespace formgen.ioc
{
/**
*/
export class class_ioc_map<type_value>
extends class_ioc_wrapper<Array<{first : string; second: type_value;}>, Record<string, type_value>>
implements interface_ioc<Record<string, type_value>>
{
/**
*/
public constructor(
element_input_factory : (() => interface_ioc<type_value>),
{
"label": label = null,
"handlers": handlers = [],
}
:
{
label ?: (null | string);
handlers ?: Array<type_handler<Record<string, type_value>>>;
}
=
{
}
)
{
super(
new class_ioc_list<{first : string; second : type_value;}>(
() => new class_ioc_wrapper<
Record<string, any>,
{first : string; second : type_value;}
>(
new class_ioc_group(
[
{
"name": "key",
"ioc": new class_ioc_text(
{
/**
* @todo parametrize
*/
"label": "Schlüssel",
}
),
"marked": true,
},
{
"name": "value",
"ioc": element_input_factory(),
"marked": true,
},
]
),
(value_inner) => ({"first": value_inner["key"], "second": value_inner["value"]}),
(value_outer) => ({"key": value_outer.first, "value": value_outer.second}),
),
{
"label": label,
/**
* @todo
*/
"handlers": [],
}
),
(value_inner) => Object.fromEntries(
value_inner.map(
entry => ([entry.first, entry.second])
)
),
(value_outer) => (
Object.entries(value_outer).map(
([key, value]) => ({"first": key, "second": (value as type_value)})
)
)
);
/*
this.element_input_factory = element_input_factory;
this.label = label;
this.notification = new trait_notification(handlers);
*/
}
}
}

View file

@ -1,9 +1,9 @@
namespace formgen.input
namespace formgen.ioc
{
/**
*/
export class class_input_number extends class_input_simple<number>
export class class_ioc_number extends class_ioc_simple<(null | number)>
{
/**
@ -32,7 +32,7 @@ namespace formgen.input
{
"label": label,
"hint": hint,
"additional_classes": ["formgen-input-number"].concat(additional_classes),
"additional_classes": ["formgen-ioc-number"].concat(additional_classes),
}
);
}

View file

@ -1,4 +1,4 @@
namespace formgen.input
namespace formgen.ioc
{
/**
@ -11,7 +11,7 @@ namespace formgen.input
/**
*/
export class class_input_select<type_value> implements interface_input<type_value>
export class class_ioc_select<type_value> implements interface_ioc<type_value>
{
/**
@ -39,6 +39,11 @@ namespace formgen.input
private element_select : (null | HTMLSelectElement);
/**
*/
private notification : trait_notification<type_value>;
/**
*/
public constructor(
@ -46,11 +51,13 @@ namespace formgen.input
{
"additional_classes": additional_classes = [],
"label": label = null,
"handlers": handlers = [],
}
:
{
additional_classes ?: Array<string>,
label ?: (null | string);
handlers ?: Array<type_handler<type_value>>;
}
=
{
@ -58,10 +65,11 @@ namespace formgen.input
)
{
this.options = options;
this.additional_classes = ["formgen-input-select"].concat(additional_classes);
this.additional_classes = ["formgen-ioc-select"].concat(additional_classes);
this.label = label;
this.value_map = new Map<string, int>();
this.element_select = null;
this.notification = new trait_notification(handlers);
}
@ -75,7 +83,7 @@ namespace formgen.input
const id : string = formgen.helpers.string.generate();
const element_container : Element = document.createElement("div");
element_container.classList.add("formgen-input");
element_container.classList.add("formgen-ioc");
for (const class_ of this.additional_classes)
{
element_container.classList.add(class_);
@ -109,6 +117,13 @@ namespace formgen.input
element_option.setAttribute("value", virtual_value);
element_select.appendChild(element_option);
}
element_select.addEventListener(
"change",
async () => {
const value = await this.read();
await this.notification.notify(value);
}
);
element_container.appendChild(element_select);
this.element_select = element_select;
}
@ -152,6 +167,17 @@ namespace formgen.input
return Promise.reject(new Error("not implemented"));
}
}
/**
* [implementation]
*/
public listen(
handler : type_handler<type_value>
) : void
{
this.notification.listen(handler);
}
}

View file

@ -1,9 +1,9 @@
namespace formgen.input
namespace formgen.ioc
{
/**
*/
export class class_input_simple<type_value> implements interface_input<type_value>
export class class_ioc_simple<type_value> implements interface_ioc<type_value>
{
/**
@ -39,7 +39,12 @@ namespace formgen.input
/**
*/
private element_input : (null | Element);
/**
*/
private notification : trait_notification<type_value>;
/**
*/
@ -51,12 +56,14 @@ namespace formgen.input
"additional_classes": additional_classes = [],
"label": label = null,
"hint": hint = null,
"handlers": handlers = [],
}
:
{
additional_classes ?: Array<string>,
label ?: (null | string);
hint ?: (null | string);
handlers ?: Array<type_handler<type_value>>;
}
=
{
@ -70,6 +77,7 @@ namespace formgen.input
this.label = label;
this.hint = hint;
this.element_input = null;
this.notification = new trait_notification(handlers);
}
@ -83,7 +91,7 @@ namespace formgen.input
const id : string = formgen.helpers.string.generate({"prefix": "input-label-pair-"});
const element_container : Element = document.createElement("div");
element_container.classList.add("formgen-input");
element_container.classList.add("formgen-ioc");
for (const class_ of this.additional_classes)
{
element_container.classList.add(class_);
@ -111,6 +119,13 @@ namespace formgen.input
const element_input : Element = document.createElement("input");
element_input.setAttribute("type", this.type);
element_input.setAttribute("id", id);
element_input.addEventListener(
"change",
async () => {
const value = await this.read();
await this.notification.notify(value);
}
);
element_container.appendChild(element_input);
this.element_input = element_input;
}
@ -142,6 +157,17 @@ namespace formgen.input
(this.element_input as HTMLInputElement).value = raw;
return Promise.resolve<void>(undefined);
}
/**
* [implementation]
*/
public listen(
handler : type_handler<type_value>
) : void
{
this.notification.listen(handler);
}
}

View file

@ -1,10 +1,10 @@
namespace formgen.input
namespace formgen.ioc
{
/**
*/
type type_item_raw = {
input : interface_input<unknown>;
ioc : interface_ioc<unknown>;
kind ?: string;
label ?: string;
}
@ -13,7 +13,7 @@ namespace formgen.input
/**
*/
type type_item = {
input : interface_input<unknown>;
ioc : interface_ioc<unknown>;
kind : string;
label : string;
}
@ -22,7 +22,7 @@ namespace formgen.input
/**
* @todo do not allow empty?
*/
export class class_input_sum implements interface_input<(null | {kind : string; value : unknown;})>
export class class_ioc_sum implements interface_ioc<(null | {kind : string; value : unknown;})>
{
/**
@ -45,16 +45,23 @@ namespace formgen.input
private kind_to_index_map : Map<string, int>;
/**
*/
private notification : trait_notification<(null | {kind : string; value : unknown;})>;
/**
*/
public constructor(
items : Array<type_item_raw>,
{
"label": label = null,
"handlers": handlers = [],
}
:
{
label ?: (null | string);
handlers ?: Array<type_handler<(null | {kind : string; value : unknown;})>>;
}
=
{
@ -65,7 +72,7 @@ namespace formgen.input
items
.map(
(item_raw, index) => ({
"input": item_raw.input,
"ioc": item_raw.ioc,
"kind": (item_raw.kind ?? ("" + (index + 1).toFixed(0))),
"label": (item_raw.label ?? ("Art " + (index + 1).toFixed(0))),
})
@ -78,6 +85,7 @@ namespace formgen.input
{
this.kind_to_index_map.set(this.items[index].kind, index);
}
this.notification = new trait_notification(handlers);
}
@ -93,8 +101,8 @@ namespace formgen.input
// structure
{
const element_container : Element = document.createElement("div");
element_container.classList.add("formgen-input");
element_container.classList.add("formgen-input-sum");
element_container.classList.add("formgen-ioc");
element_container.classList.add("formgen-ioc-sum");
// label
{
if (this.label === null)
@ -110,15 +118,15 @@ namespace formgen.input
}
// selection
{
const radio_name : string = formgen.helpers.string.generate({"prefix": "formgen-input-sum-selection-"});
const radio_name : string = formgen.helpers.string.generate({"prefix": "formgen-ioc-sum-selection-"});
element_selection = document.createElement("div");
element_selection.classList.add("formgen-input-sum-selection");
element_selection.classList.add("formgen-ioc-sum-selection");
for (const item of this.items)
{
const input_id : string = formgen.helpers.string.generate({"prefix": "input-label-pair-"});
const element_selector : Element = document.createElement("div");
element_selector.setAttribute("rel", item.kind);
element_selector.classList.add("formgen-input-sum-item-selector");
element_selector.classList.add("formgen-ioc-sum-item-selector");
// input
{
const element_selector_input : Element = document.createElement("input");
@ -141,13 +149,19 @@ namespace formgen.input
// inputs
{
element_item_inputs = document.createElement("div");
element_item_inputs.classList.add("formgen-input-sum-inputs");
element_item_inputs.classList.add("formgen-ioc-sum-inputs");
for (const item of this.items)
{
const element_item_input : Element = document.createElement("div");
element_item_input.classList.add("formgen-input-sum-item-input");
element_item_input.classList.add("formgen-ioc-sum-item-input");
element_item_input.setAttribute("rel", item.kind);
await item.input.setup(element_item_input);
await item.ioc.setup(element_item_input);
item.ioc.listen(
async () => {
const value : (null | {kind : string; value : unknown;}) = await this.read();
await this.notification.notify(value);
}
);
element_item_inputs.appendChild(element_item_input);
}
element_container.appendChild(element_item_inputs);
@ -187,7 +201,7 @@ namespace formgen.input
(node) => {
const element_input = (node as Element);
element_input.classList.toggle(
"formgen-input-sum-item-input-active",
"formgen-ioc-sum-item-input-active",
(element_input.getAttribute("rel") === kind)
);
}
@ -219,7 +233,7 @@ namespace formgen.input
const item : type_item = this.items[this.kind_to_index_map.get(this.active)];
return {
"kind": item.kind,
"value": (await item.input.read()),
"value": (await item.ioc.read()),
};
}
}
@ -235,6 +249,16 @@ namespace formgen.input
throw (new Error("not implemented"));
}
/**
*/
public listen(
handler : type_handler<(null | {kind : string; value : unknown;})>
) : void
{
this.notification.listen(handler);
}
}
}

View file

@ -1,9 +1,9 @@
namespace formgen.input
namespace formgen.ioc
{
/**
*/
export class class_input_text extends class_input_simple<string>
export class class_ioc_text extends class_ioc_simple<string>
{
/**
@ -32,7 +32,7 @@ namespace formgen.input
{
"label": label,
"hint": hint,
"additional_classes": ["formgen-input-text"].concat(additional_classes),
"additional_classes": ["formgen-ioc-text"].concat(additional_classes),
}
);
}

View file

@ -1,10 +1,10 @@
namespace formgen.input
namespace formgen.ioc
{
/**
* @todo dedicated time type
*/
export class class_input_time extends class_input_simple<string>
export class class_ioc_time extends class_ioc_simple<string>
{
/**
@ -33,7 +33,7 @@ namespace formgen.input
{
"label": label,
"hint": hint,
"additional_classes": ["formgen-input-time"].concat(additional_classes),
"additional_classes": ["formgen-ioc-time"].concat(additional_classes),
}
);
}

View file

@ -1,14 +1,14 @@
namespace formgen.input
namespace formgen.ioc
{
/**
*/
export class class_input_wrapper<type_value_inner, type_value_outer> implements interface_input<type_value_outer>
export class class_ioc_wrapper<type_value_inner, type_value_outer> implements interface_ioc<type_value_outer>
{
/**
*/
private core : interface_input<type_value_inner>;
private core : interface_ioc<type_value_inner>;
/**
@ -24,7 +24,7 @@ namespace formgen.input
/**
*/
public constructor(
core : interface_input<type_value_inner>,
core : interface_ioc<type_value_inner>,
wrap : ((type_value_inner) => type_value_outer),
unwrap : ((type_value_outer) => type_value_inner)
)
@ -69,6 +69,21 @@ namespace formgen.input
await this.core.write(value_inner);
return Promise.resolve<void>(undefined);
}
/**
* [implementation]
*/
public listen(
handler : type_handler<type_value_outer>
) : void
{
this.core.listen(
async (value_inner) => {
const value_outer : type_value_outer = this.wrap(value_inner);
await handler(value_outer);
}
)
}
}

245
source/logic/ioc/zerez.ts Normal file
View file

@ -0,0 +1,245 @@
namespace formgen.ioc
{
/**
*/
type type_data = {
manufacturer : string;
power : float;
};
/**
*/
type type_value = {
id : string;
data : (null | type_data);
};
/**
*/
type type_retrieve_data = ((id : string) => Promise<type_data>);
/**
*/
export class class_ioc_zerez implements interface_ioc<type_value>
{
/**
*/
private retrieve_data : type_retrieve_data;
/**
*/
private hint : (null | string);
/**
*/
private ioc_id : (null | interface_ioc<string>);
/**
*/
private ioc_data : (null | interface_ioc<Record<string, any>>);
/**
*/
public constructor(
retrieve : type_retrieve_data,
{
"hint": hint = null,
}
:
{
hint ?: (null | string);
}
=
{
}
)
{
this.retrieve_data = retrieve;
this.hint = hint;
this.ioc_id = null;
this.ioc_data = null;
}
/**
*/
private data_encode(
data : type_data
) : Record<string, any>
{
return {
"manufacturer": data.manufacturer,
"power": data.power,
};
}
/**
*/
private data_decode(
data_raw : Record<string, any>
) : type_data
{
return {
"manufacturer": data_raw["manufacturer"],
"power": data_raw["power"],
};
}
/**
* [implementation]
*/
public async setup(
element_target : Element
) : Promise<void>
{
const element_container : Element = document.createElement("div");
element_container.classList.add("formgen-ioc");
element_container.classList.add("formgen-ioc-zerez");
let dom_button_retrieve : HTMLButtonElement;
{
// hint
{
if (this.hint === null)
{
// do nothing
}
else
{
await (new formgen.info.class_info(this.hint)).setup(element_container);
}
}
// id ioc
{
this.ioc_id = new class_ioc_text(
{
"label": "ID",
}
);
await this.ioc_id.setup(element_container);
}
// retrieve button
{
dom_button_retrieve = document.createElement("button");
dom_button_retrieve.textContent = "ermitteln";
element_container.appendChild(dom_button_retrieve);
}
// data ioc
{
this.ioc_data = new class_ioc_group(
[
{
"name": "manufacturer",
"ioc": new class_ioc_text(
{
"label": "Hersteller",
}
),
"marked": false,
},
{
"name": "power",
"ioc": new class_ioc_number(
{
"label": "Leistung",
}
),
"marked": false,
},
]
);
await this.ioc_data.setup(element_container);
}
}
// interaction
{
dom_button_retrieve.addEventListener(
"click",
async () => {
if ((this.ioc_id === null) || (this.ioc_data == null))
{
// do nothing
}
else
{
const id : string = await this.ioc_id.read();
const data : type_data = await this.retrieve_data(id);
await this.ioc_data.write(this.data_encode(data));
}
}
);
}
element_target.appendChild(element_container);
}
/**
* [implementation]
*/
public async read(
) : Promise<type_value>
{
if (this.ioc_id === null)
{
throw (new Error("not properly initialized"));
}
else
{
return {
"id": await this.ioc_id.read(),
"data": this.data_decode(await this.ioc_data.read()),
};
}
}
/**
* [implementation]
*/
public async write(
value : type_value
) : Promise<void>
{
if (this.ioc_id === null)
{
throw (new Error("not properly initialized"));
}
else
{
if (value.data === null)
{
throw (new Error("invalid data"));
}
else
{
await this.ioc_id.write(value.id);
await this.ioc_data.write(this.data_encode(value.data));
}
}
}
/**
* [implementation]
*/
public listen(
handler : type_handler<type_value>
) : void
{
this.ioc_id.listen(handler);
this.ioc_data.listen(handler);
}
}
}

View file

@ -3,27 +3,111 @@ namespace formgen
/**
*/
let _input : (null | formgen.input.interface_input<unknown>) = null;
let _input : (null | formgen.ioc.interface_ioc<unknown>) = null;
/**
*/
async function render(
raw : string,
kind : string,
content : string,
element_target : Element
) : Promise<void>
{
element_target.innerHTML = "";
try
{
const json_schema : formgen.helpers.json_schema.type_root = (formgen.helpers.json.decode(raw) as formgen.helpers.json_schema.type_root);
const input : formgen.input.interface_input<unknown> = formgen.input.from_json_schema(
json_schema,
let input : formgen.ioc.interface_ioc<unknown>;
const variant : string = "description";
switch (kind)
{
case "manual":
{
// "map_unhandled_refs_to_empty": true,
const ioc_input = new formgen.ioc.class_ioc_group(
[
{
"name": "left",
"ioc": new formgen.ioc.class_ioc_number(
{
"label": "Eingabe | links",
}
),
"marked": true,
},
{
"name": "right",
"ioc": new formgen.ioc.class_ioc_number(
{
"label": "Eingabe | rechts",
}
),
"marked": true,
},
]
);
const ioc_output = new formgen.ioc.class_ioc_number(
{
"label": "Ausgabe",
}
);
input = new formgen.ioc.class_ioc_group(
[
{
"name": "input",
"ioc": ioc_input,
"marked": true,
},
{
"name": "output",
"ioc": ioc_output,
"marked": false,
},
],
{
// "label": "Eingabe",
}
);
break;
}
case "raw_description":
{
const description : formgen.ioc.type_description = (formgen.helpers.json.decode(content) as formgen.ioc.type_description);
input = formgen.ioc.from_raw(
description
);
break;
}
case "json_schema":
{
const json_schema : formgen.helpers.json_schema.type_root = (formgen.helpers.json.decode(content) as formgen.helpers.json_schema.type_root);
input = formgen.ioc.from_json_schema(
json_schema,
{
// "map_unhandled_refs_to_empty": true,
}
);
break;
}
}
await input.setup(element_target);
/*
ioc_input.listen(
value => {
if ((value.left === null) || (value.right === null))
{
ioc_output.write(null);
}
else
{
ioc_output.write(value.left * value.right);
}
}
);
await input.setup(element_target);
*/
_input = input;
}
catch (error)
@ -35,33 +119,50 @@ namespace formgen
/**
*/
function main(
) : void
async function main(
) : Promise<void>
{
document.querySelector("#render").addEventListener(
"click",
() => {
document.querySelector("#value").textContent = "";
render(
(document.querySelector("#description") as HTMLInputElement).value,
document.querySelector("#form")
);
}
);
document.querySelector("#read").addEventListener(
"click",
async () => {
if (_input === null)
// init:conf
{
await formgen.conf.initialize("conf.json");
}
// init:zerez
{
await formgen.helpers.zerez.initialize(
formgen.conf.get().zerez,
{
console.warn("no input present");
"fake": formgen.conf.get().zerez.fake,
}
else
{
const value = await _input.read();
document.querySelector("#value").textContent = JSON.stringify(value, undefined, " ");
);
}
// exec
{
document.querySelector("#render").addEventListener(
"click",
() => {
document.querySelector("#value").textContent = "";
render(
(document.querySelector("#description_kind") as HTMLInputElement).value,
(document.querySelector("#description_content") as HTMLInputElement).value,
document.querySelector("#form")
);
}
}
);
);
document.querySelector("#read").addEventListener(
"click",
async () => {
if (_input === null)
{
console.warn("no input present");
}
else
{
const value = await _input.read();
document.querySelector("#value").textContent = JSON.stringify(value, undefined, " ");
}
}
);
}
}
@ -73,7 +174,11 @@ namespace formgen
document.addEventListener(
"DOMContentLoaded",
() => {
main();
(
main()
.then(() => {})
.catch(console.error)
);
}
);
}

View file

@ -9,14 +9,17 @@
</head>
<body>
<div id="left">
<h2>Schema</h2>
<textarea class="codepane" id="description"></textarea>
<button class="action" id="render">erzeugen</button>
</div>
<div id="middle">
<h2>Formular</h2>
<div id="form"></div>
<button class="action" id="read">lesen</button>
</div>
<div id="right">
<h2>Wert</h2>
<textarea class="codepane" id="value" readonly="readonly"></textarea>
</div>
</body>

View file

@ -30,6 +30,11 @@ body
padding: 16px;
}
#description_kind
{
margin-bottom: 8px;
}
.codepane
{
width: 100%;
@ -70,7 +75,7 @@ body
*/
}
.formgen-input > label
.formgen-ioc > label
{
display: block;
font-size: 80%;
@ -84,30 +89,30 @@ body
text-transform: uppercase;
}
.formgen-input-list-action
.formgen-ioc-list-action
{
padding: 0 8px;
font-weight: bold;
}
.formgen-input-list-entries
.formgen-ioc-list-entries
,
.formgen-input-list-action-add
.formgen-ioc-list-action-add
{
margin-left: 32px;
}
.formgen-input-list-entry
.formgen-ioc-list-entry
{
margin-bottom: 16px;
}
.formgen-input-list-entry-input
.formgen-ioc-list-entry-input
{
margin-top: 4px;
}
.formgen-input-group-fields
.formgen-ioc-group-fields
{
margin-left: 32px;
@ -116,7 +121,7 @@ body
flex-wrap: wrap;
}
.formgen-input-group-field
.formgen-ioc-group-field
{
flex-basis: 50%;
flex-grow: 1;
@ -125,32 +130,32 @@ body
margin-bottom: 8px;
}
.formgen-input-group-field-marked > .formgen-input > label::before
.formgen-ioc-group-field-marked > .formgen-ioc > label::before
{
content: "* ";
}
.formgen-input-sum-selection
.formgen-ioc-sum-selection
{
margin-bottom: 32px;
}
.formgen-input-sum-item-selector:not(:first-child)
.formgen-ioc-sum-item-selector:not(:first-child)
{
margin-top: 8px;
}
.formgen-input-sum-item-selector > label
.formgen-ioc-sum-item-selector > label
{
margin-left: 4px;
}
.formgen-input-sum-item-input:not(.formgen-input-sum-item-input-active)
.formgen-ioc-sum-item-input:not(.formgen-ioc-sum-item-input-active)
{
display: none;
}
.formgen-input-sum-item-input > .formgen-input > label
.formgen-ioc-sum-item-input > .formgen-ioc > label
{
display: none;
}

View file

@ -20,23 +20,28 @@ ${cmd_tsc} \
${dir_source}/logic/helpers/list.ts \
${dir_source}/logic/helpers/map.ts \
${dir_source}/logic/helpers/json_schema.ts \
${dir_source}/logic/helpers/zerez.ts \
${dir_source}/logic/info.ts \
${dir_source}/logic/input/_interface.ts \
${dir_source}/logic/input/empty.ts \
${dir_source}/logic/input/wrapper.ts \
${dir_source}/logic/input/checkbox.ts \
${dir_source}/logic/input/simple.ts \
${dir_source}/logic/input/text.ts \
${dir_source}/logic/input/number.ts \
${dir_source}/logic/input/color.ts \
${dir_source}/logic/input/date.ts \
${dir_source}/logic/input/time.ts \
${dir_source}/logic/input/select.ts \
${dir_source}/logic/input/list.ts \
${dir_source}/logic/input/group.ts \
${dir_source}/logic/input/sum.ts \
${dir_source}/logic/input/_factory.ts \
${dir_source}/logic/ioc/_interface.ts \
${dir_source}/logic/ioc/_trait_notification.ts \
${dir_source}/logic/ioc/empty.ts \
${dir_source}/logic/ioc/wrapper.ts \
${dir_source}/logic/ioc/checkbox.ts \
${dir_source}/logic/ioc/simple.ts \
${dir_source}/logic/ioc/text.ts \
${dir_source}/logic/ioc/number.ts \
${dir_source}/logic/ioc/color.ts \
${dir_source}/logic/ioc/date.ts \
${dir_source}/logic/ioc/time.ts \
${dir_source}/logic/ioc/select.ts \
${dir_source}/logic/ioc/list.ts \
${dir_source}/logic/ioc/group.ts \
${dir_source}/logic/ioc/map.ts \
${dir_source}/logic/ioc/sum.ts \
${dir_source}/logic/ioc/zerez.ts \
${dir_source}/logic/ioc/_factory.ts \
${dir_source}/logic/form.ts \
${dir_source}/logic/conf.ts \
${dir_source}/logic/main.ts \
--outFile ${dir_build}/logic.js
cp ${dir_source}/structure.html ${dir_build}/index.html -u -v

5
tools/run Executable file
View file

@ -0,0 +1,5 @@
#!/usr/bin/env sh
cd build
web-server