diff --git a/application/src/main/data/json/system/scada_symbols/left-analog-water-level-meter.svg b/application/src/main/data/json/system/scada_symbols/left-analog-water-level-meter.svg index ae02548602..e242edfc11 100644 --- a/application/src/main/data/json/system/scada_symbols/left-analog-water-level-meter.svg +++ b/application/src/main/data/json/system/scada_symbols/left-analog-water-level-meter.svg @@ -1,5 +1,4 @@ - -{ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="200" height="200" fill="none" version="1.1" viewBox="0 0 200 200"><tb:metadata xmlns=""><![CDATA[{ "title": "Left analog water level meter", "description": "Left analog water level meter", "searchTags": [ @@ -49,7 +48,11 @@ { "tag": "pointer", "stateRenderFunction": "var valueSet = element.remember('valueSet');\nif (!valueSet) {\n element.remember('valueSet', true);\n element.transform({\n rotate: 0\n });\n}\n\nvar value = ctx.values.value;\nvar fullValue = ctx.values.fullValue;\n\nvar degrees = Math.max(0, Math.min(1, value/fullValue))*179.99;\nvar rotate = element.remember('rotate');\nif (degrees !== rotate) {\n element.remember('rotate', degrees);\n ctx.api.animate(element, 1000).ease('-').transform({rotate: degrees});\n}", - "actions": null + "actions": { + "click": { + "actionFunction": "ctx.api.callAction(event, 'displayClick');" + } + } } ], "behavior": [ @@ -610,7 +613,8 @@ "step": null } ] -} +}]]> + Water diff --git a/application/src/main/data/json/system/scada_symbols/right-analog-water-level-meter.svg b/application/src/main/data/json/system/scada_symbols/right-analog-water-level-meter.svg index 8658a6dc3e..e75949e374 100644 --- a/application/src/main/data/json/system/scada_symbols/right-analog-water-level-meter.svg +++ b/application/src/main/data/json/system/scada_symbols/right-analog-water-level-meter.svg @@ -1,5 +1,4 @@ - -{ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="200" height="200" fill="none" version="1.1" viewBox="0 0 200 200"><tb:metadata xmlns=""><![CDATA[{ "title": "Rigth analog water level meter", "description": "Right analog water level meter", "searchTags": [ @@ -49,7 +48,11 @@ { "tag": "pointer", "stateRenderFunction": "var valueSet = element.remember('valueSet');\nif (!valueSet) {\n element.remember('valueSet', true);\n element.transform({\n rotate: 0\n });\n}\n\nvar value = ctx.values.value;\nvar fullValue = ctx.values.fullValue;\n\nvar degrees = Math.max(0, Math.min(1, value/fullValue))*179.99;\nvar rotate = element.remember('rotate');\nif (degrees !== rotate) {\n element.remember('rotate', degrees);\n ctx.api.animate(element, 1000).ease('-').transform({rotate: degrees});\n}", - "actions": null + "actions": { + "click": { + "actionFunction": "ctx.api.callAction(event, 'displayClick');" + } + } } ], "behavior": [ @@ -610,7 +613,8 @@ "step": null } ] -} +}]]> + Water diff --git a/application/src/main/data/json/system/scada_symbols/stand-filter.svg b/application/src/main/data/json/system/scada_symbols/sand-filter.svg similarity index 99% rename from application/src/main/data/json/system/scada_symbols/stand-filter.svg rename to application/src/main/data/json/system/scada_symbols/sand-filter.svg index ebd1e28edd..1f9c0293d9 100644 --- a/application/src/main/data/json/system/scada_symbols/stand-filter.svg +++ b/application/src/main/data/json/system/scada_symbols/sand-filter.svg @@ -1,9 +1,10 @@ { - "title": "Stand filter", - "description": "Stand filter with configurable filtration mode option and various states.", + "title": "Sand filter", + "description": "Sand filter with configurable filtration mode option and various states.", "searchTags": [ - "filter" + "filter", + "sand" ], "widgetSizeX": 3, "widgetSizeY": 5, diff --git a/application/src/main/data/json/system/widget_bundles/scada_fluid_system.json b/application/src/main/data/json/system/widget_bundles/scada_fluid_system.json new file mode 100644 index 0000000000..bcb92dce1d --- /dev/null +++ b/application/src/main/data/json/system/widget_bundles/scada_fluid_system.json @@ -0,0 +1,74 @@ +{ + "widgetsBundle": { + "alias": "scada_fluid_system", + "title": "SCADA fluid system", + "image": "tb-image:c2NhZGFfZmx1aWRfc3lzdGVtX2J1bmRsZV9pbWFnZV8oMSkucG5n:IlNDQURBIGZsdWlkIHN5c3RlbSIgc3lzdGVtIGJ1bmRsZSBpbWFnZQ==:SU1BR0U=;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAAChCAMAAAC1fQA+AAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAJcEhZcwAACxMAAAsTAQCanBgAAALxUExURUdwTIuLi4uKi4qKi319fnNzc21ubnJxcW1vbnFvb5WUlHRzc7S0tI6NjY2NjcfHx4iIiJKSko+Pj5SUlKSkpIGAgIGAgBZ0MZOTk4yMjIyMjF9gYYyMjGxub3FxcV9uZqurq5aVlYqKipOTk25ubm5vcHBycm9zcEGFU3BwcaioqKurq66urjdjQZ+enhNkKmlrbo+Pj7OysnBvcKCgoHR0dKenp8LCwoCAgUyAWxFjKUGEUxJiKlB/XRZxL76+vrS0tBJjKs7OzsrKyhVxMBRiKhVuMOrq6r+/v83Nzenp6bOzs5+env///5iYmKysrL6+vtbW1qenp9fX17u7u6Kiora2tqGhobCwsM7Oztzc3OLi4tHR0d7e3uDg4Ofn58nJyevr6+bm5qampu3t7cXFxYyMjK2trdTU1Lq6uqmpqdra2pqamr29vaioqIPU7oDR67Kyspubm7e3t7W1taOjo6urq6SkpITW8HPF3tLS0q+vr6aqrYjZ84ze+MbGxoSIi7i4uNjY2MHBwWSrwoKBgX5+fuTk5FurxcLCwp2dnXB4e9DQ0MTExIqKisjIyJaVlVSkvnfH4WiaqsvLy4iIiJOSknDB22etxHZ6fTWeU32Agy2XS4aFhfv7+zCbTnZ3d5De966ytCWGQMDAwIuPkn/H3RyEOme20JCPj3/N5nnK43XB2np5eS+LSZWYm3S81Izc9nFydGKmu+/v72ahtJygo2y71J6ipCaRRKfVtPH482uToCSAPiWLQnGwxJeanZWzvYbK32Gcr3/A1VenwHnE3HC1zIbQ6G1vcWqovDqSU0CgXHSrvYrW7/T09HCZpo/U6iqSRzeHTZ26pVKguY6Rlfn5+W2AhoaptZuutJLa8VmWa3ejsX61x1CWY2KxyqWwsxp9NkiMXGeieK6trYKwjnp9gFmTpY3O45G0m36bpX2kiLzPwbGwsFKta16KcEubtUukZLbJu2eJlK3Gs3GWe5SmrMXWysnTy6iuquih9iMAAABHdFJOUwDfYEAQn0DfIJ/fgGCAvyFwn7/vYCBg/r9QkF8wMGCA3GDPIFCw73DewLaXRxB4ZN2v78/FkO+67aM974C/sN96UNWaz4CQZ2JzjQAAIb5JREFUeNrVnXlAk1e2wFEREIeplqkV6zau1S7TbdrpzJt93jQIhgCRJRikUiBAgIQtJAhpAohBlhRCQIUBCw1bpAmUSZ2HMkUEBKUidBzrWhVbrVKntvPmvb/eufd+XxYS9gz4jpJ8+fLlS34559x7v3PPPXFwGFeeGF8c/h/Ixud/89zv3/j171TBu33lsdzQkNzcvXv37NmzA/727s3NDQnlxPIk+arfvfHG73/z/OrHksFx0XPbX5ExFBFFKs98Cc8/llMQzY5jsVgMRm1WVm0tg8FixbGzgETuK9kdrAqTKlhJ65/z2Ph4UXi89nq6V4CMDSBhFEhW2Kc2pMgMhBEnS/JK3f6jx4bF0S0vPCYqiIBIaY1k7b1oQ8LMQGrjogO8gqJi1r/4eKCsdg0U+RGQOHON5OJP/mm+XCqXMj4NNQfJp0BkGMRP5LroceBw9zaB1NIakdMgF6XSYGlSfqjcGoTBjqZAAhN/PO8cT7kmjgNCmVbojlD5jvyLcrkRhEeDGDUS6O3+1HyDLGQaQZJkbAAJUwVbgFj7iBGEbQLhr5pvkJeZlhqhfEQe68vm8Xi+FsLjqSRGkAgTSEpgXuKG+Qb5IQFJRSDR5hrhcENyoSt86623sbz1FvSKuSFcGqTIQiN5fNf5BlnJsIvErZ93jTSo1UomH9SSIoqP8RkZ9UoOkEWzWbWKAmlRmArE09Mz2NMTbYUVSQsUtay46KjUGL/UER/QBbIqJlOpbljwmJgWdvbouLGmtcPctDx9wzx5cWwFT1haWlmZ44VNKz0qJhxo+AseGx8ZHQsSavSRd+AfgMh3M9jcWH9fXkxkZGFh6QgCEab7PGYgIxYgvhYgFs5OgZSWjrDYsmRh0OMEsmsMyG4jyA5KIyaQWGiUMUglpZGoxwokfnyQt8c2v/60RgAk2WsGGnn+xefWr3/llfXbt7+4aA5BrDQiMQeZto88/9wr0XFx7OhoWVJystBn/fKN/x6QAksQytnfMYHId++mTCtqBiCL3ojLgvYbOLyCkr28hKPpIyI7oUwMQkzLpBGOuWmxpgviuD1OkcVAHLLk5PhUoTAofcQnNSbwRTuDyKJZ4/gIpREVKylWGlFky7SYUwB5/tcKmkOWHp6XSnHE+6W4brSzRlhZBRP5CCdYxY319aVNy1wjzMLXXGyOSVdtpx36B9EFNEdSQHJ8vJEjXJTivtqOIMkm0+JRMZQxprU3N5TL8UXNL/SHpWYg3nnMUvlaFxvya6ZqFdn6DVthxgHuQXGEA0dgoHKRnTWimAwkVkKBmDQCHyQRQA7+3Ya8z1RVRoIUKoEjzsQB31lAFMWxK9DbO2/WOqFB0jHIFDSCnd0MJBVAvBFIq0F3w4CkHv505QZDV0d9fRJTxUwGEcoUCna0D+aI5vk+GL53Z/gRRzGKOUAheYmuT9kFBA17k9i0j4wHEgIayd9tATICILsCkWl1NDY2FTdpmhq78U13U6NGUxzNVMXLQaIVilqv0UDgYHEeXL9ZV3fvSt3NE7cfFcUDB19Zyeczf2gnjQi9ZBOC7KBAJBJe/BiN7MIauZaWkTGQQclAArllM1VeEA7Lr1XUMpJiYqJlnv+6frPm5PHjw9ePnzxZd/P2/6QHejMjG/hwKbDCPj4iTJ4UhMOVcjly/zEg8TRIrz5Drz86qEcy2Ku/3KvXZwBI0sWLHyVl1TLi2KAP3j3AuFBRUXXnelVFxYWTdUPfs/MSQR9KpXKB46xBwuN90m2A7B0DolKwoR+RmkCSwLR8aJAOgUDQKGhshFt809skEGjAtFK5XAXuzoHDd/gWYFQdPnz4/nW4qao4XnNr2ItwqBuWzRYErg2tQDg2QPZyOdCP8GiQuGgEYtRIX1mZtsegKyszaLvqywxlZWVd5QYZU5UYx/YiwxKZdLjm0XWEUVV1u78KbVTcflTzIAVzqBs2zN60YqYGEkL6EZNpeY2aQL5rbz/f3o5uzp8nW1+3t0PzW6gMjCPdeQBvqObsveuAUVVxa6gCkVwZ7q8bUiEMdUNDodPsQAJTwo0gEQgEIqbjgpg7OwyZRk0+snipDXmFqfrh0vUUh+ftuuMVZ+/3V1XUnAA5WVF16/7ZipN1d2IwR2TkT2cFkmcOQmlkAhC5LwUCnQKAGDXCsPl1rndnrHB4heoGfW+erDh8uP9h84kaJCdODD0EK7tw8kQY4SicjW09ybcAiSiaRCNyk0bAR0ymtWCNzdO7OK5xWJ1EOAru1V0Aa6rCHM0nTwIKegwqeaTEHIU5jnYCgWC8VOVpDvKWNchu3uclSJBpmYFMMOpNIsMSyfUa+OBVFcDR3Nw81NwMJNCCVV2ouz/agAfUOWvsAQLTIywACfMcVyOxiixsWp+fPv3ee+/5WGpk/Ld4kRom5p5AllV1/ARw9Pef7W8+iUEOX6jpz8IclTmb7GlaRpDcsRrxjZPy2NEKyeeI4z2TaQVODPIcTGyNRAlHOdhFKsCkmvvPfvstkNScOIlta0gaWdjQkFOZs9ZOGiFTiOOC5JJWS/J5KwFhT00jzyV5pcd7j6bz7n0/fP+fD09gkG++QSA1Qw//eX/4+ysRhaWRldU5dgWx1IitVkvy+WfvtZpMy29SkOTkFL5f+giPaKTGWiMnIsA/qqtz9tsBJIhy9ilp5PR7nwEIC4Pg6ZGJfSQZRxl8uOY+cra/H7wdN1vgIywUg83J2b/JHiBGjZDZ6fFAkEawjxCNRMVM6iM/GsUcqTxotQ4bW61+s1brdjjhOOY0axB6UtcmyNtmIHKikdPmrdYkIKtTyVUt+46pH2lGGFQ/crxuWI059lfboR8JGjPNbksjoXIeVw6RYcq00Oz0VEzL8XUqyvAv7CSHHw6Rnr0G9+yo0VIRjv2vOtgPpMga5B0cDsL9iJRDTOsANi1oVoOQs08C4vAaFS3xvA4qOXv/VsUFPNaqqahAY63jMNYiHMeWzBbEz8y0VOObViwHJt0LpADSSvsINRc6MciyVBL1iZfXnDw7jEa/FRVD/RVo+Auj35ohKcVR7TRLEJFNkLHTI9hHODBEkXyOLGsaII6vU1Gf6HtDj66Q65Fb16nrkQc3HzUQjmPODg4ey1+0eXnlst1t1WQg3hYgYdYg5s7OMbVaqeypgjgsJ1GfQO+ie1eoK8QrV/AV4oWaK3fSEQZwVEMvspwh3G7rDG4q5iSzlE8m2gKR29DIHqKR3dBqZZNWyzTNPgnIRm/CkZcnvXOz5jigVN2+DQYG1+wn7iURdRw71gL3DQxhYrWZHKLuc1RMEdlqeXWx0xRAjIkP1rPTO/D0iJzHQz07gKSagfAnif2u2oU4vJl8fsTwUB1EUS7cv33h+MmauusPUnL2V+YARnW1MsrHh88Q/ne9rry+vt6A/wzlN+rrr2XXn1cx99XfgCduiHtKDm52mYpGgifQCICQfqSvFUxr6iCOriiamBgJUYbA2OEhiGvduV1Xd/P69xENoI/C/S3AcQzOvDucIfy8GIJixU0QHdNqihu1sNnZ3X1VxfxCi6JlZZ3i+hvtzi4TgVhP6lr4CJpViKBBwN2nYVowMcL0zlNH5uAoQ4zn/3x/5879O8M8GXHz6jNnwHi474CkAwiExAbSQDLgH5GM3ksAkgBbg41pArGhp/3VCUAsU1FsasSfjRMfEEjrez7miQ+TTiss4yfy1UoSLWmIVKfExPMjqW4QvKO6+oznn5B4MYRfdGbqMzMzL2fAjf5oZ2bmIDxEIBloV0bGYKO45/Tfl06kEeQjk2RwyCOgHyn44osv9u2jMzjCpwTi4KaExAIlFWVAl8qVRg5wkDPCXCw+oBEBLQmN6EbQCbcIpLEXHmsaB/QCTX3bFquW0dxHppqK4jk2p4bPnDxu4KY25yg14wB95BUQCQRnRxExgxZuyzQ9ECvDd8hH0P6eMg0ENDVlhr+Pbbpe8FixYsVCJD9G8iNKfjCe0Afgo/HrFq5AMoXh3s8iTRyF6v37TRwt6ry8PG8kSgBpK2m7eqqtre1q2znYgg24a4dWC/Zfgh09CfoMQVf71nmbCHepbChtoO0qp7L6GM3RUr3/2ObFRBYwhK6LlyxesgS2l4DgG7jboGK+Dg9g58EbhqaExvqSJfMGsrVUDTN0hZHErND1IOZo2c/MU1fShrKc8cprNtuKCHeqZz9oaErLbCw7P38g2wAkXihS5xjdHIaJ1TnxXvEAQscYXZzW2JyLdHRyoVgP3mi6qxeUzZ9GXI6Vqr3jveKKpF5+StyV5zR4J6nCWBhky5TPc1DXKMgUaOZLI45PbN1fqk4MH2VHBPtz93x08U8XP30nl+sfLGUHifgNldWbnpri1eHBa90ZmYKe9sXzwvGEPydMGobz2FACG2SwQSYhXGCmp4bDRKo6shRszXmKIDeKM/Rd82Vaz3ND0XhTArmQEVksKoyE+h+Y3oksrERxh+ozU9Ks08G2c9e6Ovq+2+w0LxrJhyz0ooIsEq8gSR8UA3b5FpApgWxXGYUxhySOa9e9+ea6TdAOPf8DUz9K96FrkTxjlCl9LqfKQqOsmSsMp182D926cuXWUPMvN9nrnCtMia2ypXPU3P6y+TbjnZ0guQ8eNr/pYq/TOrf1dHd29bQ5u8wRx7O3GDuN8uD6s/Z6X+c+8eDRtOI+57niuPLOTjN554q9SJyzxY0ZaU0dcwQyhgOTONoH5JomITOha6oaWeb002m97wqPZebf+LpmxHHxox1/grtP374It5yhdeYaW7rCY1qf382J8m3nNl1C5qA2e2ogLoxI1bSa6fUihpu5YX2MtPBRiOQjwNkh90eP7v3C7KtxY4jWT6sFVEUyXCjTKuuFK6uJQRy3bnYmAiBbnKch4SLGz8weYoXsfDtY+unOnX+KlYbixmvI7Iw/Y4hE0zm/M4CQjZZz2qY0gaZnAhDHpVu+Kykvb+1ozW4DkFMd51rLy8uz4a+vHG129KHt8mtt6C4bbrJhTzY8lZ2dvU/EOA/PlBN5+E/iGBct7m5fKe+DYzvQ8ecZon3ZHeRM6A3wuTta8avRe+HT9+Fj0ZtklwBIW+u58r7s1p7egcsCcd+2cTnWOH+XbdBotWKNTtsDIOeaOrXa4u7iYl1xcXGnFv508ADfiYvFxd30HnhJsfgLEeOquFOHj+8S3xreufMvY2TnzuFbTV1wLH7RVYboCy0cDy+FE4jFjV1aMT4TfgPqNFq82aiDp84BSI+2q7hYXCbQZzQWG87/dPyepqS13gBBi7SEhLtdAHJNkDbQhaJKCWkooiRAUSVBwkAnPN2YgESQQAR2CQDkEw0cn4CPH4Iu5C//hUXIIPcAUjBEveBuQsIlhuj9zrS0uxp0fAJ5FQicfLAxAU5jIbDrGoDAh2kcTNDo9RDZOnBw3NZ8c/sNXVOnPg2SrTIzOwGkK/MobB0dRDEmPYSUyKOBTFPUaeAoPLqMHvUCyCXqGX1mb3OYEYTBNIKENfdCiEqPTwMgX2SQ4wfwmeBt9NTbGd9Wr4cnyV4E0on26NMyOjW6G9+NO4pfAxf1xQK9vlvQC9831gj5znvpr34A6QEpoxftFVC70ZeYMKhBIMbjE8w0smePEYSBNYJOP9CJQAT4WAE5E/y/K0DPkO00i7dNu9sBILq72AwEhvrW9vEHKD89byhuzNA3lonBOrGP9InF3bpugxikSycWa9GdFj0Sa3U6dNcND7vBpXq02jLsI2Kxjhxhw0ceIB8pQ6cpRqdBPgKPug34TBodbJfBCcvwy4t1WrS72Pi2YjHxEZ1GXKbVGA58N8FAa1ufVnB5oLenFTdRqNUqgQajDVqNc63QfHWcgjYE2iuQvmzcTrWhZ69CE4cPQq1WditpldqyH97eaUNuP2w91wYNFHo5arVa+9Cx8AbQMLXCzlb8TDY0m+Q05fhtW/HbnkKtVnYbtGt95/++ZekEnbVzDyi1SXuuxdiPTKuZF1n0I1uGONSHL/KRhtCDlCHnmfcjW4z9yKuL1zpOPBbTavS9YqrDhJ49Yno9++vmPbvjL+5Rnz5EKvuI2rz3rF169knHYq3awcwEXRvVYa5wml6m5CaPFRZjLaNKjBLbbDHWWrZpemOtZVP9QM59XTCo1Fyz0+j42evWo9+5GXc7dzQlZDSKs+0E8u+7HplcI8UJRwfEdrvwgivERyYORv9ccaBL4a7ObjteCrssab7+KBdRcANuDb3pODccS82W3S6z10nXvDnUPHTl+lDzL345ZyEoJxwoSo1Et3Z8U0enrevWbXWaiTaeWrRw4TK3ZQs9Fk3r1W4QuVME7JFlwf0yh3kWx4WrNrjDjCMlSveVq6ZOs+nE0K3Rt5NuDZ1wmmcKt5WwmJtfWlkIs3F5DTCJkpPIZzLVTy6cGsvP6473j76VDDlHLvOJsQhRJCbCZGIiBOmVgZUwL9cCqQawMoPpvnwqa35+Alnr6blCAPnJfGIABUyKBgbuShGJRIG7RKUo+yQFp38Ai3IKKL8CEB/u/wLIH+cLYzXBwBDhfn7xMSClaGYLMr3QwripofwBQGJ8wwHkV/PEAQkFGEMkQgypqT4+qalRkSibAIDi/URocRxUM3BdOOFZXngaQMKDPwaQp+cFY+MGjJEiCkcUUSPp6UFBUVGjkWjGdCQKSjNA6hqFsnwir/85gFwQSUUI5IV54FjoTqpOAIZP1EhQ0KgwPd1rdDQZtVrH8JreqFQKBZQygXn9BED6WfLoswDy8/kwKz6og2CkBwm9vJKFynAZiBrNY8MCAS9YR4oqZoCveCfy3cdfRvofT9f1f//t4dsPKuqenvtmyw3MCpzDD2wqfVTolZwkgzogkHgvi1MiEABKgmRujAJKAfNSLpwA5P63h7+58O2deQBxQ2UnUpA6RoK8ILdHxoYKZVCfjM3OUkJywX5qXSygGCuYjEsCIHeOf3P427rv657+z3nigGI5o14BkDUGFFkKhaKgtjaCibIksmCtMpuNtQJKiQ/HJB7jgvyz4ptv7hwennOQZbgMSHgMWvacDNqIQxQREVJpUVFYGL8UljFEFChQWRmMAgnThGScRcoAMjR8+HjF9/1zbVoblXzMgRYLQ4kchFEghdwCSC6ARNE8GI3nQHpBBKqQgwoToAl6Mrvt6jhuq3Xv3jBqtX47lxxPuVIp7ZgDVfoBXSCI9GSo8hPsDSvIK1GqBKBk1SKlGEmYT9o6328BpOrst2er5rr5XY4WphKOJKhYBOvpEYanZ1hAVhY7Kx+D4MpFgKLIYqGkPeMiIlvXGy4Y5BsMMpcd4kKlWVkASKkswBjBwfm7IU8aJBCB7M4PDvZEFZigQgGlE7zUw2aVNRPIH+ZSIa4kMx9x4Ep+wIExYLEjjwe5lbsg5a4U0oHzg7FSCrLMM0KZL9se/VIgv5rjltd8FQ7mIBi+/v6wYjgFgUDuNxRUREqRRlAkUGgCGZeNHv6PRpCfzKWno5Y33rSYE3EgDF9/KEoAVYpiRZDOWSqHuksSST5FwiILa3G28Uob3m4E+fmcdiF47Qqp0oBW1yIOHixVk8fGxnJA9n399dfvxsqhGAAPlOKJrYtFlnaNo5IXYNUQtFoVJ2/Ooa+7UivQcTZ7AaUPpI7YWH9FGBeKA3xy4PTpU5zYWKwUQoKrKuLCBqASqyb4x0KTrJizJosoBCqyyEgOOOZA6uBwuMG+HH9OyCcdBw6c4nI4JpKiCAU2LqIS5dhecZHaGH1xnzyMssbJyWmRUeDBzAIWeA1OvE8QLsiCF0Bijli0LCo0JCSEy8395D0ACeWiBHBYI4yqEaqkKH0NJREiL2G6jW0+JHJaYieNa7mcOXTk3Q8+/Hjf++/v+/OHH7x75NDmGbm6EjdZWCHGXHZ/rA7AIJWGPzlw4MapkFBUjiUWk1DJ7HgpEajEyt1d1m5pv3ru2tWr7VvWTho/cmoZC/LqTC0L1TEBDwGFYMPC/sHBBZOhVDIk5wNI66ncEFSiAawLG1dYUQFUg4ViE5CUD+5u1SmiGavMBG3rFKLxm6xAXpoJyMvIstC6QcpDKMPCHKjsMwVyoA0q5BhJSPFRqP/hle6D3N16nOLcqkuD7KFzUwB5xgpky0zbLLAs6EPisgrIEmFfigNRhMDqCAxyao+RxFgyGcpmgG2hpUTLrUDOaRL0CcVTyedaZwVyZoYuAkX8YNV2NIteEUXqASAOTpYEKQWBlOzBJJRKcMOVFYc6RdxuuVqbljjt8l0xbVprHGw3Xmtc1tgCcXF0mV7Op6OTB3YR6ESSaMsyU8gO0IhcwqE0Qhbc4fpLtG1FBwhR5rCNBhhSBcG0xOUExFG2gGHzk4W7M9YusQHymqvMbTogS4XLofwHbnyhzSqQktWPVKGfPaQwekjuDsq0jCox2RY4CeoTE5ljrxSdy3WNCcWG1i143cZmmGffRq3hoBZz4M3FQqZ820vWIJtfFzE2LCYLPKhjlyym/5Gz4NOQ/7C5gfEyPw+69SjU+GbRlhVLVZrA9d1huSCAZGONGJegI9uinYR4+9gwxOarGpQ/1HG+pP1qyfl2AGkvOV9CyXnYU4L/AKTykDVIQ7yI0Y4PoI4vaSd3SOi9JeSM+Kh2xgI+8vUocJG4sYsGMcUOJEgjV/GOPci2cLsFTlJQi4rkQIkyG83W0naDtlGf0dlV1tNVVlaOc1G6DChDRAzlgMSwuKmss8dgAJDEUmuQUR+cr9WDc0dQYgksixJ3dxnwQqlr+A5VE+rWGcjCqbKrjAVUo4V8fWxNRcKRu3cH7SOmImXYSQqyyCjFVt++puWGoRNWL4mhElOTQIfztQS9GkEvLtGECzWhAk0AMqK0BmGnQ3YQHNzVBIf1kopO8JpBjUDQ2dh7Vwev7kWn6cWngmVslxju0K/7mYPwjCBIJJIduWY+Au5uBkKaLQJi1f5u+ypb19R4OQFSogaOonytawOoUFYmur2sH8QP9BkAws6zBvEUQuIZPkKPDjwKmVzk0WX8kNo9oCfFt2DrEqMBgaSOeFmAcI0aCeZyJXIEkn1qB+UkXFMZayOIjY5kzZa2+rKmhLTGy1CqTIPztQaghllGbwas0MwYTMgY1GRkCAAkmW8NEjwKGsHHZgym4ZJnsLyzE+4ud5K9l3tJITR4XgCP7mKQXX62TQs7idFHaI3YBMmzBnHYevCzG4ZuWCCraWy6BiAdTU2wYLYYbqGWHNps0nRrAUT0gTUIawR8BB1fDIfBgdom/MJuctfUjU7QBImK8BT8L26CnEZ3/oQ+AiTQfH3SR/sIXRDWyrRsLHPf5PwdFPuqr+/R1SNnb6unljHf0PWUo7XM9V3Z9QDScMQaJDAG8rXg0B54gaG8vqu8vgMd31ePRZcNNz31XR03dLAWWncNDrpKtVoYBDe/BIRrphELHzE5O2q1JnB2Mgbe1nKQCIDQmxYCIMdarEH2Q97vEdNRhyzubMkRxg+p5hcNteBihG5+cYEGohECUm7qRzj0GAU1v8lB44waaRgsTgCyyVYlTADZutkaxAkysVe5TENWMV5GPTvpEGsLqAINxqEW7hH3mPsIVd2AZxo14uGvzUiK+VBo5dLtNi/7nnN7zcXWWGvVqpXTWuzisX2ZaYgCYy1yNUJsC6lkjydnD2yQQSM83Dt2+IuGKH4pNoYo05DFaPYVJmbC42EyDE+2ls4gYrGavq6CCIrxcsQ0ipdIONSgsY1SCNd4QQKX7TI0aESjX/UsggYvCsfK+hlkmzgqjT1iXBZVaoIa/u4lpgWXJPQwnr4ewS4iNfq6jWvdaclLLdVH3v3bhx+H7/srsqzqlmdmcpaVeIwCQS10yV5koZK91DCFvrDKRZGI2Fh8rauyHDPO6scpth069O67H/513773P/7z3z5499DMCrOsIk4CthVtLAhAqYQ4POUjbXsxB/YQcl2lgDCKEIdRJvP1SWSzOUgkjIZnBLKISQYp2LYKUMk400U7CqKQa3YYxtMcRoXUUoEtuK5yn1VkbQkC+asZyMxWBKK+XUQCplR8TiIhYRRAgaBWaOhe7CMhoSYOT/QzGyhoGuQzzgBl2iAm0/qyZWYBOjdkW34oHiSLIwUi8yVUQIgbG6CAEF0I9hEulwRNwbCMCsHRILAsj1mBrAOQQqNGjnzZMrOExdXUpAJWCerdjSSAIo/NV+WHEhDMwaM4SBQ7CLdZibP81ZN1Fho58uWZGZ5nJZ+oRGge/CXRXxyL55AgNsIgHHTRDFQL1m+i8ckU5ZlDX5p8ZBYgi3CJ3hgf0y+GwDQPNT0C8wr+/pxPyk8fOCUnEyTBVDAe/VYTqsSNFPLUbEEsNfLSTE+0kknPvMmowuIw8UZmevxxIPrSZ6ARX18yZYUm3xRZdDGslHFGvtMGMWnkyIxBFlnX6FXRU4i+vrsl/pdOg0Z4eBKRcNQa644Gzl4hDk4HLTRyZNtsZ6cDG9Q+Mjw5XUTPhhYUwOfnAchnpyT0tG4EyhqQiRoaUkgd7oWznaFZc9BSIzMHcXRH/u5dOBpeOYpJIqj56bAohZSlkADI6VPBwcHURDtKGfApFYpycO7DytlyOLi00CB/xj6yeean8kCZKOpCHisyPADlodA/cQQsIPmXoLLaV57U7xxlMeKiZQHqSE5yZOJ40+wzAPnQCHJkNnUkVgGJMofH2O8HKTWQM5CFUXCZC2mRJwIpwcUu6GQUYWAOx6s0cJzEh+nKmS8tNDKbCtCOkMzoXenLaIiCzDmU41SLs2qAJQyyObBGpDinBsq1www7JDpFcoRM4LDLb7JZmtaRdbNKD4LsB6UvyzsmCmrwo5/QwnlOBZBbAzwYhM5yQrlB0IEoOULgWGkPDoeX6CGKHUAQidqXleeHEuiQUtAvfMLPeypQ7tnXUFrtq1oGxqBT6JRcYSJ/g32WcbxkaVrPzO5sq10bfFmJKPcMUhrRD5uhXMDUZMiaY3z92WeflbCpTMBR+IUmuLhWc4X8BXb61cJXTSAfAMhsa2xsXODLYlJZjYCCWUbjR2KEbATyFfV7JSg3Mx4yGhu4wg32Wlaz2QLk0KwXOGzyZSlRErYfzpcdRfmyAQFJkOCIQahsWR+S+JsHIHZbHrTOAqRl1lkfTr4sNUnEBhSUhx00imi8vDCI8bdjSNZvJFdot+SLF5zNevYv1znYAUQZiHKx6ZxySMceGUn1Cfr6H//4x1fol2Ni/DAGZJR7F9oRxMFlGz3W+uBndigGByCpEuhQCIrIzy8GpflDO/Z1G4DgyrQkMZ6vdA9R2xPEwWHthr8ByF/dV9mj/XDyjUsNXbHQFf0uI1l3IQoP9wPlYI3AootdZNUFc+XG5W/bGQQmyj0WLlxtH7cjIJDV4UqvhAnkN6SIUlLaEUggpkAYEPtBIKMOj6c4PuGhCoiRrUTrKRYtV6O1SQCTqGxQemMQQuHuBlHeJ37/6wjmbp+NTz2WIL+LVUXH8KEyK279HD2WuzJhuVgiEqjB1aCGSq6uq0gg7gdSiTxMFsMs3fo4grwRF5UXub/F7LOt9nB7eaUr5DOq3V03LF/mYWbAb7BTEyP3n7GslP9/K5/YJIXJyFEAAAAASUVORK5CYII=", + "scada": true, + "description": "Bundle with SCADA symbols for fluid system", + "order": 9300, + "name": "SCADA fluid system" + }, + "widgetTypeFqns": [ + "horizontal_pipe", + "long_horizontal_pipe", + "vertical_pipe", + "long_vertical_pipe", + "left_bottom_elbow_pipe", + "bottom_right_elbow_pipe", + "top_right_elbow_pipe", + "left_top_elbow_pipe", + "cross_pipe", + "left_tee_pipe", + "bottom_tee_pipe", + "right_tee_pipe", + "top_tee_pipe", + "right_elbow_drain_pipe", + "left_elbow_drain_pipe", + "left_drain_pipe", + "right_drain_pipe", + "short_left_drain_pipe", + "short_right_drain_pipe", + "top_flow_meter", + "right_flow_meter", + "bottom_flow_meter", + "left_flow_meter", + "horizontal_inline_flow_meter", + "vertical_inline_flow_meter", + "left_analog_water_level_meter", + "right_analog_water_level_meter", + "leak_sensor", + "centrifugal_pump", + "small_right_motor_pump", + "small_left_motor_pump", + "right_motor_pump", + "left_motor_pump", + "right_heat_pump", + "left_heat_pump", + "short_bottom_filter", + "long_bottom_filter", + "short_top_filter", + "long_top_filter", + "sand_filter", + "horizontal_wheel_valve", + "vertical_wheel_valve", + "horizontal_ball_valve", + "vertical_ball_valve", + "water_stop", + "vertical_tank", + "stand_vertical_tank", + "cylindrical_tank", + "stand_cylindrical_tank", + "vertical_short_tank", + "stand_vertical_short_tank", + "large_cylindrical_tank", + "large_stand_cylindrical_tank", + "large_vertical_tank", + "large_stand_vertical_tank", + "horizontal_tank", + "stand_horizontal_tank", + "spherical_tank", + "small_spherical_tank", + "elevated_tank", + "pool" + ] +} \ No newline at end of file diff --git a/application/src/main/data/json/system/widget_bundles/scada_symbols.json b/application/src/main/data/json/system/widget_bundles/scada_symbols.json index f1fbfbc297..4de61d2b05 100644 --- a/application/src/main/data/json/system/widget_bundles/scada_symbols.json +++ b/application/src/main/data/json/system/widget_bundles/scada_symbols.json @@ -3,7 +3,7 @@ "alias": "scada_symbols", "title": "SCADA symbols", "scada": true, - "image": null, + "image": "tb-image:c2NhZGFfc3ltYm9sc19zeXN0ZW1fYnVuZGxlX2ltYWdlXygxKS5zdmc=:IlNDQURBIHN5bWJvbHMiIHN5c3RlbSBidW5kbGUgaW1hZ2U=:SU1BR0U=;data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAwIiBoZWlnaHQ9IjE2MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJtMTI2LjA0MiAzNS42NjY2LTIyLjkxNy0xMy4yNWMtMS45MTctMS4xMjUtNC4zMzMzLTEuMTI1LTYuMjUgMGwtMjIuOTE2NyAxMy4yNWMtMS45MTY2IDEuMTI1LTMuMTI1IDMuMTY2Ny0zLjEyNSA1LjQxNjd2MjYuNDU4M2MwIDIuMjUgMS4yMDg0IDQuMjkxNiAzLjEyNSA1LjQxNjZsMjIuOTE2NyAxMy4yNWMxLjkxNjcgMS4xMjUgNC4zMzMgMS4xMjUgNi4yNSAwbDIyLjkxNy0xMy4yNWMxLjkxNi0xLjEyNSAzLjEyNS0zLjE2NjYgMy4xMjUtNS40MTY2VjQxLjA4MzNjMC0yLjI1LTEuMjA5LTQuMjkxNy0zLjEyNS01LjQxNjdaTTc5LjE2NjcgNjYuMzMzM3YtMTkuMjVsMTYuNjY2NiA5LjY2NjZ2MTkuMjA4NGwtMTYuNjY2Ni05LjYyNVpNMTAwIDQ5LjU0MTZsLTE2LjY2NjctOS42NjY3TDEwMCAzMC4yNDk5bDE2LjY2NyA5LjYyNUwxMDAgNDkuNTQxNlptNC4xNjcgMjYuNDE2N1Y1Ni43NDk5bDE2LjY2Ni05LjY2NjZ2MTkuMjVsLTE2LjY2NiA5LjYyNVptLTI1LjAwMDMtNjMuNjI1SDY0LjU4MzNjLTMuNDU4MyAwLTYuMjUgMi43OTE2LTYuMjUgNi4yNXYxNC41ODMzaDguMzMzNHYtMTIuNWgxMi41di04LjMzMzNabTQxLjY2NjMgMGgxNC41ODRjMy40NTggMCA2LjI1IDIuNzkxNiA2LjI1IDYuMjV2MTQuNTgzM2gtOC4zMzR2LTEyLjVoLTEyLjV2LTguMzMzM1pNNzkuMTY2NyA5NS42NjY2SDY0LjU4MzNjLTMuNDU4MyAwLTYuMjUtMi43OTE3LTYuMjUtNi4yNVY3NC44MzMyaDguMzMzNHYxMi41MDAxaDEyLjV2OC4zMzMzWm00MS42NjYzIDBoMTQuNTg0YzMuNDU4IDAgNi4yNS0yLjc5MTcgNi4yNS02LjI1Vjc0LjgzMzJoLTguMzM0djEyLjUwMDFoLTEyLjV2OC4zMzMzWiIgZmlsbD0iIzMwNTY4MCIgZmlsbC1vcGFjaXR5PSIuNiIvPjxwYXRoIGQ9Ik02Mi41ODI4IDEyMS42MjVoNC4wMjM1Yy44NjQ1IDAgMS42MDE1LjEzIDIuMjEwOS4zOTEuNjA5NC4yNiAxLjA3NTUuNjQ1IDEuMzk4NCAxLjE1Ni4zMjgyLjUwNS40OTIyIDEuMTMuNDkyMiAxLjg3NSAwIC41NjgtLjEwNDIgMS4wNjgtLjMxMjUgMS41LS4yMDgzLjQzMi0uNTAyNi43OTctLjg4MjggMS4wOTQtLjM4MDIuMjkxLS44MzMzLjUxOC0xLjM1OTQuNjc5bC0uNTkzNy4yODloLTMuNjE3MmwtLjAxNTYtMS41NTRoMi43MTA5Yy40Njg4IDAgLjg1OTQtLjA4NCAxLjE3MTktLjI1LjMxMjUtLjE2Ny41NDY5LS4zOTQuNzAzMS0uNjguMTYxNS0uMjkyLjI0MjItLjYyLjI0MjItLjk4NCAwLS4zOTYtLjA3ODEtLjc0LS4yMzQ0LTEuMDMyLS4xNTEtLjI5Ny0uMzg1NC0uNTIzLS43MDMxLS42NzktLjMxNzctLjE2Mi0uNzIxNC0uMjQyLTEuMjEwOS0uMjQyaC0yLjA2MjVWMTMzaC0xLjk2MXYtMTEuMzc1Wk02OS4wNzUgMTMzbC0yLjY3MTktNS4xMDkgMi4wNTQ3LS4wMDggMi43MTEgNS4wMTVWMTMzSDY5LjA3NVptNy4zMjUuMTU2Yy0uNjI1IDAtMS4xOTAxLS4xMDEtMS42OTUzLS4zMDQtLjUtLjIwOS0uOTI3MS0uNDk4LTEuMjgxMy0uODY4LS4zNDg5LS4zNjktLjYxNzEtLjgwNC0uODA0Ni0xLjMwNHMtLjI4MTMtMS4wMzktLjI4MTMtMS42MTh2LS4zMTJjMC0uNjYxLjA5NjQtMS4yNi4yODkxLTEuNzk3LjE5MjctLjUzNi40NjA5LS45OTUuODA0Ny0xLjM3NS4zNDM3LS4zODUuNzUtLjY4IDEuMjE4Ny0uODgzLjQ2ODgtLjIwMy45NzY2LS4zMDQgMS41MjM0LS4zMDQuNjA0MiAwIDEuMTMyOS4xMDEgMS41ODYuMzA0LjQ1MzEuMjAzLjgyODEuNDkgMS4xMjUuODYuMzAyMS4zNjQuNTI2Ljc5OS42NzE5IDEuMzA0LjE1MS41MDYuMjI2NSAxLjA2My4yMjY1IDEuNjcydi44MDVoLTYuNTMxMnYtMS4zNTJoNC42NzE4di0uMTQ4Yy0uMDEwNC0uMzM5LS4wNzgxLS42NTYtLjIwMzEtLjk1My0uMTE5OC0uMjk3LS4zMDQ3LS41MzctLjU1NDctLjcxOS0uMjUtLjE4Mi0uNTgzMy0uMjczLTEtLjI3My0uMzEyNSAwLS41OTExLjA2Ny0uODM1OS4yMDMtLjIzOTYuMTMtLjQ0MDEuMzItLjYwMTYuNTctLjE2MTQuMjUtLjI4NjQuNTUyLS4zNzUuOTA2LS4wODMzLjM0OS0uMTI1Ljc0Mi0uMTI1IDEuMTh2LjMxMmMwIC4zNy4wNDk1LjcxNC4xNDg1IDEuMDMyLjEwNDEuMzEyLjI1NTIuNTg2LjQ1MzEuODIuMTk3OS4yMzQuNDM3NS40MTkuNzE4Ny41NTUuMjgxMy4xMy42MDE2LjE5NS45NjEuMTk1LjQ1MzEgMCAuODU2Ny0uMDkxIDEuMjEwOS0uMjczLjM1NDItLjE4My42NjE1LS40NC45MjE5LS43NzRsLjk5MjIuOTYxYy0uMTgyMy4yNjYtLjQxOTMuNTIxLS43MTEuNzY2LS4yOTE2LjIzOS0uNjQ4NC40MzUtMS4wNzAzLjU4Ni0uNDE2Ni4xNTEtLjkwMS4yMjYtMS40NTMxLjIyNlptOS43OTM3LTIuNDQ1YzAtLjE4OC0uMDQ2OC0uMzU3LS4xNDA2LS41MDgtLjA5MzctLjE1Ni0uMjczNC0uMjk3LS41MzktLjQyMi0uMjYwNS0uMTI1LS42NDU5LS4yMzktMS4xNTYzLS4zNDMtLjQ0NzktLjA5OS0uODU5NC0uMjE3LTEuMjM0NC0uMzUyLS4zNjk4LS4xNDEtLjY4NzUtLjMxLS45NTMxLS41MDgtLjI2NTYtLjE5OC0uNDcxMy0uNDMyLS42MTcyLS43MDMtLjE0NTgtLjI3MS0uMjE4Ny0uNTgzLS4yMTg3LS45MzcgMC0uMzQ0LjA3NTUtLjY3LjIyNjUtLjk3Ny4xNTExLS4zMDcuMzY3Mi0uNTc4LjY0ODUtLjgxMy4yODEyLS4yMzQuNjIyNC0uNDE5IDEuMDIzNC0uNTU0LjQwNjMtLjEzNi44NTk0LS4yMDMgMS4zNTk0LS4yMDMuNzA4MyAwIDEuMzE1MS4xMTkgMS44MjAzLjM1OS41MTA0LjIzNC45MDEuNTU1IDEuMTcxOS45NjEuMjcwOC40MDEuNDA2Mi44NTQuNDA2MiAxLjM1OWgtMS44ODI4YzAtLjIyNC0uMDU3My0uNDMyLS4xNzE5LS42MjUtLjEwOTMtLjE5OC0uMjc2LS4zNTYtLjUtLjQ3Ni0uMjIzOS0uMTI1LS41MDUyLS4xODgtLjg0MzctLjE4OC0uMzIyOSAwLS41OTEyLjA1Mi0uODA0Ny4xNTctLjIwODMuMDk4LS4zNjQ2LjIyOS0uNDY4OC4zOWExIDEgMCAwIDAtLjE0ODQuNTMxYzAgLjE0MS4wMjYxLjI2OS4wNzgxLjM4My4wNTczLjExLjE1MTEuMjExLjI4MTMuMzA1LjEzMDIuMDg4LjMwNzMuMTcyLjUzMTIuMjUuMjI5Mi4wNzguNTE1Ny4xNTQuODU5NC4yMjYuNjQ1OC4xMzYgMS4yMDA1LjMxIDEuNjY0MS41MjQuNDY4Ny4yMDguODI4MS40NzkgMS4wNzgxLjgxMi4yNS4zMjkuMzc1Ljc0NS4zNzUgMS4yNSAwIC4zNzUtLjA4MDcuNzE5LS4yNDIyIDEuMDMyLS4xNTYyLjMwNy0uMzg1NC41NzUtLjY4NzUuODA0LS4zMDIxLjIyNC0uNjY0MS4zOTktMS4wODU5LjUyNC0uNDE2Ny4xMjUtLjg4NTQuMTg3LTEuNDA2My4xODctLjc2NTYgMC0xLjQxNC0uMTM1LTEuOTQ1My0uNDA2LS41MzEyLS4yNzYtLjkzNDktLjYyOC0xLjIxMDktMS4wNTUtLjI3MDktLjQzMi0uNDA2My0uODgtLjQwNjMtMS4zNDNoMS44MjAzYy4wMjA5LjM0OS4xMTcyLjYyNy4yODkxLjgzNi4xNzcxLjIwMy4zOTU4LjM1MS42NTYyLjQ0NS4yNjU3LjA4OC41MzkxLjEzMy44MjA0LjEzMy4zMzg1IDAgLjYyMjQtLjA0NS44NTE1LS4xMzMuMjI5Mi0uMDk0LjQwMzctLjIxOS41MjM1LS4zNzUuMTE5OC0uMTYyLjE3OTYtLjM0NC4xNzk2LS41NDdabTMuMzMyOS0xLjg0NHYtLjE3OWMwLS42MS4wODg1LTEuMTc1LjI2NTYtMS42OTYuMTc3MS0uNTI2LjQzMjMtLjk4Mi43NjU2LTEuMzY3LjMzODYtLjM5MS43NS0uNjkzIDEuMjM0NC0uOTA2LjQ4OTYtLjIxOSAxLjA0MTctLjMyOCAxLjY1NjItLjMyOC42MTk4IDAgMS4xNzE5LjEwOSAxLjY1NjMuMzI4LjQ4OTYuMjEzLjkwMzYuNTE1IDEuMjQyMi45MDYuMzM4NS4zODUuNTk2My44NDEuNzczNCAxLjM2Ny4xNzcxLjUyMS4yNjU2IDEuMDg2LjI2NTYgMS42OTZ2LjE3OWMwIC42MS0uMDg4NSAxLjE3NS0uMjY1NiAxLjY5NS0uMTc3MS41MjEtLjQzNDkuOTc3LS43NzM0IDEuMzY4LS4zMzg2LjM4NS0uNzUuNjg3LTEuMjM0NC45MDYtLjQ4NDQuMjEzLTEuMDMzOS4zMi0xLjY0ODQuMzItLjYxOTggMC0xLjE3NDUtLjEwNy0xLjY2NDEtLjMyLS40ODQ0LS4yMTktLjg5NTgtLjUyMS0xLjIzNDQtLjkwNi0uMzM4NS0uMzkxLS41OTYzLS44NDctLjc3MzQtMS4zNjgtLjE3NzEtLjUyLS4yNjU2LTEuMDg1LS4yNjU2LTEuNjk1Wm0xLjg4MjgtLjE3OXYuMTc5YzAgLjM4LjAzOS43NC4xMTcyIDEuMDc4LjA3ODEuMzM5LjIwMDUuNjM2LjM2NzIuODkxLjE2NjYuMjU1LjM4MDIuNDU2LjY0MDYuNjAyLjI2MDQuMTQ1LjU3MDMuMjE4LjkyOTcuMjE4LjM0ODkgMCAuNjUxLS4wNzMuOTA2Mi0uMjE4LjI2MDQtLjE0Ni40NzQtLjM0Ny42NDA2LS42MDIuMTY2Ny0uMjU1LjI4OTEtLjU1Mi4zNjcyLS44OTEuMDgzNC0uMzM4LjEyNS0uNjk4LjEyNS0xLjA3OHYtLjE3OWMwLS4zNzYtLjA0MTYtLjczLS4xMjUtMS4wNjMtLjA3ODEtLjMzOS0uMjAzMS0uNjM4LS4zNzUtLjg5OC0uMTY2Ni0uMjYxLS4zODAyLS40NjQtLjY0MDYtLjYxLS4yNTUyLS4xNTEtLjU1OTktLjIyNi0uOTE0MS0uMjI2LS4zNTQxIDAtLjY2MTQuMDc1LS45MjE4LjIyNi0uMjU1Mi4xNDYtLjQ2NjIuMzQ5LS42MzI4LjYxLS4xNjY3LjI2LS4yODkxLjU1OS0uMzY3Mi44OTgtLjA3ODIuMzMzLS4xMTcyLjY4Ny0uMTE3MiAxLjA2M1ptMTIuODQwNiAyLjMydi02LjQ2MWgxLjg5MVYxMzNoLTEuNzgybC0uMTA5LTEuOTkyWm0uMjY2LTEuNzU4LjYzMi0uMDE2YzAgLjU2OC0uMDYyIDEuMDkyLS4xODcgMS41NzEtLjEyNS40NzQtLjMxOC44ODgtLjU3OCAxLjI0Mi0uMjYxLjM0OS0uNTk0LjYyMi0xIC44Mi0uNDA2LjE5My0uODkzLjI4OS0xLjQ2MS4yODktLjQxMiAwLS43ODktLjA2LTEuMTMzLS4xNzktLjM0NC0uMTItLjY0MS0uMzA1LS44OTA2LS41NTUtLjI0NDgtLjI1LS40MzQ5LS41NzYtLjU3MDMtLjk3Ny0uMTM1NC0uNDAxLS4yMDMxLS44OC0uMjAzMS0xLjQzN3YtNS40NjFoMS44ODN2NS40NzZjMCAuMzA4LjAzNi41NjYuMTA5Ljc3NC4wNzMuMjAzLjE3Mi4zNjcuMjk3LjQ5MnMuMjcxLjIxNC40MzguMjY2Yy4xNjYuMDUyLjM0My4wNzguNTMxLjA3OC41MzYgMCAuOTU4LS4xMDQgMS4yNjUtLjMxMy4zMTMtLjIxMy41MzQtLjUuNjY0LS44NTkuMTM2LS4zNTkuMjA0LS43NjMuMjA0LTEuMjExWm01LjY0NS0zLjA5NFYxMzNoLTEuODgzdi04LjQ1M2gxLjc5N2wuMDg2IDEuNjA5Wm0yLjU4Ni0xLjY2NC0uMDE2IDEuNzVhMy43NTc0IDMuNzU3NCAwIDAgMC0uMzc1LS4wNDdjLS4xMy0uMDEtLjI2LS4wMTUtLjM5LS4wMTUtLjMyMyAwLS42MDcuMDQ3LS44NTIuMTQtLjI0NS4wODktLjQ1LjIxOS0uNjE3LjM5MS0uMTYyLjE2Ny0uMjg3LjM3LS4zNzUuNjA5LS4wODkuMjQtLjE0MS41MDgtLjE1Ni44MDVsLS40My4wMzFjMC0uNTMxLjA1Mi0xLjAyMy4xNTYtMS40NzYuMTA0LS40NTMuMjYxLS44NTIuNDY5LTEuMTk2LjIxMy0uMzQzLjQ3OS0uNjEyLjc5Ny0uODA0LjMyMy0uMTkzLjY5NS0uMjg5IDEuMTE3LS4yODkuMTE1IDAgLjIzNy4wMS4zNjcuMDMxLjEzNi4wMjEuMjM3LjA0NC4zMDUuMDdabTQuNjc2IDcuMTY0Yy4zMDggMCAuNTg0LS4wNi44MjktLjE3OS4yNS0uMTI1LjQ1LS4yOTcuNjAxLS41MTYuMTU2LS4yMTkuMjQyLS40NzEuMjU4LS43NThoMS43NzNjLS4wMS41NDctLjE3MSAxLjA0NC0uNDg0IDEuNDkyLS4zMTIuNDQ4LS43MjcuODA1LTEuMjQyIDEuMDcxLS41MTYuMjYtMS4wODYuMzktMS43MTEuMzktLjY0NiAwLTEuMjA4LS4xMDktMS42ODgtLjMyOC0uNDc5LS4yMjQtLjg3Ny0uNTMxLTEuMTk1LS45MjItLjMxOC0uMzktLjU1Ny0uODQxLS43MTktMS4zNTEtLjE1Ni0uNTExLS4yMzQtMS4wNTgtLjIzNC0xLjY0MXYtLjI3M2MwLS41ODQuMDc4LTEuMTMxLjIzNC0xLjY0MS4xNjItLjUxNi40MDEtLjk2OS43MTktMS4zNTkuMzE4LS4zOTEuNzE2LS42OTYgMS4xOTUtLjkxNC40OC0uMjI0IDEuMDM5LS4zMzYgMS42OC0uMzM2LjY3NyAwIDEuMjcxLjEzNSAxLjc4MS40MDYuNTExLjI2NS45MTIuNjM4IDEuMjAzIDEuMTE3LjI5Ny40NzQuNDUxIDEuMDI2LjQ2MSAxLjY1NmgtMS43NzNjLS4wMTYtLjMxMi0uMDk0LS41OTMtLjIzNC0uODQzLS4xMzYtLjI1Ni0uMzI5LS40NTktLjU3OS0uNjEtLjI0NC0uMTUxLS41MzktLjIyNi0uODgyLS4yMjYtLjM4MSAwLS42OTYuMDc4LS45NDYuMjM0LS4yNS4xNTEtLjQ0NS4zNTktLjU4Ni42MjUtLjE0LjI2LS4yNDIuNTU1LS4zMDQuODgzLS4wNTguMzIzLS4wODYuNjU5LS4wODYgMS4wMDh2LjI3M2MwIC4zNDkuMDI4LjY4OC4wODYgMS4wMTYuMDU3LjMyOC4xNTYuNjIyLjI5Ny44ODIuMTQ1LjI1Ni4zNDMuNDYxLjU5My42MTguMjUuMTUxLjU2OC4yMjYuOTUzLjIyNlptOC44MzMgMS41Yy0uNjI1IDAtMS4xOS0uMTAxLTEuNjk1LS4zMDQtLjUtLjIwOS0uOTI3LS40OTgtMS4yODEtLjg2OC0uMzQ5LS4zNjktLjYxNy0uODA0LS44MDUtMS4zMDQtLjE4Ny0uNS0uMjgxLTEuMDM5LS4yODEtMS42MTh2LS4zMTJjMC0uNjYxLjA5Ni0xLjI2LjI4OS0xLjc5Ny4xOTMtLjUzNi40NjEtLjk5NS44MDUtMS4zNzUuMzQzLS4zODUuNzUtLjY4IDEuMjE4LS44ODMuNDY5LS4yMDMuOTc3LS4zMDQgMS41MjQtLjMwNC42MDQgMCAxLjEzMy4xMDEgMS41ODYuMzA0LjQ1My4yMDMuODI4LjQ5IDEuMTI1Ljg2LjMwMi4zNjQuNTI2Ljc5OS42NzIgMS4zMDQuMTUxLjUwNi4yMjYgMS4wNjMuMjI2IDEuNjcydi44MDVoLTYuNTMxdi0xLjM1Mmg0LjY3MnYtLjE0OGMtLjAxMS0uMzM5LS4wNzgtLjY1Ni0uMjAzLS45NTMtLjEyLS4yOTctLjMwNS0uNTM3LS41NTUtLjcxOS0uMjUtLjE4Mi0uNTgzLS4yNzMtMS0uMjczLS4zMTMgMC0uNTkxLjA2Ny0uODM2LjIwMy0uMjQuMTMtLjQ0LjMyLS42MDIuNTctLjE2MS4yNS0uMjg2LjU1Mi0uMzc1LjkwNi0uMDgzLjM0OS0uMTI1Ljc0Mi0uMTI1IDEuMTh2LjMxMmMwIC4zNy4wNS43MTQuMTQ5IDEuMDMyLjEwNC4zMTIuMjU1LjU4Ni40NTMuODIuMTk4LjIzNC40MzcuNDE5LjcxOS41NTUuMjgxLjEzLjYwMS4xOTUuOTYxLjE5NS40NTMgMCAuODU2LS4wOTEgMS4yMTEtLjI3My4zNTQtLjE4My42NjEtLjQ0LjkyMS0uNzc0bC45OTMuOTYxYy0uMTgzLjI2Ni0uNDIuNTIxLS43MTEuNzY2LS4yOTIuMjM5LS42NDkuNDM1LTEuMDcxLjU4Ni0uNDE2LjE1MS0uOTAxLjIyNi0xLjQ1My4yMjZabTkuNzk0LTIuNDQ1YzAtLjE4OC0uMDQ3LS4zNTctLjE0MS0uNTA4LS4wOTMtLjE1Ni0uMjczLS4yOTctLjUzOS0uNDIyLS4yNi0uMTI1LS42NDYtLjIzOS0xLjE1Ni0uMzQzLS40NDgtLjA5OS0uODU5LS4yMTctMS4yMzQtLjM1Mi0uMzctLjE0MS0uNjg4LS4zMS0uOTUzLS41MDgtLjI2Ni0uMTk4LS40NzItLjQzMi0uNjE4LS43MDMtLjE0NS0uMjcxLS4yMTgtLjU4My0uMjE4LS45MzcgMC0uMzQ0LjA3NS0uNjcuMjI2LS45NzcuMTUxLS4zMDcuMzY3LS41NzguNjQ5LS44MTMuMjgxLS4yMzQuNjIyLS40MTkgMS4wMjMtLjU1NC40MDYtLjEzNi44NTktLjIwMyAxLjM1OS0uMjAzLjcwOSAwIDEuMzE2LjExOSAxLjgyMS4zNTkuNTEuMjM0LjkwMS41NTUgMS4xNzIuOTYxLjI3LjQwMS40MDYuODU0LjQwNiAxLjM1OWgtMS44ODNjMC0uMjI0LS4wNTctLjQzMi0uMTcyLS42MjUtLjEwOS0uMTk4LS4yNzYtLjM1Ni0uNS0uNDc2LS4yMjQtLjEyNS0uNTA1LS4xODgtLjg0NC0uMTg4LS4zMjIgMC0uNTkxLjA1Mi0uODA0LjE1Ny0uMjA5LjA5OC0uMzY1LjIyOS0uNDY5LjM5LS4wOTkuMTYyLS4xNDguMzM5LS4xNDguNTMxIDAgLjE0MS4wMjYuMjY5LjA3OC4zODMuMDU3LjExLjE1MS4yMTEuMjgxLjMwNS4xMy4wODguMzA3LjE3Mi41MzEuMjUuMjI5LjA3OC41MTYuMTU0Ljg2LjIyNi42NDUuMTM2IDEuMi4zMSAxLjY2NC41MjQuNDY4LjIwOC44MjguNDc5IDEuMDc4LjgxMi4yNS4zMjkuMzc1Ljc0NS4zNzUgMS4yNSAwIC4zNzUtLjA4MS43MTktLjI0MiAxLjAzMi0uMTU3LjMwNy0uMzg2LjU3NS0uNjg4LjgwNC0uMzAyLjIyNC0uNjY0LjM5OS0xLjA4Ni41MjQtLjQxNy4xMjUtLjg4NS4xODctMS40MDYuMTg3LS43NjYgMC0xLjQxNC0uMTM1LTEuOTQ1LS40MDYtLjUzMi0uMjc2LS45MzUtLjYyOC0xLjIxMS0xLjA1NS0uMjcxLS40MzItLjQwNy0uODgtLjQwNy0xLjM0M2gxLjgyMWMuMDIxLjM0OS4xMTcuNjI3LjI4OS44MzYuMTc3LjIwMy4zOTYuMzUxLjY1Ni40NDUuMjY2LjA4OC41MzkuMTMzLjgyLjEzMy4zMzkgMCAuNjIzLS4wNDUuODUyLS4xMzMuMjI5LS4wOTQuNDA0LS4yMTkuNTIzLS4zNzUuMTItLjE2Mi4xOC0uMzQ0LjE4LS41NDdaTTYxLjEyNDIgMTQ5Ljg0NGMwLS4xOTktLjAzMTItLjM3NS0uMDkzNy0uNTI4LS4wNTg2LS4xNTYtLjE2NDEtLjI5Ni0uMzE2NC0uNDIxLS4xNDg1LS4xMjUtLjM1NTUtLjI0NS0uNjIxMS0uMzU4LS4yNjE4LS4xMTMtLjU5MzgtLjIyOC0uOTk2MS0uMzQ2LS40MjE5LS4xMjUtLjgwMjgtLjI2My0xLjE0MjYtLjQxNi0uMzM5OC0uMTU2LS42MzA5LS4zMzQtLjg3MzEtLjUzMy0uMjQyMS0uMTk5LS40Mjc3LS40MjgtLjU1NjYtLjY4NS0uMTI4OS0uMjU4LS4xOTM0LS41NTMtLjE5MzQtLjg4NSAwLS4zMzIuMDY4NC0uNjM5LjIwNTEtLjkycy4zMzIxLS41MjUuNTg2LS43MzJjLjI1NzgtLjIxMS41NjQ0LS4zNzUuOTE5OS0uNDkzLjM1NTUtLjExNy43NTE5LS4xNzUgMS4xODk0LS4xNzUuNjQwNyAwIDEuMTgzNi4xMjMgMS42Mjg5LjM2OS40NDkzLjI0Mi43OTExLjU2IDEuMDI1NC45NTUuMjM0NC4zOS4zNTE2LjgwOC4zNTE2IDEuMjU0aC0xLjEyNWMwLS4zMjEtLjA2ODQtLjYwNC0uMjA1MS0uODUtLjEzNjctLjI1LS4zNDM3LS40NDUtLjYyMTEtLjU4Ni0uMjc3My0uMTQ0LS42Mjg5LS4yMTctMS4wNTQ3LS4yMTctLjQwMjMgMC0uNzM0My4wNjEtLjk5NjEuMTgyLS4yNjE3LjEyMS0uNDU3LjI4NS0uNTg1OS40OTItLjEyNS4yMDctLjE4NzUuNDQ0LS4xODc1LjcwOSAwIC4xOC4wMzcxLjM0NC4xMTEzLjQ5Mi4wNzgyLjE0NS4xOTczLjI4LjM1NzUuNDA1LjE2NC4xMjUuMzcxMS4yNC42MjExLjM0NS4yNTM5LjEwNi41NTY2LjIwNy45MDgyLjMwNS40ODQzLjEzNy45MDIzLjI4OSAxLjI1MzkuNDU3LjM1MTUuMTY4LjY0MDYuMzU3Ljg2NzEuNTY4LjIzMDUuMjA3LjQwMDQuNDQ0LjUwOTguNzA5LjExMzMuMjYyLjE2OTkuNTU5LjE2OTkuODkxIDAgLjM0OC0uMDcwMy42NjItLjIxMDkuOTQzLS4xNDA2LjI4Mi0uMzQxOC41MjItLjYwMzUuNzIxLS4yNjE3LjE5OS0uNTc2Mi4zNTQtLjk0MzQuNDYzLS4zNjMzLjEwNS0uNzY5NS4xNTgtMS4yMTg3LjE1OGE0LjIzOCA0LjIzOCAwIDAgMS0xLjE2Ni0uMTY0Yy0uMzc4OS0uMTA5LS43MjQ3LS4yNzMtMS4wMzcyLS40OTItLjMwODUtLjIxOS0uNTU2Ni0uNDg4LS43NDQxLS44MDktLjE4MzYtLjMyNC0uMjc1NC0uNjk5LS4yNzU0LTEuMTI1aDEuMTI1YzAgLjI5My4wNTY3LjU0NS4xNjk5Ljc1Ni4xMTMzLjIwNy4yNjc2LjM3OS40NjI5LjUxNi4xOTkyLjEzNy40MjM5LjIzOC42NzM5LjMwNS4yNTM5LjA2Mi41MTc1LjA5My43OTEuMDkzLjM5NDUgMCAuNzI4NS0uMDU0IDEuMDAxOS0uMTY0LjI3MzUtLjEwOS40ODA1LS4yNjUuNjIxMS0uNDY5LjE0NDYtLjIwMy4yMTY4LS40NDMuMjE2OC0uNzJabTcuOTI4NS0uNTU3aDEuMTI1Yy0uMDU4Ni41MzktLjIxMjkgMS4wMjItLjQ2MjkgMS40NDctLjI1LjQyNi0uNjAzNS43NjQtMS4wNjA1IDEuMDE0LS40NTcuMjQ2LTEuMDI3My4zNjktMS43MTA5LjM2OS0uNSAwLS45NTUxLS4wOTQtMS4zNjUzLS4yODFhMy4wMzc3IDMuMDM3NyAwIDAgMS0xLjA0ODgtLjc5N2MtLjI5My0uMzQ4LS41MTk1LS43NjQtLjY3OTctMS4yNDgtLjE1NjItLjQ4OC0uMjM0NC0xLjAzMS0uMjM0NC0xLjYyOXYtLjg1YzAtLjU5Ny4wNzgyLTEuMTM4LjIzNDQtMS42MjMuMTYwMi0uNDg4LjM4ODctLjkwNi42ODU2LTEuMjUzYTMuMDQ4NiAzLjA0ODYgMCAwIDEgMS4wODM5LS44MDNjLjQyMTktLjE4OC44OTY1LS4yODEgMS40MjM5LS4yODEuNjQ0NSAwIDEuMTg5NC4xMjEgMS42MzQ3LjM2My40NDUzLjI0Mi43OTExLjU3OCAxLjAzNzEgMS4wMDguMjUuNDI1LjQwNDMuOTIuNDYyOSAxLjQ4MmgtMS4xMjVjLS4wNTQ3LS4zOTgtLjE1NjItLjc0LS4zMDQ3LTEuMDI1LS4xNDg0LS4yODktLjM1OTMtLjUxMi0uNjMyOC0uNjY4LS4yNzM0LS4xNTctLjYzMDgtLjIzNS0xLjA3MjItLjIzNS0uMzc4OSAwLS43MTI5LjA3My0xLjAwMi4yMTctLjI4NTEuMTQ1LS41MjU0LjM1LS43MjA3LjYxNS0uMTkxNC4yNjYtLjMzNTkuNTg0LS40MzM2Ljk1NS0uMDk3Ni4zNzItLjE0NjUuNzg0LS4xNDY1IDEuMjM3di44NjFjMCAuNDE4LjA0My44MTEuMTI4OSAxLjE3OC4wODk5LjM2Ny4yMjQ3LjY4OS40MDQzLjk2Ny4xNzk3LjI3Ny40MDgyLjQ5Ni42ODU2LjY1Ni4yNzczLjE1Ni42MDU1LjIzNC45ODQ0LjIzNC40ODA0IDAgLjg2MzItLjA3NiAxLjE0ODQtLjIyOC4yODUyLS4xNTMuNS0uMzcxLjY0NDUtLjY1Ny4xNDg1LS4yODUuMjUzOS0uNjI2LjMxNjQtMS4wMjVabTYuMDI0My01LjA2Mkw3Mi4yNTI3IDE1MmgtMS4xNTQzbDMuMjUyLTguNTMxaC43NDQxbC0uMDE3NS43NTZaTTc3LjQ0NDEgMTUybC0yLjgzLTcuNzc1LS4wMTc2LS43NTZoLjc0NDFMNzguNjA0MyAxNTJoLTEuMTYwMlptLS4xNDY0LTMuMTU4di45MjZoLTQuNzkzdi0uOTI2aDQuNzkzWk04Mi4yNTU1IDE1MmgtMS43ODEzbC4wMTE3LS45MmgxLjc2OTZjLjYwOTMgMCAxLjExNzItLjEyNyAxLjUyMzQtLjM4MS40MDYzLS4yNTguNzEwOS0uNjE3LjkxNDEtMS4wNzguMjA3LS40NjUuMzEwNS0xLjAwOC4zMTA1LTEuNjI5di0uNTIxYzAtLjQ4OS0uMDU4Ni0uOTIyLS4xNzU4LTEuMzAxLS4xMTcyLS4zODMtLjI4OS0uNzA1LS41MTU2LS45NjctLjIyNjYtLjI2NS0uNTAzOS0uNDY3LS44MzItLjYwMy0uMzI0Mi0uMTM3LS42OTczLS4yMDUtMS4xMTkyLS4yMDVoLTEuOTIxOHYtLjkyNmgxLjkyMThjLjU1ODYgMCAxLjA2ODQuMDkzIDEuNTI5My4yODEuNDYxLjE4NC44NTc1LjQ1MSAxLjE4OTUuODAzLjMzNTkuMzQ3LjU5MzcuNzY5Ljc3MzQgMS4yNjUuMTc5Ny40OTMuMjY5NiAxLjA0Ny4yNjk2IDEuNjY0di41MWMwIC42MTctLjA4OTkgMS4xNzQtLjI2OTYgMS42Ny0uMTc5Ny40OTItLjQzOTQuOTEyLS43NzkzIDEuMjYtLjMzNTkuMzQ4LS43NDIyLjYxNS0xLjIxODcuODAzLS40NzI3LjE4My0xLjAwNTkuMjc1LTEuNTk5Ni4yNzVabS0xLjE3NzgtOC41MzFWMTUyaC0xLjEzMDh2LTguNTMxaDEuMTMwOFptOS45NzM1Ljc1Nkw4OC4yMjcgMTUyaC0xLjE1NDNsMy4yNTE5LTguNTMxaC43NDQxbC0uMDE3NS43NTZaTTkzLjQxODQgMTUybC0yLjgzMDEtNy43NzUtLjAxNzYtLjc1NmguNzQ0MUw5NC41Nzg1IDE1MmgtMS4xNjAxWm0tLjE0NjUtMy4xNTh2LjkyNmgtNC43OTN2LS45MjZoNC43OTNabTkuMzUzMSAxLjQ3NmMwLS4xNTYtLjAzNS0uMy0uMTA1LS40MzMtLjA2Ny0uMTM3LS4yMDYtLjI2LS40MTYtLjM2OS0uMjA4LS4xMTQtLjUyLS4yMTEtLjkzOC0uMjkzLS4zNTItLjA3NS0uNjctLjE2Mi0uOTU1LS4yNjQtLjI4MTMtLjEwMi0uNTIxNS0uMjI1LS43MjA4LS4zNjktLjE5NTMtLjE0NS0uMzQ1Ny0uMzE1LS40NTExLS41MS0uMTA1NS0uMTk1LS4xNTgyLS40MjQtLjE1ODItLjY4NSAwLS4yNS4wNTQ2LS40ODcuMTY0LS43MDkuMTEzMy0uMjIzLjI3MTUtLjQyLjQ3NDYtLjU5Mi4yMDcxLS4xNzIuNDU1MS0uMzA3Ljc0NDUtLjQwNS4yODktLjA5Ny42MTEtLjE0Ni45NjYtLjE0Ni41MDggMCAuOTQyLjA5IDEuMzAxLjI2OS4zNi4xOC42MzUuNDIuODI2LjcyMS4xOTIuMjk3LjI4OC42MjcuMjg4Ljk5aC0xLjA4NGMwLS4xNzUtLjA1My0uMzQ1LS4xNTktLjUwOS0uMTAxLS4xNjgtLjI1Mi0uMzA3LS40NTEtLjQxNi0uMTk1LS4xMS0uNDM1LS4xNjQtLjcyMS0uMTY0LS4zIDAtLjU0NC4wNDYtLjczMi4xNC0uMTg0LjA5LS4zMTguMjA1LS40MDQuMzQ2LS4wODIuMTQxLS4xMjMzLjI4OS0uMTIzMy40NDUgMCAuMTE3LjAxOTUuMjIzLjA1ODMuMzE3LjA0My4wODkuMTE3LjE3My4yMjMuMjUyLjEwNS4wNzQuMjU0LjE0NC40NDUuMjExLjE5Mi4wNjYuNDM2LjEzMi43MzMuMTk5LjUxOS4xMTcuOTQ3LjI1OCAxLjI4My40MjIuMzM2LjE2NC41ODYuMzY1Ljc1LjYwMy4xNjQuMjM4LjI0Ni41MjcuMjQ2Ljg2NyAwIC4yNzgtLjA1OS41MzItLjE3Ni43NjItLjExMy4yMzEtLjI3OS40My0uNDk4LjU5OC0uMjE1LjE2NC0uNDczLjI5My0uNzczLjM4Ni0uMjk3LjA5LS42MzEuMTM1LTEuMDAyLjEzNS0uNTU5IDAtMS4wMzEtLjA5OS0xLjQxODItLjI5OS0uMzg2Ny0uMTk5LS42Nzk3LS40NTctLjg3ODktLjc3My0uMTk5Mi0uMzE2LS4yOTg4LS42NS0uMjk4OC0xLjAwMmgxLjA4OThjLjAxNTYuMjk3LjEwMTYuNTMzLjI1ODEuNzA5LjE1Ni4xNzIuMzQ3LjI5NS41NzQuMzY5LjIyNi4wNy40NTEuMTA2LjY3NC4xMDYuMjk3IDAgLjU0NS0uMDM5Ljc0NC0uMTE4LjIwMy0uMDc4LjM1Ny0uMTg1LjQ2My0uMzIyLjEwNS0uMTM3LjE1OC0uMjkzLjE1OC0uNDY5Wm00LjQ4OSAxLjAyNiAxLjc2NC01LjY4NGgxLjE2bC0yLjU0MyA3LjMxOWMtLjA1OS4xNTYtLjEzNy4zMjQtLjIzNC41MDMtLjA5NC4xODQtLjIxNS4zNTgtLjM2NC41MjItLjE0OC4xNjQtLjMyOC4yOTctLjUzOS4zOTgtLjIwNy4xMDYtLjQ1NS4xNTktLjc0NC4xNTktLjA4NiAwLS4xOTUtLjAxMi0uMzI4LS4wMzYtLjEzMy0uMDIzLS4yMjctLjA0My0uMjgxLS4wNThsLS4wMDYtLjg3OWMuMDMxLjAwNC4wOC4wMDguMTQ2LjAxMi4wNzEuMDA3LjExOS4wMTEuMTQ3LjAxMS4yNDYgMCAuNDU1LS4wMzMuNjI3LS4wOTkuMTcyLS4wNjMuMzE2LS4xNy40MzMtLjMyMy4xMjEtLjE0OC4yMjUtLjM1My4zMTEtLjYxNWwuNDUxLTEuMjNabS0xLjI5NS01LjY4NCAxLjY0NyA0LjkyMi4yODEgMS4xNDMtLjc3OS4zOTgtMi4zMzItNi40NjNoMS4xODNabTYuNDc2IDEuMjZWMTUyaC0xLjA5di02LjM0aDEuMDMxbC4wNTkgMS4yNlptLS4yMjMgMS42Ny0uNTA0LS4wMThjLjAwNC0uNDMzLjA2MS0uODM0LjE3LTEuMjAxLjEwOS0uMzcxLjI3MS0uNjkzLjQ4Ni0uOTY3LjIxNS0uMjczLjQ4My0uNDg0LjgwMy0uNjMzLjMyLS4xNTIuNjkxLS4yMjggMS4xMTMtLjIyOC4yOTcgMCAuNTcxLjA0My44MjEuMTI5LjI1LjA4Mi40NjYuMjEzLjY1LjM5Mi4xODQuMTguMzI2LjQxMS40MjguNjkyLjEwMS4yODEuMTUyLjYyMS4xNTIgMS4wMTlWMTUyaC0xLjA4NHYtNC4xNzJjMC0uMzMyLS4wNTctLjU5OC0uMTctLjc5Ny0uMTA5LS4xOTktLjI2Ni0uMzQzLS40NjktLjQzMy0uMjAzLS4wOTQtLjQ0MS0uMTQxLS43MTQtLjE0MS0uMzIxIDAtLjU4OC4wNTctLjgwMy4xNy0uMjE1LjExMy0uMzg3LjI2OS0uNTE2LjQ2OS0uMTI5LjE5OS0uMjIzLjQyNy0uMjgxLjY4NS0uMDU1LjI1NC0uMDgyLjUyNC0uMDgyLjgwOVptNC4xMDctLjU5OC0uNzI2LjIyM2MuMDA0LS4zNDguMDYtLjY4Mi4xNy0xLjAwMi4xMTMtLjMyLjI3NS0uNjA2LjQ4Ni0uODU2LjIxNS0uMjUuNDc4LS40NDcuNzkxLS41OTEuMzEyLS4xNDkuNjctLjIyMyAxLjA3Mi0uMjIzLjM0IDAgLjY0MS4wNDUuOTAzLjEzNS4yNjUuMDkuNDg4LjIyOC42NjguNDE2LjE4My4xODMuMzIyLjQyLjQxNi43MDkuMDkzLjI4OS4xNC42MzMuMTQgMS4wMzFWMTUyaC0xLjA5di00LjE3OGMwLS4zNTUtLjA1Ni0uNjMxLS4xNy0uODI2LS4xMDktLjE5OS0uMjY1LS4zMzgtLjQ2OC0uNDE2LS4yLS4wODItLjQzOC0uMTIzLS43MTUtLjEyMy0uMjM4IDAtLjQ0OS4wNDEtLjYzMy4xMjMtLjE4NC4wODItLjMzOC4xOTUtLjQ2My4zNGExLjQ4NSAxLjQ4NSAwIDAgMC0uMjg3LjQ4NmMtLjA2Mi4xODQtLjA5NC4zNzktLjA5NC41ODZabTUuNzU1LTQuOTkyaDEuMDl2Ny43N2wtLjA5NCAxLjIzaC0uOTk2di05Wm01LjM3MyA1Ljc3N3YuMTIzYzAgLjQ2MS0uMDU1Ljg4OS0uMTY0IDEuMjg0LS4xMDkuMzktLjI3LjczLS40OCAxLjAxOS0uMjExLjI4OS0uNDY5LjUxNC0uNzc0LjY3NC0uMzA1LjE2LS42NTQuMjQtMS4wNDkuMjQtLjQwMiAwLS43NTYtLjA2OC0xLjA2LS4yMDVhMi4wOTM0IDIuMDkzNCAwIDAgMS0uNzYyLS42MDNjLS4yMDctLjI2Mi0uMzczLS41NzktLjQ5OC0uOTUtLjEyMS0uMzcxLS4yMDUtLjc4OS0uMjUyLTEuMjU0di0uNTM5Yy4wNDctLjQ2OC4xMzEtLjg4OC4yNTItMS4yNTkuMTI1LS4zNzEuMjkxLS42ODguNDk4LS45NS4yMDctLjI2NS40NjEtLjQ2Ni43NjItLjYwMy4zLS4xNDEuNjUtLjIxMSAxLjA0OS0uMjExLjM5OCAwIC43NTEuMDc4IDEuMDYuMjM0LjMwOS4xNTMuNTY2LjM3MS43NzQuNjU3LjIxLjI4NS4zNzEuNjI3LjQ4IDEuMDI1LjEwOS4zOTUuMTY0LjgzNC4xNjQgMS4zMThabS0xLjA5LjEyM3YtLjEyM2MwLS4zMTYtLjAyOS0uNjEzLS4wODgtLjg5LS4wNTgtLjI4Mi0uMTUyLS41MjgtLjI4MS0uNzM5LS4xMjktLjIxNC0uMjk5LS4zODItLjUxLS41MDMtLjIxMS0uMTI1LS40Ny0uMTg4LS43NzktLjE4OC0uMjczIDAtLjUxMi4wNDctLjcxNS4xNDEtLjE5OS4wOTMtLjM2OS4yMi0uNTEuMzgxLS4xNC4xNTYtLjI1NS4zMzUtLjM0NS41MzktLjA4Ni4xOTktLjE1MS40MDYtLjE5NC42MjF2MS40MTJjLjA2My4yNzMuMTY0LjUzNy4zMDUuNzkxLjE0NS4yNS4zMzYuNDU1LjU3NC42MTUuMjQyLjE2LjU0MS4yNC44OTcuMjQuMjkzIDAgLjU0My0uMDU4Ljc1LS4xNzYuMjExLS4xMjEuMzgxLS4yODcuNTA5LS40OTguMTMzLS4yMTEuMjMxLS40NTUuMjkzLS43MzIuMDYzLS4yNzcuMDk0LS41NzQuMDk0LS44OTFabTIuMzc0IDB2LS4xMzRjMC0uNDU3LjA2Ni0uODgxLjE5OS0xLjI3Mi4xMzMtLjM5NC4zMjQtLjczNi41NzQtMS4wMjUuMjUtLjI5My41NTMtLjUyLjkwOS0uNjguMzU1LS4xNjQuNzU0LS4yNDYgMS4xOTUtLjI0Ni40NDUgMCAuODQ2LjA4MiAxLjIwMS4yNDYuMzYuMTYuNjY0LjM4Ny45MTQuNjguMjU0LjI4OS40NDcuNjMxLjU4IDEuMDI1LjEzMy4zOTEuMi44MTUuMiAxLjI3MnYuMTM0YzAgLjQ1Ny0uMDY3Ljg4MS0uMiAxLjI3Mi0uMTMzLjM5LS4zMjYuNzMyLS41OCAxLjAyNS0uMjUuMjg5LS41NTMuNTE2LS45MDguNjgtLjM1Mi4xNi0uNzUuMjQtMS4xOTUuMjQtLjQ0NiAwLS44NDYtLjA4LTEuMjAxLS4yNC0uMzU2LS4xNjQtLjY2MS0uMzkxLS45MTUtLjY4LS4yNS0uMjkzLS40NDEtLjYzNS0uNTc0LTEuMDI1LS4xMzMtLjM5MS0uMTk5LS44MTUtLjE5OS0xLjI3MlptMS4wODQtLjEzNHYuMTM0YzAgLjMxNy4wMzcuNjE2LjExMS44OTcuMDc1LjI3Ny4xODYuNTIzLjMzNC43MzguMTUzLjIxNS4zNDIuMzg1LjU2OS41MS4yMjYuMTIxLjQ5LjE4Mi43OTEuMTgyLjI5NyAwIC41NTYtLjA2MS43NzktLjE4Mi4yMjctLjEyNS40MTQtLjI5NS41NjItLjUxLjE0OS0uMjE1LjI2LS40NjEuMzM0LS43MzguMDc5LS4yODEuMTE4LS41OC4xMTgtLjg5N3YtLjEzNGMwLS4zMTMtLjAzOS0uNjA4LS4xMTgtLjg4NS0uMDc0LS4yODEtLjE4Ny0uNTI5LS4zMzktLjc0NC0uMTQ5LS4yMTktLjMzNi0uMzkxLS41NjMtLjUxNi0uMjIzLS4xMjUtLjQ4NC0uMTg3LS43ODUtLjE4Ny0uMjk3IDAtLjU1OS4wNjItLjc4NS4xODctLjIyMy4xMjUtLjQxLjI5Ny0uNTYzLjUxNi0uMTQ4LjIxNS0uMjU5LjQ2My0uMzM0Ljc0NC0uMDc0LjI3Ny0uMTExLjU3Mi0uMTExLjg4NVpNMTM3LjEgMTQzdjloLTEuMDl2LTloMS4wOVptNS42MzEgNy4zMThjMC0uMTU2LS4wMzUtLjMtLjEwNS0uNDMzLS4wNjctLjEzNy0uMjA1LS4yNi0uNDE2LS4zNjktLjIwNy0uMTE0LS41Mi0uMjExLS45MzgtLjI5My0uMzUxLS4wNzUtLjY3LS4xNjItLjk1NS0uMjY0LS4yODEtLjEwMi0uNTIxLS4yMjUtLjcyMS0uMzY5LS4xOTUtLjE0NS0uMzQ1LS4zMTUtLjQ1MS0uNTEtLjEwNS0uMTk1LS4xNTgtLjQyNC0uMTU4LS42ODUgMC0uMjUuMDU1LS40ODcuMTY0LS43MDkuMTEzLS4yMjMuMjcyLS40Mi40NzUtLjU5Mi4yMDctLjE3Mi40NTUtLjMwNy43NDQtLjQwNS4yODktLjA5Ny42MTEtLjE0Ni45NjctLjE0Ni41MDggMCAuOTQxLjA5IDEuMy4yNjkuMzYuMTguNjM1LjQyLjgyNy43MjEuMTkxLjI5Ny4yODcuNjI3LjI4Ny45OWgtMS4wODRjMC0uMTc1LS4wNTMtLjM0NS0uMTU4LS41MDktLjEwMi0uMTY4LS4yNTItLjMwNy0uNDUyLS40MTYtLjE5NS0uMTEtLjQzNS0uMTY0LS43Mi0uMTY0LS4zMDEgMC0uNTQ1LjA0Ni0uNzMzLjE0LS4xODMuMDktLjMxOC4yMDUtLjQwNC4zNDYtLjA4Mi4xNDEtLjEyMy4yODktLjEyMy40NDUgMCAuMTE3LjAxOS4yMjMuMDU5LjMxNy4wNDMuMDg5LjExNy4xNzMuMjIyLjI1Mi4xMDYuMDc0LjI1NC4xNDQuNDQ2LjIxMS4xOTEuMDY2LjQzNS4xMzIuNzMyLjE5OS41MTkuMTE3Ljk0Ny4yNTggMS4yODMuNDIyLjMzNi4xNjQuNTg2LjM2NS43NS42MDMuMTY0LjIzOC4yNDYuNTI3LjI0Ni44NjcgMCAuMjc4LS4wNTguNTMyLS4xNzYuNzYyLS4xMTMuMjMxLS4yNzkuNDMtLjQ5OC41OTgtLjIxNC4xNjQtLjQ3Mi4yOTMtLjc3My4zODYtLjI5Ny4wOS0uNjMxLjEzNS0xLjAwMi4xMzUtLjU1OSAwLTEuMDMxLS4wOTktMS40MTgtLjI5OS0uMzg3LS4xOTktLjY4LS40NTctLjg3OS0uNzczLS4xOTktLjMxNi0uMjk5LS42NS0uMjk5LTEuMDAyaDEuMDljLjAxNi4yOTcuMTAyLjUzMy4yNTguNzA5LjE1Ni4xNzIuMzQ4LjI5NS41NzQuMzY5LjIyNy4wNy40NTEuMTA2LjY3NC4xMDYuMjk3IDAgLjU0NS0uMDM5Ljc0NC0uMTE4LjIwMy0uMDc4LjM1OC0uMTg1LjQ2My0uMzIyLjEwNi0uMTM3LjE1OC0uMjkzLjE1OC0uNDY5WiIgZmlsbD0iIzMwNTY4MCIgZmlsbC1vcGFjaXR5PSIuOCIvPjwvc3ZnPg==", "description": "Bundle with SCADA symbols", "order": 9200, "name": "SCADA symbols" diff --git a/application/src/main/data/json/system/widget_bundles/scada_water_system_symbols.json b/application/src/main/data/json/system/widget_bundles/scada_water_system_symbols.json deleted file mode 100644 index 22575e0697..0000000000 --- a/application/src/main/data/json/system/widget_bundles/scada_water_system_symbols.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "widgetsBundle": { - "alias": "scada_water_system_symbols", - "title": "SCADA water system symbols", - "scada": true, - "image": null, - "description": "Bundle with SCADA symbols for water system", - "order": 9300, - "name": "SCADA water system symbols" - }, - "widgetTypeFqns": [ - "horizontal_pipe", - "long_horizontal_pipe", - "vertical_pipe", - "long_vertical_pipe", - "left_bottom_elbow_pipe", - "bottom_right_elbow_pipe", - "top_right_elbow_pipe", - "left_top_elbow_pipe", - "cross_pipe", - "left_tee_pipe", - "bottom_tee_pipe", - "right_tee_pipe", - "top_tee_pipe", - "right_elbow_drain_pipe", - "left_elbow_drain_pipe", - "left_drain_pipe", - "right_drain_pipe", - "short_left_drain_pipe", - "short_right_drain_pipe", - "top_flow_meter", - "right_flow_meter", - "bottom_flow_meter", - "left_flow_meter", - "horizontal_inline_flow_meter", - "vertical_inline_flow_meter", - "left_analog_water_level_meter", - "right_analog_water_level_meter", - "leak_sensor", - "centrifugal_pump", - "small_right_motor_pump", - "small_left_motor_pump", - "right_motor_pump", - "left_motor_pump", - "right_heat_pump", - "left_heat_pump", - "short_bottom_filter", - "long_bottom_filter", - "short_top_filter", - "long_top_filter", - "stand_filter", - "horizontal_wheel_valve", - "vertical_wheel_valve", - "horizontal_ball_valve", - "vertical_ball_valve", - "water_stop", - "vertical_tank", - "stand_vertical_tank", - "cylindrical_tank", - "stand_cylindrical_tank", - "vertical_short_tank", - "stand_vertical_short_tank", - "large_cylindrical_tank", - "large_stand_cylindrical_tank", - "large_vertical_tank", - "large_stand_vertical_tank", - "horizontal_tank", - "stand_horizontal_tank", - "spherical_tank", - "small_spherical_tank", - "elevated_tank", - "pool" - ] -} \ No newline at end of file diff --git a/application/src/main/data/json/system/widget_types/scada_symbol.json b/application/src/main/data/json/system/widget_types/scada_symbol.json index 15c12e1b81..bdcdd1674d 100644 --- a/application/src/main/data/json/system/widget_types/scada_symbol.json +++ b/application/src/main/data/json/system/widget_types/scada_symbol.json @@ -3,7 +3,7 @@ "name": "SCADA symbol", "deprecated": false, "scada": true, - "image": null, + "image": "tb-image:bmV3X3NjYWRhX3N5bWJvbHNfc3lzdGVtX3dpZGdldF9pbWFnZV8oMSkuc3Zn:Ik5ldyBTQ0FEQSBzeW1ib2wiIHN5c3RlbSB3aWRnZXQgaW1hZ2U=:SU1BR0U=;data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAwIiBoZWlnaHQ9IjE2MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBjbGlwLXBhdGg9InVybCgjYSkiIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBmaWxsPSIjMzA1NjgwIiBmaWxsLW9wYWNpdHk9Ii42Ij48cGF0aCBkPSJtMTQ3LjE2MyA0OC43NTM3LTE0LjcxOC0xNS4zODU1Yy0xLjIxMy0xLjI2MTQtMi42OTMtMi4xOTYtNC4zNC0yLjczOTYtNS4wNzUtNi41NDc1LTExLjE5OS0xMC42Nzc3LTIwLjEzNC0xMC42Nzc3LTguNjkwNiAwLTE2LjQzMDMgMy42MjQxLTIxLjUzMDMgMTAuMzI4SDcyLjQ0NzRjLTUuNTYzMS4wMDA1LTEwLjE1NyA0LjM2Ny0xMC4xNTcgOS45MzA3djM5Ljc5MDVoNS4wMjhWNDAuMjA5NmMwLTIuNzk1NSAyLjMzMzUtNC45MDIyIDUuMTI5LTQuOTAyMmgxMC43MjU3Yy0xLjkxMTIgMy4zNTE5LTMuMDA1NiA3Ljg0MTktMy4wMDU2IDEyLjM1ODZ2My44NDI1aC04LjM2MmMtLjY1MDggMC0xLjIzOC4yNjI1LTEuNDg4My44NjMxLS4yNTAyLjYwMDYtLjExNTYgMS4yMjg1LjM0MiAxLjY5MTFsMjIuNDE3MyAyMi42MjQ1Yy4zMjM0LjMyNjkuNzY0OC40OTUgMS4yMjQ2LjQ5NS40NTk3IDAgLjkwMTEtLjE5MjIgMS4yMjQ1LS41MTlsMjIuMjg4NC0yMi41MzA3Yy40NzktLjQ4NDQuNjIxLTEuMDgyNy4zNTgtMS43MTIzLS4yNjMtLjYyODUtLjg3Ny0uOTExNy0xLjU1OS0uOTExN0gxMDguMVY0Ny42NjZjMC00Ljk3MzIgMi40ODYtOS41NjUzIDUuODk1LTEyLjM1ODZoOS4xMjNjMS45ODEuNTU4NiAzLjQxOCAyLjA3MzcgMy40MTggNC4yMDIydjEwLjgxMTdjMCAyLjkwMTcgMi4zODYgNS42NTY0IDUuMjg3IDUuNjU2NGg4Ljg5OWMyLjUwMiAwIDQuMzg5IDEuODI2MyA0LjM4OSA0LjMyNjlsLS4xMzktLjIwOVYxMzAuMDVjMCAyLjc5NS0yLjAzMiA1LjI1Ny00LjgyNyA1LjI1N0g3Mi40NDc0Yy0yLjc5NTUgMC01LjEyOS0yLjQ2MS01LjEyOS01LjI1N3YtMi41NjRoLTUuMDI4djIuNTY0YzAgNS41NjQgNC41OTM5IDEwLjI4NSAxMC4xNTcgMTAuMjg1aDY3LjY5NzZjNS41NjMgMCA5Ljg1NS00LjcyMSA5Ljg1NS0xMC4yODVWNTYuMDg3OGMwLTIuNzQ4Ni0uOTMyLTUuMzUzMS0yLjgzNy03LjMzNDFaIi8+PHBhdGggZD0iTTEyNy42NTQgODguMTQ5NmMwLTEuNzI0LTEuMzk4LTMuMTIxOC0zLjEyMi0zLjEyMThINTMuMTIxN2MtMS43MjQgMC0zLjEyMTggMS4zOTc4LTMuMTIxOCAzLjEyMTh2MzEuNzQ0NGMwIDEuNzI0IDEuMzk3OCAzLjEyMiAzLjEyMTggMy4xMjJoNzEuNDEwM2MxLjcyNCAwIDMuMTIyLTEuMzk4IDMuMTIyLTMuMTIyVjg4LjE0OTZaTTc2LjEzNjMgMTExLjc1NWMtLjQxMjkuOTE0LTEuMDI3NCAxLjcwMi0xLjg0MzYgMi4zNjYtLjgxNTcuNjYzLTEuODI3NCAxLjE3OS0zLjAzNDcgMS41NDktMS4yMDY3LjM3LTIuNjA1LjU1NS00LjE5MjcuNTU1LTEuMjgzOCAwLTIuNTI4NS0uMTU4LTMuNzM1OC0uNDczLTEuMjA3Mi0uMzE1LTIuMjczMS0uODEtMy4xOTc3LTEuNDg1LS45MjUyLS42NzQtMS42NTkyLTEuNTUyLTIuMjAyMy0yLjU5Ni0uNTQ0MS0xLjA0NC0uODA1LTIuMDYyLS43ODMyLTMuNzM4aDQuOTU5OGMwIDEuMTE3LjE0MTMgMS40NjUuNDI0IDIuMDA5LjI4MjcuNTQ0LjY1ODEuOTk0IDEuMTI2MyAxLjMzMS40Njc2LjMzOCAxLjAxNjIuNTkyIDEuNjQ3NC43NTUuNjMwOC4xNjQgMS4yODMzLjI0NyAxLjk1NzYuMjQ3LjQ1NjQgMCAuOTQ2NC0uMDM3IDEuNDY4MS0uMTEzLjUyMjQtLjA3NiAxLjAxMTgtLjIyMiAxLjQ2ODgtLjQ0LjQ1NjQtLjIxOC44MzY4LS41MTcgMS4xNDE5LS44OTcuMzA0NC0uMzguNDU2NC0uODY1LjQ1NjQtMS40NTIgMC0uNjMxLS4yMDExLTEuMTQyLS42MDM0LTEuNTMzLS40MDI4LS4zOTItLjkzMDEtLjcxOC0xLjU4MjYtLjk3OS0uNjUyNi0uMjYxLTEuMzkyMi0uNDktMi4yMTktLjY4Ni0uODI2My0uMTk1LTEuNjY0My0uNDEzLTIuNTEyMy0uNjUyLS44NzA0LS4yMTgtMS43MTg1LS40ODQtMi41NDQ3LS44LS44MjY4LS4zMTUtMS41NjY1LS43MjMtMi4yMTktMS4yMjMtLjY1MjUtLjUtMS4xODA1LTEuMTI2LTEuNTgyNy0xLjg3Ni0uNDAyOC0uNzUtLjYwMzQtMS42NTgyLS42MDM0LTIuNzI0MSAwLTEuMTk2MS4yNTU0LTIuMjM1Mi43NjY1LTMuMTE2Mi41MTA2LS44ODEgMS4xNzk0LTEuNjE1MSAyLjAwNjctMi4yMDIyLjgyNjMtLjU4NzIgMS43NjItMS4wMjI0IDIuODA2Mi0xLjMwNTEgMS4wNDM2LS4yODI2IDIuMDg3Ny0uNDI0IDMuMTMxOC0uNDI0IDEuMjE3OSAwIDIuMzg2Ni4xMzYzIDMuNTA3My40MDc4IDEuMTIwMS4yNzIxIDIuMTE1MS43MTI5IDIuOTg1NSAxLjMyMTMuODcwMy42MDg5IDEuNTYwOSAxLjQ4NDkgMi4wNzIgMi40MzEyLjUxMDYuOTQ2NC43NjY1IDIuNDIzNS43NjY1IDMuNTQwOGgtNC45NTkyYy0uMDQzNi0uNTU4Ni0uMTkxMS0xLjM3MDktLjQ0MDItMS44MjczLS4yNTAzLS40NTctLjU4MjctLjg2NDktLjk5NTYtMS4xMjU3LS40MTI4LS4yNjA5LS44ODY2LS40NzA0LTEuNDE5LS41Nzk0LS41MzM1LS4xMDg0LTEuMTE1LS4xNzU0LTEuNzQ1OC0uMTc1NC0uNDEzNCAwLS44MjYyLjAzOC0xLjIzOTYuMTI0Ni0uNDEzNC4wODcxLS43ODg5LjIzNjMtMS4xMjYzLjQ1MzYtLjMzNzQuMjE3OS0uNjE1MS40ODc3LS44MzE4LjgxNDUtLjIxNzkuMzI2My0uMzI2My43Mzg2LS4zMjYzIDEuMjM5MiAwIC40NTY0LjA4NjYuODI2Mi4yNjE1IDEuMTA4OS4xNzM3LjI4MjcuNTE2Mi41NDM1IDEuMDI3OS43ODI1LjUxMDYuMjQgMS4yMTc5LjQ3OSAyLjEyMDcuNzE4LjkwMjIuMjQgMi4wODI2LjU0NCAzLjU0MDIuOTEzLjQzNDYuMDg4IDEuMDM4LjI0NSAxLjgxMDYuNDc0Ljc3MjEuMjI4IDEuNTM4Ni41OTIgMi4zIDEuMDkzLjc2MTUuNSAxLjQxOTYgMS4xNyAxLjk3NDMgMi4wMDcuNTU0Mi44MzguODMxOCAxLjkwOS44MzE4IDMuMjE0LjAwMTIgMS4wNjQtLjIwNjEgMi4wNTQtLjYxODkgMi45NjdabTE0LjQ4NiAzLjk5OWgtNS43NzQ5TDc3LjMxIDkyLjg0OTFoNS4yNTMxbDUuMTg3NyAxNi4yMDA5aC4wNjUzbDUuMjUzMS0xNi4yMDA5aDUuMjg1NWwtNy43MzI0IDIyLjkwNDlabTMwLjMyNzcgMGgtMy4yNDdsLS41MjEtMi42NjhjLS45MTQgMS4xNzUtMS45MjYgMS45ODMtMy4wMzUgMi40NTEtMS4xMS40NjctMi4yMy42OTUtMy4zNjEuNjk1LTEuNzg0IDAtMy4zODgtLjMxNC00LjgxMy0uOTMzLTEuNDI1LS42Mi0yLjYyNi0xLjQ3NS0zLjYwNS0yLjU2My0uOTc5LTEuMDg3LTEuNzMtMi4zNjctMi4yNTEtMy44MzUtLjUyMjYtMS40NjgtLjc4My0zLjA1MS0uNzgzLTQuNzQ4IDAtMS43NC4yNjA5LTMuMzU1Ljc4My00Ljg0NTMuNTIyLTEuNDg5OSAxLjI3Mi0yLjc4OTkgMi4yNTEtMy44OTk0Ljk3OS0xLjEwOTUgMi4xOC0xLjk3OTQgMy42MDUtMi42MTAxIDEuNDI1LS42MzA3IDMuMDI5LS45NDU4IDQuODEzLS45NDU4IDEuMTk2IDAgMi4zNTQuMTc5MyAzLjQ3NS41MzggMS4xMi4zNTkyIDIuMTMxLjg4NjYgMy4wMzQgMS41ODIxLjkwMy42OTY3IDEuNjQ4IDEuNTczOCAyLjIzNiAyLjU5NjcuNTg3IDEuMDIyOS45NDUgMi40MjUxIDEuMDc2IDMuNTQyOGgtNC44OTRjLS4zMDUtMS4xMTc3LS44OTItMi4zMDMyLTEuNzYyLTIuOTU1Ny0uODctLjY1MjUtMS45MjUtLjk4ODItMy4xNjQtLjk4ODItMS4xNTQgMC0yLjEzMi4yMTktMi45MzcuNjY0Mi0uODA1LjQ0NjQtMS40NTggMS4wNDE5LTEuOTU4IDEuNzkyMnMtLjg2NSAxLjYwMzUtMS4wOTMgMi41NjA1Yy0uMjI5Ljk1Ny0uMzQzIDEuOTQ2LS4zNDMgMi45NjggMCAuOTc5LjExNCAxLjkzMS4zNDMgMi44NTUuMjI4LjkyNS41OTMgMS43NTcgMS4wOTMgMi40OTYuNS43MzkgMS4xNTIgMS4zMzIgMS45NTggMS43NzguODA0LjQ0NiAxLjc4My42NjkgMi45MzcuNjY5IDEuNjk2IDAgMy4wMDYtLjIwNiAzLjkzMS0xLjA2NS45MjQtLjg1OSAxLjQ2Mi0yLjM5NSAxLjYxNS0zLjUxMmgtNS40Mzl2LTMuOTExaDEwLjA1NnYxMi4yOTFaIi8+PC9nPjxkZWZzPjxjbGlwUGF0aCBpZD0iYSI+PHBhdGggZmlsbD0iI2ZmZiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNTAgMTkuNjY0OCkiIGQ9Ik0wIDBoMTAwdjEyMC42N0gweiIvPjwvY2xpcFBhdGg+PC9kZWZzPjwvc3ZnPg==", "description": "", "descriptor": { "type": "rpc", diff --git a/application/src/main/data/upgrade/3.7.0/schema_update.sql b/application/src/main/data/upgrade/3.7.0/schema_update.sql index d400821fa3..05f7423003 100644 --- a/application/src/main/data/upgrade/3.7.0/schema_update.sql +++ b/application/src/main/data/upgrade/3.7.0/schema_update.sql @@ -195,4 +195,21 @@ $$ END $$; --- OAUTH2 UPDATE END \ No newline at end of file +-- OAUTH2 UPDATE END + +-- USER CREDENTIALS UPDATE START + +ALTER TABLE user_credentials ADD COLUMN IF NOT EXISTS activate_token_exp_time BIGINT; +-- Setting 24-hour TTL for existing activation tokens +UPDATE user_credentials SET activate_token_exp_time = cast(extract(EPOCH FROM NOW()) * 1000 AS BIGINT) + 86400000 + WHERE activate_token IS NOT NULL AND activate_token_exp_time IS NULL; + +ALTER TABLE user_credentials ADD COLUMN IF NOT EXISTS reset_token_exp_time BIGINT; +-- Setting 24-hour TTL for existing password reset tokens +UPDATE user_credentials SET reset_token_exp_time = cast(extract(EPOCH FROM NOW()) * 1000 AS BIGINT) + 86400000 + WHERE reset_token IS NOT NULL AND reset_token_exp_time IS NULL; + +UPDATE admin_settings SET json_value = (json_value::jsonb || '{"userActivationTokenTtl":24,"passwordResetTokenTtl":24}'::jsonb)::varchar + WHERE key = 'securitySettings'; + +-- USER CREDENTIALS UPDATE END diff --git a/application/src/main/java/org/thingsboard/server/controller/AdminController.java b/application/src/main/java/org/thingsboard/server/controller/AdminController.java index e4e6418168..a2115360d8 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AdminController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AdminController.java @@ -73,6 +73,7 @@ import org.thingsboard.server.common.data.sync.vc.VcUtils; import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.dao.audit.AuditLogService; import org.thingsboard.server.dao.settings.AdminSettingsService; +import org.thingsboard.server.dao.settings.SecuritySettingsService; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.security.auth.jwt.settings.JwtSettingsService; import org.thingsboard.server.service.security.auth.oauth2.CookieUtils; @@ -109,6 +110,7 @@ public class AdminController extends BaseController { private final SmsService smsService; private final AdminSettingsService adminSettingsService; private final SystemSecurityService systemSecurityService; + private final SecuritySettingsService securitySettingsService; private final JwtSettingsService jwtSettingsService; private final JwtTokenFactory tokenFactory; private final EntitiesVersionControlService versionControlService; @@ -167,7 +169,7 @@ public class AdminController extends BaseController { @ResponseBody public SecuritySettings getSecuritySettings() throws ThingsboardException { accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ); - return checkNotNull(systemSecurityService.getSecuritySettings()); + return checkNotNull(securitySettingsService.getSecuritySettings()); } @ApiOperation(value = "Update Security Settings (saveSecuritySettings)", @@ -179,7 +181,7 @@ public class AdminController extends BaseController { @Parameter(description = "A JSON value representing the Security Settings.") @RequestBody SecuritySettings securitySettings) throws ThingsboardException { accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.WRITE); - securitySettings = checkNotNull(systemSecurityService.saveSecuritySettings(securitySettings)); + securitySettings = checkNotNull(securitySettingsService.saveSecuritySettings(securitySettings)); return securitySettings; } diff --git a/application/src/main/java/org/thingsboard/server/controller/AuthController.java b/application/src/main/java/org/thingsboard/server/controller/AuthController.java index f95dfcb648..17f7930eff 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AuthController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AuthController.java @@ -21,17 +21,15 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationEventPublisher; -import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import org.thingsboard.rule.engine.api.MailService; import org.thingsboard.server.cache.limits.RateLimitService; @@ -48,6 +46,7 @@ import org.thingsboard.server.common.data.security.model.JwtPair; import org.thingsboard.server.common.data.security.model.SecuritySettings; import org.thingsboard.server.common.data.security.model.UserPasswordPolicy; import org.thingsboard.server.config.annotations.ApiOperation; +import org.thingsboard.server.dao.settings.SecuritySettingsService; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.security.auth.rest.RestAuthenticationDetails; import org.thingsboard.server.service.security.model.ActivateUserRequest; @@ -59,9 +58,6 @@ import org.thingsboard.server.service.security.model.UserPrincipal; import org.thingsboard.server.service.security.model.token.JwtTokenFactory; import org.thingsboard.server.service.security.system.SystemSecurityService; -import java.net.URI; -import java.net.URISyntaxException; - @RestController @TbCoreComponent @RequestMapping("/api") @@ -75,6 +71,7 @@ public class AuthController extends BaseController { private final JwtTokenFactory tokenFactory; private final MailService mailService; private final SystemSecurityService systemSecurityService; + private final SecuritySettingsService securitySettingsService; private final RateLimitService rateLimitService; private final ApplicationEventPublisher eventPublisher; @@ -82,9 +79,8 @@ public class AuthController extends BaseController { @ApiOperation(value = "Get current User (getUser)", notes = "Get the information about the User which credentials are used to perform this REST API call.") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") - @RequestMapping(value = "/auth/user", method = RequestMethod.GET) - public @ResponseBody - User getUser() throws ThingsboardException { + @GetMapping(value = "/auth/user") + public User getUser() throws ThingsboardException { SecurityUser securityUser = getCurrentUser(); return userService.findUserById(securityUser.getTenantId(), securityUser.getId()); } @@ -92,8 +88,7 @@ public class AuthController extends BaseController { @ApiOperation(value = "Logout (logout)", notes = "Special API call to record the 'logout' of the user to the Audit Logs. Since platform uses [JWT](https://jwt.io/), the actual logout is the procedure of clearing the [JWT](https://jwt.io/) token on the client side. ") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") - @RequestMapping(value = "/auth/logout", method = RequestMethod.POST) - @ResponseStatus(value = HttpStatus.OK) + @PostMapping(value = "/auth/logout") public void logout(HttpServletRequest request) throws ThingsboardException { logLogoutAction(request); } @@ -101,8 +96,7 @@ public class AuthController extends BaseController { @ApiOperation(value = "Change password for current User (changePassword)", notes = "Change the password for the User which credentials are used to perform this REST API call. Be aware that previously generated [JWT](https://jwt.io/) tokens will be still valid until they expire.") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") - @RequestMapping(value = "/auth/changePassword", method = RequestMethod.POST) - @ResponseStatus(value = HttpStatus.OK) + @PostMapping(value = "/auth/changePassword") public JwtPair changePassword(@Parameter(description = "Change Password Request") @RequestBody ChangePasswordRequest changePasswordRequest) throws ThingsboardException { String currentPassword = changePasswordRequest.getCurrentPassword(); @@ -125,46 +119,34 @@ public class AuthController extends BaseController { @ApiOperation(value = "Get the current User password policy (getUserPasswordPolicy)", notes = "API call to get the password policy for the password validation form(s).") - @RequestMapping(value = "/noauth/userPasswordPolicy", method = RequestMethod.GET) - @ResponseBody + @GetMapping(value = "/noauth/userPasswordPolicy") public UserPasswordPolicy getUserPasswordPolicy() throws ThingsboardException { - SecuritySettings securitySettings = - checkNotNull(systemSecurityService.getSecuritySettings()); + SecuritySettings securitySettings = checkNotNull(securitySettingsService.getSecuritySettings()); return securitySettings.getPasswordPolicy(); } @ApiOperation(value = "Check Activate User Token (checkActivateToken)", notes = "Checks the activation token and forwards user to 'Create Password' page. " + "If token is valid, returns '303 See Other' (redirect) response code with the correct address of 'Create Password' page and same 'activateToken' specified in the URL parameters. " + - "If token is not valid, returns '409 Conflict'.") - @RequestMapping(value = "/noauth/activate", params = {"activateToken"}, method = RequestMethod.GET) - public ResponseEntity<String> checkActivateToken( + "If token is not valid, returns '409 Conflict'. " + + "If token is expired, redirects to error page.") + @GetMapping(value = "/noauth/activate", params = {"activateToken"}) + public ResponseEntity<?> checkActivateToken( @Parameter(description = "The activate token string.") @RequestParam(value = "activateToken") String activateToken) { - HttpHeaders headers = new HttpHeaders(); - HttpStatus responseStatus; UserCredentials userCredentials = userService.findUserCredentialsByActivateToken(TenantId.SYS_TENANT_ID, activateToken); - if (userCredentials != null) { - String createURI = "/login/createPassword"; - try { - URI location = new URI(createURI + "?activateToken=" + activateToken); - headers.setLocation(location); - responseStatus = HttpStatus.SEE_OTHER; - } catch (URISyntaxException e) { - log.error("Unable to create URI with address [{}]", createURI); - responseStatus = HttpStatus.BAD_REQUEST; - } - } else { - responseStatus = HttpStatus.CONFLICT; + if (userCredentials == null) { + return response(HttpStatus.CONFLICT); + } else if (userCredentials.isActivationTokenExpired()) { + return redirectTo("/activationLinkExpired"); } - return new ResponseEntity<>(headers, responseStatus); + return redirectTo("/login/createPassword?activateToken=" + activateToken); } @ApiOperation(value = "Request reset password email (requestResetPasswordByEmail)", notes = "Request to send the reset password email if the user with specified email address is present in the database. " + "Always return '200 OK' status for security purposes.") - @RequestMapping(value = "/noauth/resetPasswordByEmail", method = RequestMethod.POST) - @ResponseStatus(value = HttpStatus.OK) + @PostMapping(value = "/noauth/resetPasswordByEmail") public void requestResetPasswordByEmail( @Parameter(description = "The JSON object representing the reset password email request.") @RequestBody ResetPasswordEmailRequest resetPasswordByEmailRequest, @@ -177,7 +159,7 @@ public class AuthController extends BaseController { String resetUrl = String.format("%s/api/noauth/resetPassword?resetToken=%s", baseUrl, userCredentials.getResetToken()); - mailService.sendResetPasswordEmailAsync(resetUrl, email); + mailService.sendResetPasswordEmailAsync(resetUrl, userCredentials.getResetTokenTtl(), email); } catch (Exception e) { log.warn("Error occurred: {}", e.getMessage()); } @@ -186,32 +168,22 @@ public class AuthController extends BaseController { @ApiOperation(value = "Check password reset token (checkResetToken)", notes = "Checks the password reset token and forwards user to 'Reset Password' page. " + "If token is valid, returns '303 See Other' (redirect) response code with the correct address of 'Reset Password' page and same 'resetToken' specified in the URL parameters. " + - "If token is not valid, returns '409 Conflict'.") - @RequestMapping(value = "/noauth/resetPassword", params = {"resetToken"}, method = RequestMethod.GET) - public ResponseEntity<String> checkResetToken( + "If token is not valid, returns '409 Conflict'. " + + "If token is expired, redirects to error page.") + @GetMapping(value = "/noauth/resetPassword", params = {"resetToken"}) + public ResponseEntity<?> checkResetToken( @Parameter(description = "The reset token string.") @RequestParam(value = "resetToken") String resetToken) { - HttpHeaders headers = new HttpHeaders(); - HttpStatus responseStatus; - String resetURI = "/login/resetPassword"; UserCredentials userCredentials = userService.findUserCredentialsByResetToken(TenantId.SYS_TENANT_ID, resetToken); - - if (userCredentials != null) { - if (!rateLimitService.checkRateLimit(LimitedApi.PASSWORD_RESET, userCredentials.getUserId(), defaultLimitsConfiguration)) { - return ResponseEntity.status(HttpStatus.TOO_MANY_REQUESTS).build(); - } - try { - URI location = new URI(resetURI + "?resetToken=" + resetToken); - headers.setLocation(location); - responseStatus = HttpStatus.SEE_OTHER; - } catch (URISyntaxException e) { - log.error("Unable to create URI with address [{}]", resetURI); - responseStatus = HttpStatus.BAD_REQUEST; - } - } else { - responseStatus = HttpStatus.CONFLICT; + if (userCredentials == null) { + return response(HttpStatus.CONFLICT); + } else if (userCredentials.isResetTokenExpired()) { + return redirectTo("/passwordResetLinkExpired"); + } + if (!rateLimitService.checkRateLimit(LimitedApi.PASSWORD_RESET, userCredentials.getUserId(), defaultLimitsConfiguration)) { + return response(HttpStatus.TOO_MANY_REQUESTS); } - return new ResponseEntity<>(headers, responseStatus); + return redirectTo("/login/resetPassword?resetToken=" + resetToken); } @ApiOperation(value = "Activate User", @@ -220,15 +192,12 @@ public class AuthController extends BaseController { "The response already contains the [JWT](https://jwt.io) activation and refresh tokens, " + "to simplify the user activation flow and avoid asking user to input password again after activation. " + "If token is valid, returns the object that contains [JWT](https://jwt.io/) access and refresh tokens. " + - "If token is not valid, returns '404 Bad Request'.") - @RequestMapping(value = "/noauth/activate", method = RequestMethod.POST) - @ResponseStatus(value = HttpStatus.OK) - @ResponseBody - public JwtPair activateUser( - @Parameter(description = "Activate user request.") - @RequestBody ActivateUserRequest activateRequest, - @RequestParam(required = false, defaultValue = "true") boolean sendActivationMail, - HttpServletRequest request) throws ThingsboardException { + "If token is not valid, returns '400 Bad Request'.") + @PostMapping(value = "/noauth/activate") + public JwtPair activateUser(@Parameter(description = "Activate user request.") + @RequestBody ActivateUserRequest activateRequest, + @RequestParam(required = false, defaultValue = "true") boolean sendActivationMail, + HttpServletRequest request) { String activateToken = activateRequest.getActivateToken(); String password = activateRequest.getPassword(); systemSecurityService.validatePassword(password, null); @@ -258,18 +227,18 @@ public class AuthController extends BaseController { @ApiOperation(value = "Reset password (resetPassword)", notes = "Checks the password reset token and updates the password. " + "If token is valid, returns the object that contains [JWT](https://jwt.io/) access and refresh tokens. " + - "If token is not valid, returns '404 Bad Request'.") - @RequestMapping(value = "/noauth/resetPassword", method = RequestMethod.POST) - @ResponseStatus(value = HttpStatus.OK) - @ResponseBody - public JwtPair resetPassword( - @Parameter(description = "Reset password request.") - @RequestBody ResetPasswordRequest resetPasswordRequest, - HttpServletRequest request) throws ThingsboardException { + "If token is not valid, returns '400 Bad Request'.") + @PostMapping(value = "/noauth/resetPassword") + public JwtPair resetPassword(@Parameter(description = "Reset password request.") + @RequestBody ResetPasswordRequest resetPasswordRequest, + HttpServletRequest request) throws ThingsboardException { String resetToken = resetPasswordRequest.getResetToken(); String password = resetPasswordRequest.getPassword(); UserCredentials userCredentials = userService.findUserCredentialsByResetToken(TenantId.SYS_TENANT_ID, resetToken); if (userCredentials != null) { + if (userCredentials.isResetTokenExpired()) { + throw new ThingsboardException("Password reset token expired", ThingsboardErrorCode.BAD_REQUEST_PARAMS); + } systemSecurityService.validatePassword(password, userCredentials); if (passwordEncoder.matches(password, userCredentials.getPassword())) { throw new ThingsboardException("New password should be different from existing!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); @@ -277,6 +246,7 @@ public class AuthController extends BaseController { String encodedPassword = passwordEncoder.encode(password); userCredentials.setPassword(encodedPassword); userCredentials.setResetToken(null); + userCredentials.setResetTokenExpTime(null); userCredentials = userService.replaceUserCredentials(TenantId.SYS_TENANT_ID, userCredentials); User user = userService.findUserById(TenantId.SYS_TENANT_ID, userCredentials.getUserId()); UserPrincipal principal = new UserPrincipal(UserPrincipal.Type.USER_NAME, user.getEmail()); diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java index 8021e71fd6..d266c7e6cc 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -27,7 +27,9 @@ import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.dao.DataAccessException; +import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.bind.MethodArgumentNotValidException; @@ -132,8 +134,8 @@ import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.exception.IncorrectParameterException; import org.thingsboard.server.dao.mobile.MobileAppService; import org.thingsboard.server.dao.model.ModelConstants; -import org.thingsboard.server.dao.oauth2.OAuth2ConfigTemplateService; import org.thingsboard.server.dao.oauth2.OAuth2ClientService; +import org.thingsboard.server.dao.oauth2.OAuth2ConfigTemplateService; import org.thingsboard.server.dao.ota.OtaPackageService; import org.thingsboard.server.dao.queue.QueueService; import org.thingsboard.server.dao.relation.RelationService; @@ -170,8 +172,8 @@ import org.thingsboard.server.service.sync.vc.EntitiesVersionControlService; import org.thingsboard.server.service.telemetry.AlarmSubscriptionService; import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; +import java.net.URI; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Objects; @@ -191,7 +193,7 @@ import static org.thingsboard.server.dao.service.Validator.validateId; @TbCoreComponent public abstract class BaseController { - private final Logger log = org.slf4j.LoggerFactory.getLogger(getClass()); + protected final Logger log = org.slf4j.LoggerFactory.getLogger(getClass()); /*Swagger UI description*/ @@ -912,6 +914,23 @@ public abstract class BaseController { } } + protected <T> ResponseEntity<T> response(HttpStatus status) { + return ResponseEntity.status(status).build(); + } + + protected <T> ResponseEntity<T> redirectTo(String location) { + URI uri; + try { + uri = URI.create(location); + } catch (IllegalArgumentException e) { + log.error("Failed to create URI from '{}'", location, e); + throw e; + } + return ResponseEntity.status(HttpStatus.SEE_OTHER) + .location(uri) + .build(); + } + protected List<OAuth2ClientId> getOAuth2ClientIds(UUID[] ids) throws ThingsboardException { if (ids == null) { return Collections.emptyList(); diff --git a/application/src/main/java/org/thingsboard/server/controller/ImageController.java b/application/src/main/java/org/thingsboard/server/controller/ImageController.java index 6ebb6fffe8..88b33389a5 100644 --- a/application/src/main/java/org/thingsboard/server/controller/ImageController.java +++ b/application/src/main/java/org/thingsboard/server/controller/ImageController.java @@ -312,7 +312,7 @@ public class ImageController extends BaseController { if (StringUtils.isNotEmpty(etag)) { etag = StringUtils.remove(etag, '\"'); // etag is wrapped in double quotes due to HTTP specification if (etag.equals(tbImageService.getETag(cacheKey))) { - return ResponseEntity.status(HttpStatus.NOT_MODIFIED).build(); + return response(HttpStatus.NOT_MODIFIED); } } diff --git a/application/src/main/java/org/thingsboard/server/controller/MobileApplicationController.java b/application/src/main/java/org/thingsboard/server/controller/MobileApplicationController.java index ca8b11ee80..11f017b85f 100644 --- a/application/src/main/java/org/thingsboard/server/controller/MobileApplicationController.java +++ b/application/src/main/java/org/thingsboard/server/controller/MobileApplicationController.java @@ -183,8 +183,7 @@ public class MobileApplicationController extends BaseController { .header("Location", appStoreLink) .build(); } else { - return ResponseEntity.status(HttpStatus.NOT_FOUND) - .build(); + return response(HttpStatus.NOT_FOUND); } } diff --git a/application/src/main/java/org/thingsboard/server/controller/UserController.java b/application/src/main/java/org/thingsboard/server/controller/UserController.java index 1772a64772..a71bd4dd38 100644 --- a/application/src/main/java/org/thingsboard/server/controller/UserController.java +++ b/application/src/main/java/org/thingsboard/server/controller/UserController.java @@ -21,7 +21,6 @@ import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationEventPublisher; import org.springframework.http.HttpStatus; @@ -44,6 +43,7 @@ import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.rule.engine.api.MailService; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.User; +import org.thingsboard.server.common.data.UserActivationLink; import org.thingsboard.server.common.data.UserEmailInfo; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; @@ -119,7 +119,6 @@ public class UserController extends BaseController { public static final String USER_ID = "userId"; public static final String PATHS = "paths"; public static final String YOU_DON_T_HAVE_PERMISSION_TO_PERFORM_THIS_OPERATION = "You don't have permission to perform this operation!"; - public static final String ACTIVATE_URL_PATTERN = "%s/api/noauth/activate?activateToken=%s"; public static final String MOBILE_TOKEN_HEADER = "X-Mobile-Token"; @Value("${security.user_token_access_enabled}") @@ -130,12 +129,8 @@ public class UserController extends BaseController { private final SystemSecurityService systemSecurityService; private final ApplicationEventPublisher eventPublisher; private final TbUserService tbUserService; - - @Autowired - private EntityQueryService entityQueryService; - - @Autowired - private EntityService entityService; + private final EntityQueryService entityQueryService; + private final EntityService entityService; @ApiOperation(value = "Get User (getUserById)", notes = "Fetch the User object based on the provided User Id. " + @@ -212,7 +207,7 @@ public class UserController extends BaseController { public User saveUser( @Parameter(description = "A JSON value representing the User.", required = true) @RequestBody User user, - @Parameter(description = "Send activation email (or use activation link)" , schema = @Schema(defaultValue = "true")) + @Parameter(description = "Send activation email (or use activation link)", schema = @Schema(defaultValue = "true")) @RequestParam(required = false, defaultValue = "true") boolean sendActivationMail, HttpServletRequest request) throws ThingsboardException { if (!Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) { user.setTenantId(getCurrentUser().getTenantId()); @@ -230,45 +225,39 @@ public class UserController extends BaseController { @Parameter(description = "Email of the user", required = true) @RequestParam(value = "email") String email, HttpServletRequest request) throws ThingsboardException { - User user = checkNotNull(userService.findUserByEmail(getCurrentUser().getTenantId(), email)); - - accessControlService.checkPermission(getCurrentUser(), Resource.USER, Operation.READ, - user.getId(), user); + SecurityUser securityUser = getCurrentUser(); + User user = checkNotNull(userService.findUserByEmail(securityUser.getTenantId(), email)); + accessControlService.checkPermission(securityUser, Resource.USER, Operation.READ, user.getId(), user); - UserCredentials userCredentials = userService.findUserCredentialsByUserId(getCurrentUser().getTenantId(), user.getId()); - if (!userCredentials.isEnabled() && userCredentials.getActivateToken() != null) { - String baseUrl = systemSecurityService.getBaseUrl(getTenantId(), getCurrentUser().getCustomerId(), request); - String activateUrl = String.format(ACTIVATE_URL_PATTERN, baseUrl, - userCredentials.getActivateToken()); - mailService.sendActivationEmail(activateUrl, email); - } else { - throw new ThingsboardException("User is already activated!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); - } + UserActivationLink activationLink = tbUserService.getActivationLink(securityUser.getTenantId(), securityUser.getCustomerId(), user.getId(), request); + mailService.sendActivationEmail(activationLink.value(), activationLink.ttlMs(), email); } - @ApiOperation(value = "Get the activation link (getActivationLink)", + @ApiOperation(value = "Get activation link (getActivationLink)", notes = "Get the activation link for the user. " + "The base url for activation link is configurable in the general settings of system administrator. " + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") - @RequestMapping(value = "/user/{userId}/activationLink", method = RequestMethod.GET, produces = "text/plain") + @GetMapping(value = "/user/{userId}/activationLink", produces = "text/plain") @ResponseBody - public String getActivationLink( - @Parameter(description = USER_ID_PARAM_DESCRIPTION) - @PathVariable(USER_ID) String strUserId, - HttpServletRequest request) throws ThingsboardException { + public String getActivationLink(@Parameter(description = USER_ID_PARAM_DESCRIPTION) + @PathVariable(USER_ID) String strUserId, + HttpServletRequest request) throws ThingsboardException { + return getActivationLinkInfo(strUserId, request).value(); + } + + @ApiOperation(value = "Get activation link info (getActivationLinkInfo)", + notes = "Get the activation link info for the user. " + + "The base url for activation link is configurable in the general settings of system administrator. " + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH) + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") + @GetMapping(value = "/user/{userId}/activationLinkInfo") + public UserActivationLink getActivationLinkInfo(@Parameter(description = USER_ID_PARAM_DESCRIPTION) + @PathVariable(USER_ID) String strUserId, + HttpServletRequest request) throws ThingsboardException { checkParameter(USER_ID, strUserId); UserId userId = new UserId(toUUID(strUserId)); - User user = checkUserId(userId, Operation.READ); - SecurityUser authUser = getCurrentUser(); - UserCredentials userCredentials = userService.findUserCredentialsByUserId(authUser.getTenantId(), user.getId()); - if (!userCredentials.isEnabled() && userCredentials.getActivateToken() != null) { - String baseUrl = systemSecurityService.getBaseUrl(getTenantId(), getCurrentUser().getCustomerId(), request); - String activateUrl = String.format(ACTIVATE_URL_PATTERN, baseUrl, - userCredentials.getActivateToken()); - return activateUrl; - } else { - throw new ThingsboardException("User is already activated!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); - } + checkUserId(userId, Operation.READ); + SecurityUser securityUser = getCurrentUser(); + return tbUserService.getActivationLink(securityUser.getTenantId(), securityUser.getCustomerId(), userId, request); } @ApiOperation(value = "Delete User (deleteUser)", @@ -411,7 +400,7 @@ public class UserController extends BaseController { public void setUserCredentialsEnabled( @Parameter(description = USER_ID_PARAM_DESCRIPTION) @PathVariable(USER_ID) String strUserId, - @Parameter(description = "Enable (\"true\") or disable (\"false\") the credentials." , schema = @Schema(defaultValue = "true")) + @Parameter(description = "Enable (\"true\") or disable (\"false\") the credentials.", schema = @Schema(defaultValue = "true")) @RequestParam(required = false, defaultValue = "true") boolean userCredentialsEnabled) throws ThingsboardException { checkParameter(USER_ID, strUserId); UserId userId = new UserId(toUUID(strUserId)); diff --git a/application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java b/application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java index 840750a781..17ceb17ed1 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java @@ -34,8 +34,10 @@ import org.thingsboard.server.common.data.alarm.AlarmComment; import org.thingsboard.server.common.data.alarm.EntityAlarm; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.domain.Domain; +import org.thingsboard.server.common.data.edge.Edge; import org.thingsboard.server.common.data.edge.EdgeEventActionType; import org.thingsboard.server.common.data.edge.EdgeEventType; +import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.RelationTypeGroup; @@ -134,6 +136,17 @@ public class EdgeEventSourcingListener { return; } try { + if (event.getEntityId().getEntityType().equals(EntityType.RULE_CHAIN) && event.getEdgeId() != null && event.getActionType().equals(ActionType.ASSIGNED_TO_EDGE)) { + try { + Edge edge = JacksonUtil.fromString(event.getBody(), Edge.class); + if (edge != null && new RuleChainId(event.getEntityId().getId()).equals(edge.getRootRuleChainId())) { + log.trace("[{}] skipping ASSIGNED_TO_EDGE event of RULE_CHAIN entity in case Edge Root Rule Chain: {}", event.getTenantId(), event); + return; + } + } catch (Exception ignored) { + return; + } + } log.trace("[{}] ActionEntityEvent called: {}", event.getTenantId(), event); tbClusterService.sendNotificationMsgToEdge(event.getTenantId(), event.getEdgeId(), event.getEntityId(), event.getBody(), null, EdgeUtils.getEdgeEventActionTypeByActionType(event.getActionType()), diff --git a/application/src/main/java/org/thingsboard/server/service/edge/RelatedEdgesSourcingListener.java b/application/src/main/java/org/thingsboard/server/service/edge/RelatedEdgesSourcingListener.java index 851f59c3ab..2132b9e4a6 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/RelatedEdgesSourcingListener.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/RelatedEdgesSourcingListener.java @@ -55,6 +55,7 @@ public class RelatedEdgesSourcingListener { @TransactionalEventListener(fallbackExecution = true) public void handleEvent(ActionEntityEvent<?> event) { executorService.submit(() -> { + log.trace("[{}] ActionEntityEvent called: {}", event.getTenantId(), event); try { switch (event.getActionType()) { case ASSIGNED_TO_EDGE, UNASSIGNED_FROM_EDGE -> @@ -69,6 +70,7 @@ public class RelatedEdgesSourcingListener { @TransactionalEventListener(fallbackExecution = true) public void handleEvent(DeleteEntityEvent<?> event) { executorService.submit(() -> { + log.trace("[{}] DeleteEntityEvent called: {}", event.getTenantId(), event); try { relatedEdgesService.publishRelatedEdgeIdsEvictEvent(event.getTenantId(), event.getEntityId()); } catch (Exception e) { diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/user/DefaultUserService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/user/DefaultUserService.java index 299d499daa..ad4b7c097e 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/user/DefaultUserService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/user/DefaultUserService.java @@ -22,7 +22,9 @@ import org.springframework.stereotype.Service; import org.thingsboard.rule.engine.api.MailService; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.User; +import org.thingsboard.server.common.data.UserActivationLink; import org.thingsboard.server.common.data.audit.ActionType; +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; @@ -33,7 +35,7 @@ import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.entitiy.AbstractTbEntityService; import org.thingsboard.server.service.security.system.SystemSecurityService; -import static org.thingsboard.server.controller.UserController.ACTIVATE_URL_PATTERN; +import java.util.concurrent.TimeUnit; @Service @TbCoreComponent @@ -53,13 +55,9 @@ public class DefaultUserService extends AbstractTbEntityService implements TbUse boolean sendEmail = tbUser.getId() == null && sendActivationMail; User savedUser = checkNotNull(userService.saveUser(tenantId, tbUser)); if (sendEmail) { - UserCredentials userCredentials = userService.findUserCredentialsByUserId(tenantId, savedUser.getId()); - String baseUrl = systemSecurityService.getBaseUrl(tenantId, customerId, request); - String activateUrl = String.format(ACTIVATE_URL_PATTERN, baseUrl, - userCredentials.getActivateToken()); - String email = savedUser.getEmail(); + UserActivationLink activationLink = getActivationLink(tenantId, customerId, savedUser.getId(), request); try { - mailService.sendActivationEmail(activateUrl, email); + mailService.sendActivationEmail(activationLink.value(), activationLink.ttlMs(), savedUser.getEmail()); } catch (ThingsboardException e) { userService.deleteUser(tenantId, savedUser); throw e; @@ -87,4 +85,24 @@ public class DefaultUserService extends AbstractTbEntityService implements TbUse throw e; } } + + @Override + public UserActivationLink getActivationLink(TenantId tenantId, CustomerId customerId, UserId userId, HttpServletRequest request) throws ThingsboardException { + UserCredentials userCredentials = userService.findUserCredentialsByUserId(tenantId, userId); + if (!userCredentials.isEnabled() && userCredentials.getActivateToken() != null) { + long ttl = userCredentials.getActivationTokenTtl(); + if (ttl < TimeUnit.MINUTES.toMillis(15)) { // renew link if less than 15 minutes before expiration + userCredentials = userService.generateUserActivationToken(userCredentials); + userCredentials = userService.saveUserCredentials(tenantId, userCredentials); + ttl = userCredentials.getActivationTokenTtl(); + log.debug("[{}][{}] Regenerated expired user activation token", tenantId, userId); + } + String baseUrl = systemSecurityService.getBaseUrl(tenantId, customerId, request); + String link = baseUrl + "/api/noauth/activate?activateToken=" + userCredentials.getActivateToken(); + return new UserActivationLink(link, ttl); + } else { + throw new ThingsboardException("User is already activated!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); + } + } + } diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/user/TbUserService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/user/TbUserService.java index 388db9df40..e7689692a4 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/user/TbUserService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/user/TbUserService.java @@ -16,14 +16,19 @@ package org.thingsboard.server.service.entitiy.user; import jakarta.servlet.http.HttpServletRequest; +import org.thingsboard.server.common.data.UserActivationLink; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.id.UserId; public interface TbUserService { User save(TenantId tenantId, CustomerId customerId, User tbUser, boolean sendActivationMail, HttpServletRequest request, User user) throws ThingsboardException; void delete(TenantId tenantId, CustomerId customerId, User user, User responsibleUser) throws ThingsboardException; + + UserActivationLink getActivationLink(TenantId tenantId, CustomerId customerId, UserId userId, HttpServletRequest request) throws ThingsboardException; + } diff --git a/application/src/main/java/org/thingsboard/server/service/install/update/DefaultCacheCleanupService.java b/application/src/main/java/org/thingsboard/server/service/install/update/DefaultCacheCleanupService.java index 0085df35d7..1a03ae491a 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/update/DefaultCacheCleanupService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/update/DefaultCacheCleanupService.java @@ -92,4 +92,5 @@ public class DefaultCacheCleanupService implements CacheCleanupService { } cacheManager.getCacheNames().forEach(this::clearCacheByName); } + } diff --git a/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java b/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java index 3577683729..1603720450 100644 --- a/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java +++ b/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java @@ -160,12 +160,12 @@ public class DefaultMailService implements MailService { } @Override - public void sendActivationEmail(String activationLink, String email) throws ThingsboardException { - + public void sendActivationEmail(String activationLink, long ttlMs, String email) throws ThingsboardException { String subject = messages.getMessage("activation.subject", null, Locale.US); Map<String, Object> model = new HashMap<>(); model.put("activationLink", activationLink); + model.put("activationLinkTtlInHours", (int) Math.ceil(ttlMs / 3600000.0)); model.put(TARGET_EMAIL, email); String message = mergeTemplateIntoString("activation.ftl", model); @@ -188,12 +188,13 @@ public class DefaultMailService implements MailService { } @Override - public void sendResetPasswordEmail(String passwordResetLink, String email) throws ThingsboardException { + public void sendResetPasswordEmail(String passwordResetLink, long ttlMs, String email) throws ThingsboardException { String subject = messages.getMessage("reset.password.subject", null, Locale.US); Map<String, Object> model = new HashMap<>(); model.put("passwordResetLink", passwordResetLink); + model.put("passwordResetLinkTtlInHours", (int) Math.ceil(ttlMs / 3600000.0)); model.put(TARGET_EMAIL, email); String message = mergeTemplateIntoString("reset.password.ftl", model); @@ -202,10 +203,10 @@ public class DefaultMailService implements MailService { } @Override - public void sendResetPasswordEmailAsync(String passwordResetLink, String email) { + public void sendResetPasswordEmailAsync(String passwordResetLink, long ttlMs, String email) { passwordResetExecutorService.execute(() -> { try { - this.sendResetPasswordEmail(passwordResetLink, email); + this.sendResetPasswordEmail(passwordResetLink, ttlMs, email); } catch (Exception e) { log.error("Error occurred: {} ", e.getMessage()); } diff --git a/application/src/main/java/org/thingsboard/server/service/mail/DefaultTbMailConfigTemplateService.java b/application/src/main/java/org/thingsboard/server/service/mail/DefaultTbMailConfigTemplateService.java index 14e52c1326..7c86771f8d 100644 --- a/application/src/main/java/org/thingsboard/server/service/mail/DefaultTbMailConfigTemplateService.java +++ b/application/src/main/java/org/thingsboard/server/service/mail/DefaultTbMailConfigTemplateService.java @@ -32,7 +32,7 @@ public class DefaultTbMailConfigTemplateService implements TbMailConfigTemplateS @PostConstruct private void postConstruct() throws IOException { - mailConfigTemplates = JacksonUtil.toJsonNode(new ClassPathResource("/templates/mail_config_templates.json").getFile()); + mailConfigTemplates = JacksonUtil.toJsonNode(new ClassPathResource("/templates/mail_config_templates.json").getInputStream()); } @Override diff --git a/application/src/main/java/org/thingsboard/server/service/mobile/secret/MobileAppSecretServiceImpl.java b/application/src/main/java/org/thingsboard/server/service/mobile/secret/MobileAppSecretServiceImpl.java index bef31622ff..73496ca1a0 100644 --- a/application/src/main/java/org/thingsboard/server/service/mobile/secret/MobileAppSecretServiceImpl.java +++ b/application/src/main/java/org/thingsboard/server/service/mobile/secret/MobileAppSecretServiceImpl.java @@ -25,11 +25,12 @@ import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.security.model.JwtPair; import org.thingsboard.server.dao.entity.AbstractCachedService; +import org.thingsboard.server.dao.settings.SecuritySettingsService; import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.model.token.JwtTokenFactory; -import org.thingsboard.server.service.security.system.SystemSecurityService; -import static org.thingsboard.server.service.security.system.DefaultSystemSecurityService.DEFAULT_MOBILE_SECRET_KEY_LENGTH; +import static org.thingsboard.server.dao.settings.DefaultSecuritySettingsService.DEFAULT_MOBILE_SECRET_KEY_LENGTH; + @Service @Slf4j @@ -37,12 +38,12 @@ import static org.thingsboard.server.service.security.system.DefaultSystemSecuri public class MobileAppSecretServiceImpl extends AbstractCachedService<String, JwtPair, MobileSecretEvictEvent> implements MobileAppSecretService { private final JwtTokenFactory tokenFactory; - private final SystemSecurityService systemSecurityService; + private final SecuritySettingsService securitySettingsService; @Override public String generateMobileAppSecret(SecurityUser securityUser) { log.trace("Executing generateSecret for user [{}]", securityUser.getId()); - Integer mobileSecretKeyLength = systemSecurityService.getSecuritySettings().getMobileSecretKeyLength(); + Integer mobileSecretKeyLength = securitySettingsService.getSecuritySettings().getMobileSecretKeyLength(); String secret = StringUtils.generateSafeToken(mobileSecretKeyLength == null ? DEFAULT_MOBILE_SECRET_KEY_LENGTH : mobileSecretKeyLength); cache.put(secret, tokenFactory.createTokenPair(securityUser)); return secret; @@ -63,4 +64,5 @@ public class MobileAppSecretServiceImpl extends AbstractCachedService<String, Jw public void handleEvictEvent(MobileSecretEvictEvent event) { cache.evict(event.getSecret()); } + } diff --git a/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestAuthenticationProvider.java b/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestAuthenticationProvider.java index 65fa344957..b9fe54deec 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestAuthenticationProvider.java +++ b/application/src/main/java/org/thingsboard/server/service/security/auth/rest/RestAuthenticationProvider.java @@ -40,6 +40,7 @@ import org.thingsboard.server.common.data.security.model.SecuritySettings; import org.thingsboard.server.common.data.security.model.UserPasswordPolicy; import org.thingsboard.server.dao.customer.CustomerService; import org.thingsboard.server.dao.exception.DataValidationException; +import org.thingsboard.server.dao.settings.SecuritySettingsService; import org.thingsboard.server.dao.user.UserService; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.security.auth.MfaAuthenticationToken; @@ -58,6 +59,7 @@ import java.util.UUID; public class RestAuthenticationProvider implements AuthenticationProvider { private final SystemSecurityService systemSecurityService; + private final SecuritySettingsService securitySettingsService; private final UserService userService; private final CustomerService customerService; private final TwoFactorAuthService twoFactorAuthService; @@ -66,10 +68,12 @@ public class RestAuthenticationProvider implements AuthenticationProvider { public RestAuthenticationProvider(final UserService userService, final CustomerService customerService, final SystemSecurityService systemSecurityService, + SecuritySettingsService securitySettingsService, TwoFactorAuthService twoFactorAuthService) { this.userService = userService; this.customerService = customerService; this.systemSecurityService = systemSecurityService; + this.securitySettingsService = securitySettingsService; this.twoFactorAuthService = twoFactorAuthService; } @@ -82,13 +86,13 @@ public class RestAuthenticationProvider implements AuthenticationProvider { throw new BadCredentialsException("Authentication Failed. Bad user principal."); } - UserPrincipal userPrincipal = (UserPrincipal) principal; + UserPrincipal userPrincipal = (UserPrincipal) principal; SecurityUser securityUser; if (userPrincipal.getType() == UserPrincipal.Type.USER_NAME) { String username = userPrincipal.getValue(); String password = (String) authentication.getCredentials(); - SecuritySettings securitySettings = systemSecurityService.getSecuritySettings(); + SecuritySettings securitySettings = securitySettingsService.getSecuritySettings(); UserPasswordPolicy passwordPolicy = securitySettings.getPasswordPolicy(); if (Boolean.TRUE.equals(passwordPolicy.getForceUserToResetPasswordIfNotValid())) { try { diff --git a/application/src/main/java/org/thingsboard/server/service/security/system/DefaultSystemSecurityService.java b/application/src/main/java/org/thingsboard/server/service/security/system/DefaultSystemSecurityService.java index 1b8cec2c91..6516bd7ce6 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/system/DefaultSystemSecurityService.java +++ b/application/src/main/java/org/thingsboard/server/service/security/system/DefaultSystemSecurityService.java @@ -18,8 +18,8 @@ package org.thingsboard.server.service.security.system; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; -import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.passay.CharacterRule; import org.passay.EnglishCharacterData; @@ -29,9 +29,6 @@ import org.passay.PasswordValidator; import org.passay.Rule; import org.passay.RuleResult; import org.passay.WhitespaceRule; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cache.annotation.CacheEvict; -import org.springframework.cache.annotation.Cacheable; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.DisabledException; import org.springframework.security.authentication.LockedException; @@ -55,6 +52,7 @@ import org.thingsboard.server.common.data.security.model.mfa.PlatformTwoFaSettin import org.thingsboard.server.dao.audit.AuditLogService; import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.settings.AdminSettingsService; +import org.thingsboard.server.dao.settings.SecuritySettingsService; import org.thingsboard.server.dao.user.UserService; import org.thingsboard.server.dao.user.UserServiceImpl; import org.thingsboard.server.service.security.auth.rest.RestAuthenticationDetails; @@ -68,76 +66,23 @@ import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; -import static org.thingsboard.server.common.data.CacheConstants.SECURITY_SETTINGS_CACHE; - @Service @Slf4j +@RequiredArgsConstructor public class DefaultSystemSecurityService implements SystemSecurityService { - public static final int DEFAULT_MOBILE_SECRET_KEY_LENGTH = 64; - - @Autowired - private AdminSettingsService adminSettingsService; - - @Autowired - private BCryptPasswordEncoder encoder; - - @Autowired - private UserService userService; - - @Autowired - private MailService mailService; - - @Autowired - private AuditLogService auditLogService; - - @Resource - private SystemSecurityService self; - - @Cacheable(cacheNames = SECURITY_SETTINGS_CACHE, key = "'securitySettings'") - @Override - public SecuritySettings getSecuritySettings() { - SecuritySettings securitySettings = null; - AdminSettings adminSettings = adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, "securitySettings"); - if (adminSettings != null) { - try { - securitySettings = JacksonUtil.convertValue(adminSettings.getJsonValue(), SecuritySettings.class); - } catch (Exception e) { - throw new RuntimeException("Failed to load security settings!", e); - } - } else { - securitySettings = new SecuritySettings(); - securitySettings.setPasswordPolicy(new UserPasswordPolicy()); - securitySettings.getPasswordPolicy().setMinimumLength(6); - securitySettings.getPasswordPolicy().setMaximumLength(72); - securitySettings.setMobileSecretKeyLength(DEFAULT_MOBILE_SECRET_KEY_LENGTH); - } - return securitySettings; - } - - @CacheEvict(cacheNames = SECURITY_SETTINGS_CACHE, key = "'securitySettings'") - @Override - public SecuritySettings saveSecuritySettings(SecuritySettings securitySettings) { - AdminSettings adminSettings = adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, "securitySettings"); - if (adminSettings == null) { - adminSettings = new AdminSettings(); - adminSettings.setTenantId(TenantId.SYS_TENANT_ID); - adminSettings.setKey("securitySettings"); - } - adminSettings.setJsonValue(JacksonUtil.valueToTree(securitySettings)); - AdminSettings savedAdminSettings = adminSettingsService.saveAdminSettings(TenantId.SYS_TENANT_ID, adminSettings); - try { - return JacksonUtil.convertValue(savedAdminSettings.getJsonValue(), SecuritySettings.class); - } catch (Exception e) { - throw new RuntimeException("Failed to load security settings!", e); - } - } + private final AdminSettingsService adminSettingsService; + private final BCryptPasswordEncoder encoder; + private final UserService userService; + private final MailService mailService; + private final AuditLogService auditLogService; + private final SecuritySettingsService securitySettingsService; @Override public void validateUserCredentials(TenantId tenantId, UserCredentials userCredentials, String username, String password) throws AuthenticationException { if (!encoder.matches(password, userCredentials.getPassword())) { int failedLoginAttempts = userService.increaseFailedLoginAttempts(tenantId, userCredentials.getUserId()); - SecuritySettings securitySettings = self.getSecuritySettings(); + SecuritySettings securitySettings = securitySettingsService.getSecuritySettings(); if (securitySettings.getMaxFailedLoginAttempts() != null && securitySettings.getMaxFailedLoginAttempts() > 0) { if (failedLoginAttempts > securitySettings.getMaxFailedLoginAttempts() && userCredentials.isEnabled()) { lockAccount(userCredentials.getUserId(), username, securitySettings.getUserLockoutNotificationEmail(), securitySettings.getMaxFailedLoginAttempts()); @@ -153,7 +98,7 @@ public class DefaultSystemSecurityService implements SystemSecurityService { userService.resetFailedLoginAttempts(tenantId, userCredentials.getUserId()); - SecuritySettings securitySettings = self.getSecuritySettings(); + SecuritySettings securitySettings = securitySettingsService.getSecuritySettings(); if (isPositiveInteger(securitySettings.getPasswordPolicy().getPasswordExpirationPeriodDays())) { if ((userCredentials.getCreatedTime() + TimeUnit.DAYS.toMillis(securitySettings.getPasswordPolicy().getPasswordExpirationPeriodDays())) @@ -181,7 +126,7 @@ public class DefaultSystemSecurityService implements SystemSecurityService { if (maxVerificationFailures != null && maxVerificationFailures > 0 && failedVerificationAttempts >= maxVerificationFailures) { userService.setUserCredentialsEnabled(TenantId.SYS_TENANT_ID, userId, false); - SecuritySettings securitySettings = self.getSecuritySettings(); + SecuritySettings securitySettings = securitySettingsService.getSecuritySettings(); lockAccount(userId, securityUser.getEmail(), securitySettings.getUserLockoutNotificationEmail(), maxVerificationFailures); throw new LockedException("User account was locked due to exceeded 2FA verification attempts"); } @@ -200,7 +145,7 @@ public class DefaultSystemSecurityService implements SystemSecurityService { @Override public void validatePassword(String password, UserCredentials userCredentials) throws DataValidationException { - SecuritySettings securitySettings = self.getSecuritySettings(); + SecuritySettings securitySettings = securitySettingsService.getSecuritySettings(); UserPasswordPolicy passwordPolicy = securitySettings.getPasswordPolicy(); validatePasswordByPolicy(password, passwordPolicy); @@ -330,4 +275,5 @@ public class DefaultSystemSecurityService implements SystemSecurityService { private static boolean isPositiveInteger(Integer val) { return val != null && val.intValue() > 0; } + } diff --git a/application/src/main/java/org/thingsboard/server/service/security/system/SystemSecurityService.java b/application/src/main/java/org/thingsboard/server/service/security/system/SystemSecurityService.java index 737bf95b13..8c1ac733ee 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/system/SystemSecurityService.java +++ b/application/src/main/java/org/thingsboard/server/service/security/system/SystemSecurityService.java @@ -22,7 +22,6 @@ import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.security.UserCredentials; -import org.thingsboard.server.common.data.security.model.SecuritySettings; import org.thingsboard.server.common.data.security.model.UserPasswordPolicy; import org.thingsboard.server.common.data.security.model.mfa.PlatformTwoFaSettings; import org.thingsboard.server.dao.exception.DataValidationException; @@ -30,10 +29,6 @@ import org.thingsboard.server.service.security.model.SecurityUser; public interface SystemSecurityService { - SecuritySettings getSecuritySettings(); - - SecuritySettings saveSecuritySettings(SecuritySettings securitySettings); - void validatePasswordByPolicy(String password, UserPasswordPolicy passwordPolicy); void validateUserCredentials(TenantId tenantId, UserCredentials userCredentials, String username, String password) throws AuthenticationException; @@ -47,4 +42,5 @@ public interface SystemSecurityService { void logLoginAction(User user, Object authenticationDetails, ActionType actionType, Exception e); void logLoginAction(User user, Object authenticationDetails, ActionType actionType, String provider, Exception e); + } diff --git a/application/src/main/resources/templates/activation.ftl b/application/src/main/resources/templates/activation.ftl index ce51930521..d5c148a56b 100644 --- a/application/src/main/resources/templates/activation.ftl +++ b/application/src/main/resources/templates/activation.ftl @@ -88,7 +88,7 @@ background-color: #f6f6f6; </tr> <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> <td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top"> - To confirm your email address and choose a password, just click the button below. + To confirm your email address and choose a password, just click the button below. The link will expire in ${activationLinkTtlInHours} hours. </td> </tr> <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> diff --git a/application/src/main/resources/templates/reset.password.ftl b/application/src/main/resources/templates/reset.password.ftl index 3f36c922f0..6b2fa5e8bf 100644 --- a/application/src/main/resources/templates/reset.password.ftl +++ b/application/src/main/resources/templates/reset.password.ftl @@ -93,7 +93,7 @@ background-color: #f6f6f6; </tr> <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> <td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top"> - Click below in order to proceed password reset procedure. + Click below in order to proceed password reset procedure. The link will expire in ${passwordResetLinkTtlInHours} hours. </td> </tr> <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 785f124583..e1893511f3 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -1658,6 +1658,8 @@ queue: connection_timeout: "${TB_QUEUE_RABBIT_MQ_CONNECTION_TIMEOUT:60000}" # RabbitMQ has a timeout for connection handshake. When clients run in heavily constrained environments, it may be necessary to increase the timeout handshake_timeout: "${TB_QUEUE_RABBIT_MQ_HANDSHAKE_TIMEOUT:10000}" + # The maximum number of messages returned in a single call of doPoll() method + max_poll_messages: "${TB_QUEUE_RABBIT_MQ_MAX_POLL_MESSAGES:1}" queue-properties: # RabbitMQ properties for Rule Engine queues rule-engine: "${TB_QUEUE_RABBIT_MQ_RE_QUEUE_PROPERTIES:x-max-length-bytes:1048576000;x-message-ttl:604800000}" diff --git a/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java b/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java index eba04e7b5e..af20c71e5b 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java @@ -145,6 +145,7 @@ import java.util.function.Consumer; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch; @@ -340,7 +341,7 @@ public abstract class AbstractWebTest extends AbstractInMemoryStorageTest { currentActivateToken = activationLink.split("=")[1]; return null; } - }).when(mailService).sendActivationEmail(anyString(), anyString()); + }).when(mailService).sendActivationEmail(anyString(), anyLong(), anyString()); Mockito.doAnswer(new Answer<Void>() { public Void answer(InvocationOnMock invocation) { @@ -349,7 +350,7 @@ public abstract class AbstractWebTest extends AbstractInMemoryStorageTest { currentResetPasswordToken = passwordResetLink.split("=")[1]; return null; } - }).when(mailService).sendResetPasswordEmailAsync(anyString(), anyString()); + }).when(mailService).sendResetPasswordEmailAsync(anyString(), anyLong(), anyString()); } @After diff --git a/application/src/test/java/org/thingsboard/server/controller/AuthControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/AuthControllerTest.java index 1cf389a93d..817ded33e7 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AuthControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AuthControllerTest.java @@ -16,20 +16,30 @@ package org.thingsboard.server.controller; import com.fasterxml.jackson.databind.JsonNode; +import org.assertj.core.data.Offset; import org.junit.After; import org.junit.Test; import org.mockito.Mockito; +import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.http.HttpHeaders; import org.testcontainers.shaded.org.apache.commons.lang3.RandomStringUtils; import org.thingsboard.common.util.JacksonUtil; +import org.thingsboard.server.common.data.StringUtils; +import org.thingsboard.server.common.data.User; +import org.thingsboard.server.common.data.UserActivationLink; import org.thingsboard.server.common.data.security.Authority; +import org.thingsboard.server.common.data.security.UserCredentials; import org.thingsboard.server.common.data.security.model.SecuritySettings; import org.thingsboard.server.dao.service.DaoSqlTest; +import org.thingsboard.server.dao.user.UserCredentialsDao; import org.thingsboard.server.service.security.auth.rest.LoginRequest; import org.thingsboard.server.service.security.model.ChangePasswordRequest; import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.within; import static org.hamcrest.Matchers.is; import static org.mockito.ArgumentMatchers.anyString; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; @@ -39,55 +49,55 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @DaoSqlTest public class AuthControllerTest extends AbstractControllerTest { + @SpyBean + private UserCredentialsDao userCredentialsDao; + @After public void tearDown() throws Exception { loginSysAdmin(); - SecuritySettings securitySettings = doGet("/api/admin/securitySettings", SecuritySettings.class); - - securitySettings.getPasswordPolicy().setMaximumLength(72); - securitySettings.getPasswordPolicy().setForceUserToResetPasswordIfNotValid(false); - - doPost("/api/admin/securitySettings", securitySettings).andExpect(status().isOk()); + updateSecuritySettings(securitySettings -> { + securitySettings.getPasswordPolicy().setMaximumLength(72); + securitySettings.getPasswordPolicy().setForceUserToResetPasswordIfNotValid(false); + }); } @Test public void testGetUser() throws Exception { - doGet("/api/auth/user") - .andExpect(status().isUnauthorized()); - + .andExpect(status().isUnauthorized()); + loginSysAdmin(); doGet("/api/auth/user") - .andExpect(status().isOk()) - .andExpect(jsonPath("$.authority",is(Authority.SYS_ADMIN.name()))) - .andExpect(jsonPath("$.email",is(SYS_ADMIN_EMAIL))); - + .andExpect(status().isOk()) + .andExpect(jsonPath("$.authority", is(Authority.SYS_ADMIN.name()))) + .andExpect(jsonPath("$.email", is(SYS_ADMIN_EMAIL))); + loginTenantAdmin(); doGet("/api/auth/user") - .andExpect(status().isOk()) - .andExpect(jsonPath("$.authority",is(Authority.TENANT_ADMIN.name()))) - .andExpect(jsonPath("$.email",is(TENANT_ADMIN_EMAIL))); - + .andExpect(status().isOk()) + .andExpect(jsonPath("$.authority", is(Authority.TENANT_ADMIN.name()))) + .andExpect(jsonPath("$.email", is(TENANT_ADMIN_EMAIL))); + loginCustomerUser(); doGet("/api/auth/user") - .andExpect(status().isOk()) - .andExpect(jsonPath("$.authority",is(Authority.CUSTOMER_USER.name()))) - .andExpect(jsonPath("$.email",is(CUSTOMER_USER_EMAIL))); + .andExpect(status().isOk()) + .andExpect(jsonPath("$.authority", is(Authority.CUSTOMER_USER.name()))) + .andExpect(jsonPath("$.email", is(CUSTOMER_USER_EMAIL))); } - + @Test public void testLoginLogout() throws Exception { loginSysAdmin(); doGet("/api/auth/user") - .andExpect(status().isOk()) - .andExpect(jsonPath("$.authority",is(Authority.SYS_ADMIN.name()))) - .andExpect(jsonPath("$.email",is(SYS_ADMIN_EMAIL))); + .andExpect(status().isOk()) + .andExpect(jsonPath("$.authority", is(Authority.SYS_ADMIN.name()))) + .andExpect(jsonPath("$.email", is(SYS_ADMIN_EMAIL))); TimeUnit.SECONDS.sleep(1); //We need to make sure that event for invalidating token was successfully processed logout(); doGet("/api/auth/user") - .andExpect(status().isUnauthorized()); + .andExpect(status().isUnauthorized()); resetTokens(); } @@ -97,14 +107,14 @@ public class AuthControllerTest extends AbstractControllerTest { loginSysAdmin(); doGet("/api/auth/user") .andExpect(status().isOk()) - .andExpect(jsonPath("$.authority",is(Authority.SYS_ADMIN.name()))) - .andExpect(jsonPath("$.email",is(SYS_ADMIN_EMAIL))); + .andExpect(jsonPath("$.authority", is(Authority.SYS_ADMIN.name()))) + .andExpect(jsonPath("$.email", is(SYS_ADMIN_EMAIL))); refreshToken(); doGet("/api/auth/user") .andExpect(status().isOk()) - .andExpect(jsonPath("$.authority",is(Authority.SYS_ADMIN.name()))) - .andExpect(jsonPath("$.email",is(SYS_ADMIN_EMAIL))); + .andExpect(jsonPath("$.authority", is(Authority.SYS_ADMIN.name()))) + .andExpect(jsonPath("$.email", is(SYS_ADMIN_EMAIL))); } @Test @@ -131,10 +141,10 @@ public class AuthControllerTest extends AbstractControllerTest { loginUser(TENANT_ADMIN_EMAIL, newPassword); loginSysAdmin(); - SecuritySettings securitySettings = doGet("/api/admin/securitySettings", SecuritySettings.class); - securitySettings.getPasswordPolicy().setMaximumLength(15); - securitySettings.getPasswordPolicy().setForceUserToResetPasswordIfNotValid(true); - doPost("/api/admin/securitySettings", securitySettings).andExpect(status().isOk()); + updateSecuritySettings(securitySettings -> { + securitySettings.getPasswordPolicy().setMaximumLength(15); + securitySettings.getPasswordPolicy().setForceUserToResetPasswordIfNotValid(true); + }); //try to login with user password that is not valid after security settings was updated doPost("/api/auth/login", new LoginRequest(TENANT_ADMIN_EMAIL, newPassword)) @@ -142,6 +152,7 @@ public class AuthControllerTest extends AbstractControllerTest { .andExpect(jsonPath("$.message", is("The entered password violates our policies. If this is your real password, please reset it."))); } + @Test public void testShouldNotResetPasswordToTooLongValue() throws Exception { loginTenantAdmin(); @@ -163,9 +174,95 @@ public class AuthControllerTest extends AbstractControllerTest { Mockito.doNothing().when(mailService).sendPasswordWasResetEmail(anyString(), anyString()); doPost("/api/noauth/resetPassword", resetPasswordRequest) - .andExpect(status().isBadRequest()) - .andExpect(jsonPath("$.message", - is("Password must be no more than 72 characters in length."))); + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.message", + is("Password must be no more than 72 characters in length."))); + } + + @Test + public void testPasswordResetLinkTtl() throws Exception { + loginSysAdmin(); + int ttl = 24; + updateSecuritySettings(securitySettings -> { + securitySettings.setPasswordResetTokenTtl(ttl); + }); + doPost("/api/noauth/resetPasswordByEmail", JacksonUtil.newObjectNode() + .put("email", TENANT_ADMIN_EMAIL)).andExpect(status().isOk()); + + UserCredentials userCredentials = userCredentialsDao.findByUserId(tenantId, tenantAdminUserId.getId()); + assertThat(userCredentials.getResetTokenExpTime()).isCloseTo(System.currentTimeMillis() + TimeUnit.HOURS.toMillis(ttl), Offset.offset(120000L)); + userCredentials.setResetTokenExpTime(System.currentTimeMillis() - 1); + userCredentialsDao.save(tenantId, userCredentials); + + doGet("/api/noauth/resetPassword?resetToken={resetToken}", this.currentResetPasswordToken) + .andExpect(status().isSeeOther()) + .andExpect(header().string(HttpHeaders.LOCATION, "/passwordResetLinkExpired")); + JsonNode resetPasswordRequest = JacksonUtil.newObjectNode() + .put("resetToken", this.currentResetPasswordToken) + .put("password", "wefwefe"); + doPost("/api/noauth/resetPassword", resetPasswordRequest).andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.message", is("Password reset token expired"))); + } + + @Test + public void testActivationLinkTtl() throws Exception { + loginSysAdmin(); + int ttl = 24; + updateSecuritySettings(securitySettings -> { + securitySettings.setUserActivationTokenTtl(ttl); + }); + + loginTenantAdmin(); + User user = new User(); + user.setAuthority(Authority.TENANT_ADMIN); + user.setEmail("tenant-admin-2@thingsboard.org"); + user = doPost("/api/user", user, User.class); + + UserCredentials userCredentials = userCredentialsDao.findByUserId(tenantId, user.getUuidId()); + assertThat(userCredentials.getActivateTokenExpTime()).isCloseTo(System.currentTimeMillis() + TimeUnit.HOURS.toMillis(ttl), Offset.offset(120000L)); + String initialActivationLink = getActivationLink(user); + String initialActivationToken = StringUtils.substringAfterLast(initialActivationLink, "activateToken="); + UserActivationLink activationLinkInfo = getActivationLinkInfo(user); + assertThat(TimeUnit.MILLISECONDS.toHours(activationLinkInfo.ttlMs())).isCloseTo(ttl, within(1L)); + assertThat(activationLinkInfo.value()).isEqualTo(initialActivationLink); + + // expiring activation token + userCredentials.setActivateTokenExpTime(System.currentTimeMillis() - 1); + userCredentialsDao.save(tenantId, userCredentials); + doGet("/api/noauth/activate?activateToken={activateToken}", initialActivationToken) + .andExpect(status().isSeeOther()) + .andExpect(header().string(HttpHeaders.LOCATION, "/activationLinkExpired")); + doPost("/api/noauth/activate", JacksonUtil.newObjectNode() + .put("activateToken", initialActivationToken) + .put("password", "wefewe")).andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.message", is("Activation token expired"))); + + // checking that activation link is regenerated when requested + UserActivationLink regeneratedActivationLink = getActivationLinkInfo(user); + assertThat(regeneratedActivationLink.value()).isNotEqualTo(initialActivationLink); + assertThat(TimeUnit.MILLISECONDS.toHours(regeneratedActivationLink.ttlMs())).isCloseTo(ttl, within(1L)); + + // checking link renewal if less than 15 minutes before expiration + userCredentials = userCredentialsDao.findByUserId(tenantId, user.getUuidId()); + userCredentials.setActivateTokenExpTime(System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(30)); + userCredentialsDao.save(tenantId, userCredentials); + activationLinkInfo = getActivationLinkInfo(user); + assertThat(activationLinkInfo.value()).isEqualTo(regeneratedActivationLink.value()); + assertThat(TimeUnit.MILLISECONDS.toMinutes(activationLinkInfo.ttlMs())).isCloseTo(30, within(1L)); + + userCredentials.setActivateTokenExpTime(System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(10)); + userCredentialsDao.save(tenantId, userCredentials); + UserActivationLink newActivationLink = getActivationLinkInfo(user); + assertThat(newActivationLink.value()).isNotEqualTo(regeneratedActivationLink.value()); + assertThat(TimeUnit.MILLISECONDS.toHours(newActivationLink.ttlMs())).isCloseTo(ttl, within(1L)); + String newActivationToken = StringUtils.substringAfterLast(newActivationLink.value(), "activateToken="); + + userCredentials = userCredentialsDao.findByUserId(tenantId, user.getUuidId()); + assertThat(userCredentials.getActivateTokenExpTime()).isCloseTo(System.currentTimeMillis() + TimeUnit.HOURS.toMillis(ttl), Offset.offset(120000L)); + + doPost("/api/noauth/activate", JacksonUtil.newObjectNode() + .put("activateToken", newActivationToken) + .put("password", "wefewe")).andExpect(status().isOk()); } @Test @@ -173,4 +270,19 @@ public class AuthControllerTest extends AbstractControllerTest { doGet("/login").andExpect(status().isOk()); doGet("/home").andExpect(status().isOk()); } + + private void updateSecuritySettings(Consumer<SecuritySettings> updater) throws Exception { + SecuritySettings securitySettings = doGet("/api/admin/securitySettings", SecuritySettings.class); + updater.accept(securitySettings); + doPost("/api/admin/securitySettings", securitySettings).andExpect(status().isOk()); + } + + private String getActivationLink(User user) throws Exception { + return doGet("/api/user/" + user.getId() + "/activationLink", String.class); + } + + private UserActivationLink getActivationLinkInfo(User user) throws Exception { + return doGet("/api/user/" + user.getId() + "/activationLinkInfo", UserActivationLink.class); + } + } diff --git a/application/src/test/java/org/thingsboard/server/controller/DomainControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/DomainControllerTest.java index c899aeeddb..aed4a06fc8 100644 --- a/application/src/test/java/org/thingsboard/server/controller/DomainControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/DomainControllerTest.java @@ -107,8 +107,8 @@ public class DomainControllerTest extends AbstractControllerTest { doPut("/api/domain/" + savedDomain.getId() + "/oauth2Clients", List.of(savedOAuth2Client.getId().getId(), savedOAuth2Client2.getId().getId())); DomainInfo retrievedDomainInfo = doGet("/api/domain/info/{id}", DomainInfo.class, savedDomain.getId().getId()); - assertThat(retrievedDomainInfo).isEqualTo(new DomainInfo(savedDomain, List.of(new OAuth2ClientInfo(savedOAuth2Client), - new OAuth2ClientInfo(savedOAuth2Client2)))); + assertThat(retrievedDomainInfo).isEqualTo(new DomainInfo(savedDomain, List.of(new OAuth2ClientInfo(savedOAuth2Client2), + new OAuth2ClientInfo(savedOAuth2Client)))); doPut("/api/domain/" + savedDomain.getId() + "/oauth2Clients", List.of(savedOAuth2Client2.getId().getId())); DomainInfo retrievedDomainInfo2 = doGet("/api/domain/info/{id}", DomainInfo.class, savedDomain.getId().getId()); diff --git a/application/src/test/java/org/thingsboard/server/controller/MobileAppControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/MobileAppControllerTest.java index d19178242a..6fd2d62d14 100644 --- a/application/src/test/java/org/thingsboard/server/controller/MobileAppControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/MobileAppControllerTest.java @@ -109,8 +109,8 @@ public class MobileAppControllerTest extends AbstractControllerTest { doPut("/api/mobileApp/" + savedMobileApp.getId() + "/oauth2Clients", List.of(savedOAuth2Client.getId().getId(), savedOAuth2Client2.getId().getId())); MobileAppInfo retrievedMobileAppInfo = doGet("/api/mobileApp/info/{id}", MobileAppInfo.class, savedMobileApp.getId().getId()); - assertThat(retrievedMobileAppInfo).isEqualTo(new MobileAppInfo(savedMobileApp, List.of(new OAuth2ClientInfo(savedOAuth2Client), - new OAuth2ClientInfo(savedOAuth2Client2)))); + assertThat(retrievedMobileAppInfo).isEqualTo(new MobileAppInfo(savedMobileApp, List.of(new OAuth2ClientInfo(savedOAuth2Client2), + new OAuth2ClientInfo(savedOAuth2Client)))); doPut("/api/mobileApp/" + savedMobileApp.getId() + "/oauth2Clients", List.of(savedOAuth2Client2.getId().getId())); MobileAppInfo retrievedMobileAppInfo2 = doGet("/api/mobileApp/info/{id}", MobileAppInfo.class, savedMobileApp.getId().getId()); diff --git a/application/src/test/java/org/thingsboard/server/edge/AbstractEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/AbstractEdgeTest.java index b3a1dd790e..5484c29305 100644 --- a/application/src/test/java/org/thingsboard/server/edge/AbstractEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/AbstractEdgeTest.java @@ -103,6 +103,7 @@ import org.thingsboard.server.gen.edge.v1.UserUpdateMsg; import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.Random; import java.util.TreeMap; import java.util.UUID; import java.util.concurrent.TimeUnit; @@ -124,6 +125,8 @@ abstract public class AbstractEdgeTest extends AbstractControllerTest { protected EdgeImitator edgeImitator; protected Edge edge; + private Random random = new Random(); + @Autowired protected EdgeEventService edgeEventService; @@ -163,15 +166,10 @@ abstract public class AbstractEdgeTest extends AbstractControllerTest { } private RuleChainId getEdgeRootRuleChainId() throws Exception { - List<RuleChain> edgeRuleChains = doGetTypedWithPageLink("/api/edge/" + edge.getUuidId() + "/ruleChains?", - new TypeReference<PageData<RuleChain>>() { - }, new PageLink(100)).getData(); - for (RuleChain edgeRuleChain : edgeRuleChains) { - if (edgeRuleChain.isRoot()) { - return edgeRuleChain.getId(); - } - } - throw new RuntimeException("Root rule chain not found"); + return doGetTypedWithPageLink("/api/ruleChains?type={type}&", new TypeReference<PageData<RuleChain>>() {}, + new PageLink(100, 0, "Edge Root Rule Chain"), + "EDGE") + .getData().get(0).getId(); } @After @@ -196,6 +194,8 @@ abstract public class AbstractEdgeTest extends AbstractControllerTest { Asset savedAsset = saveAsset("Edge Asset 1"); + updateRootRuleChainMetadata(); + edge = doPost("/api/edge", constructEdge("Test Edge", "test"), Edge.class); doPost("/api/edge/" + edge.getUuidId() @@ -207,6 +207,13 @@ abstract public class AbstractEdgeTest extends AbstractControllerTest { TimeUnit.MILLISECONDS.sleep(1000); } + protected void updateRootRuleChainMetadata() throws Exception { + RuleChainId rootRuleChainId = getEdgeRootRuleChainId(); + RuleChainMetaData rootRuleChainMetadata = doGet("/api/ruleChain/" + rootRuleChainId.getId().toString() + "/metadata", RuleChainMetaData.class); + rootRuleChainMetadata.getNodes().forEach(n -> n.setDebugMode(random.nextBoolean())); + doPost("/api/ruleChain/metadata", rootRuleChainMetadata, RuleChainMetaData.class); + } + protected void extendDeviceProfileData(DeviceProfile deviceProfile) { DeviceProfileData profileData = deviceProfile.getProfileData(); List<DeviceProfileAlarm> alarms = new ArrayList<>(); diff --git a/application/src/test/java/org/thingsboard/server/edge/DashboardEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/DashboardEdgeTest.java index b6311da80a..3b252046ab 100644 --- a/application/src/test/java/org/thingsboard/server/edge/DashboardEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/DashboardEdgeTest.java @@ -31,6 +31,7 @@ import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.dao.service.DaoSqlTest; import org.thingsboard.server.gen.edge.v1.DashboardUpdateMsg; +import org.thingsboard.server.gen.edge.v1.ResourceUpdateMsg; import org.thingsboard.server.gen.edge.v1.UpdateMsgType; import org.thingsboard.server.gen.edge.v1.UplinkMsg; @@ -44,12 +45,12 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. public class DashboardEdgeTest extends AbstractEdgeTest { private static final int MOBILE_ORDER = 5; - private static final String IMAGE = "data:image/png;base64,iVBORw0KGgoA"; + private static final String IMAGE = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjQ4IiBoZWlnaHQ9IjQ4Ij48cGF0aCBkPSJNMTMuMjMgMTAuNTZWMTBjLTEuOTQgMC0zLjk5LjM5LTMuOTkgMi42NyAwIDEuMTYuNjEgMS45NSAxLjYzIDEuOTUuNzYgMCAxLjQzLS40NyAxLjg2LTEuMjIuNTItLjkzLjUtMS44LjUtMi44NG0yLjcgNi41M2MtLjE4LjE2LS40My4xNy0uNjMuMDYtLjg5LS43NC0xLjA1LTEuMDgtMS41NC0xLjc5LTEuNDcgMS41LTIuNTEgMS45NS00LjQyIDEuOTUtMi4yNSAwLTQuMDEtMS4zOS00LjAxLTQuMTcgMC0yLjE4IDEuMTctMy42NCAyLjg2LTQuMzggMS40Ni0uNjQgMy40OS0uNzYgNS4wNC0uOTNWNy41YzAtLjY2LjA1LTEuNDEtLjMzLTEuOTYtLjMyLS40OS0uOTUtLjctMS41LS43LTEuMDIgMC0xLjkzLjUzLTIuMTUgMS42MS0uMDUuMjQtLjI1LjQ4LS40Ny40OWwtMi42LS4yOGMtLjIyLS4wNS0uNDYtLjIyLS40LS41Ni42LTMuMTUgMy40NS00LjEgNi00LjEgMS4zIDAgMyAuMzUgNC4wMyAxLjMzQzE3LjExIDQuNTUgMTcgNi4xOCAxNyA3Ljk1djQuMTdjMCAxLjI1LjUgMS44MSAxIDIuNDguMTcuMjUuMjEuNTQgMCAuNzFsLTIuMDYgMS43OGgtLjAxIj48L3BhdGg+PHBhdGggZD0iTTIwLjE2IDE5LjU0QzE4IDIxLjE0IDE0LjgyIDIyIDEyLjEgMjJjLTMuODEgMC03LjI1LTEuNDEtOS44NS0zLjc2LS4yLS4xOC0uMDItLjQzLjI1LS4yOSAyLjc4IDEuNjMgNi4yNSAyLjYxIDkuODMgMi42MSAyLjQxIDAgNS4wNy0uNSA3LjUxLTEuNTMuMzctLjE2LjY2LjI0LjMyLjUxIj48L3BhdGg+PHBhdGggZD0iTTIxLjA3IDE4LjVjLS4yOC0uMzYtMS44NS0uMTctMi41Ny0uMDgtLjE5LjAyLS4yMi0uMTYtLjAzLS4zIDEuMjQtLjg4IDMuMjktLjYyIDMuNTMtLjMzLjI0LjMtLjA3IDIuMzUtMS4yNCAzLjMyLS4xOC4xNi0uMzUuMDctLjI2LS4xMS4yNi0uNjcuODUtMi4xNC41Ny0yLjV6Ij48L3BhdGg+PC9zdmc+"; @Test public void testDashboards() throws Exception { // create dashboard and assign to edge - edgeImitator.expectMessageAmount(1); + edgeImitator.expectMessageAmount(2); Dashboard dashboard = new Dashboard(); dashboard.setTitle("Edge Test Dashboard"); dashboard.setMobileHide(true); @@ -59,23 +60,26 @@ public class DashboardEdgeTest extends AbstractEdgeTest { doPost("/api/edge/" + edge.getUuidId() + "/dashboard/" + savedDashboard.getUuidId(), Dashboard.class); Assert.assertTrue(edgeImitator.waitForMessages()); - AbstractMessage latestMessage = edgeImitator.getLatestMessage(); - Assert.assertTrue(latestMessage instanceof DashboardUpdateMsg); - DashboardUpdateMsg dashboardUpdateMsg = (DashboardUpdateMsg) latestMessage; + Optional<DashboardUpdateMsg> dashboardUpdateMsgOpt = edgeImitator.findMessageByType(DashboardUpdateMsg.class); + Assert.assertTrue(dashboardUpdateMsgOpt.isPresent()); + DashboardUpdateMsg dashboardUpdateMsg = dashboardUpdateMsgOpt.get(); Dashboard dashboardMsg = JacksonUtil.fromString(dashboardUpdateMsg.getEntity(), Dashboard.class, true); Assert.assertNotNull(dashboardMsg); Assert.assertEquals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, dashboardUpdateMsg.getMsgType()); Assert.assertEquals(savedDashboard, dashboardMsg); - Assert.assertEquals(IMAGE, dashboardMsg.getImage()); + Assert.assertEquals("tb-image;/api/images/tenant/edge_test_dashboard_dashboard_image.svg", dashboardMsg.getImage()); Assert.assertEquals(MOBILE_ORDER, dashboardMsg.getMobileOrder().intValue()); testAutoGeneratedCodeByProtobuf(dashboardUpdateMsg); + Optional<ResourceUpdateMsg> resourceUpdateMsg = edgeImitator.findMessageByType(ResourceUpdateMsg.class); + Assert.assertTrue(resourceUpdateMsg.isPresent()); + // update dashboard edgeImitator.expectMessageAmount(1); savedDashboard.setTitle("Updated Edge Test Dashboard"); savedDashboard = doPost("/api/dashboard", savedDashboard, Dashboard.class); Assert.assertTrue(edgeImitator.waitForMessages()); - latestMessage = edgeImitator.getLatestMessage(); + AbstractMessage latestMessage = edgeImitator.getLatestMessage(); Assert.assertTrue(latestMessage instanceof DashboardUpdateMsg); dashboardUpdateMsg = (DashboardUpdateMsg) latestMessage; dashboardMsg = JacksonUtil.fromString(dashboardUpdateMsg.getEntity(), Dashboard.class, true); diff --git a/application/src/test/java/org/thingsboard/server/edge/RuleChainEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/RuleChainEdgeTest.java index c694df84f8..eaf4468156 100644 --- a/application/src/test/java/org/thingsboard/server/edge/RuleChainEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/RuleChainEdgeTest.java @@ -185,6 +185,18 @@ public class RuleChainEdgeTest extends AbstractEdgeTest { return doPost("/api/ruleChain/metadata", ruleChainMetaData, RuleChainMetaData.class); } + @Test + public void testUpdateRootRuleChain() throws Exception { + edgeImitator.expectMessageAmount(2); + updateRootRuleChainMetadata(); + Assert.assertTrue(edgeImitator.waitForMessages()); + + Optional<RuleChainUpdateMsg> ruleChainUpdateMsgOpt = edgeImitator.findMessageByType(RuleChainUpdateMsg.class); + Assert.assertTrue(ruleChainUpdateMsgOpt.isPresent()); + Optional<RuleChainMetadataUpdateMsg> ruleChainMetadataUpdateMsgOpt = edgeImitator.findMessageByType(RuleChainMetadataUpdateMsg.class); + Assert.assertTrue(ruleChainMetadataUpdateMsgOpt.isPresent()); + } + @Test public void testSetRootRuleChain() throws Exception { // create rule chain diff --git a/application/src/test/java/org/thingsboard/server/transport/mqtt/mqttv3/rpc/MqttClientSideRpcIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/mqtt/mqttv3/rpc/MqttClientSideRpcIntegrationTest.java new file mode 100644 index 0000000000..6489054ba9 --- /dev/null +++ b/application/src/test/java/org/thingsboard/server/transport/mqtt/mqttv3/rpc/MqttClientSideRpcIntegrationTest.java @@ -0,0 +1,148 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.transport.mqtt.mqttv3.rpc; + +import io.netty.handler.codec.mqtt.MqttQoS; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Value; +import org.thingsboard.common.util.JacksonUtil; +import org.thingsboard.server.common.data.TenantProfile; +import org.thingsboard.server.common.data.TransportPayloadType; +import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; +import org.thingsboard.server.dao.service.DaoSqlTest; +import org.thingsboard.server.transport.mqtt.AbstractMqttIntegrationTest; +import org.thingsboard.server.transport.mqtt.MqttTestConfigProperties; +import org.thingsboard.server.transport.mqtt.limits.GatewaySessionLimits; +import org.thingsboard.server.transport.mqtt.limits.SessionLimits; +import org.thingsboard.server.transport.mqtt.mqttv3.MqttTestCallback; +import org.thingsboard.server.transport.mqtt.mqttv3.MqttTestClient; +import org.thingsboard.server.transport.mqtt.mqttv3.MqttTestSubscribeOnTopicCallback; + +import java.util.concurrent.TimeUnit; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.thingsboard.server.common.data.device.profile.MqttTopics.DEVICE_RPC_REQUESTS_TOPIC; +import static org.thingsboard.server.common.data.device.profile.MqttTopics.DEVICE_RPC_RESPONSE_SUB_TOPIC; +import static org.thingsboard.server.common.data.device.profile.MqttTopics.DEVICE_RPC_RESPONSE_TOPIC; + +@DaoSqlTest +public class MqttClientSideRpcIntegrationTest extends AbstractMqttIntegrationTest { + + @Value("${transport.mqtt.netty.max_payload_size}") + private Integer maxPayloadSize; + + @Value("${transport.mqtt.msg_queue_size_per_device_limit}") + private int maxInflightMessages; + + @Test + public void getSessionLimitsRpcForDeviceTest() throws Exception { + loginSysAdmin(); + TenantProfile tenantProfile = doGet("/api/tenantProfile/" + tenantProfileId, TenantProfile.class); + DefaultTenantProfileConfiguration profileConfiguration = tenantProfile.getDefaultProfileConfiguration(); + + profileConfiguration.setTransportDeviceMsgRateLimit("20:600"); + profileConfiguration.setTransportDeviceTelemetryMsgRateLimit("10:600"); + profileConfiguration.setTransportDeviceTelemetryDataPointsRateLimit("40:600"); + + doPost("/api/tenantProfile", tenantProfile); + + var expectedLimits = new SessionLimits(); + var deviceLimits = new SessionLimits.SessionRateLimits(profileConfiguration.getTransportDeviceMsgRateLimit(), + profileConfiguration.getTransportDeviceTelemetryMsgRateLimit(), + profileConfiguration.getTransportDeviceTelemetryDataPointsRateLimit()); + expectedLimits.setRateLimits(deviceLimits); + expectedLimits.setMaxPayloadSize(maxPayloadSize); + expectedLimits.setMaxInflightMessages(maxInflightMessages); + + MqttTestConfigProperties configProperties = MqttTestConfigProperties.builder() + .deviceName("Test Get Service Configuration") + .transportPayloadType(TransportPayloadType.JSON) + .build(); + processBeforeTest(configProperties); + + MqttTestClient client = new MqttTestClient(); + client.connectAndWait(accessToken); + + MqttTestCallback callback = new MqttTestSubscribeOnTopicCallback(DEVICE_RPC_RESPONSE_TOPIC + "1"); + client.setCallback(callback); + client.subscribeAndWait(DEVICE_RPC_RESPONSE_SUB_TOPIC, MqttQoS.AT_MOST_ONCE); + + client.publishAndWait(DEVICE_RPC_REQUESTS_TOPIC + "1", "{\"method\":\"getSessionLimits\",\"params\":{}}".getBytes()); + + assertThat(callback.getSubscribeLatch().await(DEFAULT_WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS)) + .as("await callback").isTrue(); + + var payload = callback.getPayloadBytes(); + SessionLimits actualLimits = JacksonUtil.fromBytes(payload, SessionLimits.class); + assertEquals(expectedLimits, actualLimits); + + client.disconnect(); + } + + @Test + public void getSessionLimitsRpcForGatewayTest() throws Exception { + loginSysAdmin(); + TenantProfile tenantProfile = doGet("/api/tenantProfile/" + tenantProfileId, TenantProfile.class); + DefaultTenantProfileConfiguration profileConfiguration = tenantProfile.getDefaultProfileConfiguration(); + + profileConfiguration.setTransportGatewayMsgRateLimit("100:600"); + profileConfiguration.setTransportGatewayTelemetryMsgRateLimit("50:600"); + profileConfiguration.setTransportGatewayTelemetryDataPointsRateLimit("200:600"); + + profileConfiguration.setTransportGatewayDeviceMsgRateLimit("20:600"); + profileConfiguration.setTransportGatewayDeviceTelemetryMsgRateLimit("10:600"); + profileConfiguration.setTransportGatewayDeviceTelemetryDataPointsRateLimit("40:600"); + + doPost("/api/tenantProfile", tenantProfile); + + var expectedLimits = new GatewaySessionLimits(); + var gatewayLimits = new SessionLimits.SessionRateLimits(profileConfiguration.getTransportGatewayMsgRateLimit(), + profileConfiguration.getTransportGatewayTelemetryMsgRateLimit(), + profileConfiguration.getTransportGatewayTelemetryDataPointsRateLimit()); + var gatewayDeviceLimits = new SessionLimits.SessionRateLimits(profileConfiguration.getTransportGatewayDeviceMsgRateLimit(), + profileConfiguration.getTransportGatewayDeviceTelemetryMsgRateLimit(), + profileConfiguration.getTransportGatewayDeviceTelemetryDataPointsRateLimit()); + expectedLimits.setGatewayRateLimits(gatewayLimits); + expectedLimits.setRateLimits(gatewayDeviceLimits); + expectedLimits.setMaxPayloadSize(maxPayloadSize); + expectedLimits.setMaxInflightMessages(maxInflightMessages); + + MqttTestConfigProperties configProperties = MqttTestConfigProperties.builder() + .gatewayName("Test Get Service Configuration Gateway") + .transportPayloadType(TransportPayloadType.JSON) + .build(); + processBeforeTest(configProperties); + + MqttTestClient client = new MqttTestClient(); + client.connectAndWait(gatewayAccessToken); + + MqttTestCallback callback = new MqttTestSubscribeOnTopicCallback(DEVICE_RPC_RESPONSE_TOPIC + "1"); + client.setCallback(callback); + client.subscribeAndWait(DEVICE_RPC_RESPONSE_SUB_TOPIC, MqttQoS.AT_MOST_ONCE); + + client.publishAndWait(DEVICE_RPC_REQUESTS_TOPIC + "1", "{\"method\":\"getSessionLimits\",\"params\":{}}".getBytes()); + + assertTrue(callback.getSubscribeLatch().await(DEFAULT_WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS)); + + var payload = callback.getPayloadBytes(); + SessionLimits actualLimits = JacksonUtil.fromBytes(payload, GatewaySessionLimits.class); + assertEquals(expectedLimits, actualLimits); + + client.disconnect(); + } +} diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/user/UserService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/user/UserService.java index 42f635cd43..8f22812cfc 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/user/UserService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/user/UserService.java @@ -59,6 +59,10 @@ public interface UserService extends EntityDaoService { UserCredentials requestExpiredPasswordReset(TenantId tenantId, UserCredentialsId userCredentialsId); + UserCredentials generatePasswordResetToken(UserCredentials userCredentials); + + UserCredentials generateUserActivationToken(UserCredentials userCredentials); + UserCredentials replaceUserCredentials(TenantId tenantId, UserCredentials userCredentials); void deleteUser(TenantId tenantId, User user); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/UserActivationLink.java b/common/data/src/main/java/org/thingsboard/server/common/data/UserActivationLink.java new file mode 100644 index 0000000000..f532a9b066 --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/UserActivationLink.java @@ -0,0 +1,19 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.common.data; + +public record UserActivationLink(String value, long ttlMs) { +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/security/UserCredentials.java b/common/data/src/main/java/org/thingsboard/server/common/data/security/UserCredentials.java index ed036e482a..1104ae2949 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/security/UserCredentials.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/security/UserCredentials.java @@ -16,41 +16,31 @@ package org.thingsboard.server.common.data.security; import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.databind.JsonNode; +import lombok.Data; import lombok.EqualsAndHashCode; -import org.thingsboard.server.common.data.BaseData; +import lombok.ToString; +import org.thingsboard.server.common.data.BaseDataWithAdditionalInfo; import org.thingsboard.server.common.data.id.UserCredentialsId; import org.thingsboard.server.common.data.id.UserId; -import org.thingsboard.server.common.data.validation.NoXss; -import static org.thingsboard.server.common.data.BaseDataWithAdditionalInfo.getJson; -import static org.thingsboard.server.common.data.BaseDataWithAdditionalInfo.setJson; +import java.io.Serial; +@Data @EqualsAndHashCode(callSuper = true) -public class UserCredentials extends BaseData<UserCredentialsId> { +@ToString(callSuper = true) +public class UserCredentials extends BaseDataWithAdditionalInfo<UserCredentialsId> { + @Serial private static final long serialVersionUID = -2108436378880529163L; private UserId userId; private boolean enabled; private String password; private String activateToken; + private Long activateTokenExpTime; private String resetToken; + private Long resetTokenExpTime; - @NoXss - private transient JsonNode additionalInfo; - - @JsonIgnore - private byte[] additionalInfoBytes; - - public JsonNode getAdditionalInfo() { - return getJson(() -> additionalInfo, () -> additionalInfoBytes); - } - - public void setAdditionalInfo(JsonNode settings) { - setJson(settings, json -> this.additionalInfo = json, bytes -> this.additionalInfoBytes = bytes); - } - public UserCredentials() { super(); } @@ -59,75 +49,25 @@ public class UserCredentials extends BaseData<UserCredentialsId> { super(id); } - public UserCredentials(UserCredentials userCredentials) { - super(userCredentials); - this.userId = userCredentials.getUserId(); - this.password = userCredentials.getPassword(); - this.enabled = userCredentials.isEnabled(); - this.activateToken = userCredentials.getActivateToken(); - this.resetToken = userCredentials.getResetToken(); - setAdditionalInfo(userCredentials.getAdditionalInfo()); - } - - public UserId getUserId() { - return userId; - } - - public void setUserId(UserId userId) { - this.userId = userId; - } - - public boolean isEnabled() { - return enabled; - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - public String getActivateToken() { - return activateToken; + @JsonIgnore + public boolean isActivationTokenExpired() { + return getActivationTokenTtl() == 0; } - public void setActivateToken(String activateToken) { - this.activateToken = activateToken; - } - - public String getResetToken() { - return resetToken; + @JsonIgnore + public long getActivationTokenTtl() { + return activateTokenExpTime != null ? Math.max(activateTokenExpTime - System.currentTimeMillis(), 0) : 0; } - public void setResetToken(String resetToken) { - this.resetToken = resetToken; + @JsonIgnore + public boolean isResetTokenExpired() { + return getResetTokenTtl() == 0; } - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("UserCredentials [userId="); - builder.append(userId); - builder.append(", enabled="); - builder.append(enabled); - builder.append(", password="); - builder.append(password); - builder.append(", activateToken="); - builder.append(activateToken); - builder.append(", resetToken="); - builder.append(resetToken); - builder.append(", createdTime="); - builder.append(createdTime); - builder.append(", id="); - builder.append(id); - builder.append("]"); - return builder.toString(); + @JsonIgnore + public long getResetTokenTtl() { + return resetTokenExpTime != null ? Math.max(resetTokenExpTime - System.currentTimeMillis(), 0) : 0; } } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/security/model/SecuritySettings.java b/common/data/src/main/java/org/thingsboard/server/common/data/security/model/SecuritySettings.java index aa4d303440..70e1853ffd 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/security/model/SecuritySettings.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/security/model/SecuritySettings.java @@ -16,22 +16,39 @@ package org.thingsboard.server.common.data.security.model; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; import lombok.Data; +import java.io.Serial; import java.io.Serializable; @Schema @Data public class SecuritySettings implements Serializable { + @Serial private static final long serialVersionUID = -1307613974597312465L; - @Schema(description = "The user password policy object." ) + @Schema(description = "The user password policy object.") private UserPasswordPolicy passwordPolicy; - @Schema(description = "Maximum number of failed login attempts allowed before user account is locked." ) + + @Schema(description = "Maximum number of failed login attempts allowed before user account is locked.") private Integer maxFailedLoginAttempts; - @Schema(description = "Email to use for notifications about locked users." ) + + @Schema(description = "Email to use for notifications about locked users.") private String userLockoutNotificationEmail; - @Schema(description = "Mobile secret key length" ) + + @Schema(description = "Mobile secret key length") private Integer mobileSecretKeyLength; + + @NotNull @Min(1) @Max(24) + @Schema(description = "TTL in hours for user activation link", minimum = "1", maximum = "24", requiredMode = Schema.RequiredMode.REQUIRED) + private Integer userActivationTokenTtl; + + @NotNull @Min(1) @Max(24) + @Schema(description = "TTL in hours for password reset link", minimum = "1", maximum = "24", requiredMode = Schema.RequiredMode.REQUIRED) + private Integer passwordResetTokenTtl; + } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqConsumerTemplate.java b/common/queue/src/main/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqConsumerTemplate.java index 4913d52fa8..e50afabb5d 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqConsumerTemplate.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqConsumerTemplate.java @@ -20,6 +20,8 @@ import com.google.protobuf.InvalidProtocolBufferException; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.GetResponse; +import java.util.ArrayList; +import java.util.Collection; import lombok.extern.slf4j.Slf4j; import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; import org.thingsboard.server.queue.TbQueueAdmin; @@ -31,7 +33,6 @@ import org.thingsboard.server.queue.common.DefaultTbQueueMsg; import java.io.IOException; import java.util.Collections; import java.util.List; -import java.util.Objects; import java.util.Set; import java.util.concurrent.TimeoutException; import java.util.stream.Collectors; @@ -44,6 +45,7 @@ public class TbRabbitMqConsumerTemplate<T extends TbQueueMsg> extends AbstractTb private final TbQueueMsgDecoder<T> decoder; private final Channel channel; private final Connection connection; + private final int maxPollMessages; private volatile Set<String> queues; @@ -51,6 +53,7 @@ public class TbRabbitMqConsumerTemplate<T extends TbQueueMsg> extends AbstractTb super(topic); this.admin = admin; this.decoder = decoder; + this.maxPollMessages = rabbitMqSettings.getMaxPollMessages(); try { connection = rabbitMqSettings.getConnectionFactory().newConnection(); } catch (IOException | TimeoutException e) { @@ -70,13 +73,19 @@ public class TbRabbitMqConsumerTemplate<T extends TbQueueMsg> extends AbstractTb protected List<GetResponse> doPoll(long durationInMillis) { List<GetResponse> result = queues.stream() .map(queue -> { - try { - return channel.basicGet(queue, false); - } catch (IOException e) { - log.error("Failed to get messages from queue: [{}]", queue); - throw new RuntimeException("Failed to get messages from queue.", e); + List<GetResponse> messages = new ArrayList<>(); + for (int i = 0; i < maxPollMessages; i++) { + GetResponse response = doQueuePoll(queue); + if (response == null) { + break; + } + messages.add(response); } - }).filter(Objects::nonNull).collect(Collectors.toList()); + return messages; + }) + .filter(r -> !r.isEmpty()) + .flatMap(Collection::stream) + .collect(Collectors.toList()); if (result.size() > 0) { return result; } else { @@ -84,6 +93,15 @@ public class TbRabbitMqConsumerTemplate<T extends TbQueueMsg> extends AbstractTb } } + protected GetResponse doQueuePoll(String queue) { + try { + return channel.basicGet(queue, false); + } catch (IOException e) { + log.error("Failed to get messages from queue: [{}]", queue); + throw new RuntimeException("Failed to get messages from queue.", e); + } + } + @Override protected void doSubscribe(List<String> topicNames) { queues = partitions.stream() diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqSettings.java b/common/queue/src/main/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqSettings.java index 432bce1d01..c0a2912f23 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqSettings.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqSettings.java @@ -46,6 +46,8 @@ public class TbRabbitMqSettings { private int connectionTimeout; @Value("${queue.rabbitmq.handshake_timeout:}") private int handshakeTimeout; + @Value("${queue.rabbitmq.max_poll_messages:1}") + private int maxPollMessages; private ConnectionFactory connectionFactory; diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/scheduler/DefaultSchedulerComponent.java b/common/queue/src/main/java/org/thingsboard/server/queue/scheduler/DefaultSchedulerComponent.java index a166259256..095e5b18dc 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/scheduler/DefaultSchedulerComponent.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/scheduler/DefaultSchedulerComponent.java @@ -17,6 +17,7 @@ package org.thingsboard.server.queue.scheduler; import jakarta.annotation.PostConstruct; import jakarta.annotation.PreDestroy; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.thingsboard.common.util.ThingsBoardThreadFactory; @@ -26,14 +27,15 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; +@Slf4j @Component public class DefaultSchedulerComponent implements SchedulerComponent { - protected ScheduledExecutorService schedulerExecutor; + private ScheduledExecutorService schedulerExecutor; @PostConstruct public void init() { - this.schedulerExecutor = Executors.newSingleThreadScheduledExecutor(ThingsBoardThreadFactory.forName("queue-scheduler")); + schedulerExecutor = Executors.newSingleThreadScheduledExecutor(ThingsBoardThreadFactory.forName("queue-scheduler")); } @PreDestroy @@ -52,10 +54,19 @@ public class DefaultSchedulerComponent implements SchedulerComponent { } public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) { - return schedulerExecutor.scheduleAtFixedRate(command, initialDelay, period, unit); + return schedulerExecutor.scheduleAtFixedRate(() -> runSafely(command), initialDelay, period, unit); } public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) { - return schedulerExecutor.scheduleWithFixedDelay(command, initialDelay, delay, unit); + return schedulerExecutor.scheduleWithFixedDelay(() -> runSafely(command), initialDelay, delay, unit); } + + private void runSafely(Runnable command) { + try { + command.run(); + } catch (Throwable t) { + log.error("Unexpected error occurred while executing task!", t); + } + } + } diff --git a/common/queue/src/test/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqConsumerTemplateTest.java b/common/queue/src/test/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqConsumerTemplateTest.java new file mode 100644 index 0000000000..2d6a50cea4 --- /dev/null +++ b/common/queue/src/test/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqConsumerTemplateTest.java @@ -0,0 +1,128 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.queue.rabbitmq; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; +import com.rabbitmq.client.GetResponse; +import java.nio.charset.StandardCharsets; +import java.util.Set; +import java.util.UUID; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; +import org.thingsboard.server.queue.TbQueueAdmin; +import org.thingsboard.server.queue.TbQueueMsgDecoder; +import org.thingsboard.server.queue.common.DefaultTbQueueMsg; + +@ExtendWith(MockitoExtension.class) +class TbRabbitMqConsumerTemplateTest { + + private static final String TOPIC = "some-topic"; + + @Mock + private TbQueueAdmin admin; + + @Mock + private ConnectionFactory connectionFactory; + + @Mock + private TbQueueMsgDecoder<DefaultTbQueueMsg> decoder; + + @Mock + private Connection connection; + + @Mock + private Channel channel; + + @Mock + private TopicPartitionInfo partition; + + @Mock + private GetResponse getResponse; + + private TbRabbitMqConsumerTemplate<DefaultTbQueueMsg> consumer; + + private void setUpConsumerWithMaxPollMessages(int maxPollMessages) throws Exception { + when(connectionFactory.newConnection()).thenReturn(connection); + when(connection.createChannel()).thenReturn(channel); + TbRabbitMqSettings settings = new TbRabbitMqSettings(); + settings.setMaxPollMessages(maxPollMessages); + settings.setConnectionFactory(connectionFactory); + + consumer = new TbRabbitMqConsumerTemplate<>(admin, settings, TOPIC, decoder); + when(partition.getFullTopicName()).thenReturn(TOPIC); + consumer.subscribe(Set.of(partition)); + } + + @Test + void pollWithMax5PollMessagesReturnsEmptyListIfNoMessages() throws Exception { + setUpConsumerWithMaxPollMessages(5); + when(channel.basicGet(anyString(), anyBoolean())).thenReturn(null); + + assertThat(consumer.poll(0L)).isEmpty(); + + verify(channel).basicGet(anyString(), anyBoolean()); + } + + @Test + void pollWithMax5PollMessagesReturns5MessagesIfQueueContains5() throws Exception { + setUpConsumerWithMaxPollMessages(5); + when(getResponse.getBody()).thenReturn(newMessageBody()); + when(channel.basicGet(anyString(), anyBoolean())).thenReturn(getResponse); + + assertThat(consumer.poll(0L)).hasSize(5); + + verify(channel, times(5)).basicGet(anyString(), anyBoolean()); + } + + @Test + void pollWithMax1PollMessageReturns1MessageIfQueueContainsMore() throws Exception { + setUpConsumerWithMaxPollMessages(1); + when(getResponse.getBody()).thenReturn(newMessageBody()); + when(channel.basicGet(anyString(), anyBoolean())).thenReturn(getResponse); + + assertThat(consumer.poll(0L)).hasSize(1); + + verify(channel).basicGet(anyString(), anyBoolean()); + } + + @Test + void pollWithMax3PollMessagesReturns2MessagesIfQueueContains2() throws Exception { + setUpConsumerWithMaxPollMessages(3); + when(getResponse.getBody()).thenReturn(newMessageBody()); + when(channel.basicGet(anyString(), anyBoolean())).thenReturn(getResponse, getResponse, null); + + assertThat(consumer.poll(0L)).hasSize(2); + + verify(channel, times(3)).basicGet(anyString(), anyBoolean()); + } + + private byte[] newMessageBody() { + return ("{\"key\": \"" + UUID.randomUUID() + "\"}").getBytes(StandardCharsets.UTF_8); + } + +} \ No newline at end of file diff --git a/common/queue/src/test/java/org/thingsboard/server/queue/scheduler/DefaultSchedulerComponentTest.java b/common/queue/src/test/java/org/thingsboard/server/queue/scheduler/DefaultSchedulerComponentTest.java new file mode 100644 index 0000000000..cff306c748 --- /dev/null +++ b/common/queue/src/test/java/org/thingsboard/server/queue/scheduler/DefaultSchedulerComponentTest.java @@ -0,0 +1,95 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.queue.scheduler; + +import org.awaitility.Awaitility; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.assertj.core.api.Assertions.assertThat; + +class DefaultSchedulerComponentTest { + + DefaultSchedulerComponent schedulerComponent; + + @BeforeEach + void setup() { + schedulerComponent = new DefaultSchedulerComponent(); + schedulerComponent.init(); + } + + @AfterEach + void cleanup() { + schedulerComponent.destroy(); + } + + @Test + @DisplayName("scheduleAtFixedRate() should continue periodic execution even if command throws exception") + void scheduleAtFixedRateShouldNotStopPeriodicExecutionWhenCommandThrowsException() { + // GIVEN + var wasExecutedAtLeastOnce = new AtomicBoolean(false); + + Runnable exceptionThrowingCommand = () -> { + try { + throw new RuntimeException("Unexpected exception"); + } finally { + wasExecutedAtLeastOnce.set(true); + } + }; + + // WHEN + ScheduledFuture<?> future = schedulerComponent.scheduleAtFixedRate(exceptionThrowingCommand, 0, 200, TimeUnit.MILLISECONDS); + + // THEN + Awaitility.await().alias("Wait until command is executed at least once") + .atMost(5, TimeUnit.SECONDS) + .until(wasExecutedAtLeastOnce::get); + + assertThat(future.isDone()).as("Periodic execution should not stop after unhandled exception is thrown by the command").isFalse(); + } + + @Test + @DisplayName("scheduleWithFixedDelay() should continue periodic execution even if command throws exception") + void scheduleWithFixedDelayShouldNotStopPeriodicExecutionWhenCommandThrowsException() { + // GIVEN + var wasExecutedAtLeastOnce = new AtomicBoolean(false); + + Runnable exceptionThrowingCommand = () -> { + try { + throw new RuntimeException("Unexpected exception"); + } finally { + wasExecutedAtLeastOnce.set(true); + } + }; + + // WHEN + ScheduledFuture<?> future = schedulerComponent.scheduleWithFixedDelay(exceptionThrowingCommand, 0, 200, TimeUnit.MILLISECONDS); + + // THEN + Awaitility.await().alias("Wait until command is executed at least once") + .atMost(5, TimeUnit.SECONDS) + .until(wasExecutedAtLeastOnce::get); + + assertThat(future.isDone()).as("Periodic execution should not stop after unhandled exception is thrown by the command").isFalse(); + } + +} diff --git a/common/transport/coap/src/main/proto/efento/proto_config.proto b/common/transport/coap/src/main/proto/efento/proto_config.proto index 25dbec883f..5a82ec078c 100644 --- a/common/transport/coap/src/main/proto/efento/proto_config.proto +++ b/common/transport/coap/src/main/proto/efento/proto_config.proto @@ -31,7 +31,7 @@ message ProtoOutputControlState { uint32 channel_state = 2; } -/* Message containing request data for accesing calibration parameters */ +/* Message containing request data for accessing calibration parameters */ message ProtoCalibrationParameters { /* Request details. Bitmask: */ @@ -349,4 +349,4 @@ message ProtoConfig { /* BLE advertising period configuration. */ ProtoBleAdvertisingPeriod ble_advertising_period = 59; -} \ No newline at end of file +} diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportContext.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportContext.java index 16d72ff89f..b8fd79be4b 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportContext.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportContext.java @@ -25,6 +25,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.stereotype.Component; import org.thingsboard.server.common.transport.TransportContext; +import org.thingsboard.server.common.transport.TransportTenantProfileCache; import org.thingsboard.server.transport.mqtt.adaptors.JsonMqttAdaptor; import org.thingsboard.server.transport.mqtt.adaptors.ProtoMqttAdaptor; @@ -51,6 +52,10 @@ public class MqttTransportContext extends TransportContext { @Autowired private ProtoMqttAdaptor protoMqttAdaptor; + @Getter + @Autowired + private TransportTenantProfileCache tenantProfileCache; + @Getter @Value("${transport.mqtt.netty.max_payload_size}") private Integer maxPayloadSize; diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java index eeeb287dc8..f839ed4b18 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java @@ -60,6 +60,7 @@ import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.OtaPackageId; import org.thingsboard.server.common.data.ota.OtaPackageType; import org.thingsboard.server.common.data.rpc.RpcStatus; +import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; import org.thingsboard.server.common.msg.EncryptionUtil; import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.common.msg.tools.TbRateLimitsException; @@ -78,6 +79,8 @@ import org.thingsboard.server.gen.transport.mqtt.SparkplugBProto; import org.thingsboard.server.queue.scheduler.SchedulerComponent; import org.thingsboard.server.transport.mqtt.adaptors.MqttTransportAdaptor; import org.thingsboard.server.transport.mqtt.adaptors.ProtoMqttAdaptor; +import org.thingsboard.server.transport.mqtt.limits.GatewaySessionLimits; +import org.thingsboard.server.transport.mqtt.limits.SessionLimits; import org.thingsboard.server.transport.mqtt.session.DeviceSessionCtx; import org.thingsboard.server.transport.mqtt.session.GatewaySessionHandler; import org.thingsboard.server.transport.mqtt.session.MqttTopicMatcher; @@ -130,6 +133,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement private static final Pattern FW_REQUEST_PATTERN = Pattern.compile(MqttTopics.DEVICE_FIRMWARE_REQUEST_TOPIC_PATTERN); private static final Pattern SW_REQUEST_PATTERN = Pattern.compile(MqttTopics.DEVICE_SOFTWARE_REQUEST_TOPIC_PATTERN); + private static final String SESSION_LIMITS = "getSessionLimits"; private static final String PAYLOAD_TOO_LARGE = "PAYLOAD_TOO_LARGE"; @@ -493,8 +497,12 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement transportService.process(deviceSessionCtx.getSessionInfo(), rpcResponseMsg, getPubAckCallback(ctx, msgId, rpcResponseMsg)); } else if (topicName.startsWith(MqttTopics.DEVICE_RPC_REQUESTS_TOPIC)) { TransportProtos.ToServerRpcRequestMsg rpcRequestMsg = payloadAdaptor.convertToServerRpcRequest(deviceSessionCtx, mqttMsg, MqttTopics.DEVICE_RPC_REQUESTS_TOPIC); - transportService.process(deviceSessionCtx.getSessionInfo(), rpcRequestMsg, getPubAckCallback(ctx, msgId, rpcRequestMsg)); toServerRpcSubTopicType = TopicType.V1; + if (SESSION_LIMITS.equals(rpcRequestMsg.getMethodName())) { + onGetSessionLimitsRpc(deviceSessionCtx.getSessionInfo(), ctx, msgId, rpcRequestMsg); + } else { + transportService.process(deviceSessionCtx.getSessionInfo(), rpcRequestMsg, getPubAckCallback(ctx, msgId, rpcRequestMsg)); + } } else if (topicName.equals(MqttTopics.DEVICE_CLAIM_TOPIC)) { TransportProtos.ClaimDeviceMsg claimDeviceMsg = payloadAdaptor.convertToClaimDevice(deviceSessionCtx, mqttMsg); transportService.process(deviceSessionCtx.getSessionInfo(), claimDeviceMsg, getPubAckCallback(ctx, msgId, claimDeviceMsg)); @@ -928,7 +936,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement } } else { log.debug("[{}] Failed to process unsubscription [{}] to [{}] - Subscription not found", sessionId, mqttMsg.variableHeader().messageId(), topicName); - unSubResults.add((short)MqttReasonCodes.UnsubAck.NO_SUBSCRIPTION_EXISTED.byteValue()); + unSubResults.add((short) MqttReasonCodes.UnsubAck.NO_SUBSCRIPTION_EXISTED.byteValue()); } } if (!activityReported) { @@ -1055,6 +1063,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement log.debug("[{}][{}][{}] IOException: {}", sessionId, Optional.ofNullable(this.deviceSessionCtx.getDeviceInfo()).map(TransportDeviceInfo::getDeviceId).orElse(null), Optional.ofNullable(this.deviceSessionCtx.getDeviceInfo()).map(TransportDeviceInfo::getDeviceName).orElse(""), + cause.getMessage(), cause); } else if (log.isInfoEnabled()) { log.info("[{}][{}][{}] IOException: {}", sessionId, @@ -1330,6 +1339,43 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement } } + private void onGetSessionLimitsRpc(TransportProtos.SessionInfoProto sessionInfo, ChannelHandlerContext ctx, int msgId, TransportProtos.ToServerRpcRequestMsg rpcRequestMsg) { + var tenantProfile = context.getTenantProfileCache().get(deviceSessionCtx.getTenantId()); + DefaultTenantProfileConfiguration profile = tenantProfile.getDefaultProfileConfiguration(); + + SessionLimits sessionLimits; + + if (sessionInfo.getIsGateway()) { + var gatewaySessionLimits = new GatewaySessionLimits(); + var gatewayLimits = new SessionLimits.SessionRateLimits(profile.getTransportGatewayMsgRateLimit(), + profile.getTransportGatewayTelemetryMsgRateLimit(), + profile.getTransportGatewayTelemetryDataPointsRateLimit()); + var gatewayDeviceLimits = new SessionLimits.SessionRateLimits(profile.getTransportGatewayDeviceMsgRateLimit(), + profile.getTransportGatewayDeviceTelemetryMsgRateLimit(), + profile.getTransportGatewayDeviceTelemetryDataPointsRateLimit()); + gatewaySessionLimits.setGatewayRateLimits(gatewayLimits); + gatewaySessionLimits.setRateLimits(gatewayDeviceLimits); + sessionLimits = gatewaySessionLimits; + } else { + var rateLimits = new SessionLimits.SessionRateLimits(profile.getTransportDeviceMsgRateLimit(), + profile.getTransportDeviceTelemetryMsgRateLimit(), + profile.getTransportDeviceTelemetryDataPointsRateLimit()); + sessionLimits = new SessionLimits(); + sessionLimits.setRateLimits(rateLimits); + } + sessionLimits.setMaxPayloadSize(context.getMaxPayloadSize()); + sessionLimits.setMaxInflightMessages(context.getMessageQueueSizePerDeviceLimit()); + + ack(ctx, msgId, MqttReasonCodes.PubAck.SUCCESS); + + TransportProtos.ToServerRpcResponseMsg responseMsg = TransportProtos.ToServerRpcResponseMsg.newBuilder() + .setRequestId(rpcRequestMsg.getRequestId()) + .setPayload(JacksonUtil.toString(sessionLimits)) + .build(); + + onToServerRpcResponse(responseMsg); + } + private void handleToSparkplugDeviceRpcRequest(TransportProtos.ToDeviceRpcRequestMsg rpcRequest) throws ThingsboardException { SparkplugMessageType messageType = SparkplugMessageType.parseMessageType(rpcRequest.getMethodName()); SparkplugRpcRequestHeader header; diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/limits/GatewaySessionLimits.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/limits/GatewaySessionLimits.java new file mode 100644 index 0000000000..6b59f6bbbd --- /dev/null +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/limits/GatewaySessionLimits.java @@ -0,0 +1,25 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.transport.mqtt.limits; + +import lombok.Data; + +@Data +public class GatewaySessionLimits extends SessionLimits { + + private SessionRateLimits gatewayRateLimits; + +} diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/limits/SessionLimits.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/limits/SessionLimits.java new file mode 100644 index 0000000000..b607bfadfc --- /dev/null +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/limits/SessionLimits.java @@ -0,0 +1,29 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.transport.mqtt.limits; + +import lombok.Data; +import org.thingsboard.server.common.data.TransportPayloadType; + +@Data +public class SessionLimits { + + private int maxPayloadSize; + private int maxInflightMessages; + private SessionRateLimits rateLimits; + + public record SessionRateLimits(String messages, String telemetryMessages, String telemetryDataPoints) {} +} diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/DeviceSessionCtx.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/DeviceSessionCtx.java index 6562fa65bf..a3b254c99e 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/DeviceSessionCtx.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/session/DeviceSessionCtx.java @@ -82,6 +82,7 @@ public class DeviceSessionCtx extends MqttDeviceAwareSessionContext { private volatile MqttTopicFilter telemetryTopicFilter = MqttTopicFilterFactory.getDefaultTelemetryFilter(); private volatile MqttTopicFilter attributesPublishTopicFilter = MqttTopicFilterFactory.getDefaultAttributesFilter(); private volatile MqttTopicFilter attributesSubscribeTopicFilter = MqttTopicFilterFactory.getDefaultAttributesFilter(); + @Getter private volatile TransportPayloadType payloadType = TransportPayloadType.JSON; private volatile Descriptors.Descriptor attributesDynamicMessageDescriptor; private volatile Descriptors.Descriptor telemetryDynamicMessageDescriptor; diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/activity/AbstractActivityManager.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/activity/AbstractActivityManager.java index f754d6f5b1..ac535d28e1 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/activity/AbstractActivityManager.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/activity/AbstractActivityManager.java @@ -69,7 +69,7 @@ public abstract class AbstractActivityManager<Key, Metadata> implements Activity log.error("Failed to process activity event: provided activity key is null."); return; } - log.debug("Received activity event for key: [{}]", key); + log.debug("Received activity event for key: [{}]. Event time: [{}].", key, newLastRecordedTime); var shouldReport = new AtomicBoolean(false); var lastRecordedTime = new AtomicLong(); @@ -94,7 +94,7 @@ public abstract class AbstractActivityManager<Key, Metadata> implements Activity }); if (shouldReport.get() && lastReportedTime.get() < lastRecordedTime.get()) { - log.debug("Going to report first activity event for key: [{}].", key); + log.debug("Going to report first activity event for key: [{}]. Event time: [{}].", key, lastRecordedTime.get()); reportActivity(key, metadata, lastRecordedTime.get(), new ActivityReportCallback<>() { @Override public void onSuccess(Key key, long reportedTime) { @@ -103,7 +103,7 @@ public abstract class AbstractActivityManager<Key, Metadata> implements Activity @Override public void onFailure(Key key, Throwable t) { - log.debug("Failed to report first activity event for key: [{}].", key, t); + log.debug("Failed to report first activity event for key: [{}]. Event time: [{}].", key, lastRecordedTime.get(), t); } }); } @@ -113,50 +113,59 @@ public abstract class AbstractActivityManager<Key, Metadata> implements Activity public void onReportingPeriodEnd() { log.debug("Going to end reporting period."); for (Map.Entry<Key, ActivityStateWrapper> entry : states.entrySet()) { - var key = entry.getKey(); - var stateWrapper = entry.getValue(); - var currentState = stateWrapper.getState(); - - long lastRecordedTime = currentState.getLastRecordedTime(); - long lastReportedTime = stateWrapper.getLastReportedTime(); - var metadata = currentState.getMetadata(); - - boolean hasExpired; - boolean shouldReport; - - var updatedState = updateState(key, currentState); - if (updatedState != null) { - stateWrapper.setState(updatedState); - lastRecordedTime = updatedState.getLastRecordedTime(); - metadata = updatedState.getMetadata(); - hasExpired = hasExpired(lastRecordedTime); - shouldReport = stateWrapper.getStrategy().onReportingPeriodEnd(); - } else { - states.remove(key); - hasExpired = false; - shouldReport = true; + Key key = entry.getKey(); + ActivityStateWrapper stateWrapper = entry.getValue(); + try { + reportLastEvent(key, stateWrapper); + } catch (Exception e) { + log.error("Failed to report last activity event on reporting period end for key: [{}]. State: [{}].", key, stateWrapper, e); } + } + } - if (hasExpired) { - states.remove(key); - onStateExpiry(key, metadata); - shouldReport = true; - } + private void reportLastEvent(Key key, ActivityStateWrapper stateWrapper) { + var currentState = stateWrapper.getState(); + + long lastRecordedTime = currentState.getLastRecordedTime(); + long lastReportedTime = stateWrapper.getLastReportedTime(); + var metadata = currentState.getMetadata(); + + boolean hasExpired; + boolean shouldReport; + + var updatedState = updateState(key, currentState); + if (updatedState != null) { + stateWrapper.setState(updatedState); + lastRecordedTime = updatedState.getLastRecordedTime(); + metadata = updatedState.getMetadata(); + hasExpired = hasExpired(lastRecordedTime); + shouldReport = stateWrapper.getStrategy().onReportingPeriodEnd(); + } else { + states.remove(key); + hasExpired = false; + shouldReport = true; + } - if (shouldReport && lastReportedTime < lastRecordedTime) { - log.debug("Going to report last activity event for key: [{}].", key); - reportActivity(key, metadata, lastRecordedTime, new ActivityReportCallback<>() { - @Override - public void onSuccess(Key key, long reportedTime) { - updateLastReportedTime(key, reportedTime); - } - - @Override - public void onFailure(Key key, Throwable t) { - log.debug("Failed to report last activity event for key: [{}].", key, t); - } - }); - } + if (hasExpired) { + states.remove(key); + onStateExpiry(key, metadata); + shouldReport = true; + } + + if (shouldReport && lastReportedTime < lastRecordedTime) { + long timeToReport = lastRecordedTime; + log.debug("Going to report last activity event for key: [{}]. Event time: [{}].", key, timeToReport); + reportActivity(key, metadata, timeToReport, new ActivityReportCallback<>() { + @Override + public void onSuccess(Key key, long reportedTime) { + updateLastReportedTime(key, reportedTime); + } + + @Override + public void onFailure(Key key, Throwable t) { + log.debug("Failed to report last activity event for key: [{}]. Event time: [{}].", key, timeToReport, t); + } + }); } } diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/activity/strategy/FirstAndLastEventActivityStrategy.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/activity/strategy/FirstAndLastEventActivityStrategy.java index a5a59046ae..9ced9bd90b 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/activity/strategy/FirstAndLastEventActivityStrategy.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/activity/strategy/FirstAndLastEventActivityStrategy.java @@ -16,7 +16,9 @@ package org.thingsboard.server.common.transport.activity.strategy; import lombok.EqualsAndHashCode; +import lombok.ToString; +@ToString @EqualsAndHashCode public final class FirstAndLastEventActivityStrategy implements ActivityStrategy { diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/activity/strategy/FirstEventActivityStrategy.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/activity/strategy/FirstEventActivityStrategy.java index 5353635c45..3b5d9dfc8d 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/activity/strategy/FirstEventActivityStrategy.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/activity/strategy/FirstEventActivityStrategy.java @@ -16,7 +16,9 @@ package org.thingsboard.server.common.transport.activity.strategy; import lombok.EqualsAndHashCode; +import lombok.ToString; +@ToString @EqualsAndHashCode public final class FirstEventActivityStrategy implements ActivityStrategy { diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/session/DeviceAwareSessionContext.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/session/DeviceAwareSessionContext.java index 4c30609e18..1558bbc08b 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/session/DeviceAwareSessionContext.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/session/DeviceAwareSessionContext.java @@ -23,6 +23,7 @@ import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration; import org.thingsboard.server.common.data.device.profile.MqttDeviceProfileTransportConfiguration; import org.thingsboard.server.common.data.id.DeviceId; +import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.transport.auth.TransportDeviceInfo; import org.thingsboard.server.gen.transport.TransportProtos; @@ -40,6 +41,8 @@ public abstract class DeviceAwareSessionContext implements SessionContext { @Getter private volatile DeviceId deviceId; @Getter + private volatile TenantId tenantId; + @Getter protected volatile TransportDeviceInfo deviceInfo; @Getter @Setter @@ -58,6 +61,7 @@ public abstract class DeviceAwareSessionContext implements SessionContext { public void setDeviceInfo(TransportDeviceInfo deviceInfo) { this.deviceInfo = deviceInfo; this.deviceId = deviceInfo.getDeviceId(); + this.tenantId = deviceInfo.getTenantId(); } @Override @@ -65,7 +69,6 @@ public abstract class DeviceAwareSessionContext implements SessionContext { this.sessionInfo = sessionInfo; this.deviceProfile = deviceProfile; this.deviceInfo.setDeviceType(deviceProfile.getName()); - } @Override diff --git a/common/util/src/main/java/org/thingsboard/common/util/JacksonUtil.java b/common/util/src/main/java/org/thingsboard/common/util/JacksonUtil.java index ff5716a361..02af9b53f8 100644 --- a/common/util/src/main/java/org/thingsboard/common/util/JacksonUtil.java +++ b/common/util/src/main/java/org/thingsboard/common/util/JacksonUtil.java @@ -38,6 +38,7 @@ import org.thingsboard.server.common.data.kv.KvEntry; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.io.Reader; import java.io.Writer; import java.nio.file.Files; @@ -259,6 +260,15 @@ public class JacksonUtil { } } + public static JsonNode toJsonNode(InputStream value) { + try { + return value != null ? OBJECT_MAPPER.readTree(value) : null; + } catch (IOException e) { + throw new IllegalArgumentException("The given InputStream value: " + + value + " cannot be transformed to a JsonNode", e); + } + } + public static ObjectNode newObjectNode() { return newObjectNode(OBJECT_MAPPER); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileServiceImpl.java index 95786f0a6a..7d4d5300f9 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileServiceImpl.java @@ -236,8 +236,9 @@ public class AssetProfileServiceImpl extends CachedVersionedEntityService<AssetP log.trace("Executing findOrCreateAssetProfile"); AssetProfile assetProfile = findAssetProfileByName(tenantId, name, false); if (assetProfile == null) { + boolean isDefault = "default".equals(name) && findDefaultAssetProfile(tenantId) == null; try { - assetProfile = this.doCreateDefaultAssetProfile(tenantId, name, name.equals("default"), true); + assetProfile = this.doCreateAssetProfile(tenantId, name, isDefault, true); } catch (DataValidationException e) { if (ASSET_PROFILE_WITH_SUCH_NAME_ALREADY_EXISTS.equals(e.getMessage())) { assetProfile = findAssetProfileByName(tenantId, name, false); @@ -252,10 +253,10 @@ public class AssetProfileServiceImpl extends CachedVersionedEntityService<AssetP @Override public AssetProfile createDefaultAssetProfile(TenantId tenantId) { log.trace("Executing createDefaultAssetProfile tenantId [{}]", tenantId); - return doCreateDefaultAssetProfile(tenantId, "default", true, false); + return doCreateAssetProfile(tenantId, "default", true, false); } - private AssetProfile doCreateDefaultAssetProfile(TenantId tenantId, String profileName, boolean defaultProfile, boolean publishSaveEvent) { + private AssetProfile doCreateAssetProfile(TenantId tenantId, String profileName, boolean defaultProfile, boolean publishSaveEvent) { validateId(tenantId, id -> INCORRECT_TENANT_ID + id); AssetProfile assetProfile = new AssetProfile(); assetProfile.setTenantId(tenantId); diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java index 1528763775..09e2be01e0 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java @@ -271,8 +271,9 @@ public class DeviceProfileServiceImpl extends CachedVersionedEntityService<Devic log.trace("Executing findOrCreateDefaultDeviceProfile"); DeviceProfile deviceProfile = findDeviceProfileByName(tenantId, name, false); if (deviceProfile == null) { + boolean isDefault = "default".equals(name) && findDefaultDeviceProfile(tenantId) == null; try { - deviceProfile = this.doCreateDefaultDeviceProfile(tenantId, name, name.equals("default"), true); + deviceProfile = this.doCreateDeviceProfile(tenantId, name, isDefault, true); } catch (DataValidationException e) { if (DEVICE_PROFILE_WITH_SUCH_NAME_ALREADY_EXISTS.equals(e.getMessage())) { deviceProfile = findDeviceProfileByName(tenantId, name, false); @@ -287,10 +288,10 @@ public class DeviceProfileServiceImpl extends CachedVersionedEntityService<Devic @Override public DeviceProfile createDefaultDeviceProfile(TenantId tenantId) { log.trace("Executing createDefaultDeviceProfile tenantId [{}]", tenantId); - return doCreateDefaultDeviceProfile(tenantId, "default", true, false); + return doCreateDeviceProfile(tenantId, "default", true, false); } - private DeviceProfile doCreateDefaultDeviceProfile(TenantId tenantId, String profileName, boolean defaultProfile, boolean publishSaveEvent) { + private DeviceProfile doCreateDeviceProfile(TenantId tenantId, String profileName, boolean defaultProfile, boolean publishSaveEvent) { validateId(tenantId, id -> INCORRECT_TENANT_ID + id); DeviceProfile deviceProfile = new DeviceProfile(); deviceProfile.setTenantId(tenantId); diff --git a/dao/src/main/java/org/thingsboard/server/dao/domain/DomainServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/domain/DomainServiceImpl.java index b7a13313b7..8a735303a7 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/domain/DomainServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/domain/DomainServiceImpl.java @@ -36,6 +36,7 @@ import org.thingsboard.server.dao.eventsourcing.DeleteEntityEvent; import org.thingsboard.server.dao.eventsourcing.SaveEntityEvent; import org.thingsboard.server.dao.oauth2.OAuth2ClientDao; +import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Optional; @@ -149,6 +150,7 @@ public class DomainServiceImpl extends AbstractEntityService implements DomainSe } List<OAuth2ClientInfo> clients = oauth2ClientDao.findByDomainId(domain.getUuidId()).stream() .map(OAuth2ClientInfo::new) + .sorted(Comparator.comparing(OAuth2ClientInfo::getTitle)) .collect(Collectors.toList()); return new DomainInfo(domain, clients); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/edge/BaseRelatedEdgesService.java b/dao/src/main/java/org/thingsboard/server/dao/edge/BaseRelatedEdgesService.java index 265831640c..bedee455f4 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/edge/BaseRelatedEdgesService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/edge/BaseRelatedEdgesService.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.dao.edge; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; @@ -30,6 +31,7 @@ import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.dao.entity.AbstractCachedEntityService; @Service +@Slf4j public class BaseRelatedEdgesService extends AbstractCachedEntityService<RelatedEdgesCacheKey, RelatedEdgesCacheValue, RelatedEdgesEvictEvent> implements RelatedEdgesService { public static final int RELATED_EDGES_CACHE_ITEMS = 1000; @@ -47,6 +49,7 @@ public class BaseRelatedEdgesService extends AbstractCachedEntityService<Related @Override public PageData<EdgeId> findEdgeIdsByEntityId(TenantId tenantId, EntityId entityId, PageLink pageLink) { + log.trace("Executing findEdgeIdsByEntityId, tenantId [{}], entityId [{}], pageLink [{}]", tenantId, entityId, pageLink); if (!pageLink.equals(FIRST_PAGE)) { return edgeService.findEdgeIdsByTenantIdAndEntityId(tenantId, entityId, pageLink); } @@ -56,6 +59,7 @@ public class BaseRelatedEdgesService extends AbstractCachedEntityService<Related @Override public void publishRelatedEdgeIdsEvictEvent(TenantId tenantId, EntityId entityId) { + log.trace("Executing publishRelatedEdgeIdsEvictEvent, tenantId [{}], entityId [{}]", tenantId, entityId); publishEvictEvent(new RelatedEdgesEvictEvent(tenantId, entityId)); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/mobile/MobileAppServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/mobile/MobileAppServiceImpl.java index 1e89b3c645..66431a38dc 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/mobile/MobileAppServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/mobile/MobileAppServiceImpl.java @@ -36,6 +36,7 @@ import org.thingsboard.server.dao.eventsourcing.DeleteEntityEvent; import org.thingsboard.server.dao.eventsourcing.SaveEntityEvent; import org.thingsboard.server.dao.oauth2.OAuth2ClientDao; +import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Optional; @@ -143,6 +144,7 @@ public class MobileAppServiceImpl extends AbstractEntityService implements Mobil private MobileAppInfo getMobileAppInfo(MobileApp mobileApp) { List<OAuth2ClientInfo> clients = oauth2ClientDao.findByMobileAppId(mobileApp.getUuidId()).stream() .map(OAuth2ClientInfo::new) + .sorted(Comparator.comparing(OAuth2ClientInfo::getTitle)) .collect(Collectors.toList()); return new MobileAppInfo(mobileApp, clients); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java index 1fbab9c47c..b920160cc0 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java @@ -79,7 +79,9 @@ public class ModelConstants { public static final String USER_CREDENTIALS_ENABLED_PROPERTY = "enabled"; public static final String USER_CREDENTIALS_PASSWORD_PROPERTY = "password"; //NOSONAR, the constant used to identify password column name (not password value itself) public static final String USER_CREDENTIALS_ACTIVATE_TOKEN_PROPERTY = "activate_token"; + public static final String USER_CREDENTIALS_ACTIVATE_TOKEN_EXP_TIME_PROPERTY = "activate_token_exp_time"; public static final String USER_CREDENTIALS_RESET_TOKEN_PROPERTY = "reset_token"; + public static final String USER_CREDENTIALS_RESET_TOKEN_EXP_TIME_PROPERTY = "reset_token_exp_time"; public static final String USER_CREDENTIALS_ADDITIONAL_PROPERTY = "additional_info"; /** diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserCredentialsEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserCredentialsEntity.java index 59ba5ac4dd..edd1536a04 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserCredentialsEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserCredentialsEntity.java @@ -50,9 +50,15 @@ public final class UserCredentialsEntity extends BaseSqlEntity<UserCredentials> @Column(name = ModelConstants.USER_CREDENTIALS_ACTIVATE_TOKEN_PROPERTY, unique = true) private String activateToken; + @Column(name = ModelConstants.USER_CREDENTIALS_ACTIVATE_TOKEN_EXP_TIME_PROPERTY) + private Long activateTokenExpTime; + @Column(name = ModelConstants.USER_CREDENTIALS_RESET_TOKEN_PROPERTY, unique = true) private String resetToken; + @Column(name = ModelConstants.USER_CREDENTIALS_RESET_TOKEN_EXP_TIME_PROPERTY) + private Long resetTokenExpTime; + @Convert(converter = JsonConverter.class) @Column(name = ModelConstants.USER_CREDENTIALS_ADDITIONAL_PROPERTY) private JsonNode additionalInfo; @@ -72,7 +78,9 @@ public final class UserCredentialsEntity extends BaseSqlEntity<UserCredentials> this.enabled = userCredentials.isEnabled(); this.password = userCredentials.getPassword(); this.activateToken = userCredentials.getActivateToken(); + this.activateTokenExpTime = userCredentials.getActivateTokenExpTime(); this.resetToken = userCredentials.getResetToken(); + this.resetTokenExpTime = userCredentials.getResetTokenExpTime(); this.additionalInfo = userCredentials.getAdditionalInfo(); } @@ -86,7 +94,9 @@ public final class UserCredentialsEntity extends BaseSqlEntity<UserCredentials> userCredentials.setEnabled(enabled); userCredentials.setPassword(password); userCredentials.setActivateToken(activateToken); + userCredentials.setActivateTokenExpTime(activateTokenExpTime); userCredentials.setResetToken(resetToken); + userCredentials.setResetTokenExpTime(resetTokenExpTime); userCredentials.setAdditionalInfo(additionalInfo); return userCredentials; } diff --git a/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientServiceImpl.java index 6ab4909421..880329335c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/oauth2/OAuth2ClientServiceImpl.java @@ -35,6 +35,7 @@ import org.thingsboard.server.dao.eventsourcing.DeleteEntityEvent; import org.thingsboard.server.dao.eventsourcing.SaveEntityEvent; import org.thingsboard.server.dao.service.DataValidator; +import java.util.Comparator; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; @@ -68,7 +69,6 @@ public class OAuth2ClientServiceImpl extends AbstractEntityService implements OA } @Override - @Transactional public OAuth2Client saveOAuth2Client(TenantId tenantId, OAuth2Client oAuth2Client) { log.trace("Executing saveOAuth2Client [{}]", oAuth2Client); oAuth2ClientDataValidator.validate(oAuth2Client, OAuth2Client::getTenantId); @@ -96,7 +96,6 @@ public class OAuth2ClientServiceImpl extends AbstractEntityService implements OA } @Override - @Transactional public void deleteOAuth2ClientById(TenantId tenantId, OAuth2ClientId oAuth2ClientId) { log.trace("Executing deleteOAuth2ClientById [{}]", oAuth2ClientId); oauth2ClientDao.removeById(tenantId, oAuth2ClientId.getId()); @@ -126,6 +125,7 @@ public class OAuth2ClientServiceImpl extends AbstractEntityService implements OA return oauth2ClientDao.findByIds(tenantId.getId(), oAuth2ClientIds) .stream() .map(OAuth2ClientInfo::new) + .sorted(Comparator.comparing(OAuth2ClientInfo::getTitle)) .collect(Collectors.toList()); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java b/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java index 902bf0f6a7..6f34437e0d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java @@ -640,10 +640,8 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC log.warn("[{}] Failed to create ruleChain relation. Edge Id: [{}]", ruleChainId, edgeId); throw new RuntimeException(e); } - if (!ruleChainId.equals(edge.getRootRuleChainId())) { - eventPublisher.publishEvent(ActionEntityEvent.builder().tenantId(tenantId).edgeId(edgeId).entityId(ruleChainId) - .actionType(ActionType.ASSIGNED_TO_EDGE).build()); - } + eventPublisher.publishEvent(ActionEntityEvent.builder().tenantId(tenantId).edgeId(edgeId).entityId(ruleChainId) + .actionType(ActionType.ASSIGNED_TO_EDGE).body(JacksonUtil.toString(edge)).build()); return ruleChain; } diff --git a/dao/src/main/java/org/thingsboard/server/dao/settings/DefaultSecuritySettingsService.java b/dao/src/main/java/org/thingsboard/server/dao/settings/DefaultSecuritySettingsService.java new file mode 100644 index 0000000000..18c2f68c0a --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/settings/DefaultSecuritySettingsService.java @@ -0,0 +1,81 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.dao.settings; + +import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.thingsboard.common.util.JacksonUtil; +import org.thingsboard.server.common.data.AdminSettings; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.security.model.SecuritySettings; +import org.thingsboard.server.common.data.security.model.UserPasswordPolicy; +import org.thingsboard.server.dao.service.ConstraintValidator; + +import static org.thingsboard.server.common.data.CacheConstants.SECURITY_SETTINGS_CACHE; + +@Service +@RequiredArgsConstructor +public class DefaultSecuritySettingsService implements SecuritySettingsService { + + private final AdminSettingsService adminSettingsService; + + public static final int DEFAULT_MOBILE_SECRET_KEY_LENGTH = 64; + + @Cacheable(cacheNames = SECURITY_SETTINGS_CACHE, key = "'securitySettings'") + @Override + public SecuritySettings getSecuritySettings() { + AdminSettings adminSettings = adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, "securitySettings"); + SecuritySettings securitySettings; + if (adminSettings != null) { + try { + securitySettings = JacksonUtil.convertValue(adminSettings.getJsonValue(), SecuritySettings.class); + } catch (Exception e) { + throw new RuntimeException("Failed to load security settings!", e); + } + } else { + securitySettings = new SecuritySettings(); + securitySettings.setPasswordPolicy(new UserPasswordPolicy()); + securitySettings.getPasswordPolicy().setMinimumLength(6); + securitySettings.getPasswordPolicy().setMaximumLength(72); + securitySettings.setMobileSecretKeyLength(DEFAULT_MOBILE_SECRET_KEY_LENGTH); + securitySettings.setPasswordResetTokenTtl(24); + securitySettings.setUserActivationTokenTtl(24); + } + return securitySettings; + } + + @CacheEvict(cacheNames = SECURITY_SETTINGS_CACHE, key = "'securitySettings'") + @Override + public SecuritySettings saveSecuritySettings(SecuritySettings securitySettings) { + ConstraintValidator.validateFields(securitySettings); + AdminSettings adminSettings = adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, "securitySettings"); + if (adminSettings == null) { + adminSettings = new AdminSettings(); + adminSettings.setTenantId(TenantId.SYS_TENANT_ID); + adminSettings.setKey("securitySettings"); + } + adminSettings.setJsonValue(JacksonUtil.valueToTree(securitySettings)); + AdminSettings savedAdminSettings = adminSettingsService.saveAdminSettings(TenantId.SYS_TENANT_ID, adminSettings); + try { + return JacksonUtil.convertValue(savedAdminSettings.getJsonValue(), SecuritySettings.class); + } catch (Exception e) { + throw new RuntimeException("Failed to load security settings!", e); + } + } + +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/settings/SecuritySettingsService.java b/dao/src/main/java/org/thingsboard/server/dao/settings/SecuritySettingsService.java new file mode 100644 index 0000000000..8b9e3bfeee --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/settings/SecuritySettingsService.java @@ -0,0 +1,26 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.dao.settings; + +import org.thingsboard.server.common.data.security.model.SecuritySettings; + +public interface SecuritySettingsService { + + SecuritySettings getSecuritySettings(); + + SecuritySettings saveSecuritySettings(SecuritySettings securitySettings); + +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/user/UserServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/user/UserServiceImpl.java index f64ccf4970..ba0d3d69f3 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/user/UserServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/user/UserServiceImpl.java @@ -63,6 +63,7 @@ import org.thingsboard.server.dao.eventsourcing.SaveEntityEvent; import org.thingsboard.server.dao.exception.IncorrectParameterException; import org.thingsboard.server.dao.service.DataValidator; import org.thingsboard.server.dao.service.PaginatedRemover; +import org.thingsboard.server.dao.settings.SecuritySettingsService; import org.thingsboard.server.dao.sql.JpaExecutorService; import java.util.ArrayList; @@ -72,6 +73,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.concurrent.TimeUnit; import static org.thingsboard.server.common.data.StringUtils.generateSafeToken; import static org.thingsboard.server.dao.service.Validator.validateId; @@ -102,6 +104,7 @@ public class UserServiceImpl extends AbstractCachedEntityService<UserCacheKey, U private final UserAuthSettingsDao userAuthSettingsDao; private final UserSettingsService userSettingsService; private final UserSettingsDao userSettingsDao; + private final SecuritySettingsService securitySettingsService; private final DataValidator<User> userValidator; private final DataValidator<UserCredentials> userCredentialsValidator; private final ApplicationEventPublisher eventPublisher; @@ -178,9 +181,9 @@ public class UserServiceImpl extends AbstractCachedEntityService<UserCacheKey, U countService.publishCountEntityEvictEvent(savedUser.getTenantId(), EntityType.USER); UserCredentials userCredentials = new UserCredentials(); userCredentials.setEnabled(false); - userCredentials.setActivateToken(generateSafeToken(DEFAULT_TOKEN_LENGTH)); userCredentials.setUserId(new UserId(savedUser.getUuidId())); userCredentials.setAdditionalInfo(JacksonUtil.newObjectNode()); + userCredentials = generateUserActivationToken(userCredentials); userCredentialsDao.save(user.getTenantId(), userCredentials); } eventPublisher.publishEvent(SaveEntityEvent.builder() @@ -242,8 +245,12 @@ public class UserServiceImpl extends AbstractCachedEntityService<UserCacheKey, U if (userCredentials.isEnabled()) { throw new IncorrectParameterException("User credentials already activated"); } + if (userCredentials.isActivationTokenExpired()) { + throw new IncorrectParameterException("Activation token expired"); + } userCredentials.setEnabled(true); userCredentials.setActivateToken(null); + userCredentials.setActivateTokenExpTime(null); userCredentials.setPassword(password); if (userCredentials.getPassword() != null) { updatePasswordHistory(userCredentials); @@ -263,7 +270,7 @@ public class UserServiceImpl extends AbstractCachedEntityService<UserCacheKey, U if (!userCredentials.isEnabled()) { throw new DisabledException(String.format("User credentials not enabled [%s]", email)); } - userCredentials.setResetToken(generateSafeToken(DEFAULT_TOKEN_LENGTH)); + userCredentials = generatePasswordResetToken(userCredentials); return saveUserCredentials(tenantId, userCredentials); } @@ -273,10 +280,26 @@ public class UserServiceImpl extends AbstractCachedEntityService<UserCacheKey, U if (!userCredentials.isEnabled()) { throw new IncorrectParameterException("Unable to reset password for inactive user"); } - userCredentials.setResetToken(generateSafeToken(DEFAULT_TOKEN_LENGTH)); + userCredentials = generatePasswordResetToken(userCredentials); return saveUserCredentials(tenantId, userCredentials); } + @Override + public UserCredentials generatePasswordResetToken(UserCredentials userCredentials) { + userCredentials.setResetToken(generateSafeToken(DEFAULT_TOKEN_LENGTH)); + int ttlHours = securitySettingsService.getSecuritySettings().getPasswordResetTokenTtl(); + userCredentials.setResetTokenExpTime(System.currentTimeMillis() + TimeUnit.HOURS.toMillis(ttlHours)); + return userCredentials; + } + + @Override + public UserCredentials generateUserActivationToken(UserCredentials userCredentials) { + userCredentials.setActivateToken(generateSafeToken(DEFAULT_TOKEN_LENGTH)); + int ttlHours = securitySettingsService.getSecuritySettings().getUserActivationTokenTtl(); + userCredentials.setActivateTokenExpTime(System.currentTimeMillis() + TimeUnit.HOURS.toMillis(ttlHours)); + return userCredentials; + } + @Override public UserCredentials replaceUserCredentials(TenantId tenantId, UserCredentials userCredentials) { log.trace("Executing replaceUserCredentials [{}]", userCredentials); diff --git a/dao/src/main/resources/sql/schema-entities.sql b/dao/src/main/resources/sql/schema-entities.sql index 46e739e5d5..9c95f385f8 100644 --- a/dao/src/main/resources/sql/schema-entities.sql +++ b/dao/src/main/resources/sql/schema-entities.sql @@ -491,9 +491,11 @@ CREATE TABLE IF NOT EXISTS user_credentials ( id uuid NOT NULL CONSTRAINT user_credentials_pkey PRIMARY KEY, created_time bigint NOT NULL, activate_token varchar(255) UNIQUE, + activate_token_exp_time BIGINT, enabled boolean, password varchar(255), reset_token varchar(255) UNIQUE, + reset_token_exp_time BIGINT, user_id uuid UNIQUE, additional_info varchar DEFAULT '{}' ); diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/AssetProfileServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/AssetProfileServiceTest.java index d7b17fe53a..7271a0fc8a 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/AssetProfileServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/AssetProfileServiceTest.java @@ -163,6 +163,18 @@ public class AssetProfileServiceTest extends AbstractServiceTest { }); } + @Test + public void testSaveAssetProfileWithNameDefaultAndProfileWithIsDefaultAndDifferentNameAlreadyExists() { + AssetProfile defaultAssetProfile = assetProfileService.findDefaultAssetProfile(tenantId); + Assert.assertNotNull(defaultAssetProfile); + defaultAssetProfile.setName("Asset Profile 1"); + assetProfileService.saveAssetProfile(defaultAssetProfile); + AssetProfile createdAssetProfile = assetProfileService.findOrCreateAssetProfile(tenantId, "default"); + Assert.assertNotNull(createdAssetProfile); + Assert.assertEquals("default", createdAssetProfile.getName()); + Assert.assertFalse(createdAssetProfile.isDefault()); + } + @Test public void testDeleteAssetProfileWithExistingAsset() { AssetProfile assetProfile = this.createAssetProfile(tenantId, "Asset Profile"); diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/DeviceProfileServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/DeviceProfileServiceTest.java index 51abe245b2..aa14e20151 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/DeviceProfileServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/DeviceProfileServiceTest.java @@ -209,6 +209,18 @@ public class DeviceProfileServiceTest extends AbstractServiceTest { }); } + @Test + public void testSaveDeviceProfileWithNameDefaultAndProfileWithIsDefaultAndDifferentNameAlreadyExists() { + DeviceProfile defaultDeviceProfile = deviceProfileService.findDefaultDeviceProfile(tenantId); + Assert.assertNotNull(defaultDeviceProfile); + defaultDeviceProfile.setName("Device Profile 1"); + deviceProfileService.saveDeviceProfile(defaultDeviceProfile); + DeviceProfile createdDeviceProfile = deviceProfileService.findOrCreateDeviceProfile(tenantId, "default"); + Assert.assertNotNull(createdDeviceProfile); + Assert.assertEquals("default", createdDeviceProfile.getName()); + Assert.assertFalse(createdDeviceProfile.isDefault()); + } + @Ignore @Test public void testChangeDeviceProfileTypeWithExistingDevices() { diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/user/JpaUserCredentialsDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/user/JpaUserCredentialsDaoTest.java index a1e559414e..d68197c1bd 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/sql/user/JpaUserCredentialsDaoTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/sql/user/JpaUserCredentialsDaoTest.java @@ -63,7 +63,9 @@ public class JpaUserCredentialsDaoTest extends AbstractJpaDaoTest { userCredentials.setUserId(new UserId(UUID.randomUUID())); userCredentials.setPassword("password"); userCredentials.setActivateToken("ACTIVATE_TOKEN_" + number); + userCredentials.setActivateTokenExpTime(123L); userCredentials.setResetToken("RESET_TOKEN_" + number); + userCredentials.setResetTokenExpTime(321L); return userCredentialsDao.save(SYSTEM_TENANT_ID, userCredentials); } diff --git a/msa/js-executor/config/default.yml b/msa/js-executor/config/default.yml index 0e15413e31..f5bde183e4 100644 --- a/msa/js-executor/config/default.yml +++ b/msa/js-executor/config/default.yml @@ -34,7 +34,7 @@ kafka: partitions_consumed_concurrently: "1" # (EXPERIMENTAL) increase this value if you are planning to handle more than one partition (scale up, scale down) - this will decrease the latency requestTimeout: "30000" # The default value in kafkajs is: 30000 connectionTimeout: "1000" # The default value in kafkajs is: 1000 - compression: "gzip" # gzip or uncompressed + compression: "none" # gzip or uncompressed topic_properties: "retention.ms:604800000;segment.bytes:52428800;retention.bytes:104857600;partitions:100;min.insync.replicas:1" use_confluent_cloud: false client_id: "kafkajs" #inject pod name to easy identify the client using /opt/kafka/bin/kafka-consumer-groups.sh diff --git a/netty-mqtt/src/main/java/org/thingsboard/mqtt/MqttHandler.java b/netty-mqtt/src/main/java/org/thingsboard/mqtt/MqttHandler.java index 5c3e311a1e..86c856f304 100644 --- a/netty-mqtt/src/main/java/org/thingsboard/mqtt/MqttHandler.java +++ b/netty-mqtt/src/main/java/org/thingsboard/mqtt/MqttHandler.java @@ -15,10 +15,30 @@ */ package org.thingsboard.mqtt; -import com.google.common.util.concurrent.ListenableFuture; +import java.util.concurrent.Future; import io.netty.buffer.ByteBuf; public interface MqttHandler { - - ListenableFuture<Void> onMessage(String topic, ByteBuf payload); + /** + * Changing ListenableFuture to Future allows you to choose CompletableFuture, + * which gives developers the freedom to choose the orchestration method. + * CompletableFuture is a newer, more evolved version that eliminates callback hell, + * is easier to use, and comes with the JDK. jdk 1.8 was previously used with the Before JDK1.8, + * use ListenableFuture, after that, it is recommended to use CompletableFuture. + * ListenableFuture It's still written that way.{@link MqttMessageListener#onMessage(topic, payload)} + * public ListenableFuture<Void> onMessage(String topic, ByteBuf message) { + * log.info("MQTT message [{}], topic [{}]", message.toString(StandardCharsets.UTF_8), topic); + * events.add(new MqttEvent(topic, message.toString(StandardCharsets.UTF_8))); + * return Futures.immediateVoidFuture(); + * } + * CompletableFuture It's like this. + * public CompletableFuture<Void> onMessage(String topic, ByteBuf message) { + * log.info("MQTT message [{}], topic [{}]", message.toString(StandardCharsets.UTF_8), topic); + * events.add(new MqttEvent(topic, message.toString(StandardCharsets.UTF_8))); + * return CompletableFuture.completedFuture(null); + * } + * This change does not affect the system's current use of ListenableFuture so that it is free to choose between ListenableFuture or + * CompletableFuture in new development. + */ + Future<Void> onMessage(String topic, ByteBuf payload); } diff --git a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java index 6d1fcec080..818d714a3b 100644 --- a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java +++ b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java @@ -515,13 +515,16 @@ public class RestClient implements Closeable { return restTemplate.postForEntity(baseURL + "/api/alarm", alarm, Alarm.class).getBody(); } - public List<EntitySubtype> getAlarmTypes(PageLink pageLink) { + public PageData<EntitySubtype> getAlarmTypes(PageLink pageLink) { + Map<String, String> params = new HashMap<>(); + addPageLinkToParam(params, pageLink); return restTemplate.exchange( baseURL + "/api/alarm/types?" + getUrlParams(pageLink), HttpMethod.GET, HttpEntity.EMPTY, - new ParameterizedTypeReference<List<EntitySubtype>>() { - }).getBody(); + new ParameterizedTypeReference<PageData<EntitySubtype>>() { + }, + params).getBody(); } public AlarmComment saveAlarmComment(AlarmId alarmId, AlarmComment alarmComment) { diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/MailService.java b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/MailService.java index ecaf7ef3f9..043181a710 100644 --- a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/MailService.java +++ b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/MailService.java @@ -32,13 +32,13 @@ public interface MailService { void sendTestMail(JsonNode config, String email) throws ThingsboardException; - void sendActivationEmail(String activationLink, String email) throws ThingsboardException; + void sendActivationEmail(String activationLink, long ttlMs, String email) throws ThingsboardException; void sendAccountActivatedEmail(String loginLink, String email) throws ThingsboardException; - void sendResetPasswordEmail(String passwordResetLink, String email) throws ThingsboardException; + void sendResetPasswordEmail(String passwordResetLink, long ttlMs, String email) throws ThingsboardException; - void sendResetPasswordEmailAsync(String passwordResetLink, String email); + void sendResetPasswordEmailAsync(String passwordResetLink, long ttlMs, String email); void sendPasswordWasResetEmail(String loginLink, String email) throws ThingsboardException; diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java index c21914577f..f8ec81abcf 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java @@ -122,7 +122,7 @@ public class TbHttpClient { SslContext sslContext = config.getCredentials().initSslContext(); httpClient = httpClient.secure(t -> t.sslContext(sslContext)); } - } else if (!config.isUseSimpleClientHttpFactory()) { + } else if (config.isUseSimpleClientHttpFactory()) { if (CredentialsType.CERT_PEM == config.getCredentials().getType()) { throw new TbNodeException("Simple HTTP Factory does not support CERT PEM credentials!"); } @@ -347,8 +347,7 @@ public class TbHttpClient { Properties properties = System.getProperties(); if (properties.containsKey(HTTP_PROXY_HOST) || properties.containsKey(HTTPS_PROXY_HOST)) { createHttpProxyFrom(option, properties); - } - if (properties.containsKey(SOCKS_PROXY_HOST)) { + } else if (properties.containsKey(SOCKS_PROXY_HOST)) { createSocksProxyFrom(option, properties); } } diff --git a/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js b/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js index 2c723830bd..0892bcd150 100644 --- a/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js +++ b/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js @@ -1,25 +1,25 @@ -System.register(["@angular/core","@shared/public-api","@ngrx/store","@angular/forms","@angular/common","@angular/material/input","@angular/material/form-field","@angular/material/slide-toggle","@angular/flex-layout/flex","@ngx-translate/core","@angular/material/button","@angular/material/icon","@angular/material/select","@angular/material/core","@angular/material/tooltip","@angular/material/expansion","rxjs","@shared/components/hint-tooltip-icon.component","@shared/components/help-popup.component","@shared/pipe/safe.pipe","@core/public-api","@shared/components/js-func.component","@shared/components/script-lang.component","@angular/cdk/keycodes","@angular/material/checkbox","@angular/material/chips","@shared/components/entity/entity-type-select.component","@shared/components/relation/relation-type-autocomplete.component","@shared/components/entity/entity-select.component","@shared/components/toggle-header.component","@shared/components/toggle-select.component","@angular/cdk/coercion","@shared/components/tb-error.component","@angular/flex-layout/extended","@angular/material/list","@angular/cdk/drag-drop","rxjs/operators","@angular/material/autocomplete","@shared/pipe/highlight.pipe","@home/components/public-api","tslib","@shared/components/entity/entity-subtype-list.component","@home/components/relation/relation-filters.component","@shared/components/file-input.component","@shared/components/button/toggle-password.component","@shared/components/string-items-list.component","@shared/components/entity/entity-list.component","@shared/components/notification/template-autocomplete.component","@shared/components/tb-checkbox.component","@home/components/sms/sms-provider-configuration.component","@angular/material/radio","@shared/components/slack-conversation-autocomplete.component","@shared/components/entity/entity-autocomplete.component","@shared/components/entity/entity-type-list.component","@angular/cdk/platform"],(function(e){"use strict";var t,n,r,o,a,i,l,s,m,p,d,u,c,g,f,y,b,x,h,v,C,F,k,T,L,I,N,S,q,A,M,E,G,w,D,V,P,R,O,_,B,K,z,H,U,j,$,J,Q,Y,W,Z,X,ee,te,ne,re,oe,ae,ie,le,se,me,pe,de,ue,ce,ge,fe,ye,be,xe,he,ve,Ce,Fe,ke,Te,Le,Ie,Ne,Se,qe,Ae,Me,Ee,Ge,we,De,Ve,Pe,Re,Oe,_e,Be,Ke,ze,He,Ue,je,$e,Je,Qe,Ye,We,Ze,Xe,et,tt,nt,rt,ot,at,it,lt,st,mt,pt;return{setters:[function(e){t=e,n=e.Component,r=e.InjectionToken,o=e.Injectable,a=e.Inject,i=e.Optional,l=e.EventEmitter,s=e.Directive,m=e.Input,p=e.Output,d=e.NgModule,u=e.ViewChild,c=e.forwardRef},function(e){g=e.RuleNodeConfigurationComponent,f=e.AttributeScope,y=e.telemetryTypeTranslations,b=e.ScriptLanguage,x=e.AlarmSeverity,h=e.alarmSeverityTranslations,v=e.EntitySearchDirection,C=e.EntityType,F=e.entityFields,k=e.PageComponent,T=e.messageTypeNames,L=e.MessageType,I=e.coerceBoolean,N=e.entitySearchDirectionTranslations,S=e,q=e.AlarmStatus,A=e.alarmStatusTranslations,M=e.SharedModule,E=e.AggregationType,G=e.aggregationTranslations,w=e.NotificationType,D=e.SlackChanelType,V=e.SlackChanelTypesTranslateMap},function(e){P=e},function(e){R=e,O=e.Validators,_=e.NgControl,B=e.NG_VALUE_ACCESSOR,K=e.NG_VALIDATORS,z=e.FormArray,H=e.FormGroup},function(e){U=e,j=e.DOCUMENT,$=e.CommonModule},function(e){J=e},function(e){Q=e},function(e){Y=e},function(e){W=e},function(e){Z=e},function(e){X=e},function(e){ee=e},function(e){te=e},function(e){ne=e},function(e){re=e},function(e){oe=e},function(e){ae=e.Subject,ie=e.takeUntil,le=e.of,se=e.EMPTY,me=e.fromEvent},function(e){pe=e},function(e){de=e},function(e){ue=e},function(e){ce=e.getCurrentAuthState,ge=e,fe=e.isDefinedAndNotNull,ye=e.isEqual,be=e.deepTrim,xe=e.isObject,he=e.isNotEmptyStr},function(e){ve=e},function(e){Ce=e},function(e){Fe=e.ENTER,ke=e.COMMA,Te=e.SEMICOLON},function(e){Le=e},function(e){Ie=e},function(e){Ne=e},function(e){Se=e},function(e){qe=e},function(e){Ae=e},function(e){Me=e},function(e){Ee=e.coerceBooleanProperty,Ge=e.coerceElement,we=e.coerceNumberProperty},function(e){De=e},function(e){Ve=e},function(e){Pe=e},function(e){Re=e},function(e){Oe=e.tap,_e=e.map,Be=e.startWith,Ke=e.mergeMap,ze=e.share,He=e.takeUntil,Ue=e.auditTime},function(e){je=e},function(e){$e=e},function(e){Je=e.HomeComponentsModule},function(e){Qe=e.__decorate},function(e){Ye=e},function(e){We=e},function(e){Ze=e},function(e){Xe=e},function(e){et=e},function(e){tt=e},function(e){nt=e},function(e){rt=e},function(e){ot=e},function(e){at=e},function(e){it=e},function(e){lt=e},function(e){st=e},function(e){mt=e.normalizePassiveListenerOptions,pt=e}],execute:function(){class dt extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.emptyConfigForm}onConfigurationSet(e){this.emptyConfigForm=this.fb.group({})}}e("EmptyConfigComponent",dt),dt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),dt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:dt,selector:"tb-node-empty-config",usesInheritance:!0,ngImport:t,template:"<div></div>",isInline:!0}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dt,decorators:[{type:n,args:[{selector:"tb-node-empty-config",template:"<div></div>"}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ut extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.assignCustomerConfigForm}onConfigurationSet(e){this.assignCustomerConfigForm=this.fb.group({customerNamePattern:[e?e.customerNamePattern:null,[O.required,O.pattern(/.*\S.*/)]],createCustomerIfNotExists:[!!e&&e.createCustomerIfNotExists,[]]})}prepareOutputConfig(e){return e.customerNamePattern=e.customerNamePattern.trim(),e}}e("AssignCustomerConfigComponent",ut),ut.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ut,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ut.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ut,selector:"tb-action-node-assign-to-customer-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="assignCustomerConfigForm" fxLayout="column">\n <div class="tb-form-panel no-padding no-border">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.customer-name-pattern</mat-label>\n <input required matInput formControlName="customerNamePattern">\n <mat-error *ngIf="assignCustomerConfigForm.get(\'customerNamePattern\').hasError(\'required\') ||\n assignCustomerConfigForm.get(\'customerNamePattern\').hasError(\'pattern\')">\n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.customer-name-pattern-hint</mat-hint>\n </mat-form-field>\n <div class="tb-form-row">\n <mat-slide-toggle class="mat-slide" formControlName="createCustomerIfNotExists">\n {{ \'tb.rulenode.create-customer-if-not-exists\' | translate }}\n </mat-slide-toggle>\n </div>\n </div>\n</section>\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ut,decorators:[{type:n,args:[{selector:"tb-action-node-assign-to-customer-config",template:'<section [formGroup]="assignCustomerConfigForm" fxLayout="column">\n <div class="tb-form-panel no-padding no-border">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.customer-name-pattern</mat-label>\n <input required matInput formControlName="customerNamePattern">\n <mat-error *ngIf="assignCustomerConfigForm.get(\'customerNamePattern\').hasError(\'required\') ||\n assignCustomerConfigForm.get(\'customerNamePattern\').hasError(\'pattern\')">\n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.customer-name-pattern-hint</mat-hint>\n </mat-form-field>\n <div class="tb-form-row">\n <mat-slide-toggle class="mat-slide" formControlName="createCustomerIfNotExists">\n {{ \'tb.rulenode.create-customer-if-not-exists\' | translate }}\n </mat-slide-toggle>\n </div>\n </div>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});const ct=new r("WindowToken","undefined"!=typeof window&&window.document?{providedIn:"root",factory:()=>window}:{providedIn:"root",factory:()=>{}});class gt{constructor(e,t,n){this.ngZone=e,this.document=t,this.window=n,this.copySubject=new ae,this.copyResponse$=this.copySubject.asObservable(),this.config={}}configure(e){this.config=e}copy(e){if(!this.isSupported||!e)return this.pushCopyResponse({isSuccess:!1,content:e});const t=this.copyFromContent(e);return t?this.pushCopyResponse({content:e,isSuccess:t}):this.pushCopyResponse({isSuccess:!1,content:e})}get isSupported(){return!!this.document.queryCommandSupported&&!!this.document.queryCommandSupported("copy")&&!!this.window}isTargetValid(e){if(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement){if(e.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');return!0}throw new Error("Target should be input or textarea")}copyFromInputElement(e,t=!0){try{this.selectTarget(e);const n=this.copyText();return this.clearSelection(t?e:void 0,this.window),n&&this.isCopySuccessInIE11()}catch(e){return!1}}isCopySuccessInIE11(){const e=this.window.clipboardData;return!(e&&e.getData&&!e.getData("Text"))}copyFromContent(e,t=this.document.body){if(this.tempTextArea&&!t.contains(this.tempTextArea)&&this.destroy(this.tempTextArea.parentElement||void 0),!this.tempTextArea){this.tempTextArea=this.createTempTextArea(this.document,this.window);try{t.appendChild(this.tempTextArea)}catch(e){throw new Error("Container should be a Dom element")}}this.tempTextArea.value=e;const n=this.copyFromInputElement(this.tempTextArea,!1);return this.config.cleanUpAfterCopy&&this.destroy(this.tempTextArea.parentElement||void 0),n}destroy(e=this.document.body){this.tempTextArea&&(e.removeChild(this.tempTextArea),this.tempTextArea=void 0)}selectTarget(e){return e.select(),e.setSelectionRange(0,e.value.length),e.value.length}copyText(){return this.document.execCommand("copy")}clearSelection(e,t){e&&e.focus(),t.getSelection()?.removeAllRanges()}createTempTextArea(e,t){const n="rtl"===e.documentElement.getAttribute("dir");let r;r=e.createElement("textarea"),r.style.fontSize="12pt",r.style.border="0",r.style.padding="0",r.style.margin="0",r.style.position="absolute",r.style[n?"right":"left"]="-9999px";const o=t.pageYOffset||e.documentElement.scrollTop;return r.style.top=o+"px",r.setAttribute("readonly",""),r}pushCopyResponse(e){this.copySubject.observers.length>0&&this.ngZone.run((()=>{this.copySubject.next(e)}))}pushCopyReponse(e){this.pushCopyResponse(e)}}gt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:gt,deps:[{token:t.NgZone},{token:j},{token:ct,optional:!0}],target:t.ɵɵFactoryTarget.Injectable}),gt.ɵprov=t.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:gt,providedIn:"root"}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:gt,decorators:[{type:o,args:[{providedIn:"root"}]}],ctorParameters:function(){return[{type:t.NgZone},{type:void 0,decorators:[{type:a,args:[j]}]},{type:void 0,decorators:[{type:i},{type:a,args:[ct]}]}]}});class ft{constructor(e,t,n,r){this.ngZone=e,this.host=t,this.renderer=n,this.clipboardSrv=r,this.cbOnSuccess=new l,this.cbOnError=new l,this.onClick=e=>{this.clipboardSrv.isSupported?this.targetElm&&this.clipboardSrv.isTargetValid(this.targetElm)?this.handleResult(this.clipboardSrv.copyFromInputElement(this.targetElm),this.targetElm.value,e):this.cbContent&&this.handleResult(this.clipboardSrv.copyFromContent(this.cbContent,this.container),this.cbContent,e):this.handleResult(!1,void 0,e)}}ngOnInit(){this.ngZone.runOutsideAngular((()=>{this.clickListener=this.renderer.listen(this.host.nativeElement,"click",this.onClick)}))}ngOnDestroy(){this.clickListener&&this.clickListener(),this.clipboardSrv.destroy(this.container)}handleResult(e,t,n){let r={isSuccess:e,content:t,successMessage:this.cbSuccessMsg,event:n};e?this.cbOnSuccess.observed&&this.ngZone.run((()=>{this.cbOnSuccess.emit(r)})):this.cbOnError.observed&&this.ngZone.run((()=>{this.cbOnError.emit(r)})),this.clipboardSrv.pushCopyResponse(r)}}ft.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:ft,deps:[{token:t.NgZone},{token:t.ElementRef},{token:t.Renderer2},{token:gt}],target:t.ɵɵFactoryTarget.Directive}),ft.ɵdir=t.ɵɵngDeclareDirective({minVersion:"12.0.0",version:"13.0.1",type:ft,selector:"[ngxClipboard]",inputs:{targetElm:["ngxClipboard","targetElm"],container:"container",cbContent:"cbContent",cbSuccessMsg:"cbSuccessMsg"},outputs:{cbOnSuccess:"cbOnSuccess",cbOnError:"cbOnError"},ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:ft,decorators:[{type:s,args:[{selector:"[ngxClipboard]"}]}],ctorParameters:function(){return[{type:t.NgZone},{type:t.ElementRef},{type:t.Renderer2},{type:gt}]},propDecorators:{targetElm:[{type:m,args:["ngxClipboard"]}],container:[{type:m}],cbContent:[{type:m}],cbSuccessMsg:[{type:m}],cbOnSuccess:[{type:p}],cbOnError:[{type:p}]}});class yt{constructor(e,t,n){this._clipboardService=e,this._viewContainerRef=t,this._templateRef=n}ngOnInit(){this._clipboardService.isSupported&&this._viewContainerRef.createEmbeddedView(this._templateRef)}}yt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:yt,deps:[{token:gt},{token:t.ViewContainerRef},{token:t.TemplateRef}],target:t.ɵɵFactoryTarget.Directive}),yt.ɵdir=t.ɵɵngDeclareDirective({minVersion:"12.0.0",version:"13.0.1",type:yt,selector:"[ngxClipboardIfSupported]",ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:yt,decorators:[{type:s,args:[{selector:"[ngxClipboardIfSupported]"}]}],ctorParameters:function(){return[{type:gt},{type:t.ViewContainerRef},{type:t.TemplateRef}]}});class bt{}bt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:bt,deps:[],target:t.ɵɵFactoryTarget.NgModule}),bt.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:bt,declarations:[ft,yt],imports:[$],exports:[ft,yt]}),bt.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:bt,imports:[[$]]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:bt,decorators:[{type:d,args:[{imports:[$],declarations:[ft,yt],exports:[ft,yt]}]}]});class xt{constructor(){this.textAlign="left"}}e("ExampleHintComponent",xt),xt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xt,deps:[],target:t.ɵɵFactoryTarget.Component}),xt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:xt,selector:"tb-example-hint",inputs:{hintText:"hintText",popupHelpLink:"popupHelpLink",textAlign:"textAlign"},ngImport:t,template:'<div [hidden]="!hintText" class="tb-form-hint tb-primary-fill space-between">\n <div [innerHTML]=" hintText | translate | safe: \'html\'"\n [style.text-align]="textAlign"\n class="hint-text"></div>\n <div *ngIf="popupHelpLink" class="see-example" tb-help-popup="{{ popupHelpLink }}"\n hintMode\n tb-help-popup-placement="right"\n trigger-style="letter-spacing:0.25px; font-size:12px"\n [tb-help-popup-style]="{maxWidth: \'820px\'}"\n trigger-text="{{ \'tb.key-val.see-examples\' | translate }}">\n </div>\n</div>\n',styles:[":host .space-between{display:flex;justify-content:space-between;gap:20px}:host .space-between .see-example{display:flex;flex-shrink:0}:host .hint-text{width:100%}\n"],dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"pipe",type:ue.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xt,decorators:[{type:n,args:[{selector:"tb-example-hint",template:'<div [hidden]="!hintText" class="tb-form-hint tb-primary-fill space-between">\n <div [innerHTML]=" hintText | translate | safe: \'html\'"\n [style.text-align]="textAlign"\n class="hint-text"></div>\n <div *ngIf="popupHelpLink" class="see-example" tb-help-popup="{{ popupHelpLink }}"\n hintMode\n tb-help-popup-placement="right"\n trigger-style="letter-spacing:0.25px; font-size:12px"\n [tb-help-popup-style]="{maxWidth: \'820px\'}"\n trigger-text="{{ \'tb.key-val.see-examples\' | translate }}">\n </div>\n</div>\n',styles:[":host .space-between{display:flex;justify-content:space-between;gap:20px}:host .space-between .see-example{display:flex;flex-shrink:0}:host .hint-text{width:100%}\n"]}]}],propDecorators:{hintText:[{type:m}],popupHelpLink:[{type:m}],textAlign:[{type:m}]}});class ht extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopeMap=f,this.attributeScopes=Object.keys(f),this.telemetryTypeTranslationsMap=y}configForm(){return this.attributesConfigForm}onConfigurationSet(e){this.attributesConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]],notifyDevice:[!e||e.notifyDevice,[]],sendAttributesUpdatedNotification:[!!e&&e.sendAttributesUpdatedNotification,[]],updateAttributesOnlyOnValueChange:[!!e&&e.updateAttributesOnlyOnValueChange,[]]}),this.attributesConfigForm.get("scope").valueChanges.subscribe((e=>{e!==f.SHARED_SCOPE&&this.attributesConfigForm.get("notifyDevice").patchValue(!1,{emitEvent:!1}),e===f.CLIENT_SCOPE&&this.attributesConfigForm.get("sendAttributesUpdatedNotification").patchValue(!1,{emitEvent:!1}),this.attributesConfigForm.get("updateAttributesOnlyOnValueChange").patchValue(!1,{emitEvent:!1})}))}}e("AttributesConfigComponent",ht),ht.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ht,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ht.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ht,selector:"tb-action-node-attributes-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="attributesConfigForm" class="tb-form-panel no-border no-padding">\n <div class="tb-form-panel stroked">\n <tb-example-hint [hintText]="\'tb.rulenode.attributes-scope-hint\'">\n </tb-example-hint>\n <div class="tb-form-row no-border no-padding tb-standard-fields">\n <mat-form-field class="flex">\n <mat-label>{{ \'tb.rulenode.attributes-scope\' | translate }}</mat-label>\n <mat-select required\n class="tb-entity-type-select" matInput formControlName="scope">\n <mat-option *ngFor="let scope of attributeScopes" [value]="scope">\n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label>{{ \'tb.rulenode.attributes-scope-value\' | translate }}</mat-label>\n <input type="text" matInput readonly disabled [ngModel]="attributesConfigForm.get(\'scope\').value" [ngModelOptions]="{standalone: true}">\n <button type="button"\n matSuffix\n mat-icon-button\n aria-label="Copy"\n ngxClipboard\n [cbContent]="attributesConfigForm.get(\'scope\').value"\n matTooltip="{{ \'tb.rulenode.attributes-scope-value-copy\' | translate }}">\n <mat-icon aria-hidden="false"\n aria-label="help-icon">content_copy\n </mat-icon>\n </button>\n </mat-form-field>\n </div>\n </div>\n\n <section class="tb-form-panel stroked">\n <mat-expansion-panel class="tb-settings">\n <mat-expansion-panel-header>\n <mat-panel-title translate>tb.rulenode.advanced-settings</mat-panel-title>\n </mat-expansion-panel-header>\n <div tb-hint-tooltip-icon="{{ (attributesConfigForm.get(\'updateAttributesOnlyOnValueChange\').value\n ? \'tb.rulenode.update-attributes-only-on-value-change-hint-enabled\'\n : \'tb.rulenode.update-attributes-only-on-value-change-hint\') | translate }}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="updateAttributesOnlyOnValueChange">\n {{ \'tb.rulenode.update-attributes-only-on-value-change\' | translate }}\n </mat-slide-toggle>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.send-attributes-updated-notification-hint\' | translate }}"\n *ngIf="attributesConfigForm.get(\'scope\').value !== attributeScopeMap.CLIENT_SCOPE"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="sendAttributesUpdatedNotification">\n {{ \'tb.rulenode.send-attributes-updated-notification\' | translate }}\n </mat-slide-toggle>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.notify-device-on-update-hint\' | translate }}"\n *ngIf="attributesConfigForm.get(\'scope\').value === attributeScopeMap.SHARED_SCOPE"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="notifyDevice">\n {{ \'tb.rulenode.notify-device\' | translate }}\n </mat-slide-toggle>\n </div>\n </mat-expansion-panel>\n </section>\n</section>\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"component",type:oe.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:oe.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:oe.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:ft,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ht,decorators:[{type:n,args:[{selector:"tb-action-node-attributes-config",template:'<section [formGroup]="attributesConfigForm" class="tb-form-panel no-border no-padding">\n <div class="tb-form-panel stroked">\n <tb-example-hint [hintText]="\'tb.rulenode.attributes-scope-hint\'">\n </tb-example-hint>\n <div class="tb-form-row no-border no-padding tb-standard-fields">\n <mat-form-field class="flex">\n <mat-label>{{ \'tb.rulenode.attributes-scope\' | translate }}</mat-label>\n <mat-select required\n class="tb-entity-type-select" matInput formControlName="scope">\n <mat-option *ngFor="let scope of attributeScopes" [value]="scope">\n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label>{{ \'tb.rulenode.attributes-scope-value\' | translate }}</mat-label>\n <input type="text" matInput readonly disabled [ngModel]="attributesConfigForm.get(\'scope\').value" [ngModelOptions]="{standalone: true}">\n <button type="button"\n matSuffix\n mat-icon-button\n aria-label="Copy"\n ngxClipboard\n [cbContent]="attributesConfigForm.get(\'scope\').value"\n matTooltip="{{ \'tb.rulenode.attributes-scope-value-copy\' | translate }}">\n <mat-icon aria-hidden="false"\n aria-label="help-icon">content_copy\n </mat-icon>\n </button>\n </mat-form-field>\n </div>\n </div>\n\n <section class="tb-form-panel stroked">\n <mat-expansion-panel class="tb-settings">\n <mat-expansion-panel-header>\n <mat-panel-title translate>tb.rulenode.advanced-settings</mat-panel-title>\n </mat-expansion-panel-header>\n <div tb-hint-tooltip-icon="{{ (attributesConfigForm.get(\'updateAttributesOnlyOnValueChange\').value\n ? \'tb.rulenode.update-attributes-only-on-value-change-hint-enabled\'\n : \'tb.rulenode.update-attributes-only-on-value-change-hint\') | translate }}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="updateAttributesOnlyOnValueChange">\n {{ \'tb.rulenode.update-attributes-only-on-value-change\' | translate }}\n </mat-slide-toggle>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.send-attributes-updated-notification-hint\' | translate }}"\n *ngIf="attributesConfigForm.get(\'scope\').value !== attributeScopeMap.CLIENT_SCOPE"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="sendAttributesUpdatedNotification">\n {{ \'tb.rulenode.send-attributes-updated-notification\' | translate }}\n </mat-slide-toggle>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.notify-device-on-update-hint\' | translate }}"\n *ngIf="attributesConfigForm.get(\'scope\').value === attributeScopeMap.SHARED_SCOPE"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="notifyDevice">\n {{ \'tb.rulenode.notify-device\' | translate }}\n </mat-slide-toggle>\n </div>\n </mat-expansion-panel>\n </section>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class vt extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ce(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-details-function"}configForm(){return this.clearAlarmConfigForm}onConfigurationSet(e){this.clearAlarmConfigForm=this.fb.group({scriptLang:[e?e.scriptLang:b.JS,[O.required]],alarmDetailsBuildJs:[e?e.alarmDetailsBuildJs:null,[]],alarmDetailsBuildTbel:[e?e.alarmDetailsBuildTbel:null,[]],alarmType:[e?e.alarmType:null,[O.required]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.clearAlarmConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.clearAlarmConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.clearAlarmConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.clearAlarmConfigForm.get("alarmDetailsBuildJs").setValidators(t===b.JS?[O.required]:[]),this.clearAlarmConfigForm.get("alarmDetailsBuildJs").updateValueAndValidity({emitEvent:e}),this.clearAlarmConfigForm.get("alarmDetailsBuildTbel").setValidators(t===b.TBEL?[O.required]:[]),this.clearAlarmConfigForm.get("alarmDetailsBuildTbel").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),e}testScript(e){const t=this.clearAlarmConfigForm.get("scriptLang").value,n=t===b.JS?"alarmDetailsBuildJs":"alarmDetailsBuildTbel",r=t===b.JS?"rulenode/clear_alarm_node_script_fn":"rulenode/tbel/clear_alarm_node_script_fn",o=this.clearAlarmConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"json",this.translate.instant("tb.rulenode.details"),"Details",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.clearAlarmConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.clearAlarmConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}e("ClearAlarmConfigComponent",vt),vt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vt,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:ge.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),vt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:vt,selector:"tb-action-node-clear-alarm-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'<section [formGroup]="clearAlarmConfigForm" fxLayout="column">\n <tb-script-lang formControlName="scriptLang" *ngIf="tbelEnabled"></tb-script-lang>\n <tb-js-func *ngIf="clearAlarmConfigForm.get(\'scriptLang\').value === scriptLanguage.JS"\n #jsFuncComponent\n formControlName="alarmDetailsBuildJs"\n functionName="Details"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n helpId="rulenode/clear_alarm_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <tb-js-func *ngIf="clearAlarmConfigForm.get(\'scriptLang\').value === scriptLanguage.TBEL"\n #tbelFuncComponent\n formControlName="alarmDetailsBuildTbel"\n functionName="Details"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n [disableUndefinedCheck]="true"\n [scriptLanguage]="scriptLanguage.TBEL"\n helpId="rulenode/tbel/clear_alarm_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <div fxLayout="row" style="padding-bottom: 16px;">\n <button mat-button mat-raised-button color="primary" (click)="testScript()">\n {{ testScriptLabel | translate }}\n </button>\n </div>\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.alarm-type</mat-label>\n <input required matInput formControlName="alarmType">\n <mat-error *ngIf="clearAlarmConfigForm.get(\'alarmType\').hasError(\'required\')">\n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n</section>\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Ce.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vt,decorators:[{type:n,args:[{selector:"tb-action-node-clear-alarm-config",template:'<section [formGroup]="clearAlarmConfigForm" fxLayout="column">\n <tb-script-lang formControlName="scriptLang" *ngIf="tbelEnabled"></tb-script-lang>\n <tb-js-func *ngIf="clearAlarmConfigForm.get(\'scriptLang\').value === scriptLanguage.JS"\n #jsFuncComponent\n formControlName="alarmDetailsBuildJs"\n functionName="Details"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n helpId="rulenode/clear_alarm_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <tb-js-func *ngIf="clearAlarmConfigForm.get(\'scriptLang\').value === scriptLanguage.TBEL"\n #tbelFuncComponent\n formControlName="alarmDetailsBuildTbel"\n functionName="Details"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n [disableUndefinedCheck]="true"\n [scriptLanguage]="scriptLanguage.TBEL"\n helpId="rulenode/tbel/clear_alarm_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <div fxLayout="row" style="padding-bottom: 16px;">\n <button mat-button mat-raised-button color="primary" (click)="testScript()">\n {{ testScriptLabel | translate }}\n </button>\n </div>\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.alarm-type</mat-label>\n <input required matInput formControlName="alarmType">\n <mat-error *ngIf="clearAlarmConfigForm.get(\'alarmType\').hasError(\'required\')">\n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:ge.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}});class Ct extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.alarmSeverities=Object.keys(x),this.alarmSeverityTranslationMap=h,this.separatorKeysCodes=[Fe,ke,Te],this.tbelEnabled=ce(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-details-function"}configForm(){return this.createAlarmConfigForm}onConfigurationSet(e){this.createAlarmConfigForm=this.fb.group({scriptLang:[e?e.scriptLang:b.JS,[O.required]],alarmDetailsBuildJs:[e?e.alarmDetailsBuildJs:null,[]],alarmDetailsBuildTbel:[e?e.alarmDetailsBuildTbel:null,[]],useMessageAlarmData:[!!e&&e.useMessageAlarmData,[]],overwriteAlarmDetails:[!!e&&e.overwriteAlarmDetails,[]],alarmType:[e?e.alarmType:null,[]],severity:[e?e.severity:null,[]],propagate:[!!e&&e.propagate,[]],relationTypes:[e?e.relationTypes:null,[]],propagateToOwner:[!!e&&e.propagateToOwner,[]],propagateToTenant:[!!e&&e.propagateToTenant,[]],dynamicSeverity:!1}),this.createAlarmConfigForm.get("dynamicSeverity").valueChanges.subscribe((e=>{e?this.createAlarmConfigForm.get("severity").patchValue("",{emitEvent:!1}):this.createAlarmConfigForm.get("severity").patchValue(this.alarmSeverities[0],{emitEvent:!1})}))}validatorTriggers(){return["useMessageAlarmData","overwriteAlarmDetails","scriptLang"]}updateValidators(e){const t=this.createAlarmConfigForm.get("useMessageAlarmData").value,n=this.createAlarmConfigForm.get("overwriteAlarmDetails").value;t?(this.createAlarmConfigForm.get("alarmType").setValidators([]),this.createAlarmConfigForm.get("severity").setValidators([])):(this.createAlarmConfigForm.get("alarmType").setValidators([O.required]),this.createAlarmConfigForm.get("severity").setValidators([O.required])),this.createAlarmConfigForm.get("alarmType").updateValueAndValidity({emitEvent:e}),this.createAlarmConfigForm.get("severity").updateValueAndValidity({emitEvent:e});let r=this.createAlarmConfigForm.get("scriptLang").value;r!==b.TBEL||this.tbelEnabled||(r=b.JS,this.createAlarmConfigForm.get("scriptLang").patchValue(r,{emitEvent:!1}),setTimeout((()=>{this.createAlarmConfigForm.updateValueAndValidity({emitEvent:!0})})));const o=!1===t||!0===n;this.createAlarmConfigForm.get("alarmDetailsBuildJs").setValidators(o&&r===b.JS?[O.required]:[]),this.createAlarmConfigForm.get("alarmDetailsBuildTbel").setValidators(o&&r===b.TBEL?[O.required]:[]),this.createAlarmConfigForm.get("alarmDetailsBuildJs").updateValueAndValidity({emitEvent:e}),this.createAlarmConfigForm.get("alarmDetailsBuildTbel").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),e}testScript(e){const t=this.createAlarmConfigForm.get("scriptLang").value,n=t===b.JS?"alarmDetailsBuildJs":"alarmDetailsBuildTbel",r=t===b.JS?"rulenode/create_alarm_node_script_fn":"rulenode/tbel/create_alarm_node_script_fn",o=this.createAlarmConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"json",this.translate.instant("tb.rulenode.details"),"Details",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.createAlarmConfigForm.get(n).setValue(e),this.changeScript.emit())}))}removeKey(e,t){const n=this.createAlarmConfigForm.get(t).value,r=n.indexOf(e);r>=0&&(n.splice(r,1),this.createAlarmConfigForm.get(t).setValue(n,{emitEvent:!0}))}addKey(e,t){const n=e.input;let r=e.value;if((r||"").trim()){r=r.trim();let e=this.createAlarmConfigForm.get(t).value;e&&-1!==e.indexOf(r)||(e||(e=[]),e.push(r),this.createAlarmConfigForm.get(t).setValue(e,{emitEvent:!0}))}n&&(n.value="")}onValidate(){const e=this.createAlarmConfigForm.get("useMessageAlarmData").value,t=this.createAlarmConfigForm.get("overwriteAlarmDetails").value;if(!e||t){this.createAlarmConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}}e("CreateAlarmConfigComponent",Ct),Ct.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ct,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:ge.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Ct.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ct,selector:"tb-action-node-create-alarm-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'<section [formGroup]="createAlarmConfigForm" fxLayout="column">\n <mat-checkbox formControlName="useMessageAlarmData">\n {{ \'tb.rulenode.use-message-alarm-data\' | translate }}\n </mat-checkbox>\n <mat-checkbox formControlName="overwriteAlarmDetails" *ngIf="createAlarmConfigForm.get(\'useMessageAlarmData\').value === true">\n {{ \'tb.rulenode.overwrite-alarm-details\' | translate }}\n </mat-checkbox>\n <section fxLayout="column" *ngIf="createAlarmConfigForm.get(\'useMessageAlarmData\').value === false ||\n createAlarmConfigForm.get(\'overwriteAlarmDetails\').value === true">\n <tb-script-lang formControlName="scriptLang" *ngIf="tbelEnabled"></tb-script-lang>\n <tb-js-func *ngIf="createAlarmConfigForm.get(\'scriptLang\').value === scriptLanguage.JS"\n #jsFuncComponent\n formControlName="alarmDetailsBuildJs"\n functionName="Details"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n helpId="rulenode/create_alarm_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <tb-js-func *ngIf="createAlarmConfigForm.get(\'scriptLang\').value === scriptLanguage.TBEL"\n #tbelFuncComponent\n formControlName="alarmDetailsBuildTbel"\n functionName="Details"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n [disableUndefinedCheck]="true"\n [scriptLanguage]="scriptLanguage.TBEL"\n helpId="rulenode/tbel/create_alarm_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <div fxLayout="row" style="padding-bottom: 16px;">\n <button mat-button mat-raised-button color="primary" (click)="testScript()">\n {{ testScriptLabel | translate }}\n </button>\n </div>\n </section>\n <section fxLayout="column" *ngIf="createAlarmConfigForm.get(\'useMessageAlarmData\').value === false">\n <mat-form-field fxFlex subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.alarm-type</mat-label>\n <input required matInput formControlName="alarmType">\n <mat-error *ngIf="createAlarmConfigForm.get(\'alarmType\').hasError(\'required\')">\n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <mat-checkbox formControlName="dynamicSeverity">\n {{ \'tb.rulenode.use-alarm-severity-pattern\' | translate }}\n </mat-checkbox>\n <mat-form-field fxFlex *ngIf="!createAlarmConfigForm.get(\'dynamicSeverity\').value">\n <mat-label translate>tb.rulenode.alarm-severity</mat-label>\n <mat-select formControlName="severity" required>\n <mat-option *ngFor="let severity of alarmSeverities" [value]="severity">\n {{ alarmSeverityTranslationMap.get(severity) | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf="createAlarmConfigForm.get(\'severity\').hasError(\'required\')">\n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex *ngIf="createAlarmConfigForm.get(\'dynamicSeverity\').value" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.alarm-severity-pattern</mat-label>\n <input matInput formControlName="severity" required>\n <mat-error *ngIf="createAlarmConfigForm.get(\'severity\').hasError(\'required\')">\n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n </mat-error>\n <mat-hint [innerHTML]="\'tb.rulenode.alarm-severity-pattern-hint\' | translate | safe: \'html\'"></mat-hint>\n </mat-form-field>\n <mat-checkbox formControlName="propagate">\n {{ \'tb.rulenode.propagate\' | translate }}\n </mat-checkbox>\n <section *ngIf="createAlarmConfigForm.get(\'propagate\').value === true">\n <mat-form-field floatLabel="always" class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.relation-types-list</mat-label>\n <mat-chip-grid #relationTypesChipList>\n <mat-chip-row\n *ngFor="let key of createAlarmConfigForm.get(\'relationTypes\').value;"\n (removed)="removeKey(key, \'relationTypes\')">\n {{key}}\n <mat-icon matChipRemove>close</mat-icon>\n </mat-chip-row>\n <input matInput type="text" placeholder="{{\'tb.rulenode.relation-types-list\' | translate}}"\n [matChipInputFor]="relationTypesChipList"\n [matChipInputSeparatorKeyCodes]="separatorKeysCodes"\n (matChipInputTokenEnd)="addKey($event, \'relationTypes\')"\n [matChipInputAddOnBlur]="true">\n </mat-chip-grid>\n <mat-hint translate>tb.rulenode.relation-types-list-hint</mat-hint>\n </mat-form-field>\n </section>\n <mat-checkbox formControlName="propagateToOwner">\n {{ \'tb.rulenode.propagate-to-owner\' | translate }}\n </mat-checkbox>\n <mat-checkbox formControlName="propagateToTenant">\n {{ \'tb.rulenode.propagate-to-tenant\' | translate }}\n </mat-checkbox>\n </section>\n</section>\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Ie.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:Ie.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:Ie.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:Ie.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Ce.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:ue.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ct,decorators:[{type:n,args:[{selector:"tb-action-node-create-alarm-config",template:'<section [formGroup]="createAlarmConfigForm" fxLayout="column">\n <mat-checkbox formControlName="useMessageAlarmData">\n {{ \'tb.rulenode.use-message-alarm-data\' | translate }}\n </mat-checkbox>\n <mat-checkbox formControlName="overwriteAlarmDetails" *ngIf="createAlarmConfigForm.get(\'useMessageAlarmData\').value === true">\n {{ \'tb.rulenode.overwrite-alarm-details\' | translate }}\n </mat-checkbox>\n <section fxLayout="column" *ngIf="createAlarmConfigForm.get(\'useMessageAlarmData\').value === false ||\n createAlarmConfigForm.get(\'overwriteAlarmDetails\').value === true">\n <tb-script-lang formControlName="scriptLang" *ngIf="tbelEnabled"></tb-script-lang>\n <tb-js-func *ngIf="createAlarmConfigForm.get(\'scriptLang\').value === scriptLanguage.JS"\n #jsFuncComponent\n formControlName="alarmDetailsBuildJs"\n functionName="Details"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n helpId="rulenode/create_alarm_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <tb-js-func *ngIf="createAlarmConfigForm.get(\'scriptLang\').value === scriptLanguage.TBEL"\n #tbelFuncComponent\n formControlName="alarmDetailsBuildTbel"\n functionName="Details"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n [disableUndefinedCheck]="true"\n [scriptLanguage]="scriptLanguage.TBEL"\n helpId="rulenode/tbel/create_alarm_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <div fxLayout="row" style="padding-bottom: 16px;">\n <button mat-button mat-raised-button color="primary" (click)="testScript()">\n {{ testScriptLabel | translate }}\n </button>\n </div>\n </section>\n <section fxLayout="column" *ngIf="createAlarmConfigForm.get(\'useMessageAlarmData\').value === false">\n <mat-form-field fxFlex subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.alarm-type</mat-label>\n <input required matInput formControlName="alarmType">\n <mat-error *ngIf="createAlarmConfigForm.get(\'alarmType\').hasError(\'required\')">\n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <mat-checkbox formControlName="dynamicSeverity">\n {{ \'tb.rulenode.use-alarm-severity-pattern\' | translate }}\n </mat-checkbox>\n <mat-form-field fxFlex *ngIf="!createAlarmConfigForm.get(\'dynamicSeverity\').value">\n <mat-label translate>tb.rulenode.alarm-severity</mat-label>\n <mat-select formControlName="severity" required>\n <mat-option *ngFor="let severity of alarmSeverities" [value]="severity">\n {{ alarmSeverityTranslationMap.get(severity) | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf="createAlarmConfigForm.get(\'severity\').hasError(\'required\')">\n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex *ngIf="createAlarmConfigForm.get(\'dynamicSeverity\').value" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.alarm-severity-pattern</mat-label>\n <input matInput formControlName="severity" required>\n <mat-error *ngIf="createAlarmConfigForm.get(\'severity\').hasError(\'required\')">\n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n </mat-error>\n <mat-hint [innerHTML]="\'tb.rulenode.alarm-severity-pattern-hint\' | translate | safe: \'html\'"></mat-hint>\n </mat-form-field>\n <mat-checkbox formControlName="propagate">\n {{ \'tb.rulenode.propagate\' | translate }}\n </mat-checkbox>\n <section *ngIf="createAlarmConfigForm.get(\'propagate\').value === true">\n <mat-form-field floatLabel="always" class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.relation-types-list</mat-label>\n <mat-chip-grid #relationTypesChipList>\n <mat-chip-row\n *ngFor="let key of createAlarmConfigForm.get(\'relationTypes\').value;"\n (removed)="removeKey(key, \'relationTypes\')">\n {{key}}\n <mat-icon matChipRemove>close</mat-icon>\n </mat-chip-row>\n <input matInput type="text" placeholder="{{\'tb.rulenode.relation-types-list\' | translate}}"\n [matChipInputFor]="relationTypesChipList"\n [matChipInputSeparatorKeyCodes]="separatorKeysCodes"\n (matChipInputTokenEnd)="addKey($event, \'relationTypes\')"\n [matChipInputAddOnBlur]="true">\n </mat-chip-grid>\n <mat-hint translate>tb.rulenode.relation-types-list-hint</mat-hint>\n </mat-form-field>\n </section>\n <mat-checkbox formControlName="propagateToOwner">\n {{ \'tb.rulenode.propagate-to-owner\' | translate }}\n </mat-checkbox>\n <mat-checkbox formControlName="propagateToTenant">\n {{ \'tb.rulenode.propagate-to-tenant\' | translate }}\n </mat-checkbox>\n </section>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:ge.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}});class Ft extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=new Map([[v.FROM,"tb.rulenode.search-direction-from"],[v.TO,"tb.rulenode.search-direction-to"]]),this.entityType=C,this.entityTypeNamePatternTranslation=new Map([[C.DEVICE,"tb.rulenode.device-name-pattern"],[C.ASSET,"tb.rulenode.asset-name-pattern"],[C.ENTITY_VIEW,"tb.rulenode.entity-view-name-pattern"],[C.CUSTOMER,"tb.rulenode.customer-title-pattern"],[C.USER,"tb.rulenode.user-name-pattern"],[C.DASHBOARD,"tb.rulenode.dashboard-name-pattern"],[C.EDGE,"tb.rulenode.edge-name-pattern"]]),this.allowedEntityTypes=[C.DEVICE,C.ASSET,C.ENTITY_VIEW,C.TENANT,C.CUSTOMER,C.USER,C.DASHBOARD,C.EDGE]}configForm(){return this.createRelationConfigForm}onConfigurationSet(e){this.createRelationConfigForm=this.fb.group({direction:[e?e.direction:null,[O.required]],entityType:[e?e.entityType:null,[O.required]],entityNamePattern:[e?e.entityNamePattern:null,[]],entityTypePattern:[e?e.entityTypePattern:null,[]],relationType:[e?e.relationType:null,[O.required]],createEntityIfNotExists:[!!e&&e.createEntityIfNotExists,[]],removeCurrentRelations:[!!e&&e.removeCurrentRelations,[]],changeOriginatorToRelatedEntity:[!!e&&e.changeOriginatorToRelatedEntity,[]]})}validatorTriggers(){return["entityType","createEntityIfNotExists"]}updateValidators(e){const t=this.createRelationConfigForm.get("entityType").value;if(t?this.createRelationConfigForm.get("entityNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)]):this.createRelationConfigForm.get("entityNamePattern").setValidators([]),!t||t!==C.DEVICE&&t!==C.ASSET)this.createRelationConfigForm.get("entityTypePattern").setValidators([]);else{const e=[O.pattern(/.*\S.*/)];this.createRelationConfigForm.get("createEntityIfNotExists").value&&e.push(O.required),this.createRelationConfigForm.get("entityTypePattern").setValidators(e)}this.createRelationConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e}),this.createRelationConfigForm.get("entityTypePattern").updateValueAndValidity({emitEvent:e})}prepareOutputConfig(e){return e.entityNamePattern=e.entityNamePattern?e.entityNamePattern.trim():null,e.entityTypePattern=e.entityTypePattern?e.entityTypePattern.trim():null,e}}e("CreateRelationConfigComponent",Ft),Ft.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ft,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Ft.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ft,selector:"tb-action-node-create-relation-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="createRelationConfigForm" class="tb-form-panel no-padding no-border">\n <div class="tb-form-panel stroked no-padding-bottom">\n <div class="tb-form-panel-title" translate>tb.rulenode.relation-parameters</div>\n <div fxLayout="column">\n <mat-form-field class="mat-block" hideRequiredMarker>\n <mat-label translate>relation.direction</mat-label>\n <mat-select required matInput formControlName="direction">\n <mat-option *ngFor="let type of directionTypes" [value]="type">\n {{ directionTypeTranslations.get(type) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <tb-relation-type-autocomplete\n required\n formControlName="relationType">\n </tb-relation-type-autocomplete>\n </div>\n </div>\n\n <div class="tb-form-panel stroked no-padding-bottom">\n <div class="tb-form-panel-title" translate>tb.rulenode.target-entity</div>\n <div fxLayout="row" fxLayoutGap="16px">\n <tb-entity-type-select\n fxFlex\n showLabel\n required\n [allowedEntityTypes]="allowedEntityTypes"\n formControlName="entityType">\n </tb-entity-type-select>\n\n <mat-form-field *ngIf="createRelationConfigForm.get(\'entityType\').value &&\n createRelationConfigForm.get(\'entityType\').value !== entityType.TENANT"\n fxFlex class="mat-block">\n <mat-label>{{ entityTypeNamePatternTranslation.get(createRelationConfigForm.get(\'entityType\').value) | translate }}</mat-label>\n <input required matInput formControlName="entityNamePattern">\n </mat-form-field>\n\n <mat-form-field *ngIf="createRelationConfigForm.get(\'entityType\').value === entityType.DEVICE ||\n createRelationConfigForm.get(\'entityType\').value === entityType.ASSET"\n fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.profile-name</mat-label>\n <input matInput formControlName="entityTypePattern">\n </mat-form-field>\n </div>\n\n <tb-example-hint [hintText]="\'tb.rulenode.kv-map-pattern-hint\'"\n *ngIf="createRelationConfigForm.get(\'entityType\').value === entityType.CUSTOMER ||\n createRelationConfigForm.get(\'entityType\').value === entityType.DEVICE ||\n createRelationConfigForm.get(\'entityType\').value === entityType.ASSET"></tb-example-hint>\n\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.create-entity-if-not-exists-hint\' | translate }}"\n *ngIf="createRelationConfigForm.get(\'entityType\').value === entityType.CUSTOMER ||\n createRelationConfigForm.get(\'entityType\').value === entityType.DEVICE ||\n createRelationConfigForm.get(\'entityType\').value === entityType.ASSET"\n style="margin-bottom: 18px"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="createEntityIfNotExists">\n {{ \'tb.rulenode.create-entity-if-not-exists\' | translate }}\n </mat-slide-toggle>\n </div>\n </div>\n <section class="tb-form-panel stroked no-padding">\n <mat-expansion-panel class="tb-settings">\n <mat-expansion-panel-header style="padding: 16px">\n <mat-panel-title translate>tb.rulenode.advanced-settings</mat-panel-title>\n </mat-expansion-panel-header>\n <div class="tb-form-panel no-border no-padding-top">\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.remove-current-relations-hint\' | translate }}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="removeCurrentRelations">\n {{ \'tb.rulenode.remove-current-relations\' | translate }}\n </mat-slide-toggle>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.change-originator-to-related-entity-hint\' | translate }}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="changeOriginatorToRelatedEntity">\n {{ \'tb.rulenode.change-originator-to-related-entity\' | translate }}\n </mat-slide-toggle>\n </div>\n </div>\n </mat-expansion-panel>\n </section>\n</section>\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ne.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"component",type:Se.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"component",type:oe.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:oe.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:oe.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ft,decorators:[{type:n,args:[{selector:"tb-action-node-create-relation-config",template:'<section [formGroup]="createRelationConfigForm" class="tb-form-panel no-padding no-border">\n <div class="tb-form-panel stroked no-padding-bottom">\n <div class="tb-form-panel-title" translate>tb.rulenode.relation-parameters</div>\n <div fxLayout="column">\n <mat-form-field class="mat-block" hideRequiredMarker>\n <mat-label translate>relation.direction</mat-label>\n <mat-select required matInput formControlName="direction">\n <mat-option *ngFor="let type of directionTypes" [value]="type">\n {{ directionTypeTranslations.get(type) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <tb-relation-type-autocomplete\n required\n formControlName="relationType">\n </tb-relation-type-autocomplete>\n </div>\n </div>\n\n <div class="tb-form-panel stroked no-padding-bottom">\n <div class="tb-form-panel-title" translate>tb.rulenode.target-entity</div>\n <div fxLayout="row" fxLayoutGap="16px">\n <tb-entity-type-select\n fxFlex\n showLabel\n required\n [allowedEntityTypes]="allowedEntityTypes"\n formControlName="entityType">\n </tb-entity-type-select>\n\n <mat-form-field *ngIf="createRelationConfigForm.get(\'entityType\').value &&\n createRelationConfigForm.get(\'entityType\').value !== entityType.TENANT"\n fxFlex class="mat-block">\n <mat-label>{{ entityTypeNamePatternTranslation.get(createRelationConfigForm.get(\'entityType\').value) | translate }}</mat-label>\n <input required matInput formControlName="entityNamePattern">\n </mat-form-field>\n\n <mat-form-field *ngIf="createRelationConfigForm.get(\'entityType\').value === entityType.DEVICE ||\n createRelationConfigForm.get(\'entityType\').value === entityType.ASSET"\n fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.profile-name</mat-label>\n <input matInput formControlName="entityTypePattern">\n </mat-form-field>\n </div>\n\n <tb-example-hint [hintText]="\'tb.rulenode.kv-map-pattern-hint\'"\n *ngIf="createRelationConfigForm.get(\'entityType\').value === entityType.CUSTOMER ||\n createRelationConfigForm.get(\'entityType\').value === entityType.DEVICE ||\n createRelationConfigForm.get(\'entityType\').value === entityType.ASSET"></tb-example-hint>\n\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.create-entity-if-not-exists-hint\' | translate }}"\n *ngIf="createRelationConfigForm.get(\'entityType\').value === entityType.CUSTOMER ||\n createRelationConfigForm.get(\'entityType\').value === entityType.DEVICE ||\n createRelationConfigForm.get(\'entityType\').value === entityType.ASSET"\n style="margin-bottom: 18px"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="createEntityIfNotExists">\n {{ \'tb.rulenode.create-entity-if-not-exists\' | translate }}\n </mat-slide-toggle>\n </div>\n </div>\n <section class="tb-form-panel stroked no-padding">\n <mat-expansion-panel class="tb-settings">\n <mat-expansion-panel-header style="padding: 16px">\n <mat-panel-title translate>tb.rulenode.advanced-settings</mat-panel-title>\n </mat-expansion-panel-header>\n <div class="tb-form-panel no-border no-padding-top">\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.remove-current-relations-hint\' | translate }}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="removeCurrentRelations">\n {{ \'tb.rulenode.remove-current-relations\' | translate }}\n </mat-slide-toggle>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.change-originator-to-related-entity-hint\' | translate }}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="changeOriginatorToRelatedEntity">\n {{ \'tb.rulenode.change-originator-to-related-entity\' | translate }}\n </mat-slide-toggle>\n </div>\n </div>\n </mat-expansion-panel>\n </section>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class kt extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=new Map([[v.FROM,"tb.rulenode.del-relation-direction-from"],[v.TO,"tb.rulenode.del-relation-direction-to"]]),this.entityTypeNamePatternTranslation=new Map([[C.DEVICE,"tb.rulenode.device-name-pattern"],[C.ASSET,"tb.rulenode.asset-name-pattern"],[C.ENTITY_VIEW,"tb.rulenode.entity-view-name-pattern"],[C.CUSTOMER,"tb.rulenode.customer-title-pattern"],[C.USER,"tb.rulenode.user-name-pattern"],[C.DASHBOARD,"tb.rulenode.dashboard-name-pattern"],[C.EDGE,"tb.rulenode.edge-name-pattern"]]),this.entityType=C,this.allowedEntityTypes=[C.DEVICE,C.ASSET,C.ENTITY_VIEW,C.TENANT,C.CUSTOMER,C.USER,C.DASHBOARD,C.EDGE]}configForm(){return this.deleteRelationConfigForm}onConfigurationSet(e){this.deleteRelationConfigForm=this.fb.group({deleteForSingleEntity:[!!e&&e.deleteForSingleEntity,[]],direction:[e?e.direction:null,[O.required]],entityType:[e?e.entityType:null,[]],entityNamePattern:[e?e.entityNamePattern:null,[]],relationType:[e?e.relationType:null,[O.required]]})}validatorTriggers(){return["deleteForSingleEntity","entityType"]}updateValidators(e){const t=this.deleteRelationConfigForm.get("deleteForSingleEntity").value,n=this.deleteRelationConfigForm.get("entityType").value;t?this.deleteRelationConfigForm.get("entityType").setValidators([O.required]):this.deleteRelationConfigForm.get("entityType").setValidators([]),t&&n&&n!==C.TENANT?this.deleteRelationConfigForm.get("entityNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)]):this.deleteRelationConfigForm.get("entityNamePattern").setValidators([]),this.deleteRelationConfigForm.get("entityType").updateValueAndValidity({emitEvent:!1}),this.deleteRelationConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e})}prepareOutputConfig(e){return e.entityNamePattern=e.entityNamePattern?e.entityNamePattern.trim():null,e}}e("DeleteRelationConfigComponent",kt),kt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),kt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:kt,selector:"tb-action-node-delete-relation-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="deleteRelationConfigForm" class="tb-form-panel no-padding no-border">\n <div class="tb-form-panel stroked no-padding-bottom">\n <div class="tb-form-panel-title" translate>tb.rulenode.relation-parameters</div>\n <div fxLayout="column">\n <mat-form-field class="mat-block" hideRequiredMarker>\n <mat-label translate>relation.direction</mat-label>\n <mat-select required matInput formControlName="direction">\n <mat-option *ngFor="let type of directionTypes" [value]="type">\n {{ directionTypeTranslations.get(type) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <tb-relation-type-autocomplete\n required\n formControlName="relationType">\n </tb-relation-type-autocomplete>\n </div>\n </div>\n <div class="tb-form-panel stroked">\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.delete-relation-with-specific-entity-hint\' | translate }}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="deleteForSingleEntity">\n {{ \'tb.rulenode.delete-relation-with-specific-entity\' | translate }}\n </mat-slide-toggle>\n </div>\n <div *ngIf="deleteRelationConfigForm.get(\'deleteForSingleEntity\').value">\n <div fxLayout="row" fxLayoutGap="10px">\n <tb-entity-type-select\n fxFlex\n showLabel\n required\n [allowedEntityTypes]="allowedEntityTypes"\n formControlName="entityType">\n </tb-entity-type-select>\n <mat-form-field *ngIf="deleteRelationConfigForm.get(\'entityType\').value && deleteRelationConfigForm.get(\'entityType\').value !== entityType.TENANT"\n fxFlex class="mat-block">\n <mat-label>{{ entityTypeNamePatternTranslation.get(deleteRelationConfigForm.get(\'entityType\').value) | translate }}</mat-label>\n <input required matInput formControlName="entityNamePattern">\n </mat-form-field>\n </div>\n <tb-example-hint *ngIf="deleteRelationConfigForm.get(\'entityType\').value && deleteRelationConfigForm.get(\'entityType\').value !== entityType.TENANT"\n [hintText]="\'tb.rulenode.kv-map-single-pattern-hint\'"></tb-example-hint>\n </div>\n </div>\n</section>\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ne.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"component",type:Se.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kt,decorators:[{type:n,args:[{selector:"tb-action-node-delete-relation-config",template:'<section [formGroup]="deleteRelationConfigForm" class="tb-form-panel no-padding no-border">\n <div class="tb-form-panel stroked no-padding-bottom">\n <div class="tb-form-panel-title" translate>tb.rulenode.relation-parameters</div>\n <div fxLayout="column">\n <mat-form-field class="mat-block" hideRequiredMarker>\n <mat-label translate>relation.direction</mat-label>\n <mat-select required matInput formControlName="direction">\n <mat-option *ngFor="let type of directionTypes" [value]="type">\n {{ directionTypeTranslations.get(type) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <tb-relation-type-autocomplete\n required\n formControlName="relationType">\n </tb-relation-type-autocomplete>\n </div>\n </div>\n <div class="tb-form-panel stroked">\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.delete-relation-with-specific-entity-hint\' | translate }}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="deleteForSingleEntity">\n {{ \'tb.rulenode.delete-relation-with-specific-entity\' | translate }}\n </mat-slide-toggle>\n </div>\n <div *ngIf="deleteRelationConfigForm.get(\'deleteForSingleEntity\').value">\n <div fxLayout="row" fxLayoutGap="10px">\n <tb-entity-type-select\n fxFlex\n showLabel\n required\n [allowedEntityTypes]="allowedEntityTypes"\n formControlName="entityType">\n </tb-entity-type-select>\n <mat-form-field *ngIf="deleteRelationConfigForm.get(\'entityType\').value && deleteRelationConfigForm.get(\'entityType\').value !== entityType.TENANT"\n fxFlex class="mat-block">\n <mat-label>{{ entityTypeNamePatternTranslation.get(deleteRelationConfigForm.get(\'entityType\').value) | translate }}</mat-label>\n <input required matInput formControlName="entityNamePattern">\n </mat-form-field>\n </div>\n <tb-example-hint *ngIf="deleteRelationConfigForm.get(\'entityType\').value && deleteRelationConfigForm.get(\'entityType\').value !== entityType.TENANT"\n [hintText]="\'tb.rulenode.kv-map-single-pattern-hint\'"></tb-example-hint>\n </div>\n </div>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Tt extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.deviceProfile}onConfigurationSet(e){this.deviceProfile=this.fb.group({persistAlarmRulesState:[!!e&&e.persistAlarmRulesState],fetchAlarmRulesStateOnStart:[!!e&&e.fetchAlarmRulesStateOnStart]})}validatorTriggers(){return["persistAlarmRulesState"]}updateValidators(e){this.deviceProfile.get("persistAlarmRulesState").value?this.deviceProfile.get("fetchAlarmRulesStateOnStart").enable({emitEvent:!1}):(this.deviceProfile.get("fetchAlarmRulesStateOnStart").setValue(!1,{emitEvent:!1}),this.deviceProfile.get("fetchAlarmRulesStateOnStart").disable({emitEvent:!1})),this.deviceProfile.get("fetchAlarmRulesStateOnStart").updateValueAndValidity({emitEvent:e})}}e("DeviceProfileConfigComponent",Tt),Tt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Tt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Tt,selector:"tb-device-profile-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="deviceProfile" class="tb-form-panel stroked">\n <div class="tb-form-hint tb-primary-fill" translate>tb.rulenode.device-profile-node-hint</div>\n <div tb-hint-tooltip-icon="{{\'tb.rulenode.persist-alarm-rules-hint\' | translate }}"\n class="tb-form-row no-border no-padding slide-toggle">\n <mat-slide-toggle class="mat-slide" formControlName="persistAlarmRulesState">\n {{ \'tb.rulenode.persist-alarm-rules\' | translate }}\n </mat-slide-toggle>\n </div>\n <div tb-hint-tooltip-icon="{{\'tb.rulenode.fetch-alarm-rules-hint\' | translate }}"\n class="tb-form-row no-border no-padding slide-toggle">\n <mat-slide-toggle class="mat-slide" formControlName="fetchAlarmRulesStateOnStart">\n {{ \'tb.rulenode.fetch-alarm-rules\' | translate }}\n </mat-slide-toggle>\n </div>\n</section>\n',dependencies:[{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tt,decorators:[{type:n,args:[{selector:"tb-device-profile-config",template:'<section [formGroup]="deviceProfile" class="tb-form-panel stroked">\n <div class="tb-form-hint tb-primary-fill" translate>tb.rulenode.device-profile-node-hint</div>\n <div tb-hint-tooltip-icon="{{\'tb.rulenode.persist-alarm-rules-hint\' | translate }}"\n class="tb-form-row no-border no-padding slide-toggle">\n <mat-slide-toggle class="mat-slide" formControlName="persistAlarmRulesState">\n {{ \'tb.rulenode.persist-alarm-rules\' | translate }}\n </mat-slide-toggle>\n </div>\n <div tb-hint-tooltip-icon="{{\'tb.rulenode.fetch-alarm-rules-hint\' | translate }}"\n class="tb-form-row no-border no-padding slide-toggle">\n <mat-slide-toggle class="mat-slide" formControlName="fetchAlarmRulesStateOnStart">\n {{ \'tb.rulenode.fetch-alarm-rules\' | translate }}\n </mat-slide-toggle>\n </div>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Lt extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ce(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-generator-function"}configForm(){return this.generatorConfigForm}onConfigurationSet(e){this.generatorConfigForm=this.fb.group({msgCount:[e?e.msgCount:null,[O.required,O.min(0)]],periodInSeconds:[e?e.periodInSeconds:null,[O.required,O.min(1)]],originator:[e?e.originator:null,[]],scriptLang:[e?e.scriptLang:b.JS,[O.required]],jsScript:[e?e.jsScript:null,[]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.generatorConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.generatorConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.generatorConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.generatorConfigForm.get("jsScript").setValidators(t===b.JS?[O.required]:[]),this.generatorConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.generatorConfigForm.get("tbelScript").setValidators(t===b.TBEL?[O.required]:[]),this.generatorConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS),e.originatorId&&e.originatorType?e.originator={id:e.originatorId,entityType:e.originatorType}:e.originator=null,delete e.originatorId,delete e.originatorType),e}prepareOutputConfig(e){return e.originator?(e.originatorId=e.originator.id,e.originatorType=e.originator.entityType):(e.originatorId=null,e.originatorType=null),delete e.originator,e}testScript(e){const t=this.generatorConfigForm.get("scriptLang").value,n=t===b.JS?"jsScript":"tbelScript",r=t===b.JS?"rulenode/generator_node_script_fn":"rulenode/tbel/generator_node_script_fn",o=this.generatorConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"generate",this.translate.instant("tb.rulenode.generator"),"Generate",["prevMsg","prevMetadata","prevMsgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.generatorConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.generatorConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}var It;e("GeneratorConfigComponent",Lt),Lt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lt,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:ge.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Lt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Lt,selector:"tb-action-node-generator-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'<section [formGroup]="generatorConfigForm" fxLayout="column">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.message-count</mat-label>\n <input required type="number" min="0" step="1" matInput formControlName="msgCount">\n <mat-error *ngIf="generatorConfigForm.get(\'msgCount\').hasError(\'required\')">\n {{ \'tb.rulenode.message-count-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="generatorConfigForm.get(\'msgCount\').hasError(\'min\')">\n {{ \'tb.rulenode.min-message-count-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.period-seconds</mat-label>\n <input required type="number" min="1" step="1" matInput formControlName="periodInSeconds">\n <mat-error *ngIf="generatorConfigForm.get(\'periodInSeconds\').hasError(\'required\')">\n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="generatorConfigForm.get(\'periodInSeconds\').hasError(\'min\')">\n {{ \'tb.rulenode.min-period-seconds-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <div fxLayout="column">\n <label class="tb-small">{{ \'tb.rulenode.originator\' | translate }}</label>\n <tb-entity-select\n required="false"\n formControlName="originator">\n </tb-entity-select>\n </div>\n\n <tb-script-lang formControlName="scriptLang" *ngIf="tbelEnabled"></tb-script-lang>\n <tb-js-func *ngIf="generatorConfigForm.get(\'scriptLang\').value === scriptLanguage.JS"\n #jsFuncComponent\n formControlName="jsScript"\n functionName="Generate"\n [functionArgs]="[\'prevMsg\', \'prevMetadata\', \'prevMsgType\']"\n helpId="rulenode/generator_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <tb-js-func *ngIf="generatorConfigForm.get(\'scriptLang\').value === scriptLanguage.TBEL"\n #tbelFuncComponent\n formControlName="tbelScript"\n functionName="Generate"\n [functionArgs]="[\'prevMsg\', \'prevMetadata\', \'prevMsgType\']"\n [disableUndefinedCheck]="true"\n [scriptLanguage]="scriptLanguage.TBEL"\n helpId="rulenode/tbel/generator_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <div fxLayout="row" style="padding-bottom: 16px;">\n <button mat-button mat-raised-button color="primary" (click)="testScript()">\n {{ testScriptLabel | translate }}\n </button>\n </div>\n</section>\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:qe.EntitySelectComponent,selector:"tb-entity-select",inputs:["allowedEntityTypes","useAliasEntityTypes","required","disabled"]},{kind:"component",type:ve.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Ce.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lt,decorators:[{type:n,args:[{selector:"tb-action-node-generator-config",template:'<section [formGroup]="generatorConfigForm" fxLayout="column">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.message-count</mat-label>\n <input required type="number" min="0" step="1" matInput formControlName="msgCount">\n <mat-error *ngIf="generatorConfigForm.get(\'msgCount\').hasError(\'required\')">\n {{ \'tb.rulenode.message-count-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="generatorConfigForm.get(\'msgCount\').hasError(\'min\')">\n {{ \'tb.rulenode.min-message-count-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.period-seconds</mat-label>\n <input required type="number" min="1" step="1" matInput formControlName="periodInSeconds">\n <mat-error *ngIf="generatorConfigForm.get(\'periodInSeconds\').hasError(\'required\')">\n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="generatorConfigForm.get(\'periodInSeconds\').hasError(\'min\')">\n {{ \'tb.rulenode.min-period-seconds-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <div fxLayout="column">\n <label class="tb-small">{{ \'tb.rulenode.originator\' | translate }}</label>\n <tb-entity-select\n required="false"\n formControlName="originator">\n </tb-entity-select>\n </div>\n\n <tb-script-lang formControlName="scriptLang" *ngIf="tbelEnabled"></tb-script-lang>\n <tb-js-func *ngIf="generatorConfigForm.get(\'scriptLang\').value === scriptLanguage.JS"\n #jsFuncComponent\n formControlName="jsScript"\n functionName="Generate"\n [functionArgs]="[\'prevMsg\', \'prevMetadata\', \'prevMsgType\']"\n helpId="rulenode/generator_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <tb-js-func *ngIf="generatorConfigForm.get(\'scriptLang\').value === scriptLanguage.TBEL"\n #tbelFuncComponent\n formControlName="tbelScript"\n functionName="Generate"\n [functionArgs]="[\'prevMsg\', \'prevMetadata\', \'prevMsgType\']"\n [disableUndefinedCheck]="true"\n [scriptLanguage]="scriptLanguage.TBEL"\n helpId="rulenode/tbel/generator_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <div fxLayout="row" style="padding-bottom: 16px;">\n <button mat-button mat-raised-button color="primary" (click)="testScript()">\n {{ testScriptLabel | translate }}\n </button>\n </div>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:ge.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}}),function(e){e.CUSTOMER="CUSTOMER",e.TENANT="TENANT",e.RELATED="RELATED",e.ALARM_ORIGINATOR="ALARM_ORIGINATOR",e.ENTITY="ENTITY"}(It||(It={}));const Nt=new Map([[It.CUSTOMER,"tb.rulenode.originator-customer"],[It.TENANT,"tb.rulenode.originator-tenant"],[It.RELATED,"tb.rulenode.originator-related"],[It.ALARM_ORIGINATOR,"tb.rulenode.originator-alarm-originator"],[It.ENTITY,"tb.rulenode.originator-entity"]]),St=new Map([[It.CUSTOMER,"tb.rulenode.originator-customer-desc"],[It.TENANT,"tb.rulenode.originator-tenant-desc"],[It.RELATED,"tb.rulenode.originator-related-entity-desc"],[It.ALARM_ORIGINATOR,"tb.rulenode.originator-alarm-originator-desc"],[It.ENTITY,"tb.rulenode.originator-entity-by-name-pattern-desc"]]),qt=[F.createdTime,F.name,{value:"type",name:"tb.rulenode.profile-name",keyName:"originatorProfileName"},F.firstName,F.lastName,F.email,F.title,F.country,F.state,F.city,F.address,F.address2,F.zip,F.phone,F.label,{value:"id",name:"tb.rulenode.id",keyName:"id"},{value:"additionalInfo",name:"tb.rulenode.additional-info",keyName:"additionalInfo"}],At=new Map([["type","profileName"],["createdTime","createdTime"],["name","name"],["firstName","firstName"],["lastName","lastName"],["email","email"],["title","title"],["country","country"],["state","state"],["city","city"],["address","address"],["address2","address2"],["zip","zip"],["phone","phone"],["label","label"],["id","id"],["additionalInfo","additionalInfo"]]);var Mt;!function(e){e.CIRCLE="CIRCLE",e.POLYGON="POLYGON"}(Mt||(Mt={}));const Et=new Map([[Mt.CIRCLE,"tb.rulenode.perimeter-circle"],[Mt.POLYGON,"tb.rulenode.perimeter-polygon"]]);var Gt;!function(e){e.MILLISECONDS="MILLISECONDS",e.SECONDS="SECONDS",e.MINUTES="MINUTES",e.HOURS="HOURS",e.DAYS="DAYS"}(Gt||(Gt={}));const wt=new Map([[Gt.MILLISECONDS,"tb.rulenode.time-unit-milliseconds"],[Gt.SECONDS,"tb.rulenode.time-unit-seconds"],[Gt.MINUTES,"tb.rulenode.time-unit-minutes"],[Gt.HOURS,"tb.rulenode.time-unit-hours"],[Gt.DAYS,"tb.rulenode.time-unit-days"]]);var Dt;!function(e){e.METER="METER",e.KILOMETER="KILOMETER",e.FOOT="FOOT",e.MILE="MILE",e.NAUTICAL_MILE="NAUTICAL_MILE"}(Dt||(Dt={}));const Vt=new Map([[Dt.METER,"tb.rulenode.range-unit-meter"],[Dt.KILOMETER,"tb.rulenode.range-unit-kilometer"],[Dt.FOOT,"tb.rulenode.range-unit-foot"],[Dt.MILE,"tb.rulenode.range-unit-mile"],[Dt.NAUTICAL_MILE,"tb.rulenode.range-unit-nautical-mile"]]);var Pt;!function(e){e.ID="ID",e.TITLE="TITLE",e.COUNTRY="COUNTRY",e.STATE="STATE",e.CITY="CITY",e.ZIP="ZIP",e.ADDRESS="ADDRESS",e.ADDRESS2="ADDRESS2",e.PHONE="PHONE",e.EMAIL="EMAIL",e.ADDITIONAL_INFO="ADDITIONAL_INFO"}(Pt||(Pt={}));const Rt=new Map([[Pt.ID,"tb.rulenode.entity-details-id"],[Pt.TITLE,"tb.rulenode.entity-details-title"],[Pt.COUNTRY,"tb.rulenode.entity-details-country"],[Pt.STATE,"tb.rulenode.entity-details-state"],[Pt.CITY,"tb.rulenode.entity-details-city"],[Pt.ZIP,"tb.rulenode.entity-details-zip"],[Pt.ADDRESS,"tb.rulenode.entity-details-address"],[Pt.ADDRESS2,"tb.rulenode.entity-details-address2"],[Pt.PHONE,"tb.rulenode.entity-details-phone"],[Pt.EMAIL,"tb.rulenode.entity-details-email"],[Pt.ADDITIONAL_INFO,"tb.rulenode.entity-details-additional_info"]]);var Ot;!function(e){e.FIRST="FIRST",e.LAST="LAST",e.ALL="ALL"}(Ot||(Ot={}));const _t=new Map([[Ot.FIRST,"tb.rulenode.first"],[Ot.LAST,"tb.rulenode.last"],[Ot.ALL,"tb.rulenode.all"]]),Bt=new Map([[Ot.FIRST,"tb.rulenode.first-mode-hint"],[Ot.LAST,"tb.rulenode.last-mode-hint"],[Ot.ALL,"tb.rulenode.all-mode-hint"]]);var Kt,zt;!function(e){e.ASC="ASC",e.DESC="DESC"}(Kt||(Kt={})),function(e){e.ATTRIBUTES="ATTRIBUTES",e.LATEST_TELEMETRY="LATEST_TELEMETRY",e.FIELDS="FIELDS"}(zt||(zt={}));const Ht=new Map([[zt.ATTRIBUTES,"tb.rulenode.attributes"],[zt.LATEST_TELEMETRY,"tb.rulenode.latest-telemetry"],[zt.FIELDS,"tb.rulenode.fields"]]),Ut=new Map([[zt.ATTRIBUTES,"tb.rulenode.add-mapped-attribute-to"],[zt.LATEST_TELEMETRY,"tb.rulenode.add-mapped-latest-telemetry-to"],[zt.FIELDS,"tb.rulenode.add-mapped-fields-to"]]),jt=new Map([[Kt.ASC,"tb.rulenode.ascending"],[Kt.DESC,"tb.rulenode.descending"]]);var $t;!function(e){e.STANDARD="STANDARD",e.FIFO="FIFO"}($t||($t={}));const Jt=new Map([[$t.STANDARD,"tb.rulenode.sqs-queue-standard"],[$t.FIFO,"tb.rulenode.sqs-queue-fifo"]]),Qt=["anonymous","basic","cert.PEM"],Yt=new Map([["anonymous","tb.rulenode.credentials-anonymous"],["basic","tb.rulenode.credentials-basic"],["cert.PEM","tb.rulenode.credentials-pem"]]),Wt=["sas","cert.PEM"],Zt=new Map([["sas","tb.rulenode.credentials-sas"],["cert.PEM","tb.rulenode.credentials-pem"]]);var Xt;!function(e){e.GET="GET",e.POST="POST",e.PUT="PUT",e.DELETE="DELETE"}(Xt||(Xt={}));const en=["US-ASCII","ISO-8859-1","UTF-8","UTF-16BE","UTF-16LE","UTF-16"],tn=new Map([["US-ASCII","tb.rulenode.charset-us-ascii"],["ISO-8859-1","tb.rulenode.charset-iso-8859-1"],["UTF-8","tb.rulenode.charset-utf-8"],["UTF-16BE","tb.rulenode.charset-utf-16be"],["UTF-16LE","tb.rulenode.charset-utf-16le"],["UTF-16","tb.rulenode.charset-utf-16"]]);var nn;!function(e){e.CUSTOM="CUSTOM",e.ADD="ADD",e.SUB="SUB",e.MULT="MULT",e.DIV="DIV",e.SIN="SIN",e.SINH="SINH",e.COS="COS",e.COSH="COSH",e.TAN="TAN",e.TANH="TANH",e.ACOS="ACOS",e.ASIN="ASIN",e.ATAN="ATAN",e.ATAN2="ATAN2",e.EXP="EXP",e.EXPM1="EXPM1",e.SQRT="SQRT",e.CBRT="CBRT",e.GET_EXP="GET_EXP",e.HYPOT="HYPOT",e.LOG="LOG",e.LOG10="LOG10",e.LOG1P="LOG1P",e.CEIL="CEIL",e.FLOOR="FLOOR",e.FLOOR_DIV="FLOOR_DIV",e.FLOOR_MOD="FLOOR_MOD",e.ABS="ABS",e.MIN="MIN",e.MAX="MAX",e.POW="POW",e.SIGNUM="SIGNUM",e.RAD="RAD",e.DEG="DEG"}(nn||(nn={}));const rn=new Map([[nn.CUSTOM,{value:nn.CUSTOM,name:"Custom Function",description:"Use this function to specify complex mathematical expression.",minArgs:1,maxArgs:16}],[nn.ADD,{value:nn.ADD,name:"Addition",description:"x + y",minArgs:2,maxArgs:2}],[nn.SUB,{value:nn.SUB,name:"Subtraction",description:"x - y",minArgs:2,maxArgs:2}],[nn.MULT,{value:nn.MULT,name:"Multiplication",description:"x * y",minArgs:2,maxArgs:2}],[nn.DIV,{value:nn.DIV,name:"Division",description:"x / y",minArgs:2,maxArgs:2}],[nn.SIN,{value:nn.SIN,name:"Sine",description:"Returns the trigonometric sine of an angle in radians.",minArgs:1,maxArgs:1}],[nn.SINH,{value:nn.SINH,name:"Hyperbolic sine",description:"Returns the hyperbolic sine of an argument.",minArgs:1,maxArgs:1}],[nn.COS,{value:nn.COS,name:"Cosine",description:"Returns the trigonometric cosine of an angle in radians.",minArgs:1,maxArgs:1}],[nn.COSH,{value:nn.COSH,name:"Hyperbolic cosine",description:"Returns the hyperbolic cosine of an argument.",minArgs:1,maxArgs:1}],[nn.TAN,{value:nn.TAN,name:"Tangent",description:"Returns the trigonometric tangent of an angle in radians",minArgs:1,maxArgs:1}],[nn.TANH,{value:nn.TANH,name:"Hyperbolic tangent",description:"Returns the hyperbolic tangent of an argument",minArgs:1,maxArgs:1}],[nn.ACOS,{value:nn.ACOS,name:"Arc cosine",description:"Returns the arc cosine of an argument",minArgs:1,maxArgs:1}],[nn.ASIN,{value:nn.ASIN,name:"Arc sine",description:"Returns the arc sine of an argument",minArgs:1,maxArgs:1}],[nn.ATAN,{value:nn.ATAN,name:"Arc tangent",description:"Returns the arc tangent of an argument",minArgs:1,maxArgs:1}],[nn.ATAN2,{value:nn.ATAN2,name:"2-argument arc tangent",description:"Returns the angle theta from the conversion of rectangular coordinates (x, y) to polar coordinates (r, theta)",minArgs:2,maxArgs:2}],[nn.EXP,{value:nn.EXP,name:"Exponential",description:"Returns Euler's number e raised to the power of an argument",minArgs:1,maxArgs:1}],[nn.EXPM1,{value:nn.EXPM1,name:"Exponential minus one",description:"Returns Euler's number e raised to the power of an argument minus one",minArgs:1,maxArgs:1}],[nn.SQRT,{value:nn.SQRT,name:"Square",description:"Returns the correctly rounded positive square root of an argument",minArgs:1,maxArgs:1}],[nn.CBRT,{value:nn.CBRT,name:"Cube root",description:"Returns the cube root of an argument",minArgs:1,maxArgs:1}],[nn.GET_EXP,{value:nn.GET_EXP,name:"Get exponent",description:"Returns the unbiased exponent used in the representation of an argument",minArgs:1,maxArgs:1}],[nn.HYPOT,{value:nn.HYPOT,name:"Square root",description:"Returns the square root of the squares of the arguments",minArgs:2,maxArgs:2}],[nn.LOG,{value:nn.LOG,name:"Logarithm",description:"Returns the natural logarithm of an argument",minArgs:1,maxArgs:1}],[nn.LOG10,{value:nn.LOG10,name:"Base 10 logarithm",description:"Returns the base 10 logarithm of an argument",minArgs:1,maxArgs:1}],[nn.LOG1P,{value:nn.LOG1P,name:"Logarithm of the sum",description:"Returns the natural logarithm of the sum of an argument",minArgs:1,maxArgs:1}],[nn.CEIL,{value:nn.CEIL,name:"Ceiling",description:"Returns the smallest (closest to negative infinity) of an argument",minArgs:1,maxArgs:1}],[nn.FLOOR,{value:nn.FLOOR,name:"Floor",description:"Returns the largest (closest to positive infinity) of an argument",minArgs:1,maxArgs:1}],[nn.FLOOR_DIV,{value:nn.FLOOR_DIV,name:"Floor division",description:"Returns the largest (closest to positive infinity) of the arguments",minArgs:2,maxArgs:2}],[nn.FLOOR_MOD,{value:nn.FLOOR_MOD,name:"Floor modulus",description:"Returns the floor modulus of the arguments",minArgs:2,maxArgs:2}],[nn.ABS,{value:nn.ABS,name:"Absolute",description:"Returns the absolute value of an argument",minArgs:1,maxArgs:1}],[nn.MIN,{value:nn.MIN,name:"Min",description:"Returns the smaller of the arguments",minArgs:2,maxArgs:2}],[nn.MAX,{value:nn.MAX,name:"Max",description:"Returns the greater of the arguments",minArgs:2,maxArgs:2}],[nn.POW,{value:nn.POW,name:"Raise to a power",description:"Returns the value of the first argument raised to the power of the second argument",minArgs:2,maxArgs:2}],[nn.SIGNUM,{value:nn.SIGNUM,name:"Sign of a real number",description:"Returns the signum function of the argument",minArgs:1,maxArgs:1}],[nn.RAD,{value:nn.RAD,name:"Radian",description:"Converts an angle measured in degrees to an approximately equivalent angle measured in radians",minArgs:1,maxArgs:1}],[nn.DEG,{value:nn.DEG,name:"Degrees",description:"Converts an angle measured in radians to an approximately equivalent angle measured in degrees.",minArgs:1,maxArgs:1}]]);var on,an,ln;!function(e){e.MESSAGE_BODY="MESSAGE_BODY",e.MESSAGE_METADATA="MESSAGE_METADATA",e.ATTRIBUTE="ATTRIBUTE",e.TIME_SERIES="TIME_SERIES",e.CONSTANT="CONSTANT"}(on||(on={})),function(e){e.MESSAGE_BODY="MESSAGE_BODY",e.MESSAGE_METADATA="MESSAGE_METADATA",e.ATTRIBUTE="ATTRIBUTE",e.TIME_SERIES="TIME_SERIES"}(an||(an={})),function(e){e.DATA="DATA",e.METADATA="METADATA"}(ln||(ln={}));const sn=new Map([[ln.DATA,"tb.rulenode.message-to-metadata"],[ln.METADATA,"tb.rulenode.metadata-to-message"]]),mn=(new Map([[ln.DATA,"tb.rulenode.from-message"],[ln.METADATA,"tb.rulenode.from-metadata"]]),new Map([[ln.DATA,"tb.rulenode.message"],[ln.METADATA,"tb.rulenode.metadata"]])),pn=new Map([[ln.DATA,"tb.rulenode.message"],[ln.METADATA,"tb.rulenode.message-metadata"]]),dn=new Map([[on.MESSAGE_BODY,{name:"tb.rulenode.message-body-type",description:"Fetch argument value from incoming message"}],[on.MESSAGE_METADATA,{name:"tb.rulenode.message-metadata-type",description:"Fetch argument value from incoming message metadata"}],[on.ATTRIBUTE,{name:"tb.rulenode.attribute-type",description:"Fetch attribute value from database"}],[on.TIME_SERIES,{name:"tb.rulenode.time-series-type",description:"Fetch latest time-series value from database"}],[on.CONSTANT,{name:"tb.rulenode.constant-type",description:"Define constant value"}]]),un=new Map([[an.MESSAGE_BODY,{name:"tb.rulenode.message-body-type",description:"Add result to the outgoing message"}],[an.MESSAGE_METADATA,{name:"tb.rulenode.message-metadata-type",description:"Add result to the outgoing message metadata"}],[an.ATTRIBUTE,{name:"tb.rulenode.attribute-type",description:"Store result as an entity attribute in the database"}],[an.TIME_SERIES,{name:"tb.rulenode.time-series-type",description:"Store result as an entity time-series in the database"}]]),cn=["x","y","z","a","b","c","d","k","l","m","n","o","p","r","s","t"];var gn,fn;!function(e){e.SHARED_SCOPE="SHARED_SCOPE",e.SERVER_SCOPE="SERVER_SCOPE",e.CLIENT_SCOPE="CLIENT_SCOPE"}(gn||(gn={})),function(e){e.SHARED_SCOPE="SHARED_SCOPE",e.SERVER_SCOPE="SERVER_SCOPE"}(fn||(fn={}));const yn=new Map([[gn.SHARED_SCOPE,"tb.rulenode.shared-scope"],[gn.SERVER_SCOPE,"tb.rulenode.server-scope"],[gn.CLIENT_SCOPE,"tb.rulenode.client-scope"]]);var bn;!function(e){e.ON_FIRST_MESSAGE="ON_FIRST_MESSAGE",e.ON_EACH_MESSAGE="ON_EACH_MESSAGE"}(bn||(bn={}));const xn=new Map([[bn.ON_EACH_MESSAGE,{value:!0,name:"tb.rulenode.presence-monitoring-strategy-on-each-message"}],[bn.ON_FIRST_MESSAGE,{value:!1,name:"tb.rulenode.presence-monitoring-strategy-on-first-message"}]]);class hn extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.perimeterType=Mt,this.perimeterTypes=Object.keys(Mt),this.perimeterTypeTranslationMap=Et,this.rangeUnits=Object.keys(Dt),this.rangeUnitTranslationMap=Vt,this.presenceMonitoringStrategies=xn,this.presenceMonitoringStrategyKeys=Array.from(this.presenceMonitoringStrategies.keys()),this.timeUnits=Object.keys(Gt),this.timeUnitsTranslationMap=wt,this.defaultPaddingEnable=!0}configForm(){return this.geoActionConfigForm}onConfigurationSet(e){this.geoActionConfigForm=this.fb.group({reportPresenceStatusOnEachMessage:[!e||e.reportPresenceStatusOnEachMessage,[O.required]],latitudeKeyName:[e?e.latitudeKeyName:null,[O.required]],longitudeKeyName:[e?e.longitudeKeyName:null,[O.required]],perimeterType:[e?e.perimeterType:null,[O.required]],fetchPerimeterInfoFromMessageMetadata:[!!e&&e.fetchPerimeterInfoFromMessageMetadata,[]],perimeterKeyName:[e?e.perimeterKeyName:null,[]],centerLatitude:[e?e.centerLatitude:null,[]],centerLongitude:[e?e.centerLatitude:null,[]],range:[e?e.range:null,[]],rangeUnit:[e?e.rangeUnit:null,[]],polygonsDefinition:[e?e.polygonsDefinition:null,[]],minInsideDuration:[e?e.minInsideDuration:null,[O.required,O.min(1),O.max(2147483647)]],minInsideDurationTimeUnit:[e?e.minInsideDurationTimeUnit:null,[O.required]],minOutsideDuration:[e?e.minOutsideDuration:null,[O.required,O.min(1),O.max(2147483647)]],minOutsideDurationTimeUnit:[e?e.minOutsideDurationTimeUnit:null,[O.required]]})}validatorTriggers(){return["fetchPerimeterInfoFromMessageMetadata","perimeterType"]}updateValidators(e){const t=this.geoActionConfigForm.get("fetchPerimeterInfoFromMessageMetadata").value,n=this.geoActionConfigForm.get("perimeterType").value;t?this.geoActionConfigForm.get("perimeterKeyName").setValidators([O.required]):this.geoActionConfigForm.get("perimeterKeyName").setValidators([]),t||n!==Mt.CIRCLE?(this.geoActionConfigForm.get("centerLatitude").setValidators([]),this.geoActionConfigForm.get("centerLongitude").setValidators([]),this.geoActionConfigForm.get("range").setValidators([]),this.geoActionConfigForm.get("rangeUnit").setValidators([]),this.defaultPaddingEnable=!0):(this.geoActionConfigForm.get("centerLatitude").setValidators([O.required,O.min(-90),O.max(90)]),this.geoActionConfigForm.get("centerLongitude").setValidators([O.required,O.min(-180),O.max(180)]),this.geoActionConfigForm.get("range").setValidators([O.required,O.min(0)]),this.geoActionConfigForm.get("rangeUnit").setValidators([O.required]),this.defaultPaddingEnable=!1),t||n!==Mt.POLYGON?this.geoActionConfigForm.get("polygonsDefinition").setValidators([]):this.geoActionConfigForm.get("polygonsDefinition").setValidators([O.required]),this.geoActionConfigForm.get("perimeterKeyName").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("centerLatitude").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("centerLongitude").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("range").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("rangeUnit").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("polygonsDefinition").updateValueAndValidity({emitEvent:e})}}e("GpsGeoActionConfigComponent",hn),hn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),hn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:hn,selector:"tb-action-node-gps-geofencing-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="geoActionConfigForm" class="tb-form-panel no-border no-padding">\n <section class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.coordinate-field-names</div>\n <section>\n <div fxLayout="row" fxLayoutGap="16px">\n <mat-form-field fxFlex="50" class="mat-block">\n <mat-label>{{ \'tb.rulenode.latitude-field-name\' | translate }}</mat-label>\n <input matInput formControlName="latitudeKeyName" required>\n <mat-error *ngIf="geoActionConfigForm.get(\'latitudeKeyName\').hasError(\'required\')">\n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex="50" class="mat-block">\n <mat-label>{{ \'tb.rulenode.longitude-field-name\' | translate }}</mat-label>\n <input matInput formControlName="longitudeKeyName" required>\n <mat-error *ngIf="geoActionConfigForm.get(\'longitudeKeyName\').hasError(\'required\')">\n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <div class="tb-form-hint tb-primary-fill" translate>tb.rulenode.coordinate-field-hint</div>\n </section>\n </section>\n <section class="tb-form-panel stroked" [class.no-padding-bottom]="!defaultPaddingEnable">\n <div class="tb-form-panel-title" translate>tb.rulenode.geofence-configuration</div>\n <section fxLayout="column">\n <mat-form-field fxFlex class="mat-block" hideRequiredMarker>\n <mat-label>{{ \'tb.rulenode.perimeter-type\' | translate }}</mat-label>\n <mat-select formControlName="perimeterType">\n <mat-option *ngFor="let type of perimeterTypes" [value]="type">\n {{ perimeterTypeTranslationMap.get(type) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <div tb-hint-tooltip-icon="{{ geoActionConfigForm.get(\'perimeterType\').value === perimeterType.CIRCLE\n ? (\'tb.rulenode.fetch-circle-parameter-info-from-metadata-hint\'\n | translate : { perimeterKeyName: geoActionConfigForm.get(\'perimeterKeyName\').valid\n ? geoActionConfigForm.get(\'perimeterKeyName\').value\n : \'ss_perimeter\'})\n : (\'tb.rulenode.fetch-poligon-parameter-info-from-metadata-hint\'\n | translate : { perimeterKeyName: geoActionConfigForm.get(\'perimeterKeyName\').valid\n ? geoActionConfigForm.get(\'perimeterKeyName\').value\n : \'ss_perimeter\'}) }}"\n class="tb-form-row no-border no-padding slide-toggle">\n <mat-slide-toggle class="mat-slide" formControlName="fetchPerimeterInfoFromMessageMetadata">\n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n </mat-slide-toggle>\n </div>\n <mat-form-field *ngIf="geoActionConfigForm.get(\'fetchPerimeterInfoFromMessageMetadata\').value" class="mat-block">\n <mat-label>{{ \'tb.rulenode.perimeter-key-name\' | translate }}</mat-label>\n <input matInput formControlName="perimeterKeyName" required>\n <mat-error *ngIf="geoActionConfigForm.get(\'perimeterKeyName\').hasError(\'required\')">\n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n </mat-error>\n <mat-hint>{{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}</mat-hint>\n </mat-form-field>\n <div fxLayout="column"\n *ngIf="geoActionConfigForm.get(\'perimeterType\').value === perimeterType.CIRCLE &&\n !geoActionConfigForm.get(\'fetchPerimeterInfoFromMessageMetadata\').value">\n <div fxLayout="row" fxLayoutGap="16px">\n <mat-form-field fxFlex>\n <mat-label>{{ \'tb.rulenode.circle-center-latitude\' | translate }}</mat-label>\n <input type="number" min="-90" max="90" step="0.1" matInput formControlName="centerLatitude" required>\n <mat-error *ngIf="geoActionConfigForm.get(\'centerLatitude\').hasError(\'required\')">\n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex>\n <mat-label>{{ \'tb.rulenode.circle-center-longitude\' | translate }}</mat-label>\n <input type="number" min="-180" max="180" step="0.1" matInput formControlName="centerLongitude" required>\n <mat-error *ngIf="geoActionConfigForm.get(\'centerLongitude\').hasError(\'required\')">\n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <div fxLayout="row" fxLayoutGap="16px">\n <mat-form-field fxFlex>\n <mat-label>{{ \'tb.rulenode.range\' | translate }}</mat-label>\n <input type="number" min="0" step="0.1" matInput formControlName="range" required>\n <mat-error *ngIf="geoActionConfigForm.get(\'range\').hasError(\'required\')">\n {{ \'tb.rulenode.range-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex>\n <mat-label>{{ \'tb.rulenode.range-units\' | translate }}</mat-label>\n <mat-select formControlName="rangeUnit" required>\n <mat-option *ngFor="let type of rangeUnits" [value]="type">\n {{ rangeUnitTranslationMap.get(type) | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf="geoActionConfigForm.get(\'rangeUnit\').hasError(\'required\')">\n {{ \'tb.rulenode.range-units-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n </div>\n <div fxLayout="column" *ngIf="geoActionConfigForm.get(\'perimeterType\').value === perimeterType.POLYGON &&\n !geoActionConfigForm.get(\'fetchPerimeterInfoFromMessageMetadata\').value">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.polygon-definition</mat-label>\n <input matInput formControlName="polygonsDefinition" required>\n <mat-icon matSuffix class="margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.polygon-definition-hint\' | translate }}">\n help\n </mat-icon>\n <mat-error *ngIf="geoActionConfigForm.get(\'polygonsDefinition\').hasError(\'required\')">\n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n </section>\n </section>\n <section class="tb-form-panel stroked no-padding-bottom">\n <div fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap.lt-md="16px" fxLayoutAlign="space-between">\n <div class="tb-form-panel-title">{{ \'tb.rulenode.presence-monitoring-strategy\' | translate }}</div>\n <tb-toggle-select class="fetch-to-data-toggle" formControlName="reportPresenceStatusOnEachMessage" appearance="fill" >\n <tb-toggle-option *ngFor="let strategy of presenceMonitoringStrategyKeys" [value]="presenceMonitoringStrategies.get(strategy).value">\n {{ presenceMonitoringStrategies.get(strategy).name | translate }}\n </tb-toggle-option>\n </tb-toggle-select>\n </div>\n <div class="tb-form-hint tb-primary-fill"> {{ geoActionConfigForm.get(\'reportPresenceStatusOnEachMessage\').value === false ?\n (\'tb.rulenode.presence-monitoring-strategy-on-first-message-hint\' | translate) :\n (\'tb.rulenode.presence-monitoring-strategy-on-each-message-hint\' | translate) }}\n </div>\n <section fxLayout="column">\n <div *ngIf="geoActionConfigForm.get(\'reportPresenceStatusOnEachMessage\').value === false">\n <div fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap.gt-sm="8px">\n <mat-form-field fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.min-inside-duration</mat-label>\n <input type="number" step="1" min="1" max="2147483647" matInput formControlName="minInsideDuration" required>\n <mat-error *ngIf="geoActionConfigForm.get(\'minInsideDuration\').hasError(\'required\')">\n {{ \'tb.rulenode.min-inside-duration-value-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="geoActionConfigForm.get(\'minInsideDuration\').hasError(\'min\')">\n {{ \'tb.rulenode.time-value-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="geoActionConfigForm.get(\'minInsideDuration\').hasError(\'max\')">\n {{ \'tb.rulenode.time-value-range\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.min-inside-duration-time-unit</mat-label>\n <mat-select formControlName="minInsideDurationTimeUnit" required>\n <mat-option *ngFor="let timeUnit of timeUnits" [value]="timeUnit">\n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap.gt-sm="8px">\n <mat-form-field fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.min-outside-duration</mat-label>\n <input type="number" step="1" min="1" max="2147483647" matInput formControlName="minOutsideDuration" required>\n <mat-error *ngIf="geoActionConfigForm.get(\'minOutsideDuration\').hasError(\'required\')">\n {{ \'tb.rulenode.min-outside-duration-value-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="geoActionConfigForm.get(\'minOutsideDuration\').hasError(\'min\')">\n {{ \'tb.rulenode.time-value-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="geoActionConfigForm.get(\'minOutsideDuration\').hasError(\'max\')">\n {{ \'tb.rulenode.time-value-range\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.min-outside-duration-time-unit</mat-label>\n <mat-select formControlName="minOutsideDurationTimeUnit" required>\n <mat-option *ngFor="let timeUnit of timeUnits" [value]="timeUnit">\n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n </div>\n </section>\n </section>\n</section>\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Ae.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Me.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hn,decorators:[{type:n,args:[{selector:"tb-action-node-gps-geofencing-config",template:'<section [formGroup]="geoActionConfigForm" class="tb-form-panel no-border no-padding">\n <section class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.coordinate-field-names</div>\n <section>\n <div fxLayout="row" fxLayoutGap="16px">\n <mat-form-field fxFlex="50" class="mat-block">\n <mat-label>{{ \'tb.rulenode.latitude-field-name\' | translate }}</mat-label>\n <input matInput formControlName="latitudeKeyName" required>\n <mat-error *ngIf="geoActionConfigForm.get(\'latitudeKeyName\').hasError(\'required\')">\n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex="50" class="mat-block">\n <mat-label>{{ \'tb.rulenode.longitude-field-name\' | translate }}</mat-label>\n <input matInput formControlName="longitudeKeyName" required>\n <mat-error *ngIf="geoActionConfigForm.get(\'longitudeKeyName\').hasError(\'required\')">\n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <div class="tb-form-hint tb-primary-fill" translate>tb.rulenode.coordinate-field-hint</div>\n </section>\n </section>\n <section class="tb-form-panel stroked" [class.no-padding-bottom]="!defaultPaddingEnable">\n <div class="tb-form-panel-title" translate>tb.rulenode.geofence-configuration</div>\n <section fxLayout="column">\n <mat-form-field fxFlex class="mat-block" hideRequiredMarker>\n <mat-label>{{ \'tb.rulenode.perimeter-type\' | translate }}</mat-label>\n <mat-select formControlName="perimeterType">\n <mat-option *ngFor="let type of perimeterTypes" [value]="type">\n {{ perimeterTypeTranslationMap.get(type) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <div tb-hint-tooltip-icon="{{ geoActionConfigForm.get(\'perimeterType\').value === perimeterType.CIRCLE\n ? (\'tb.rulenode.fetch-circle-parameter-info-from-metadata-hint\'\n | translate : { perimeterKeyName: geoActionConfigForm.get(\'perimeterKeyName\').valid\n ? geoActionConfigForm.get(\'perimeterKeyName\').value\n : \'ss_perimeter\'})\n : (\'tb.rulenode.fetch-poligon-parameter-info-from-metadata-hint\'\n | translate : { perimeterKeyName: geoActionConfigForm.get(\'perimeterKeyName\').valid\n ? geoActionConfigForm.get(\'perimeterKeyName\').value\n : \'ss_perimeter\'}) }}"\n class="tb-form-row no-border no-padding slide-toggle">\n <mat-slide-toggle class="mat-slide" formControlName="fetchPerimeterInfoFromMessageMetadata">\n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n </mat-slide-toggle>\n </div>\n <mat-form-field *ngIf="geoActionConfigForm.get(\'fetchPerimeterInfoFromMessageMetadata\').value" class="mat-block">\n <mat-label>{{ \'tb.rulenode.perimeter-key-name\' | translate }}</mat-label>\n <input matInput formControlName="perimeterKeyName" required>\n <mat-error *ngIf="geoActionConfigForm.get(\'perimeterKeyName\').hasError(\'required\')">\n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n </mat-error>\n <mat-hint>{{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}</mat-hint>\n </mat-form-field>\n <div fxLayout="column"\n *ngIf="geoActionConfigForm.get(\'perimeterType\').value === perimeterType.CIRCLE &&\n !geoActionConfigForm.get(\'fetchPerimeterInfoFromMessageMetadata\').value">\n <div fxLayout="row" fxLayoutGap="16px">\n <mat-form-field fxFlex>\n <mat-label>{{ \'tb.rulenode.circle-center-latitude\' | translate }}</mat-label>\n <input type="number" min="-90" max="90" step="0.1" matInput formControlName="centerLatitude" required>\n <mat-error *ngIf="geoActionConfigForm.get(\'centerLatitude\').hasError(\'required\')">\n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex>\n <mat-label>{{ \'tb.rulenode.circle-center-longitude\' | translate }}</mat-label>\n <input type="number" min="-180" max="180" step="0.1" matInput formControlName="centerLongitude" required>\n <mat-error *ngIf="geoActionConfigForm.get(\'centerLongitude\').hasError(\'required\')">\n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <div fxLayout="row" fxLayoutGap="16px">\n <mat-form-field fxFlex>\n <mat-label>{{ \'tb.rulenode.range\' | translate }}</mat-label>\n <input type="number" min="0" step="0.1" matInput formControlName="range" required>\n <mat-error *ngIf="geoActionConfigForm.get(\'range\').hasError(\'required\')">\n {{ \'tb.rulenode.range-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex>\n <mat-label>{{ \'tb.rulenode.range-units\' | translate }}</mat-label>\n <mat-select formControlName="rangeUnit" required>\n <mat-option *ngFor="let type of rangeUnits" [value]="type">\n {{ rangeUnitTranslationMap.get(type) | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf="geoActionConfigForm.get(\'rangeUnit\').hasError(\'required\')">\n {{ \'tb.rulenode.range-units-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n </div>\n <div fxLayout="column" *ngIf="geoActionConfigForm.get(\'perimeterType\').value === perimeterType.POLYGON &&\n !geoActionConfigForm.get(\'fetchPerimeterInfoFromMessageMetadata\').value">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.polygon-definition</mat-label>\n <input matInput formControlName="polygonsDefinition" required>\n <mat-icon matSuffix class="margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.polygon-definition-hint\' | translate }}">\n help\n </mat-icon>\n <mat-error *ngIf="geoActionConfigForm.get(\'polygonsDefinition\').hasError(\'required\')">\n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n </section>\n </section>\n <section class="tb-form-panel stroked no-padding-bottom">\n <div fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap.lt-md="16px" fxLayoutAlign="space-between">\n <div class="tb-form-panel-title">{{ \'tb.rulenode.presence-monitoring-strategy\' | translate }}</div>\n <tb-toggle-select class="fetch-to-data-toggle" formControlName="reportPresenceStatusOnEachMessage" appearance="fill" >\n <tb-toggle-option *ngFor="let strategy of presenceMonitoringStrategyKeys" [value]="presenceMonitoringStrategies.get(strategy).value">\n {{ presenceMonitoringStrategies.get(strategy).name | translate }}\n </tb-toggle-option>\n </tb-toggle-select>\n </div>\n <div class="tb-form-hint tb-primary-fill"> {{ geoActionConfigForm.get(\'reportPresenceStatusOnEachMessage\').value === false ?\n (\'tb.rulenode.presence-monitoring-strategy-on-first-message-hint\' | translate) :\n (\'tb.rulenode.presence-monitoring-strategy-on-each-message-hint\' | translate) }}\n </div>\n <section fxLayout="column">\n <div *ngIf="geoActionConfigForm.get(\'reportPresenceStatusOnEachMessage\').value === false">\n <div fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap.gt-sm="8px">\n <mat-form-field fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.min-inside-duration</mat-label>\n <input type="number" step="1" min="1" max="2147483647" matInput formControlName="minInsideDuration" required>\n <mat-error *ngIf="geoActionConfigForm.get(\'minInsideDuration\').hasError(\'required\')">\n {{ \'tb.rulenode.min-inside-duration-value-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="geoActionConfigForm.get(\'minInsideDuration\').hasError(\'min\')">\n {{ \'tb.rulenode.time-value-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="geoActionConfigForm.get(\'minInsideDuration\').hasError(\'max\')">\n {{ \'tb.rulenode.time-value-range\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.min-inside-duration-time-unit</mat-label>\n <mat-select formControlName="minInsideDurationTimeUnit" required>\n <mat-option *ngFor="let timeUnit of timeUnits" [value]="timeUnit">\n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap.gt-sm="8px">\n <mat-form-field fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.min-outside-duration</mat-label>\n <input type="number" step="1" min="1" max="2147483647" matInput formControlName="minOutsideDuration" required>\n <mat-error *ngIf="geoActionConfigForm.get(\'minOutsideDuration\').hasError(\'required\')">\n {{ \'tb.rulenode.min-outside-duration-value-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="geoActionConfigForm.get(\'minOutsideDuration\').hasError(\'min\')">\n {{ \'tb.rulenode.time-value-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="geoActionConfigForm.get(\'minOutsideDuration\').hasError(\'max\')">\n {{ \'tb.rulenode.time-value-range\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.min-outside-duration-time-unit</mat-label>\n <mat-select formControlName="minOutsideDurationTimeUnit" required>\n <mat-option *ngFor="let timeUnit of timeUnits" [value]="timeUnit">\n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n </div>\n </section>\n </section>\n</section>\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class vn extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ce(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-to-string-function"}configForm(){return this.logConfigForm}onConfigurationSet(e){this.logConfigForm=this.fb.group({scriptLang:[e?e.scriptLang:b.JS,[O.required]],jsScript:[e?e.jsScript:null,[]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.logConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.logConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.logConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.logConfigForm.get("jsScript").setValidators(t===b.JS?[O.required]:[]),this.logConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.logConfigForm.get("tbelScript").setValidators(t===b.TBEL?[O.required]:[]),this.logConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),e}testScript(e){const t=this.logConfigForm.get("scriptLang").value,n=t===b.JS?"jsScript":"tbelScript",r=t===b.JS?"rulenode/log_node_script_fn":"rulenode/tbel/log_node_script_fn",o=this.logConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"string",this.translate.instant("tb.rulenode.to-string"),"ToString",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.logConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.logConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}e("LogConfigComponent",vn),vn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vn,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:ge.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),vn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:vn,selector:"tb-action-node-log-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'<section [formGroup]="logConfigForm" fxLayout="column">\n <tb-script-lang formControlName="scriptLang" *ngIf="tbelEnabled"></tb-script-lang>\n <tb-js-func *ngIf="logConfigForm.get(\'scriptLang\').value === scriptLanguage.JS"\n #jsFuncComponent\n formControlName="jsScript"\n functionName="ToString"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n helpId="rulenode/log_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <tb-js-func *ngIf="logConfigForm.get(\'scriptLang\').value === scriptLanguage.TBEL"\n #tbelFuncComponent\n formControlName="tbelScript"\n functionName="ToString"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n [disableUndefinedCheck]="true"\n [scriptLanguage]="scriptLanguage.TBEL"\n helpId="rulenode/tbel/log_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <div fxLayout="row">\n <button mat-button mat-raised-button color="primary" (click)="testScript()">\n {{ testScriptLabel | translate }}\n </button>\n </div>\n</section>\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ce.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vn,decorators:[{type:n,args:[{selector:"tb-action-node-log-config",template:'<section [formGroup]="logConfigForm" fxLayout="column">\n <tb-script-lang formControlName="scriptLang" *ngIf="tbelEnabled"></tb-script-lang>\n <tb-js-func *ngIf="logConfigForm.get(\'scriptLang\').value === scriptLanguage.JS"\n #jsFuncComponent\n formControlName="jsScript"\n functionName="ToString"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n helpId="rulenode/log_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <tb-js-func *ngIf="logConfigForm.get(\'scriptLang\').value === scriptLanguage.TBEL"\n #tbelFuncComponent\n formControlName="tbelScript"\n functionName="ToString"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n [disableUndefinedCheck]="true"\n [scriptLanguage]="scriptLanguage.TBEL"\n helpId="rulenode/tbel/log_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <div fxLayout="row">\n <button mat-button mat-raised-button color="primary" (click)="testScript()">\n {{ testScriptLabel | translate }}\n </button>\n </div>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:ge.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}});class Cn extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.msgCountConfigForm}onConfigurationSet(e){this.msgCountConfigForm=this.fb.group({interval:[e?e.interval:null,[O.required,O.min(1)]],telemetryPrefix:[e?e.telemetryPrefix:null,[O.required]]})}}e("MsgCountConfigComponent",Cn),Cn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Cn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Cn,selector:"tb-action-node-msg-count-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="msgCountConfigForm" fxLayout="column">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.interval-seconds</mat-label>\n <input required type="number" min="1" step="1" matInput formControlName="interval">\n <mat-error *ngIf="msgCountConfigForm.get(\'interval\').hasError(\'required\')">\n {{ \'tb.rulenode.interval-seconds-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="msgCountConfigForm.get(\'interval\').hasError(\'min\')">\n {{ \'tb.rulenode.min-interval-seconds-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.output-timeseries-key-prefix</mat-label>\n <input required matInput formControlName="telemetryPrefix">\n <mat-error *ngIf="msgCountConfigForm.get(\'telemetryPrefix\').hasError(\'required\')">\n {{ \'tb.rulenode.output-timeseries-key-prefix-required\' | translate }}\n </mat-error>\n </mat-form-field>\n</section>\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cn,decorators:[{type:n,args:[{selector:"tb-action-node-msg-count-config",template:'<section [formGroup]="msgCountConfigForm" fxLayout="column">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.interval-seconds</mat-label>\n <input required type="number" min="1" step="1" matInput formControlName="interval">\n <mat-error *ngIf="msgCountConfigForm.get(\'interval\').hasError(\'required\')">\n {{ \'tb.rulenode.interval-seconds-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="msgCountConfigForm.get(\'interval\').hasError(\'min\')">\n {{ \'tb.rulenode.min-interval-seconds-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.output-timeseries-key-prefix</mat-label>\n <input required matInput formControlName="telemetryPrefix">\n <mat-error *ngIf="msgCountConfigForm.get(\'telemetryPrefix\').hasError(\'required\')">\n {{ \'tb.rulenode.output-timeseries-key-prefix-required\' | translate }}\n </mat-error>\n </mat-form-field>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Fn extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.msgDelayConfigForm}onConfigurationSet(e){this.msgDelayConfigForm=this.fb.group({useMetadataPeriodInSecondsPatterns:[!!e&&e.useMetadataPeriodInSecondsPatterns,[]],periodInSeconds:[e?e.periodInSeconds:null,[]],periodInSecondsPattern:[e?e.periodInSecondsPattern:null,[]],maxPendingMsgs:[e?e.maxPendingMsgs:null,[O.required,O.min(1),O.max(1e5)]]})}validatorTriggers(){return["useMetadataPeriodInSecondsPatterns"]}updateValidators(e){this.msgDelayConfigForm.get("useMetadataPeriodInSecondsPatterns").value?(this.msgDelayConfigForm.get("periodInSecondsPattern").setValidators([O.required]),this.msgDelayConfigForm.get("periodInSeconds").setValidators([])):(this.msgDelayConfigForm.get("periodInSecondsPattern").setValidators([]),this.msgDelayConfigForm.get("periodInSeconds").setValidators([O.required,O.min(0)])),this.msgDelayConfigForm.get("periodInSecondsPattern").updateValueAndValidity({emitEvent:e}),this.msgDelayConfigForm.get("periodInSeconds").updateValueAndValidity({emitEvent:e})}}e("MsgDelayConfigComponent",Fn),Fn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Fn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Fn,selector:"tb-action-node-msg-delay-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="msgDelayConfigForm" fxLayout="column">\n <mat-checkbox formControlName="useMetadataPeriodInSecondsPatterns">\n {{ \'tb.rulenode.use-metadata-period-in-seconds-patterns\' | translate }}\n </mat-checkbox>\n <div class="tb-hint" translate>tb.rulenode.use-metadata-period-in-seconds-patterns-hint</div>\n <mat-form-field *ngIf="msgDelayConfigForm.get(\'useMetadataPeriodInSecondsPatterns\').value !== true; else periodInSecondsPattern"\n class="mat-block">\n <mat-label translate>tb.rulenode.period-seconds</mat-label>\n <input required type="number" min="0" step="1" matInput formControlName="periodInSeconds">\n <mat-error *ngIf="msgDelayConfigForm.get(\'periodInSeconds\').hasError(\'required\')">\n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="msgDelayConfigForm.get(\'periodInSeconds\').hasError(\'min\')">\n {{ \'tb.rulenode.min-period-0-seconds-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <ng-template #periodInSecondsPattern>\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.period-in-seconds-pattern</mat-label>\n <input required matInput formControlName="periodInSecondsPattern">\n <mat-error *ngIf="msgDelayConfigForm.get(\'periodInSecondsPattern\').hasError(\'required\')">\n {{ \'tb.rulenode.period-in-seconds-pattern-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n </ng-template>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.max-pending-messages</mat-label>\n <input required type="number" min="1" max="100000" step="1" matInput formControlName="maxPendingMsgs">\n <mat-error *ngIf="msgDelayConfigForm.get(\'maxPendingMsgs\').hasError(\'required\')">\n {{ \'tb.rulenode.max-pending-messages-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="msgDelayConfigForm.get(\'maxPendingMsgs\').hasError(\'min\')">\n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="msgDelayConfigForm.get(\'maxPendingMsgs\').hasError(\'max\')">\n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n </mat-error>\n </mat-form-field>\n</section>\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fn,decorators:[{type:n,args:[{selector:"tb-action-node-msg-delay-config",template:'<section [formGroup]="msgDelayConfigForm" fxLayout="column">\n <mat-checkbox formControlName="useMetadataPeriodInSecondsPatterns">\n {{ \'tb.rulenode.use-metadata-period-in-seconds-patterns\' | translate }}\n </mat-checkbox>\n <div class="tb-hint" translate>tb.rulenode.use-metadata-period-in-seconds-patterns-hint</div>\n <mat-form-field *ngIf="msgDelayConfigForm.get(\'useMetadataPeriodInSecondsPatterns\').value !== true; else periodInSecondsPattern"\n class="mat-block">\n <mat-label translate>tb.rulenode.period-seconds</mat-label>\n <input required type="number" min="0" step="1" matInput formControlName="periodInSeconds">\n <mat-error *ngIf="msgDelayConfigForm.get(\'periodInSeconds\').hasError(\'required\')">\n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="msgDelayConfigForm.get(\'periodInSeconds\').hasError(\'min\')">\n {{ \'tb.rulenode.min-period-0-seconds-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <ng-template #periodInSecondsPattern>\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.period-in-seconds-pattern</mat-label>\n <input required matInput formControlName="periodInSecondsPattern">\n <mat-error *ngIf="msgDelayConfigForm.get(\'periodInSecondsPattern\').hasError(\'required\')">\n {{ \'tb.rulenode.period-in-seconds-pattern-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n </ng-template>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.max-pending-messages</mat-label>\n <input required type="number" min="1" max="100000" step="1" matInput formControlName="maxPendingMsgs">\n <mat-error *ngIf="msgDelayConfigForm.get(\'maxPendingMsgs\').hasError(\'required\')">\n {{ \'tb.rulenode.max-pending-messages-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="msgDelayConfigForm.get(\'maxPendingMsgs\').hasError(\'min\')">\n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="msgDelayConfigForm.get(\'maxPendingMsgs\').hasError(\'max\')">\n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n </mat-error>\n </mat-form-field>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class kn extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopes=Object.keys(f),this.telemetryTypeTranslationsMap=y}configForm(){return this.pushToCloudConfigForm}onConfigurationSet(e){this.pushToCloudConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]]})}}e("PushToCloudConfigComponent",kn),kn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),kn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:kn,selector:"tb-action-node-push-to-cloud-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="pushToCloudConfigForm" class="tb-form-panel no-border no-padding">\n <div class="tb-form-panel stroked">\n <tb-example-hint [hintText]="\'tb.rulenode.attributes-scope-hint\'">\n </tb-example-hint>\n <div class="tb-form-row no-border no-padding tb-standard-fields">\n <mat-form-field class="flex">\n <mat-label>{{ \'tb.rulenode.attributes-scope\' | translate }}</mat-label>\n <mat-select required\n class="tb-entity-type-select" matInput formControlName="scope">\n <mat-option *ngFor="let scope of attributeScopes" [value]="scope">\n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label>{{ \'tb.rulenode.attributes-scope-value\' | translate }}</mat-label>\n <input type="text" matInput readonly disabled [ngModel]="pushToCloudConfigForm.get(\'scope\').value" [ngModelOptions]="{standalone: true}">\n <button type="button"\n matSuffix\n mat-icon-button\n aria-label="Copy"\n ngxClipboard\n [cbContent]="pushToCloudConfigForm.get(\'scope\').value"\n matTooltip="{{ \'tb.rulenode.attributes-scope-value-copy\' | translate }}">\n <mat-icon aria-hidden="false"\n aria-label="help-icon">content_copy\n </mat-icon>\n </button>\n </mat-form-field>\n </div>\n </div>\n</section>\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:ft,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kn,decorators:[{type:n,args:[{selector:"tb-action-node-push-to-cloud-config",template:'<section [formGroup]="pushToCloudConfigForm" class="tb-form-panel no-border no-padding">\n <div class="tb-form-panel stroked">\n <tb-example-hint [hintText]="\'tb.rulenode.attributes-scope-hint\'">\n </tb-example-hint>\n <div class="tb-form-row no-border no-padding tb-standard-fields">\n <mat-form-field class="flex">\n <mat-label>{{ \'tb.rulenode.attributes-scope\' | translate }}</mat-label>\n <mat-select required\n class="tb-entity-type-select" matInput formControlName="scope">\n <mat-option *ngFor="let scope of attributeScopes" [value]="scope">\n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label>{{ \'tb.rulenode.attributes-scope-value\' | translate }}</mat-label>\n <input type="text" matInput readonly disabled [ngModel]="pushToCloudConfigForm.get(\'scope\').value" [ngModelOptions]="{standalone: true}">\n <button type="button"\n matSuffix\n mat-icon-button\n aria-label="Copy"\n ngxClipboard\n [cbContent]="pushToCloudConfigForm.get(\'scope\').value"\n matTooltip="{{ \'tb.rulenode.attributes-scope-value-copy\' | translate }}">\n <mat-icon aria-hidden="false"\n aria-label="help-icon">content_copy\n </mat-icon>\n </button>\n </mat-form-field>\n </div>\n </div>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Tn extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopes=Object.keys(f),this.telemetryTypeTranslationsMap=y}configForm(){return this.pushToEdgeConfigForm}onConfigurationSet(e){this.pushToEdgeConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]]})}}e("PushToEdgeConfigComponent",Tn),Tn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Tn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Tn,selector:"tb-action-node-push-to-edge-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="pushToEdgeConfigForm" class="tb-form-panel no-border no-padding">\n <div class="tb-form-panel stroked">\n <tb-example-hint [hintText]="\'tb.rulenode.attributes-scope-hint\'">\n </tb-example-hint>\n <div class="tb-form-row no-border no-padding tb-standard-fields">\n <mat-form-field class="flex">\n <mat-label>{{ \'tb.rulenode.attributes-scope\' | translate }}</mat-label>\n <mat-select required\n class="tb-entity-type-select" matInput formControlName="scope">\n <mat-option *ngFor="let scope of attributeScopes" [value]="scope">\n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label>{{ \'tb.rulenode.attributes-scope-value\' | translate }}</mat-label>\n <input type="text" matInput readonly disabled [ngModel]="pushToEdgeConfigForm.get(\'scope\').value" [ngModelOptions]="{standalone: true}">\n <button type="button"\n matSuffix\n mat-icon-button\n aria-label="Copy"\n ngxClipboard\n [cbContent]="pushToEdgeConfigForm.get(\'scope\').value"\n matTooltip="{{ \'tb.rulenode.attributes-scope-value-copy\' | translate }}">\n <mat-icon aria-hidden="false"\n aria-label="help-icon">content_copy\n </mat-icon>\n </button>\n </mat-form-field>\n </div>\n </div>\n</section>\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:ft,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tn,decorators:[{type:n,args:[{selector:"tb-action-node-push-to-edge-config",template:'<section [formGroup]="pushToEdgeConfigForm" class="tb-form-panel no-border no-padding">\n <div class="tb-form-panel stroked">\n <tb-example-hint [hintText]="\'tb.rulenode.attributes-scope-hint\'">\n </tb-example-hint>\n <div class="tb-form-row no-border no-padding tb-standard-fields">\n <mat-form-field class="flex">\n <mat-label>{{ \'tb.rulenode.attributes-scope\' | translate }}</mat-label>\n <mat-select required\n class="tb-entity-type-select" matInput formControlName="scope">\n <mat-option *ngFor="let scope of attributeScopes" [value]="scope">\n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label>{{ \'tb.rulenode.attributes-scope-value\' | translate }}</mat-label>\n <input type="text" matInput readonly disabled [ngModel]="pushToEdgeConfigForm.get(\'scope\').value" [ngModelOptions]="{standalone: true}">\n <button type="button"\n matSuffix\n mat-icon-button\n aria-label="Copy"\n ngxClipboard\n [cbContent]="pushToEdgeConfigForm.get(\'scope\').value"\n matTooltip="{{ \'tb.rulenode.attributes-scope-value-copy\' | translate }}">\n <mat-icon aria-hidden="false"\n aria-label="help-icon">content_copy\n </mat-icon>\n </button>\n </mat-form-field>\n </div>\n </div>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Ln extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.rpcReplyConfigForm}onConfigurationSet(e){this.rpcReplyConfigForm=this.fb.group({serviceIdMetaDataAttribute:[e?e.serviceIdMetaDataAttribute:null,[]],sessionIdMetaDataAttribute:[e?e.sessionIdMetaDataAttribute:null,[]],requestIdMetaDataAttribute:[e?e.requestIdMetaDataAttribute:null,[]]})}}e("RpcReplyConfigComponent",Ln),Ln.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ln,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Ln.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ln,selector:"tb-action-node-rpc-reply-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="rpcReplyConfigForm" class="tb-form-panel stroked no-padding-bottom">\n <div class="tb-form-panel-title" translate>tb.rulenode.reply-routing-configuration</div>\n <tb-example-hint [hintText]="\'tb.rulenode.reply-routing-configuration-hint\'">\n </tb-example-hint>\n <div class="tb-form-row no-border no-padding tb-standard-fields column-xs">\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.service-id-metadata-attribute</mat-label>\n <input matInput formControlName="serviceIdMetaDataAttribute">\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.session-id-metadata-attribute</mat-label>\n <input matInput formControlName="sessionIdMetaDataAttribute">\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.request-id-metadata-attribute</mat-label>\n <input matInput formControlName="requestIdMetaDataAttribute">\n </mat-form-field>\n </div>\n</section>\n',dependencies:[{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ln,decorators:[{type:n,args:[{selector:"tb-action-node-rpc-reply-config",template:'<section [formGroup]="rpcReplyConfigForm" class="tb-form-panel stroked no-padding-bottom">\n <div class="tb-form-panel-title" translate>tb.rulenode.reply-routing-configuration</div>\n <tb-example-hint [hintText]="\'tb.rulenode.reply-routing-configuration-hint\'">\n </tb-example-hint>\n <div class="tb-form-row no-border no-padding tb-standard-fields column-xs">\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.service-id-metadata-attribute</mat-label>\n <input matInput formControlName="serviceIdMetaDataAttribute">\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.session-id-metadata-attribute</mat-label>\n <input matInput formControlName="sessionIdMetaDataAttribute">\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.request-id-metadata-attribute</mat-label>\n <input matInput formControlName="requestIdMetaDataAttribute">\n </mat-form-field>\n </div>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class In extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.rpcRequestConfigForm}onConfigurationSet(e){this.rpcRequestConfigForm=this.fb.group({timeoutInSeconds:[e?e.timeoutInSeconds:null,[O.required,O.min(0)]]})}}e("RpcRequestConfigComponent",In),In.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:In,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),In.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:In,selector:"tb-action-node-rpc-request-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="rpcRequestConfigForm" fxLayout="column">\n <mat-form-field fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.timeout-sec</mat-label>\n <input type="number" min="0" step="1" matInput formControlName="timeoutInSeconds" required>\n <mat-error *ngIf="rpcRequestConfigForm.get(\'timeoutInSeconds\').hasError(\'required\')">\n {{ \'tb.rulenode.timeout-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="rpcRequestConfigForm.get(\'timeoutInSeconds\').hasError(\'min\')">\n {{ \'tb.rulenode.min-timeout-message\' | translate }}\n </mat-error>\n </mat-form-field>\n</section>\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:In,decorators:[{type:n,args:[{selector:"tb-action-node-rpc-request-config",template:'<section [formGroup]="rpcRequestConfigForm" fxLayout="column">\n <mat-form-field fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.timeout-sec</mat-label>\n <input type="number" min="0" step="1" matInput formControlName="timeoutInSeconds" required>\n <mat-error *ngIf="rpcRequestConfigForm.get(\'timeoutInSeconds\').hasError(\'required\')">\n {{ \'tb.rulenode.timeout-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="rpcRequestConfigForm.get(\'timeoutInSeconds\').hasError(\'min\')">\n {{ \'tb.rulenode.min-timeout-message\' | translate }}\n </mat-error>\n </mat-form-field>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Nn extends k{get required(){return this.requiredValue}set required(e){this.requiredValue=Ee(e)}constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.injector=n,this.fb=r,this.propagateChange=null,this.valueChangeSubscription=null}ngOnInit(){this.ngControl=this.injector.get(_),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.kvListFormGroup=this.fb.group({}),this.kvListFormGroup.addControl("keyVals",this.fb.array([]))}keyValsFormArray(){return this.kvListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.kvListFormGroup.disable({emitEvent:!1}):this.kvListFormGroup.enable({emitEvent:!1})}writeValue(e){this.valueChangeSubscription&&this.valueChangeSubscription.unsubscribe();const t=[];if(e)for(const n of Object.keys(e))Object.prototype.hasOwnProperty.call(e,n)&&t.push(this.fb.group({key:[n,[O.required]],value:[e[n],[O.required]]}));this.kvListFormGroup.setControl("keyVals",this.fb.array(t)),this.valueChangeSubscription=this.kvListFormGroup.valueChanges.subscribe((()=>{this.updateModel()}))}removeKeyVal(e){this.kvListFormGroup.get("keyVals").removeAt(e)}addKeyVal(){this.kvListFormGroup.get("keyVals").push(this.fb.group({key:["",[O.required]],value:["",[O.required]]}))}validate(e){const t=this.kvListFormGroup.get("keyVals").value;if(!t.length&&this.required)return{kvMapRequired:!0};if(!this.kvListFormGroup.valid)return{kvFieldsRequired:!0};if(this.uniqueKeyValuePairValidator)for(const e of t)if(e.key===e.value)return{uniqueKeyValuePair:!0};return null}updateModel(){const e=this.kvListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.kvListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("KvMapConfigOldComponent",Nn),Nn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nn,deps:[{token:P.Store},{token:Z.TranslateService},{token:t.Injector},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Nn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Nn,selector:"tb-kv-map-config-old",inputs:{disabled:"disabled",uniqueKeyValuePairValidator:"uniqueKeyValuePairValidator",requiredText:"requiredText",keyText:"keyText",keyRequiredText:"keyRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",required:"required"},providers:[{provide:B,useExisting:c((()=>Nn)),multi:!0},{provide:K,useExisting:c((()=>Nn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'<section fxLayout="column" class="tb-kv-map-config" [formGroup]="kvListFormGroup">\n <div class="header" fxFlex fxLayout="row" fxLayoutGap="8px">\n <span class="cell tb-required" fxFlex>{{ keyText | translate }}</span>\n <span class="cell tb-required" fxFlex>{{ valText | translate }}</span>\n <span [fxShow]="!disabled" style="width: 52px;" innerHTML="&nbsp"></span>\n </div>\n <div class="body">\n <div class="row" fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px"\n formArrayName="keyVals"\n *ngFor="let keyValControl of keyValsFormArray().controls; let $index = index">\n <mat-form-field fxFlex class="cell mat-block">\n <input [formControl]="keyValControl.get(\'key\')" matInput required\n placeholder="{{ keyText | translate }}"/>\n <mat-error *ngIf="keyValControl.get(\'key\').hasError(\'required\')">\n {{ keyRequiredText | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex class="cell mat-block">\n <input [formControl]="keyValControl.get(\'value\')" matInput required\n placeholder="{{ valText | translate }}"/>\n <mat-error *ngIf="keyValControl.get(\'value\').hasError(\'required\')">\n {{ valRequiredText | translate }}\n </mat-error>\n </mat-form-field>\n <button mat-icon-button color="primary"\n [fxShow]="!disabled"\n type="button"\n (click)="removeKeyVal($index)"\n [disabled]="isLoading$ | async"\n matTooltip="{{ \'tb.key-val.remove-entry\' | translate }}"\n matTooltipPosition="above">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n <div *ngIf="hintText" class="tb-hint" [innerHTML]="hintText | translate | safe: \'html\'"></div>\n </div>\n <tb-error [error]="ngControl.hasError(\'kvMapRequired\') || ngControl.hasError(\'uniqueKeyValuePair\') ?\n (ngControl.hasError(\'kvMapRequired\') ? translate.instant(requiredText) :\n translate.instant(\'tb.key-val.unique-key-value-pair-error\', {keyText: translate.instant(keyText),\n valText: translate.instant(valText)})) : \'\'"></tb-error>\n <div style="margin-top: 16px;">\n <button mat-button mat-raised-button color="primary"\n [fxShow]="!disabled"\n [disabled]="isLoading$ | async"\n (click)="addKeyVal()"\n type="button"\n matTooltip="{{ \'tb.key-val.add-entry\' | translate }}"\n matTooltipPosition="above">\n <mat-icon>add</mat-icon>\n {{ \'action.add\' | translate }}\n </button>\n </div>\n</section>\n',styles:[":host .tb-kv-map-config{margin-bottom:16px}:host .tb-kv-map-config .header{padding-left:5px;padding-right:5px;padding-bottom:5px}:host .tb-kv-map-config .header .cell{padding-left:5px;padding-right:5px;color:#757575;font-size:12px;font-weight:700;white-space:nowrap}:host .tb-kv-map-config .header .tb-required:after{color:#757575;font-size:12px;font-weight:700}:host .tb-kv-map-config .body{padding-left:5px;padding-right:5px;padding-bottom:0;max-height:300px;overflow:auto}:host .tb-kv-map-config .body .cell{padding-left:5px;padding-right:5px}:host .tb-kv-map-config tb-error{display:block;margin-top:-12px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:De.TbErrorComponent,selector:"tb-error",inputs:["noMargin","error"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:Ve.DefaultShowHideDirective,selector:" [fxShow], [fxShow.print], [fxShow.xs], [fxShow.sm], [fxShow.md], [fxShow.lg], [fxShow.xl], [fxShow.lt-sm], [fxShow.lt-md], [fxShow.lt-lg], [fxShow.lt-xl], [fxShow.gt-xs], [fxShow.gt-sm], [fxShow.gt-md], [fxShow.gt-lg], [fxHide], [fxHide.print], [fxHide.xs], [fxHide.sm], [fxHide.md], [fxHide.lg], [fxHide.xl], [fxHide.lt-sm], [fxHide.lt-md], [fxHide.lt-lg], [fxHide.lt-xl], [fxHide.gt-xs], [fxHide.gt-sm], [fxHide.gt-md], [fxHide.gt-lg]",inputs:["fxShow","fxShow.print","fxShow.xs","fxShow.sm","fxShow.md","fxShow.lg","fxShow.xl","fxShow.lt-sm","fxShow.lt-md","fxShow.lt-lg","fxShow.lt-xl","fxShow.gt-xs","fxShow.gt-sm","fxShow.gt-md","fxShow.gt-lg","fxHide","fxHide.print","fxHide.xs","fxHide.sm","fxHide.md","fxHide.lg","fxHide.xl","fxHide.lt-sm","fxHide.lt-md","fxHide.lt-lg","fxHide.lt-xl","fxHide.gt-xs","fxHide.gt-sm","fxHide.gt-md","fxHide.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormArrayName,selector:"[formArrayName]",inputs:["formArrayName"]},{kind:"pipe",type:U.AsyncPipe,name:"async"},{kind:"pipe",type:ue.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nn,decorators:[{type:n,args:[{selector:"tb-kv-map-config-old",providers:[{provide:B,useExisting:c((()=>Nn)),multi:!0},{provide:K,useExisting:c((()=>Nn)),multi:!0}],template:'<section fxLayout="column" class="tb-kv-map-config" [formGroup]="kvListFormGroup">\n <div class="header" fxFlex fxLayout="row" fxLayoutGap="8px">\n <span class="cell tb-required" fxFlex>{{ keyText | translate }}</span>\n <span class="cell tb-required" fxFlex>{{ valText | translate }}</span>\n <span [fxShow]="!disabled" style="width: 52px;" innerHTML="&nbsp"></span>\n </div>\n <div class="body">\n <div class="row" fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px"\n formArrayName="keyVals"\n *ngFor="let keyValControl of keyValsFormArray().controls; let $index = index">\n <mat-form-field fxFlex class="cell mat-block">\n <input [formControl]="keyValControl.get(\'key\')" matInput required\n placeholder="{{ keyText | translate }}"/>\n <mat-error *ngIf="keyValControl.get(\'key\').hasError(\'required\')">\n {{ keyRequiredText | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex class="cell mat-block">\n <input [formControl]="keyValControl.get(\'value\')" matInput required\n placeholder="{{ valText | translate }}"/>\n <mat-error *ngIf="keyValControl.get(\'value\').hasError(\'required\')">\n {{ valRequiredText | translate }}\n </mat-error>\n </mat-form-field>\n <button mat-icon-button color="primary"\n [fxShow]="!disabled"\n type="button"\n (click)="removeKeyVal($index)"\n [disabled]="isLoading$ | async"\n matTooltip="{{ \'tb.key-val.remove-entry\' | translate }}"\n matTooltipPosition="above">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n <div *ngIf="hintText" class="tb-hint" [innerHTML]="hintText | translate | safe: \'html\'"></div>\n </div>\n <tb-error [error]="ngControl.hasError(\'kvMapRequired\') || ngControl.hasError(\'uniqueKeyValuePair\') ?\n (ngControl.hasError(\'kvMapRequired\') ? translate.instant(requiredText) :\n translate.instant(\'tb.key-val.unique-key-value-pair-error\', {keyText: translate.instant(keyText),\n valText: translate.instant(valText)})) : \'\'"></tb-error>\n <div style="margin-top: 16px;">\n <button mat-button mat-raised-button color="primary"\n [fxShow]="!disabled"\n [disabled]="isLoading$ | async"\n (click)="addKeyVal()"\n type="button"\n matTooltip="{{ \'tb.key-val.add-entry\' | translate }}"\n matTooltipPosition="above">\n <mat-icon>add</mat-icon>\n {{ \'action.add\' | translate }}\n </button>\n </div>\n</section>\n',styles:[":host .tb-kv-map-config{margin-bottom:16px}:host .tb-kv-map-config .header{padding-left:5px;padding-right:5px;padding-bottom:5px}:host .tb-kv-map-config .header .cell{padding-left:5px;padding-right:5px;color:#757575;font-size:12px;font-weight:700;white-space:nowrap}:host .tb-kv-map-config .header .tb-required:after{color:#757575;font-size:12px;font-weight:700}:host .tb-kv-map-config .body{padding-left:5px;padding-right:5px;padding-bottom:0;max-height:300px;overflow:auto}:host .tb-kv-map-config .body .cell{padding-left:5px;padding-right:5px}:host .tb-kv-map-config tb-error{display:block;margin-top:-12px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:t.Injector},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:m}],uniqueKeyValuePairValidator:[{type:m}],requiredText:[{type:m}],keyText:[{type:m}],keyRequiredText:[{type:m}],valText:[{type:m}],valRequiredText:[{type:m}],hintText:[{type:m}],required:[{type:m}]}});class Sn extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.saveToCustomTableConfigForm}onConfigurationSet(e){this.saveToCustomTableConfigForm=this.fb.group({tableName:[e?e.tableName:null,[O.required,O.pattern(/.*\S.*/)]],fieldsMapping:[e?e.fieldsMapping:null,[O.required]]})}prepareOutputConfig(e){return e.tableName=e.tableName.trim(),e}}e("SaveToCustomTableConfigComponent",Sn),Sn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Sn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Sn,selector:"tb-action-node-custom-table-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="saveToCustomTableConfigForm" fxLayout="column">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.custom-table-name</mat-label>\n <input required matInput formControlName="tableName">\n <mat-error *ngIf="saveToCustomTableConfigForm.get(\'tableName\').hasError(\'required\') ||\n saveToCustomTableConfigForm.get(\'tableName\').hasError(\'pattern\')">\n {{ \'tb.rulenode.custom-table-name-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.custom-table-hint</mat-hint>\n </mat-form-field>\n <label translate class="tb-title tb-required">tb.rulenode.fields-mapping</label>\n <tb-kv-map-config-old\n required\n formControlName="fieldsMapping"\n requiredText="tb.rulenode.fields-mapping-required"\n keyText="tb.rulenode.message-field"\n keyRequiredText="tb.rulenode.message-field-required"\n valText="tb.rulenode.table-col"\n valRequiredText="tb.rulenode.table-col-required">\n </tb-kv-map-config-old>\n</section>\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sn,decorators:[{type:n,args:[{selector:"tb-action-node-custom-table-config",template:'<section [formGroup]="saveToCustomTableConfigForm" fxLayout="column">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.custom-table-name</mat-label>\n <input required matInput formControlName="tableName">\n <mat-error *ngIf="saveToCustomTableConfigForm.get(\'tableName\').hasError(\'required\') ||\n saveToCustomTableConfigForm.get(\'tableName\').hasError(\'pattern\')">\n {{ \'tb.rulenode.custom-table-name-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.custom-table-hint</mat-hint>\n </mat-form-field>\n <label translate class="tb-title tb-required">tb.rulenode.fields-mapping</label>\n <tb-kv-map-config-old\n required\n formControlName="fieldsMapping"\n requiredText="tb.rulenode.fields-mapping-required"\n keyText="tb.rulenode.message-field"\n keyRequiredText="tb.rulenode.message-field-required"\n valText="tb.rulenode.table-col"\n valRequiredText="tb.rulenode.table-col-required">\n </tb-kv-map-config-old>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class qn extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.timeseriesConfigForm}onConfigurationSet(e){this.timeseriesConfigForm=this.fb.group({defaultTTL:[e?e.defaultTTL:null,[O.required,O.min(0)]],skipLatestPersistence:[!!e&&e.skipLatestPersistence,[]],useServerTs:[!!e&&e.useServerTs,[]]})}}e("TimeseriesConfigComponent",qn),qn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),qn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:qn,selector:"tb-action-node-timeseries-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="timeseriesConfigForm" class="tb-form-panel no-border no-padding">\n <mat-form-field fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.default-ttl</mat-label>\n <input type="number" min="0" step="1" matInput formControlName="defaultTTL" required>\n <mat-icon class="help-icon margin-8 cursor-pointer"\n aria-hidden="false"\n aria-label="help-icon"\n matSuffix\n matTooltip="{{ \'tb.rulenode.default-ttl-hint\' | translate }}">\n help\n </mat-icon>\n <mat-error *ngIf="timeseriesConfigForm.get(\'defaultTTL\').hasError(\'required\')">\n {{ \'tb.rulenode.default-ttl-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="timeseriesConfigForm.get(\'defaultTTL\').hasError(\'min\')">\n {{ \'tb.rulenode.min-default-ttl-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <div class="tb-form-panel stroked">\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.use-server-ts-hint\' | translate}}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="useServerTs">\n {{ \'tb.rulenode.use-server-ts\' | translate }}\n </mat-slide-toggle>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.skip-latest-persistence-hint\' | translate}}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="skipLatestPersistence">\n {{ \'tb.rulenode.skip-latest-persistence\' | translate }}\n </mat-slide-toggle>\n </div>\n </div>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qn,decorators:[{type:n,args:[{selector:"tb-action-node-timeseries-config",template:'<section [formGroup]="timeseriesConfigForm" class="tb-form-panel no-border no-padding">\n <mat-form-field fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.default-ttl</mat-label>\n <input type="number" min="0" step="1" matInput formControlName="defaultTTL" required>\n <mat-icon class="help-icon margin-8 cursor-pointer"\n aria-hidden="false"\n aria-label="help-icon"\n matSuffix\n matTooltip="{{ \'tb.rulenode.default-ttl-hint\' | translate }}">\n help\n </mat-icon>\n <mat-error *ngIf="timeseriesConfigForm.get(\'defaultTTL\').hasError(\'required\')">\n {{ \'tb.rulenode.default-ttl-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="timeseriesConfigForm.get(\'defaultTTL\').hasError(\'min\')">\n {{ \'tb.rulenode.min-default-ttl-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <div class="tb-form-panel stroked">\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.use-server-ts-hint\' | translate}}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="useServerTs">\n {{ \'tb.rulenode.use-server-ts\' | translate }}\n </mat-slide-toggle>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.skip-latest-persistence-hint\' | translate}}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="skipLatestPersistence">\n {{ \'tb.rulenode.skip-latest-persistence\' | translate }}\n </mat-slide-toggle>\n </div>\n </div>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class An extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.unassignCustomerConfigForm}onConfigurationSet(e){this.unassignCustomerConfigForm=this.fb.group({customerNamePattern:[e?e.customerNamePattern:null,[]],createCustomerIfNotExists:[!!e&&e?.createCustomerIfNotExists,[]]})}validatorTriggers(){return["createCustomerIfNotExists"]}updateValidators(e){this.unassignCustomerConfigForm.get("createCustomerIfNotExists").value?this.unassignCustomerConfigForm.get("customerNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)]):this.unassignCustomerConfigForm.get("customerNamePattern").setValidators([]),this.unassignCustomerConfigForm.get("customerNamePattern").updateValueAndValidity({emitEvent:e})}prepareOutputConfig(e){return e.customerNamePattern=e.customerNamePattern.trim(),e}}e("UnassignCustomerConfigComponent",An),An.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:An,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),An.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:An,selector:"tb-action-node-un-assign-to-customer-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="unassignCustomerConfigForm" fxLayout="column">\n <div class="tb-form-panel no-padding no-border">\n\n <div class="tb-form-panel stroked" [class.no-padding-bottom]="unassignCustomerConfigForm.get(\'createCustomerIfNotExists\').value">\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.unassign-from-customer-tooltip\' | translate }}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="createCustomerIfNotExists">\n {{ \'tb.rulenode.unassign-from-customer\' | translate }}\n </mat-slide-toggle>\n </div>\n <mat-form-field class="mat-block" subscriptSizing="dynamic" *ngIf="unassignCustomerConfigForm.get(\'createCustomerIfNotExists\').value">\n <mat-label translate>tb.rulenode.customer-name-pattern</mat-label>\n <input required matInput formControlName="customerNamePattern">\n <mat-error *ngIf="unassignCustomerConfigForm.get(\'customerNamePattern\').hasError(\'required\') ||\n unassignCustomerConfigForm.get(\'customerNamePattern\').hasError(\'pattern\')">\n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.customer-name-pattern-hint</mat-hint>\n </mat-form-field>\n </div>\n </div>\n</section>\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:An,decorators:[{type:n,args:[{selector:"tb-action-node-un-assign-to-customer-config",template:'<section [formGroup]="unassignCustomerConfigForm" fxLayout="column">\n <div class="tb-form-panel no-padding no-border">\n\n <div class="tb-form-panel stroked" [class.no-padding-bottom]="unassignCustomerConfigForm.get(\'createCustomerIfNotExists\').value">\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.unassign-from-customer-tooltip\' | translate }}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="createCustomerIfNotExists">\n {{ \'tb.rulenode.unassign-from-customer\' | translate }}\n </mat-slide-toggle>\n </div>\n <mat-form-field class="mat-block" subscriptSizing="dynamic" *ngIf="unassignCustomerConfigForm.get(\'createCustomerIfNotExists\').value">\n <mat-label translate>tb.rulenode.customer-name-pattern</mat-label>\n <input required matInput formControlName="customerNamePattern">\n <mat-error *ngIf="unassignCustomerConfigForm.get(\'customerNamePattern\').hasError(\'required\') ||\n unassignCustomerConfigForm.get(\'customerNamePattern\').hasError(\'pattern\')">\n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.customer-name-pattern-hint</mat-hint>\n </mat-form-field>\n </div>\n </div>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Mn extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.sendRestApiCallReplyConfigForm}onConfigurationSet(e){this.sendRestApiCallReplyConfigForm=this.fb.group({requestIdMetaDataAttribute:[e?e.requestIdMetaDataAttribute:null,[]],serviceIdMetaDataAttribute:[e?e.serviceIdMetaDataAttribute:null,[]]})}}e("SendRestApiCallReplyConfigComponent",Mn),Mn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Mn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Mn,selector:"tb-action-node-send-rest-api-call-reply-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="sendRestApiCallReplyConfigForm" class="tb-form-panel stroked no-padding-bottom">\n <div class="tb-form-panel-title" translate>tb.rulenode.reply-routing-configuration</div>\n <tb-example-hint [hintText]="\'tb.rulenode.reply-routing-configuration-hint\'">\n </tb-example-hint>\n <div class="tb-form-row no-border no-padding tb-standard-fields column-xs">\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.service-id-metadata-attribute</mat-label>\n <input matInput formControlName="serviceIdMetaDataAttribute">\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.request-id-metadata-attribute</mat-label>\n <input matInput formControlName="requestIdMetaDataAttribute">\n </mat-form-field>\n </div>\n</section>\n',dependencies:[{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mn,decorators:[{type:n,args:[{selector:"tb-action-node-send-rest-api-call-reply-config",template:'<section [formGroup]="sendRestApiCallReplyConfigForm" class="tb-form-panel stroked no-padding-bottom">\n <div class="tb-form-panel-title" translate>tb.rulenode.reply-routing-configuration</div>\n <tb-example-hint [hintText]="\'tb.rulenode.reply-routing-configuration-hint\'">\n </tb-example-hint>\n <div class="tb-form-row no-border no-padding tb-standard-fields column-xs">\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.service-id-metadata-attribute</mat-label>\n <input matInput formControlName="serviceIdMetaDataAttribute">\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.request-id-metadata-attribute</mat-label>\n <input matInput formControlName="requestIdMetaDataAttribute">\n </mat-form-field>\n </div>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class En extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopeMap=f,this.attributeScopes=Object.keys(f),this.telemetryTypeTranslationsMap=y,this.separatorKeysCodes=[Fe,ke,Te]}configForm(){return this.deleteAttributesConfigForm}onConfigurationSet(e){this.deleteAttributesConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]],keys:[e?e.keys:null,[O.required]],sendAttributesDeletedNotification:[!!e&&e.sendAttributesDeletedNotification,[]],notifyDevice:[!!e&&e.notifyDevice,[]]}),this.deleteAttributesConfigForm.get("scope").valueChanges.subscribe((e=>{e!==f.SHARED_SCOPE&&this.deleteAttributesConfigForm.get("notifyDevice").patchValue(!1,{emitEvent:!1})}))}removeKey(e){const t=this.deleteAttributesConfigForm.get("keys").value,n=t.indexOf(e);n>=0&&(t.splice(n,1),this.deleteAttributesConfigForm.get("keys").patchValue(t,{emitEvent:!0}))}addKey(e){const t=e.input;let n=e.value;if((n||"").trim()){n=n.trim();let e=this.deleteAttributesConfigForm.get("keys").value;e&&-1!==e.indexOf(n)||(e||(e=[]),e.push(n),this.deleteAttributesConfigForm.get("keys").patchValue(e,{emitEvent:!0}))}t&&(t.value="")}}e("DeleteAttributesConfigComponent",En),En.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:En,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),En.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:En,selector:"tb-action-node-delete-attributes-config",viewQueries:[{propertyName:"attributeChipList",first:!0,predicate:["attributeChipList"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'<section [formGroup]="deleteAttributesConfigForm" class="tb-form-panel no-border no-padding">\n <div class="tb-form-panel stroked">\n <tb-example-hint [hintText]="\'tb.rulenode.attributes-scope-hint\'">\n </tb-example-hint>\n <div class="tb-form-row no-border no-padding tb-standard-fields">\n <mat-form-field class="flex">\n <mat-label>{{ \'tb.rulenode.attributes-scope\' | translate }}</mat-label>\n <mat-select required\n class="tb-entity-type-select" matInput formControlName="scope">\n <mat-option *ngFor="let scope of attributeScopes" [value]="scope">\n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label>{{ \'tb.rulenode.attributes-scope-value\' | translate }}</mat-label>\n <input type="text" matInput readonly disabled [ngModel]="deleteAttributesConfigForm.get(\'scope\').value" [ngModelOptions]="{standalone: true}">\n <button type="button"\n matSuffix\n mat-icon-button\n aria-label="Copy"\n ngxClipboard\n [cbContent]="deleteAttributesConfigForm.get(\'scope\').value"\n matTooltip="{{ \'tb.rulenode.attributes-scope-value-copy\' | translate }}">\n <mat-icon aria-hidden="false"\n aria-label="help-icon">content_copy\n </mat-icon>\n </button>\n </mat-form-field>\n </div>\n </div>\n\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label>{{ \'tb.rulenode.attributes-keys\' | translate }}</mat-label>\n <mat-chip-grid formControlName="keys" #attributeChipList>\n <mat-chip-row\n *ngFor="let key of deleteAttributesConfigForm.get(\'keys\').value;"\n (removed)="removeKey(key)">\n {{key}}\n <mat-icon matChipRemove>close</mat-icon>\n </mat-chip-row>\n <input matInput type="text"\n [matChipInputFor]="attributeChipList"\n [matChipInputSeparatorKeyCodes]="separatorKeysCodes"\n (matChipInputTokenEnd)="addKey($event)"\n [matChipInputAddOnBlur]="true">\n </mat-chip-grid>\n <mat-error *ngIf="deleteAttributesConfigForm.get(\'keys\').hasError(\'required\')">{{ \'tb.rulenode.attributes-keys-required\' | translate }}</mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n\n <section class="tb-form-panel stroked">\n <mat-expansion-panel class="tb-settings">\n <mat-expansion-panel-header>\n <mat-panel-title translate>tb.rulenode.advanced-settings</mat-panel-title>\n </mat-expansion-panel-header>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.send-attributes-deleted-notification-hint\' | translate }}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="sendAttributesDeletedNotification">\n {{ \'tb.rulenode.send-attributes-deleted-notification\' | translate }}\n </mat-slide-toggle>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.notify-device-on-delete-hint\' | translate }}"\n *ngIf="deleteAttributesConfigForm.get(\'scope\').value === attributeScopeMap.SHARED_SCOPE"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="notifyDevice">\n {{ \'tb.rulenode.notify-device\' | translate }}\n </mat-slide-toggle>\n </div>\n </mat-expansion-panel>\n </section>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"component",type:oe.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:oe.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:oe.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"component",type:Ie.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:Ie.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:Ie.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:Ie.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:ft,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:En,decorators:[{type:n,args:[{selector:"tb-action-node-delete-attributes-config",template:'<section [formGroup]="deleteAttributesConfigForm" class="tb-form-panel no-border no-padding">\n <div class="tb-form-panel stroked">\n <tb-example-hint [hintText]="\'tb.rulenode.attributes-scope-hint\'">\n </tb-example-hint>\n <div class="tb-form-row no-border no-padding tb-standard-fields">\n <mat-form-field class="flex">\n <mat-label>{{ \'tb.rulenode.attributes-scope\' | translate }}</mat-label>\n <mat-select required\n class="tb-entity-type-select" matInput formControlName="scope">\n <mat-option *ngFor="let scope of attributeScopes" [value]="scope">\n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label>{{ \'tb.rulenode.attributes-scope-value\' | translate }}</mat-label>\n <input type="text" matInput readonly disabled [ngModel]="deleteAttributesConfigForm.get(\'scope\').value" [ngModelOptions]="{standalone: true}">\n <button type="button"\n matSuffix\n mat-icon-button\n aria-label="Copy"\n ngxClipboard\n [cbContent]="deleteAttributesConfigForm.get(\'scope\').value"\n matTooltip="{{ \'tb.rulenode.attributes-scope-value-copy\' | translate }}">\n <mat-icon aria-hidden="false"\n aria-label="help-icon">content_copy\n </mat-icon>\n </button>\n </mat-form-field>\n </div>\n </div>\n\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label>{{ \'tb.rulenode.attributes-keys\' | translate }}</mat-label>\n <mat-chip-grid formControlName="keys" #attributeChipList>\n <mat-chip-row\n *ngFor="let key of deleteAttributesConfigForm.get(\'keys\').value;"\n (removed)="removeKey(key)">\n {{key}}\n <mat-icon matChipRemove>close</mat-icon>\n </mat-chip-row>\n <input matInput type="text"\n [matChipInputFor]="attributeChipList"\n [matChipInputSeparatorKeyCodes]="separatorKeysCodes"\n (matChipInputTokenEnd)="addKey($event)"\n [matChipInputAddOnBlur]="true">\n </mat-chip-grid>\n <mat-error *ngIf="deleteAttributesConfigForm.get(\'keys\').hasError(\'required\')">{{ \'tb.rulenode.attributes-keys-required\' | translate }}</mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n\n <section class="tb-form-panel stroked">\n <mat-expansion-panel class="tb-settings">\n <mat-expansion-panel-header>\n <mat-panel-title translate>tb.rulenode.advanced-settings</mat-panel-title>\n </mat-expansion-panel-header>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.send-attributes-deleted-notification-hint\' | translate }}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="sendAttributesDeletedNotification">\n {{ \'tb.rulenode.send-attributes-deleted-notification\' | translate }}\n </mat-slide-toggle>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.notify-device-on-delete-hint\' | translate }}"\n *ngIf="deleteAttributesConfigForm.get(\'scope\').value === attributeScopeMap.SHARED_SCOPE"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="notifyDevice">\n {{ \'tb.rulenode.notify-device\' | translate }}\n </mat-slide-toggle>\n </div>\n </mat-expansion-panel>\n </section>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]},propDecorators:{attributeChipList:[{type:u,args:["attributeChipList"]}]}});class Gn extends k{get function(){return this.functionValue}set function(e){e&&this.functionValue!==e&&(this.functionValue=e,this.setupArgumentsFormGroup(!0))}constructor(e,t){super(e),this.store=e,this.fb=t,this.maxArgs=16,this.minArgs=1,this.displayArgumentName=!1,this.mathFunctionMap=rn,this.ArgumentType=on,this.attributeScopeMap=yn,this.argumentTypeMap=dn,this.arguments=Object.values(on),this.attributeScope=Object.values(gn),this.propagateChange=null,this.valueChangeSubscription=[]}ngOnInit(){this.argumentsFormGroup=this.fb.group({arguments:this.fb.array([])}),this.valueChangeSubscription.push(this.argumentsFormGroup.valueChanges.subscribe((()=>{this.updateModel()}))),this.setupArgumentsFormGroup()}onDrop(e){const t=this.argumentsFormArray,n=t.at(e.previousIndex);t.removeAt(e.previousIndex),t.insert(e.currentIndex,n),this.updateArgumentNames()}get argumentsFormArray(){return this.argumentsFormGroup.get("arguments")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.argumentsFormGroup.disable({emitEvent:!1}):(this.argumentsFormGroup.enable({emitEvent:!1}),this.argumentsFormArray.controls.forEach((e=>this.updateArgumentControlValidators(e))))}ngOnDestroy(){this.valueChangeSubscription.length&&this.valueChangeSubscription.forEach((e=>e.unsubscribe()))}writeValue(e){const t=[];e&&e.forEach(((e,n)=>{t.push(this.createArgumentControl(e,n))})),this.argumentsFormGroup.setControl("arguments",this.fb.array(t),{emitEvent:!1}),this.setupArgumentsFormGroup()}removeArgument(e){this.argumentsFormArray.removeAt(e),this.updateArgumentNames()}addArgument(e=!0){const t=this.argumentsFormArray,n=this.createArgumentControl(null,t.length);t.push(n,{emitEvent:e})}validate(e){return this.argumentsFormGroup.valid?null:{argumentsRequired:!0}}setupArgumentsFormGroup(e=!1){if(this.function&&(this.maxArgs=this.mathFunctionMap.get(this.function).maxArgs,this.minArgs=this.mathFunctionMap.get(this.function).minArgs,this.displayArgumentName=this.function===nn.CUSTOM),this.argumentsFormGroup){for(this.argumentsFormGroup.get("arguments").setValidators([O.minLength(this.minArgs),O.maxLength(this.maxArgs)]);this.argumentsFormArray.length>this.maxArgs;)this.removeArgument(this.maxArgs-1);for(;this.argumentsFormArray.length<this.minArgs;)this.addArgument(e);this.argumentsFormGroup.get("arguments").updateValueAndValidity({emitEvent:!1})}}createArgumentControl(e,t){const n=this.fb.group({type:[e?.type,[O.required]],key:[e?.key,[O.required]],name:[cn[t],[O.required]],attributeScope:[e?.attributeScope??gn.SERVER_SCOPE,[O.required]],defaultValue:[e?.defaultValue?e?.defaultValue:null]});return this.updateArgumentControlValidators(n),this.valueChangeSubscription.push(n.get("type").valueChanges.subscribe((()=>{this.updateArgumentControlValidators(n),n.get("attributeScope").updateValueAndValidity({emitEvent:!1}),n.get("defaultValue").updateValueAndValidity({emitEvent:!1})}))),n}updateArgumentControlValidators(e){const t=e.get("type").value;t===on.ATTRIBUTE?e.get("attributeScope").enable({emitEvent:!1}):e.get("attributeScope").disable({emitEvent:!1}),t&&t!==on.CONSTANT?e.get("defaultValue").enable({emitEvent:!1}):e.get("defaultValue").disable({emitEvent:!1})}updateArgumentNames(){this.argumentsFormArray.controls.forEach(((e,t)=>{e.get("name").setValue(cn[t])}))}updateModel(){const e=this.argumentsFormArray.value;e.length&&this.argumentsFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}}e("ArgumentsMapConfigComponent",Gn),Gn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Gn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Gn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Gn,selector:"tb-arguments-map-config",inputs:{disabled:"disabled",function:"function"},providers:[{provide:B,useExisting:c((()=>Gn)),multi:!0},{provide:K,useExisting:c((()=>Gn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'<section fxLayout="column">\n\n <div [ngClass]="{\'tb-readonly\': disabled}"\n style="max-height: 500px; overflow: auto;">\n <mat-list class="tb-drop-list arguments-list" cdkDropList cdkDropListOrientation="vertical"\n [formGroup]="argumentsFormGroup"\n (cdkDropListDropped)="onDrop($event)"\n [cdkDropListDisabled]="disabled">\n <mat-list-item *ngFor="let argumentControl of argumentsFormArray.controls; let $index = index"\n formArrayName="arguments"\n cdkDrag class="tb-argument tb-draggable"\n [cdkDragDisabled]="disabled"\n style="height: 100%">\n <div fxFlex fxLayout="row" fxLayoutAlign="start center">\n <button *ngIf="!disabled" mat-icon-button color="primary"\n cdkDragHandle\n class="tb-drag-handle handle"\n style="min-width: 40px; margin: 0"\n matTooltip="{{ \'action.drag\' | translate }}"\n matTooltipPosition="above">\n <mat-icon>drag_handle</mat-icon>\n </button>\n <div fxFlex fxLAyout="row" fxLayoutAlign="start center" fxLayoutGap="16px">\n <span *ngIf="displayArgumentName"\n style="padding: 0 10px; min-width: 20px;">{{argumentControl.get(\'name\').value}}.</span>\n <div fxFlex fxLayout="column">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.argument-source-field-input</mat-label>\n <mat-select [formControl]="argumentControl.get(\'type\')" required>\n <mat-select-trigger>\n {{ argumentTypeMap.get(argumentControl.get(\'type\').value)?.name | translate }}\n </mat-select-trigger>\n <mat-option *ngFor="let argument of arguments" [value]="argument"\n style="border-bottom: 1px solid #eee;">\n {{ argumentTypeMap.get(argument).name | translate }}\n <small style="display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">\n {{ argumentTypeMap.get(argument).description }}\n </small>\n </mat-option>\n </mat-select>\n <mat-error *ngIf="argumentControl.get(\'type\').hasError(\'required\')" translate>\n tb.rulenode.argument-source-field-input-required\n </mat-error>\n </mat-form-field>\n <div fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="16px">\n <mat-form-field fxFlex="50" floatLabel="always" class="mat-block"\n *ngIf="argumentControl.get(\'type\').value && argumentControl.get(\'type\').value !== ArgumentType.CONSTANT">\n <mat-label translate>tb.rulenode.argument-key-field-input</mat-label>\n <input [formControl]="argumentControl.get(\'key\')" matInput required/>\n <mat-icon class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon" matSuffix\n color="primary"\n matTooltip="{{ \'tb.rulenode.math-templatization-tooltip\' | translate }}">\n help\n </mat-icon>\n <mat-error *ngIf="argumentControl.get(\'key\').hasError(\'required\')" translate>\n tb.rulenode.argument-key-field-input-required\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex floatLabel="always" class="mat-block"\n *ngIf="argumentControl.get(\'type\').value === ArgumentType.CONSTANT">\n <mat-label translate>tb.rulenode.constant-value-field-input</mat-label>\n <input [formControl]="argumentControl.get(\'key\')"\n matInput\n required\n step="1" min="0"\n type="number"/>\n <mat-error *ngIf="argumentControl.get(\'key\').hasError(\'required\')" translate>\n tb.rulenode.constant-value-field-input-required\n </mat-error>\n </mat-form-field>\n <mat-form-field *ngIf="argumentControl.get(\'type\').value && argumentControl.get(\'type\').value !== ArgumentType.CONSTANT"\n fxFlex="50" floatLabel="always" class="mat-block">\n <mat-label translate>tb.rulenode.default-value-field-input</mat-label>\n <input [formControl]="argumentControl.get(\'defaultValue\')" matInput step="1" type="number"/>\n </mat-form-field>\n </div>\n <mat-form-field *ngIf="argumentControl.get(\'type\').value === ArgumentType.ATTRIBUTE" class="mat-block">\n <mat-label translate>tb.rulenode.attribute-scope-field-input</mat-label>\n <mat-select required [formControl]="argumentControl.get(\'attributeScope\')">\n <mat-option *ngFor="let scope of attributeScope" [value]="scope">\n {{ attributeScopeMap.get(scope) | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf="argumentControl.get(\'attributeScope\').hasError(\'required\')" translate>\n tb.rulenode.attribute-scope-field-input-required\n </mat-error>\n </mat-form-field>\n </div>\n <button *ngIf="!disabled" mat-icon-button color="primary" style="min-width: 40px;"\n (click)="removeArgument($index)"\n matTooltip="{{ \'action.remove\' | translate }}"\n matTooltipPosition="above">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n </div>\n </mat-list-item>\n </mat-list>\n </div>\n <div *ngIf="!argumentsFormArray.length">\n <span translate fxLayoutAlign="center center"\n class="tb-prompt">tb.rulenode.no-arguments-prompt</span>\n </div>\n <button mat-button mat-raised-button color="primary"\n [disabled]="argumentsFormArray.length >= maxArgs"\n (click)="addArgument()"\n type="button"\n matTooltipPosition="above">\n <mat-icon>add</mat-icon>\n {{ \'action.add\' | translate }}\n </button>\n</section>\n',styles:[":host .mat-mdc-list-item.tb-argument{border:solid rgba(0,0,0,.25) 1px;border-radius:4px;padding:10px 0;margin-bottom:16px}:host .arguments-list{padding:0}\n"],dependencies:[{kind:"directive",type:U.NgClass,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:te.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Pe.MatList,selector:"mat-list",exportAs:["matList"]},{kind:"component",type:Pe.MatListItem,selector:"mat-list-item, a[mat-list-item], button[mat-list-item]",inputs:["activated"],exportAs:["matListItem"]},{kind:"directive",type:Re.CdkDropList,selector:"[cdkDropList], cdk-drop-list",inputs:["cdkDropListConnectedTo","cdkDropListData","cdkDropListOrientation","id","cdkDropListLockAxis","cdkDropListDisabled","cdkDropListSortingDisabled","cdkDropListEnterPredicate","cdkDropListSortPredicate","cdkDropListAutoScrollDisabled","cdkDropListAutoScrollStep"],outputs:["cdkDropListDropped","cdkDropListEntered","cdkDropListExited","cdkDropListSorted"],exportAs:["cdkDropList"]},{kind:"directive",type:Re.CdkDrag,selector:"[cdkDrag]",inputs:["cdkDragData","cdkDragLockAxis","cdkDragRootElement","cdkDragBoundary","cdkDragStartDelay","cdkDragFreeDragPosition","cdkDragDisabled","cdkDragConstrainPosition","cdkDragPreviewClass","cdkDragPreviewContainer"],outputs:["cdkDragStarted","cdkDragReleased","cdkDragEnded","cdkDragEntered","cdkDragExited","cdkDragDropped","cdkDragMoved"],exportAs:["cdkDrag"]},{kind:"directive",type:Re.CdkDragHandle,selector:"[cdkDragHandle]",inputs:["cdkDragHandleDisabled"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:Ve.DefaultClassDirective,selector:" [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl], [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl], [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]",inputs:["ngClass","ngClass.xs","ngClass.sm","ngClass.md","ngClass.lg","ngClass.xl","ngClass.lt-sm","ngClass.lt-md","ngClass.lt-lg","ngClass.lt-xl","ngClass.gt-xs","ngClass.gt-sm","ngClass.gt-md","ngClass.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormArrayName,selector:"[formArrayName]",inputs:["formArrayName"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Gn,decorators:[{type:n,args:[{selector:"tb-arguments-map-config",providers:[{provide:B,useExisting:c((()=>Gn)),multi:!0},{provide:K,useExisting:c((()=>Gn)),multi:!0}],template:'<section fxLayout="column">\n\n <div [ngClass]="{\'tb-readonly\': disabled}"\n style="max-height: 500px; overflow: auto;">\n <mat-list class="tb-drop-list arguments-list" cdkDropList cdkDropListOrientation="vertical"\n [formGroup]="argumentsFormGroup"\n (cdkDropListDropped)="onDrop($event)"\n [cdkDropListDisabled]="disabled">\n <mat-list-item *ngFor="let argumentControl of argumentsFormArray.controls; let $index = index"\n formArrayName="arguments"\n cdkDrag class="tb-argument tb-draggable"\n [cdkDragDisabled]="disabled"\n style="height: 100%">\n <div fxFlex fxLayout="row" fxLayoutAlign="start center">\n <button *ngIf="!disabled" mat-icon-button color="primary"\n cdkDragHandle\n class="tb-drag-handle handle"\n style="min-width: 40px; margin: 0"\n matTooltip="{{ \'action.drag\' | translate }}"\n matTooltipPosition="above">\n <mat-icon>drag_handle</mat-icon>\n </button>\n <div fxFlex fxLAyout="row" fxLayoutAlign="start center" fxLayoutGap="16px">\n <span *ngIf="displayArgumentName"\n style="padding: 0 10px; min-width: 20px;">{{argumentControl.get(\'name\').value}}.</span>\n <div fxFlex fxLayout="column">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.argument-source-field-input</mat-label>\n <mat-select [formControl]="argumentControl.get(\'type\')" required>\n <mat-select-trigger>\n {{ argumentTypeMap.get(argumentControl.get(\'type\').value)?.name | translate }}\n </mat-select-trigger>\n <mat-option *ngFor="let argument of arguments" [value]="argument"\n style="border-bottom: 1px solid #eee;">\n {{ argumentTypeMap.get(argument).name | translate }}\n <small style="display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">\n {{ argumentTypeMap.get(argument).description }}\n </small>\n </mat-option>\n </mat-select>\n <mat-error *ngIf="argumentControl.get(\'type\').hasError(\'required\')" translate>\n tb.rulenode.argument-source-field-input-required\n </mat-error>\n </mat-form-field>\n <div fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="16px">\n <mat-form-field fxFlex="50" floatLabel="always" class="mat-block"\n *ngIf="argumentControl.get(\'type\').value && argumentControl.get(\'type\').value !== ArgumentType.CONSTANT">\n <mat-label translate>tb.rulenode.argument-key-field-input</mat-label>\n <input [formControl]="argumentControl.get(\'key\')" matInput required/>\n <mat-icon class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon" matSuffix\n color="primary"\n matTooltip="{{ \'tb.rulenode.math-templatization-tooltip\' | translate }}">\n help\n </mat-icon>\n <mat-error *ngIf="argumentControl.get(\'key\').hasError(\'required\')" translate>\n tb.rulenode.argument-key-field-input-required\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex floatLabel="always" class="mat-block"\n *ngIf="argumentControl.get(\'type\').value === ArgumentType.CONSTANT">\n <mat-label translate>tb.rulenode.constant-value-field-input</mat-label>\n <input [formControl]="argumentControl.get(\'key\')"\n matInput\n required\n step="1" min="0"\n type="number"/>\n <mat-error *ngIf="argumentControl.get(\'key\').hasError(\'required\')" translate>\n tb.rulenode.constant-value-field-input-required\n </mat-error>\n </mat-form-field>\n <mat-form-field *ngIf="argumentControl.get(\'type\').value && argumentControl.get(\'type\').value !== ArgumentType.CONSTANT"\n fxFlex="50" floatLabel="always" class="mat-block">\n <mat-label translate>tb.rulenode.default-value-field-input</mat-label>\n <input [formControl]="argumentControl.get(\'defaultValue\')" matInput step="1" type="number"/>\n </mat-form-field>\n </div>\n <mat-form-field *ngIf="argumentControl.get(\'type\').value === ArgumentType.ATTRIBUTE" class="mat-block">\n <mat-label translate>tb.rulenode.attribute-scope-field-input</mat-label>\n <mat-select required [formControl]="argumentControl.get(\'attributeScope\')">\n <mat-option *ngFor="let scope of attributeScope" [value]="scope">\n {{ attributeScopeMap.get(scope) | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf="argumentControl.get(\'attributeScope\').hasError(\'required\')" translate>\n tb.rulenode.attribute-scope-field-input-required\n </mat-error>\n </mat-form-field>\n </div>\n <button *ngIf="!disabled" mat-icon-button color="primary" style="min-width: 40px;"\n (click)="removeArgument($index)"\n matTooltip="{{ \'action.remove\' | translate }}"\n matTooltipPosition="above">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n </div>\n </mat-list-item>\n </mat-list>\n </div>\n <div *ngIf="!argumentsFormArray.length">\n <span translate fxLayoutAlign="center center"\n class="tb-prompt">tb.rulenode.no-arguments-prompt</span>\n </div>\n <button mat-button mat-raised-button color="primary"\n [disabled]="argumentsFormArray.length >= maxArgs"\n (click)="addArgument()"\n type="button"\n matTooltipPosition="above">\n <mat-icon>add</mat-icon>\n {{ \'action.add\' | translate }}\n </button>\n</section>\n',styles:[":host .mat-mdc-list-item.tb-argument{border:solid rgba(0,0,0,.25) 1px;border-radius:4px;padding:10px 0;margin-bottom:16px}:host .arguments-list{padding:0}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:m}],function:[{type:m}]}});class wn extends k{get required(){return this.requiredValue}set required(e){this.requiredValue=Ee(e)}constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.injector=n,this.fb=r,this.searchText="",this.dirty=!1,this.mathOperation=[...rn.values()],this.propagateChange=null}ngOnInit(){this.mathFunctionForm=this.fb.group({operation:[""]}),this.filteredOptions=this.mathFunctionForm.get("operation").valueChanges.pipe(Oe((e=>{let t;t="string"==typeof e&&nn[e]?nn[e]:null,this.updateView(t)})),_e((e=>(this.searchText=e||"",e?this._filter(e):this.mathOperation.slice()))))}_filter(e){const t=e.toLowerCase();return this.mathOperation.filter((e=>e.name.toLowerCase().includes(t)||e.value.toLowerCase().includes(t)))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.mathFunctionForm.disable({emitEvent:!1}):this.mathFunctionForm.enable({emitEvent:!1})}mathFunctionDisplayFn(e){if(e){const t=rn.get(e);return t.value+" | "+t.name}return""}writeValue(e){this.modelValue=e,this.mathFunctionForm.get("operation").setValue(e,{emitEvent:!1}),this.dirty=!0}updateView(e){this.modelValue!==e&&(this.modelValue=e,this.propagateChange(this.modelValue))}onFocus(){this.dirty&&(this.mathFunctionForm.get("operation").updateValueAndValidity({onlySelf:!0}),this.dirty=!1)}clear(){this.mathFunctionForm.get("operation").patchValue(""),setTimeout((()=>{this.operationInput.nativeElement.blur(),this.operationInput.nativeElement.focus()}),0)}}e("MathFunctionAutocompleteComponent",wn),wn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:wn,deps:[{token:P.Store},{token:Z.TranslateService},{token:t.Injector},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),wn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:wn,selector:"tb-math-function-autocomplete",inputs:{required:"required",disabled:"disabled"},providers:[{provide:B,useExisting:c((()=>wn)),multi:!0}],viewQueries:[{propertyName:"operationInput",first:!0,predicate:["operationInput"],descendants:!0,static:!0}],usesInheritance:!0,ngImport:t,template:'<mat-form-field [formGroup]="mathFunctionForm" class="mat-block">\n <mat-label translate>tb.rulenode.functions-field-input</mat-label>\n <input [required]="required"\n (focusin)="onFocus()"\n type="text"\n #operationInput matInput\n formControlName="operation"\n [matAutocomplete]="auto">\n <button *ngIf="mathFunctionForm.get(\'operation\').value"\n type="button"\n matSuffix mat-icon-button aria-label="Clear"\n (click)="clear()">\n <mat-icon class="material-icons">close</mat-icon>\n </button>\n <mat-autocomplete #auto="matAutocomplete" class="tb-autocomplete" [displayWith]="mathFunctionDisplayFn">\n <mat-option *ngFor="let option of filteredOptions | async" [value]="option.value">\n <span [innerHTML]="option.value + \' | \' + option.name | highlight:searchText"></span>\n <small style="display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">\n {{ option.description }}\n </small>\n </mat-option>\n <mat-option *ngIf="!(filteredOptions | async)?.length" [value]="null">\n <span translate>tb.rulenode.no-option-found</span>\n </mat-option>\n </mat-autocomplete>\n</mat-form-field>\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:je.MatAutocomplete,selector:"mat-autocomplete",inputs:["disableRipple","hideSingleSelectionIndicator"],exportAs:["matAutocomplete"]},{kind:"directive",type:je.MatAutocompleteTrigger,selector:"input[matAutocomplete], textarea[matAutocomplete]",exportAs:["matAutocompleteTrigger"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:U.AsyncPipe,name:"async"},{kind:"pipe",type:$e.HighlightPipe,name:"highlight"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:wn,decorators:[{type:n,args:[{selector:"tb-math-function-autocomplete",providers:[{provide:B,useExisting:c((()=>wn)),multi:!0}],template:'<mat-form-field [formGroup]="mathFunctionForm" class="mat-block">\n <mat-label translate>tb.rulenode.functions-field-input</mat-label>\n <input [required]="required"\n (focusin)="onFocus()"\n type="text"\n #operationInput matInput\n formControlName="operation"\n [matAutocomplete]="auto">\n <button *ngIf="mathFunctionForm.get(\'operation\').value"\n type="button"\n matSuffix mat-icon-button aria-label="Clear"\n (click)="clear()">\n <mat-icon class="material-icons">close</mat-icon>\n </button>\n <mat-autocomplete #auto="matAutocomplete" class="tb-autocomplete" [displayWith]="mathFunctionDisplayFn">\n <mat-option *ngFor="let option of filteredOptions | async" [value]="option.value">\n <span [innerHTML]="option.value + \' | \' + option.name | highlight:searchText"></span>\n <small style="display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">\n {{ option.description }}\n </small>\n </mat-option>\n <mat-option *ngIf="!(filteredOptions | async)?.length" [value]="null">\n <span translate>tb.rulenode.no-option-found</span>\n </mat-option>\n </mat-autocomplete>\n</mat-form-field>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:t.Injector},{type:R.UntypedFormBuilder}]},propDecorators:{required:[{type:m}],disabled:[{type:m}],operationInput:[{type:u,args:["operationInput",{static:!0}]}]}});class Dn extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.MathFunction=nn,this.ArgumentTypeResult=an,this.argumentTypeResultMap=un,this.attributeScopeMap=yn,this.argumentsResult=Object.values(an),this.attributeScopeResult=Object.values(fn)}configForm(){return this.mathFunctionConfigForm}onConfigurationSet(e){this.mathFunctionConfigForm=this.fb.group({operation:[e?e.operation:null,[O.required]],arguments:[e?e.arguments:null,[O.required]],customFunction:[e?e.customFunction:"",[O.required]],result:this.fb.group({type:[e?e.result.type:null,[O.required]],attributeScope:[e?e.result.attributeScope:null,[O.required]],key:[e?e.result.key:"",[O.required]],resultValuePrecision:[e?e.result.resultValuePrecision:0],addToBody:[!!e&&e.result.addToBody],addToMetadata:[!!e&&e.result.addToMetadata]})})}updateValidators(e){const t=this.mathFunctionConfigForm.get("operation").value,n=this.mathFunctionConfigForm.get("result.type").value;t===nn.CUSTOM?(this.mathFunctionConfigForm.get("customFunction").enable({emitEvent:!1}),null===this.mathFunctionConfigForm.get("customFunction").value&&this.mathFunctionConfigForm.get("customFunction").patchValue("(x - 32) / 1.8",{emitEvent:!1})):this.mathFunctionConfigForm.get("customFunction").disable({emitEvent:!1}),n===an.ATTRIBUTE?this.mathFunctionConfigForm.get("result.attributeScope").enable({emitEvent:!1}):this.mathFunctionConfigForm.get("result.attributeScope").disable({emitEvent:!1}),this.mathFunctionConfigForm.get("customFunction").updateValueAndValidity({emitEvent:e}),this.mathFunctionConfigForm.get("result.attributeScope").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["operation","result.type"]}}e("MathFunctionConfigComponent",Dn),Dn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Dn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Dn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Dn,selector:"tb-action-node-math-function-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="mathFunctionConfigForm" fxLayout="column">\n <tb-math-function-autocomplete\n fxFlex="30" fxFlex.md fxFlex.xs\n required\n formControlName="operation">\n </tb-math-function-autocomplete>\n <fieldset class="fields-group" fxLayout="column" fxLayoutGap="8px">\n <legend class="group-title" translate>tb.rulenode.argument-tile</legend>\n <tb-arguments-map-config formControlName="arguments"\n [function]="mathFunctionConfigForm.get(\'operation\').value">\n </tb-arguments-map-config>\n </fieldset>\n <fieldset *ngIf="mathFunctionConfigForm.get(\'operation\').value === MathFunction.CUSTOM"\n class="fields-group" fxLayout="column" fxLayoutGap="8px">\n <legend class="group-title">{{\'tb.rulenode.custom-expression-field-input\' | translate }} *</legend>\n <mat-form-field fxFlex class="mat-block no-margin-top" subscriptSizing="dynamic">\n <input matInput formControlName="customFunction" required/>\n <mat-error *ngIf="mathFunctionConfigForm.get(\'customFunction\').hasError(\'required\')" translate>\n tb.rulenode.custom-expression-field-input-required\n </mat-error>\n <mat-hint translate>tb.rulenode.custom-expression-field-input-hint</mat-hint>\n </mat-form-field>\n </fieldset>\n <fieldset class="fields-group" fxLayout="column" fxLayoutGap="8px">\n <legend class="group-title" translate>tb.rulenode.result-title</legend>\n <div formGroupName="result">\n <mat-form-field fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.type-field-input</mat-label>\n <mat-select formControlName="type" required>\n <mat-select-trigger>\n {{ argumentTypeResultMap.get(mathFunctionConfigForm.get(\'result.type\').value)?.name | translate }}\n </mat-select-trigger>\n <mat-option *ngFor="let argument of argumentsResult" [value]="argument"\n style="border-bottom: 1px solid #eee;">\n {{ argumentTypeResultMap.get(argument).name | translate }}\n <small style="display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">\n {{ argumentTypeResultMap.get(argument).description }}\n </small>\n </mat-option>\n </mat-select>\n <mat-error *ngIf="mathFunctionConfigForm.get(\'result.type\').hasError(\'required\')" translate>\n tb.rulenode.type-field-input-required\n </mat-error>\n </mat-form-field>\n <div fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="16px">\n <mat-form-field fxFlex class="mat-block" *ngIf="mathFunctionConfigForm.get(\'result\').get(\'type\').value === ArgumentTypeResult.ATTRIBUTE">\n <mat-label translate>tb.rulenode.attribute-scope-field-input</mat-label>\n <mat-select required formControlName="attributeScope">\n <mat-option *ngFor="let scope of attributeScopeResult" [value]="scope">\n {{ attributeScopeMap.get(scope) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field fxFlex floatLabel="always" class="mat-block">\n <mat-label translate>tb.rulenode.key-field-input</mat-label>\n <input matInput formControlName="key" required/>\n <mat-icon class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon" matSuffix\n color="primary"\n matTooltip="{{ \'tb.rulenode.math-templatization-tooltip\' | translate }}">help</mat-icon>\n <mat-error *ngIf="mathFunctionConfigForm.get(\'result.key\').hasError(\'required\')" translate>\n tb.rulenode.key-field-input-required\n </mat-error>\n </mat-form-field>\n </div>\n <div fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="16px">\n <mat-form-field fxFlex floatLabel="always" class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.number-floating-point-field-input</mat-label>\n <input formControlName="resultValuePrecision"\n matInput\n step="1" min="0"\n type="number"/>\n <mat-hint [innerHTML]="\'tb.rulenode.number-floating-point-field-input-hint\' | translate | safe: \'html\'"></mat-hint>\n </mat-form-field>\n </div>\n <div *ngIf="[ArgumentTypeResult.ATTRIBUTE, ArgumentTypeResult.TIME_SERIES].includes(mathFunctionConfigForm.get(\'result\').get(\'type\').value)"\n fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutAlign="start" fxLayoutGap.gt-xs="16px" style="padding-top: 16px;">\n <mat-checkbox formControlName="addToBody">\n {{\'tb.rulenode.add-to-message-field-input\' | translate }}\n </mat-checkbox>\n <mat-checkbox formControlName="addToMetadata">\n {{\'tb.rulenode.add-to-metadata-field-input\' | translate}}\n </mat-checkbox>\n </div>\n </div>\n </fieldset>\n</section>\n',styles:[":host ::ng-deep .fields-group{padding:0 16px 8px;margin:10px 0;border:1px groove rgba(0,0,0,.25);border-radius:4px}:host ::ng-deep .fields-group .mat-mdc-form-field .mat-mdc-form-field-infix{width:100%}:host ::ng-deep .fields-group legend{color:#000000b3;width:-moz-fit-content;width:fit-content}:host ::ng-deep .fields-group legend+*{display:block}:host ::ng-deep .fields-group legend+*.no-margin-top{margin-top:0}\n"],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:te.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:R.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Gn,selector:"tb-arguments-map-config",inputs:["disabled","function"]},{kind:"component",type:wn,selector:"tb-math-function-autocomplete",inputs:["required","disabled"]},{kind:"pipe",type:ue.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Dn,decorators:[{type:n,args:[{selector:"tb-action-node-math-function-config",template:'<section [formGroup]="mathFunctionConfigForm" fxLayout="column">\n <tb-math-function-autocomplete\n fxFlex="30" fxFlex.md fxFlex.xs\n required\n formControlName="operation">\n </tb-math-function-autocomplete>\n <fieldset class="fields-group" fxLayout="column" fxLayoutGap="8px">\n <legend class="group-title" translate>tb.rulenode.argument-tile</legend>\n <tb-arguments-map-config formControlName="arguments"\n [function]="mathFunctionConfigForm.get(\'operation\').value">\n </tb-arguments-map-config>\n </fieldset>\n <fieldset *ngIf="mathFunctionConfigForm.get(\'operation\').value === MathFunction.CUSTOM"\n class="fields-group" fxLayout="column" fxLayoutGap="8px">\n <legend class="group-title">{{\'tb.rulenode.custom-expression-field-input\' | translate }} *</legend>\n <mat-form-field fxFlex class="mat-block no-margin-top" subscriptSizing="dynamic">\n <input matInput formControlName="customFunction" required/>\n <mat-error *ngIf="mathFunctionConfigForm.get(\'customFunction\').hasError(\'required\')" translate>\n tb.rulenode.custom-expression-field-input-required\n </mat-error>\n <mat-hint translate>tb.rulenode.custom-expression-field-input-hint</mat-hint>\n </mat-form-field>\n </fieldset>\n <fieldset class="fields-group" fxLayout="column" fxLayoutGap="8px">\n <legend class="group-title" translate>tb.rulenode.result-title</legend>\n <div formGroupName="result">\n <mat-form-field fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.type-field-input</mat-label>\n <mat-select formControlName="type" required>\n <mat-select-trigger>\n {{ argumentTypeResultMap.get(mathFunctionConfigForm.get(\'result.type\').value)?.name | translate }}\n </mat-select-trigger>\n <mat-option *ngFor="let argument of argumentsResult" [value]="argument"\n style="border-bottom: 1px solid #eee;">\n {{ argumentTypeResultMap.get(argument).name | translate }}\n <small style="display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">\n {{ argumentTypeResultMap.get(argument).description }}\n </small>\n </mat-option>\n </mat-select>\n <mat-error *ngIf="mathFunctionConfigForm.get(\'result.type\').hasError(\'required\')" translate>\n tb.rulenode.type-field-input-required\n </mat-error>\n </mat-form-field>\n <div fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="16px">\n <mat-form-field fxFlex class="mat-block" *ngIf="mathFunctionConfigForm.get(\'result\').get(\'type\').value === ArgumentTypeResult.ATTRIBUTE">\n <mat-label translate>tb.rulenode.attribute-scope-field-input</mat-label>\n <mat-select required formControlName="attributeScope">\n <mat-option *ngFor="let scope of attributeScopeResult" [value]="scope">\n {{ attributeScopeMap.get(scope) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field fxFlex floatLabel="always" class="mat-block">\n <mat-label translate>tb.rulenode.key-field-input</mat-label>\n <input matInput formControlName="key" required/>\n <mat-icon class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon" matSuffix\n color="primary"\n matTooltip="{{ \'tb.rulenode.math-templatization-tooltip\' | translate }}">help</mat-icon>\n <mat-error *ngIf="mathFunctionConfigForm.get(\'result.key\').hasError(\'required\')" translate>\n tb.rulenode.key-field-input-required\n </mat-error>\n </mat-form-field>\n </div>\n <div fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="16px">\n <mat-form-field fxFlex floatLabel="always" class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.number-floating-point-field-input</mat-label>\n <input formControlName="resultValuePrecision"\n matInput\n step="1" min="0"\n type="number"/>\n <mat-hint [innerHTML]="\'tb.rulenode.number-floating-point-field-input-hint\' | translate | safe: \'html\'"></mat-hint>\n </mat-form-field>\n </div>\n <div *ngIf="[ArgumentTypeResult.ATTRIBUTE, ArgumentTypeResult.TIME_SERIES].includes(mathFunctionConfigForm.get(\'result\').get(\'type\').value)"\n fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutAlign="start" fxLayoutGap.gt-xs="16px" style="padding-top: 16px;">\n <mat-checkbox formControlName="addToBody">\n {{\'tb.rulenode.add-to-message-field-input\' | translate }}\n </mat-checkbox>\n <mat-checkbox formControlName="addToMetadata">\n {{\'tb.rulenode.add-to-metadata-field-input\' | translate}}\n </mat-checkbox>\n </div>\n </div>\n </fieldset>\n</section>\n',styles:[":host ::ng-deep .fields-group{padding:0 16px 8px;margin:10px 0;border:1px groove rgba(0,0,0,.25);border-radius:4px}:host ::ng-deep .fields-group .mat-mdc-form-field .mat-mdc-form-field-infix{width:100%}:host ::ng-deep .fields-group legend{color:#000000b3;width:-moz-fit-content;width:fit-content}:host ::ng-deep .fields-group legend+*{display:block}:host ::ng-deep .fields-group legend+*.no-margin-top{margin-top:0}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Vn extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.messageTypeNames=T,this.eventOptions=[L.CONNECT_EVENT,L.ACTIVITY_EVENT,L.DISCONNECT_EVENT,L.INACTIVITY_EVENT]}configForm(){return this.deviceState}prepareInputConfig(e){return{event:fe(e?.event)?e.event:L.ACTIVITY_EVENT}}onConfigurationSet(e){this.deviceState=this.fb.group({event:[e.event,[O.required]]})}}e("DeviceStateConfigComponent",Vn),Vn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Vn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Vn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Vn,selector:"tb-action-node-device-state-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="deviceState">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label>{{ \'tb.rulenode.select-device-connectivity-event\' | translate }}</mat-label>\n <mat-select formControlName="event">\n <mat-option *ngFor="let eventOption of eventOptions" [value]="eventOption">\n {{ messageTypeNames.get(eventOption) }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n</section>\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Vn,decorators:[{type:n,args:[{selector:"tb-action-node-device-state-config",template:'<section [formGroup]="deviceState">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label>{{ \'tb.rulenode.select-device-connectivity-event\' | translate }}</mat-label>\n <mat-select formControlName="event">\n <mat-option *ngFor="let eventOption of eventOptions" [value]="eventOption">\n {{ messageTypeNames.get(eventOption) }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Pn{constructor(e,t){this.injector=e,this.fb=t,this.propagateChange=()=>{},this.destroy$=new ae,this.disabled=!1,this.uniqueKeyValuePairValidator=!1,this.required=!1,this.duplicateValuesValidator=e=>e.controls.key.value===e.controls.value.value&&e.controls.key.value&&e.controls.value.value?{uniqueKeyValuePair:!0}:null,this.oneMapRequiredValidator=e=>e.get("keyVals").value.length,this.propagateNestedErrors=e=>{if(this.kvListFormGroup&&this.kvListFormGroup.get("keyVals")&&"VALID"===this.kvListFormGroup.get("keyVals")?.status)return null;const t={};if(this.kvListFormGroup&&this.kvListFormGroup.setErrors(null),e instanceof z||e instanceof H){if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;for(const n of Object.keys(e.controls)){const r=this.propagateNestedErrors(e.controls[n]);if(r&&Object.keys(r).length)for(const e of Object.keys(r))t[e]=!0}return t}if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;return ye(t,{})?null:t}}ngOnInit(){this.ngControl=this.injector.get(_),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.kvListFormGroup=this.fb.group({keyVals:this.fb.array([])},{validators:[this.propagateNestedErrors,this.oneMapRequiredValidator]}),this.kvListFormGroup.valueChanges.pipe(ie(this.destroy$)).subscribe((()=>{this.updateModel()}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}keyValsFormArray(){return this.kvListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.kvListFormGroup.disable({emitEvent:!1}):this.kvListFormGroup.enable({emitEvent:!1})}writeValue(e){const t=Object.keys(e).map((t=>({key:t,value:e[t]})));if(this.keyValsFormArray().length===t.length)this.keyValsFormArray().patchValue(t,{emitEvent:!1});else{const e=[];t.forEach((t=>{e.push(this.fb.group({key:[t.key,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],value:[t.value,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]},{validators:this.uniqueKeyValuePairValidator?[this.duplicateValuesValidator]:[]}))})),this.kvListFormGroup.setControl("keyVals",this.fb.array(e,this.propagateNestedErrors),{emitEvent:!1})}}removeKeyVal(e){this.keyValsFormArray().removeAt(e)}addKeyVal(){this.keyValsFormArray().push(this.fb.group({key:["",[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],value:["",[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]},{validators:this.uniqueKeyValuePairValidator?[this.duplicateValuesValidator]:[]}))}validate(){const e=this.kvListFormGroup.get("keyVals").value;if(!e.length&&this.required)return{kvMapRequired:!0};if(!this.kvListFormGroup.valid)return{kvFieldsRequired:!0};if(this.uniqueKeyValuePairValidator)for(const t of e)if(t.key===t.value)return{uniqueKeyValuePair:!0};return null}updateModel(){const e=this.kvListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.kvListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("KvMapConfigComponent",Pn),Pn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Pn,deps:[{token:t.Injector},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Pn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Pn,selector:"tb-kv-map-config",inputs:{disabled:"disabled",uniqueKeyValuePairValidator:"uniqueKeyValuePairValidator",labelText:"labelText",requiredText:"requiredText",keyText:"keyText",keyRequiredText:"keyRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",popupHelpLink:"popupHelpLink",required:"required"},providers:[{provide:B,useExisting:c((()=>Pn)),multi:!0},{provide:K,useExisting:c((()=>Pn)),multi:!0}],ngImport:t,template:'<section [formGroup]="kvListFormGroup" class="tb-form-panel stroked">\n <div class="tb-form-row no-padding no-border space-between">\n <div class="tb-form-panel-title">{{ labelText }}</div>\n <div class="tb-form-panel-hint tb-error" translate *ngIf="kvListFormGroup.hasError(\'kvMapRequired\')">\n {{ requiredText }}\n </div>\n <div class="tb-form-panel-hint tb-error" translate *ngIf="kvListFormGroup.hasError(\'required\')">\n tb.rulenode.map-fields-required\n </div>\n <div class="tb-form-panel-hint tb-error" translate *ngIf="kvListFormGroup.hasError(\'uniqueKeyValuePair\')">\n {{ \'tb.key-val.unique-key-value-pair-error\' | translate:\n {\n valText: valText,\n keyText: keyText\n } }}\n </div>\n </div>\n <div class="tb-form-panel no-border no-padding">\n <div class="tb-form-table">\n <div class="tb-form-table-header">\n <div class="tb-form-table-header-cell field-space">{{ keyText }}</div>\n <div class="tb-form-table-header-cell field-space">{{ valText }}</div>\n <div class="tb-form-table-header-cell actions-header"></div>\n </div>\n <div class="tb-form-table-body">\n <div class="tb-form-table-row"\n *ngFor="let keyValControl of keyValsFormArray().controls; let $index = index;">\n <mat-form-field class="tb-inline-field field-space" appearance="outline" subscriptSizing="dynamic">\n <input [placeholder]="keyText+\'*\'" [formControl]="keyValControl.get(\'key\')" matInput/>\n </mat-form-field>\n <mat-form-field class="tb-inline-field field-space" appearance="outline" subscriptSizing="dynamic">\n <input [placeholder]="valText+\'*\'" [formControl]="keyValControl.get(\'value\')" matInput/>\n </mat-form-field>\n <div class="tb-form-table-row-cell-buttons">\n <button [class.tb-hidden]="keyValsFormArray().controls.length === 1"\n type="button"\n mat-icon-button\n (click)="removeKeyVal($index)"\n [disabled]="disabled"\n matTooltip="{{ \'tb.key-val.remove-mapping-entry\' | translate }}"\n matTooltipPosition="above">\n <mat-icon>delete</mat-icon>\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n <div>\n <button type="button" mat-stroked-button color="primary" (click)="addKeyVal()">\n {{ \'tb.key-val.add-mapping-entry\' | translate }}\n </button>\n </div>\n <tb-example-hint [hintText]="hintText" [popupHelpLink]="popupHelpLink" *ngIf="popupHelpLink || hintText"></tb-example-hint>\n</section>\n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),Qe([I()],Pn.prototype,"disabled",void 0),Qe([I()],Pn.prototype,"uniqueKeyValuePairValidator",void 0),Qe([I()],Pn.prototype,"required",void 0),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Pn,decorators:[{type:n,args:[{selector:"tb-kv-map-config",providers:[{provide:B,useExisting:c((()=>Pn)),multi:!0},{provide:K,useExisting:c((()=>Pn)),multi:!0}],template:'<section [formGroup]="kvListFormGroup" class="tb-form-panel stroked">\n <div class="tb-form-row no-padding no-border space-between">\n <div class="tb-form-panel-title">{{ labelText }}</div>\n <div class="tb-form-panel-hint tb-error" translate *ngIf="kvListFormGroup.hasError(\'kvMapRequired\')">\n {{ requiredText }}\n </div>\n <div class="tb-form-panel-hint tb-error" translate *ngIf="kvListFormGroup.hasError(\'required\')">\n tb.rulenode.map-fields-required\n </div>\n <div class="tb-form-panel-hint tb-error" translate *ngIf="kvListFormGroup.hasError(\'uniqueKeyValuePair\')">\n {{ \'tb.key-val.unique-key-value-pair-error\' | translate:\n {\n valText: valText,\n keyText: keyText\n } }}\n </div>\n </div>\n <div class="tb-form-panel no-border no-padding">\n <div class="tb-form-table">\n <div class="tb-form-table-header">\n <div class="tb-form-table-header-cell field-space">{{ keyText }}</div>\n <div class="tb-form-table-header-cell field-space">{{ valText }}</div>\n <div class="tb-form-table-header-cell actions-header"></div>\n </div>\n <div class="tb-form-table-body">\n <div class="tb-form-table-row"\n *ngFor="let keyValControl of keyValsFormArray().controls; let $index = index;">\n <mat-form-field class="tb-inline-field field-space" appearance="outline" subscriptSizing="dynamic">\n <input [placeholder]="keyText+\'*\'" [formControl]="keyValControl.get(\'key\')" matInput/>\n </mat-form-field>\n <mat-form-field class="tb-inline-field field-space" appearance="outline" subscriptSizing="dynamic">\n <input [placeholder]="valText+\'*\'" [formControl]="keyValControl.get(\'value\')" matInput/>\n </mat-form-field>\n <div class="tb-form-table-row-cell-buttons">\n <button [class.tb-hidden]="keyValsFormArray().controls.length === 1"\n type="button"\n mat-icon-button\n (click)="removeKeyVal($index)"\n [disabled]="disabled"\n matTooltip="{{ \'tb.key-val.remove-mapping-entry\' | translate }}"\n matTooltipPosition="above">\n <mat-icon>delete</mat-icon>\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n <div>\n <button type="button" mat-stroked-button color="primary" (click)="addKeyVal()">\n {{ \'tb.key-val.add-mapping-entry\' | translate }}\n </button>\n </div>\n <tb-example-hint [hintText]="hintText" [popupHelpLink]="popupHelpLink" *ngIf="popupHelpLink || hintText"></tb-example-hint>\n</section>\n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:t.Injector},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:m}],uniqueKeyValuePairValidator:[{type:m}],labelText:[{type:m}],requiredText:[{type:m}],keyText:[{type:m}],keyRequiredText:[{type:m}],valText:[{type:m}],valRequiredText:[{type:m}],hintText:[{type:m}],popupHelpLink:[{type:m}],required:[{type:m}]}});class Rn extends k{get required(){return this.requiredValue}set required(e){this.requiredValue=Ee(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.values(v),this.directionTypeTranslations=N,this.entityType=C,this.propagateChange=null}ngOnInit(){this.deviceRelationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[O.required]],maxLevel:[null,[O.min(1)]],relationType:[null],deviceTypes:[null,[O.required]]}),this.deviceRelationsQueryFormGroup.valueChanges.subscribe((e=>{this.deviceRelationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.deviceRelationsQueryFormGroup.disable({emitEvent:!1}):this.deviceRelationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.deviceRelationsQueryFormGroup.reset(e,{emitEvent:!1})}}e("DeviceRelationsQueryConfigComponent",Rn),Rn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Rn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Rn,selector:"tb-device-relations-query-config",inputs:{disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:c((()=>Rn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'<section fxLayout="column" [formGroup]="deviceRelationsQueryFormGroup">\n <div fxLayoutGap="22px" fxLayout="row">\n <mat-form-field class="mat-block" subscriptSizing="dynamic" fxFlex="50" style="min-width: 100px;" hideRequiredMarker>\n <mat-label translate>relation.direction</mat-label>\n <mat-select required formControlName="direction">\n <mat-option *ngFor="let type of directionTypes" [value]="type">\n {{ directionTypeTranslations.get(type) | translate }} <span translate>tb.rulenode.relations-query-config-direction-suffix</span>\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field fxFlex="50" floatLabel="always" class="mat-block">\n <mat-label translate>tb.rulenode.max-relation-level</mat-label>\n <input matInput\n type="number"\n min="1"\n step="1"\n placeholder="{{ \'tb.rulenode.unlimited-level\' | translate }}"\n formControlName="maxLevel">\n <mat-error *ngIf="deviceRelationsQueryFormGroup.get(\'maxLevel\').hasError(\'min\')">\n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.last-level-device-relation-tooltip\' | translate }}"\n *ngIf="deviceRelationsQueryFormGroup.get(\'maxLevel\').value > 1"\n class="tb-form-row no-border no-padding last-level-slide-toggle">\n <mat-slide-toggle class="mat-slide" formControlName="fetchLastLevelOnly">\n {{ \'alias.last-level-relation\' | translate }}\n </mat-slide-toggle>\n </div>\n <tb-relation-type-autocomplete\n fxFlex\n formControlName="relationType">\n </tb-relation-type-autocomplete>\n <tb-entity-subtype-list\n required\n [label]="\'tb.rulenode.device-profiles\' | translate"\n [entityType]="entityType.DEVICE"\n [emptyInputPlaceholder]="\'tb.rulenode.add-device-profile\' | translate"\n [filledInputPlaceholder]="\'tb.rulenode.add-device-profile\' | translate"\n formControlName="deviceTypes">\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon" color="primary"\n matTooltip="{{ \'tb.rulenode.chip-help\' | translate: { inputName: \'tb.rulenode.device-profile\' | translate } }}">help</mat-icon>\n </tb-entity-subtype-list>\n</section>\n',styles:[":host .last-level-slide-toggle{margin:8px 0 24px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ye.EntitySubTypeListComponent,selector:"tb-entity-subtype-list",inputs:["required","floatLabel","label","disabled","entityType","emptyInputPlaceholder","filledInputPlaceholder","appearance","subscriptSizing","additionalClasses"]},{kind:"component",type:Se.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rn,decorators:[{type:n,args:[{selector:"tb-device-relations-query-config",providers:[{provide:B,useExisting:c((()=>Rn)),multi:!0}],template:'<section fxLayout="column" [formGroup]="deviceRelationsQueryFormGroup">\n <div fxLayoutGap="22px" fxLayout="row">\n <mat-form-field class="mat-block" subscriptSizing="dynamic" fxFlex="50" style="min-width: 100px;" hideRequiredMarker>\n <mat-label translate>relation.direction</mat-label>\n <mat-select required formControlName="direction">\n <mat-option *ngFor="let type of directionTypes" [value]="type">\n {{ directionTypeTranslations.get(type) | translate }} <span translate>tb.rulenode.relations-query-config-direction-suffix</span>\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field fxFlex="50" floatLabel="always" class="mat-block">\n <mat-label translate>tb.rulenode.max-relation-level</mat-label>\n <input matInput\n type="number"\n min="1"\n step="1"\n placeholder="{{ \'tb.rulenode.unlimited-level\' | translate }}"\n formControlName="maxLevel">\n <mat-error *ngIf="deviceRelationsQueryFormGroup.get(\'maxLevel\').hasError(\'min\')">\n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.last-level-device-relation-tooltip\' | translate }}"\n *ngIf="deviceRelationsQueryFormGroup.get(\'maxLevel\').value > 1"\n class="tb-form-row no-border no-padding last-level-slide-toggle">\n <mat-slide-toggle class="mat-slide" formControlName="fetchLastLevelOnly">\n {{ \'alias.last-level-relation\' | translate }}\n </mat-slide-toggle>\n </div>\n <tb-relation-type-autocomplete\n fxFlex\n formControlName="relationType">\n </tb-relation-type-autocomplete>\n <tb-entity-subtype-list\n required\n [label]="\'tb.rulenode.device-profiles\' | translate"\n [entityType]="entityType.DEVICE"\n [emptyInputPlaceholder]="\'tb.rulenode.add-device-profile\' | translate"\n [filledInputPlaceholder]="\'tb.rulenode.add-device-profile\' | translate"\n formControlName="deviceTypes">\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon" color="primary"\n matTooltip="{{ \'tb.rulenode.chip-help\' | translate: { inputName: \'tb.rulenode.device-profile\' | translate } }}">help</mat-icon>\n </tb-entity-subtype-list>\n</section>\n',styles:[":host .last-level-slide-toggle{margin:8px 0 24px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:m}],required:[{type:m}]}});class On extends k{get required(){return this.requiredValue}set required(e){this.requiredValue=Ee(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.values(v),this.directionTypeTranslations=N,this.propagateChange=null}ngOnInit(){this.relationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[O.required]],maxLevel:[null,[O.min(1)]],filters:[null]}),this.relationsQueryFormGroup.valueChanges.subscribe((e=>{this.relationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.relationsQueryFormGroup.disable({emitEvent:!1}):this.relationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.relationsQueryFormGroup.reset(e||{},{emitEvent:!1})}}e("RelationsQueryConfigComponent",On),On.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:On,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),On.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:On,selector:"tb-relations-query-config",inputs:{disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:c((()=>On)),multi:!0}],usesInheritance:!0,ngImport:t,template:'<section [formGroup]="relationsQueryFormGroup" class="tb-form-panel stroked">\n <div class="tb-form-panel-title tb-required" translate>tb.rulenode.relations-query</div>\n <section>\n <div fxLayoutGap="16px" fxLayout="row">\n <mat-form-field fxFlex="50" class="mat-block" style="min-width: 100px;" hideRequiredMarker>\n <mat-label translate>relation.direction</mat-label>\n <mat-select required formControlName="direction">\n <mat-option *ngFor="let type of directionTypes" [value]="type">\n {{ directionTypeTranslations.get(type) | translate }} <span translate>tb.rulenode.relations-query-config-direction-suffix</span>\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field fxFlex="50" floatLabel="always" class="mat-block">\n <mat-label translate>tb.rulenode.max-relation-level</mat-label>\n <input matInput\n type="number"\n min="1"\n step="1"\n placeholder="{{ \'tb.rulenode.unlimited-level\' | translate }}"\n formControlName="maxLevel">\n <mat-error *ngIf="relationsQueryFormGroup.get(\'maxLevel\').hasError(\'min\')">\n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.last-level-relation-tooltip\' | translate }}"\n *ngIf="relationsQueryFormGroup.get(\'maxLevel\').value > 1"\n class="tb-form-row no-border no-padding last-level-slide-toggle">\n <mat-slide-toggle class="mat-slide" formControlName="fetchLastLevelOnly">\n {{ \'alias.last-level-relation\' | translate }}\n </mat-slide-toggle>\n </div>\n </section>\n <section [formGroup]="relationsQueryFormGroup" class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>relation.relation-filters</div>\n <tb-relation-filters\n formControlName="filters">\n </tb-relation-filters>\n </section>\n</section>\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:We.RelationFiltersComponent,selector:"tb-relation-filters",inputs:["disabled","allowedEntityTypes"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:On,decorators:[{type:n,args:[{selector:"tb-relations-query-config",providers:[{provide:B,useExisting:c((()=>On)),multi:!0}],template:'<section [formGroup]="relationsQueryFormGroup" class="tb-form-panel stroked">\n <div class="tb-form-panel-title tb-required" translate>tb.rulenode.relations-query</div>\n <section>\n <div fxLayoutGap="16px" fxLayout="row">\n <mat-form-field fxFlex="50" class="mat-block" style="min-width: 100px;" hideRequiredMarker>\n <mat-label translate>relation.direction</mat-label>\n <mat-select required formControlName="direction">\n <mat-option *ngFor="let type of directionTypes" [value]="type">\n {{ directionTypeTranslations.get(type) | translate }} <span translate>tb.rulenode.relations-query-config-direction-suffix</span>\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field fxFlex="50" floatLabel="always" class="mat-block">\n <mat-label translate>tb.rulenode.max-relation-level</mat-label>\n <input matInput\n type="number"\n min="1"\n step="1"\n placeholder="{{ \'tb.rulenode.unlimited-level\' | translate }}"\n formControlName="maxLevel">\n <mat-error *ngIf="relationsQueryFormGroup.get(\'maxLevel\').hasError(\'min\')">\n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.last-level-relation-tooltip\' | translate }}"\n *ngIf="relationsQueryFormGroup.get(\'maxLevel\').value > 1"\n class="tb-form-row no-border no-padding last-level-slide-toggle">\n <mat-slide-toggle class="mat-slide" formControlName="fetchLastLevelOnly">\n {{ \'alias.last-level-relation\' | translate }}\n </mat-slide-toggle>\n </div>\n </section>\n <section [formGroup]="relationsQueryFormGroup" class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>relation.relation-filters</div>\n <tb-relation-filters\n formControlName="filters">\n </tb-relation-filters>\n </section>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:m}],required:[{type:m}]}});class _n extends k{get required(){return this.requiredValue}set required(e){this.requiredValue=Ee(e)}constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.truncate=n,this.fb=r,this.placeholder="tb.rulenode.add-message-type",this.separatorKeysCodes=[Fe,ke,Te],this.messageTypes=[],this.messageTypesList=[],this.searchText="",this.propagateChange=e=>{},this.messageTypeConfigForm=this.fb.group({messageType:[null]});for(const e of Object.keys(L))this.messageTypesList.push({name:T.get(L[e]),value:e})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}ngOnInit(){this.filteredMessageTypes=this.messageTypeConfigForm.get("messageType").valueChanges.pipe(Be(""),_e((e=>e||"")),Ke((e=>this.fetchMessageTypes(e))),ze())}setDisabledState(e){this.disabled=e,this.disabled?this.messageTypeConfigForm.disable({emitEvent:!1}):this.messageTypeConfigForm.enable({emitEvent:!1})}writeValue(e){this.searchText="",this.messageTypes.length=0,e&&e.forEach((e=>{const t=this.messageTypesList.find((t=>t.value===e));t?this.messageTypes.push({name:t.name,value:t.value}):this.messageTypes.push({name:e,value:e})}))}displayMessageTypeFn(e){return e?e.name:void 0}textIsNotEmpty(e){return e&&e.length>0}createMessageType(e,t){e.preventDefault(),this.transformMessageType(t)}add(e){this.transformMessageType(e.value)}fetchMessageTypes(e){if(this.searchText=e,this.searchText&&this.searchText.length){const e=this.searchText.toUpperCase();return le(this.messageTypesList.filter((t=>t.name.toUpperCase().includes(e))))}return le(this.messageTypesList)}transformMessageType(e){if((e||"").trim()){let t;const n=e.trim(),r=this.messageTypesList.find((e=>e.name===n));t=r?{name:r.name,value:r.value}:{name:n,value:n},t&&this.addMessageType(t)}this.clear("")}remove(e){const t=this.messageTypes.indexOf(e);t>=0&&(this.messageTypes.splice(t,1),this.updateModel())}selected(e){this.addMessageType(e.option.value),this.clear("")}addMessageType(e){-1===this.messageTypes.findIndex((t=>t.value===e.value))&&(this.messageTypes.push(e),this.updateModel())}onFocus(){this.messageTypeConfigForm.get("messageType").updateValueAndValidity({onlySelf:!0,emitEvent:!0})}clear(e=""){this.messageTypeInput.nativeElement.value=e,this.messageTypeConfigForm.get("messageType").patchValue(null,{emitEvent:!0}),setTimeout((()=>{this.messageTypeInput.nativeElement.blur(),this.messageTypeInput.nativeElement.focus()}),0)}updateModel(){const e=this.messageTypes.map((e=>e.value));this.required?(this.chipList.errorState=!e.length,this.propagateChange(e.length>0?e:null)):(this.chipList.errorState=!1,this.propagateChange(e))}}e("MessageTypesConfigComponent",_n),_n.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_n,deps:[{token:P.Store},{token:Z.TranslateService},{token:S.TruncatePipe},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),_n.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:_n,selector:"tb-message-types-config",inputs:{required:"required",label:"label",placeholder:"placeholder",disabled:"disabled"},providers:[{provide:B,useExisting:c((()=>_n)),multi:!0}],viewQueries:[{propertyName:"chipList",first:!0,predicate:["chipList"],descendants:!0},{propertyName:"matAutocomplete",first:!0,predicate:["messageTypeAutocomplete"],descendants:!0},{propertyName:"messageTypeInput",first:!0,predicate:["messageTypeInput"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'<mat-form-field [formGroup]="messageTypeConfigForm" style="width: 100%;">\n <mat-label *ngIf="label">{{ label }}</mat-label>\n <mat-chip-grid #chipList [required]="required">\n <mat-chip-row\n *ngFor="let messageType of messageTypes"\n [removable]="true"\n (removed)="remove(messageType)">\n {{messageType.name}}\n <mat-icon matChipRemove>close</mat-icon>\n </mat-chip-row>\n <input matInput type="text" placeholder="{{ placeholder | translate }}"\n #messageTypeInput\n (focusin)="onFocus()"\n formControlName="messageType"\n matAutocompleteOrigin\n #origin="matAutocompleteOrigin"\n [matAutocompleteConnectedTo]="origin"\n [matAutocomplete]="messageTypeAutocomplete"\n [matChipInputFor]="chipList"\n [matChipInputSeparatorKeyCodes]="separatorKeysCodes"\n (matChipInputTokenEnd)="add($event)">\n </mat-chip-grid>\n <mat-autocomplete #messageTypeAutocomplete="matAutocomplete"\n class="tb-autocomplete"\n (optionSelected)="selected($event)"\n [displayWith]="displayMessageTypeFn">\n <mat-option *ngFor="let messageType of filteredMessageTypes | async" [value]="messageType">\n <span [innerHTML]="messageType.name | highlight:searchText"></span>\n </mat-option>\n <mat-option *ngIf="(filteredMessageTypes | async)?.length === 0" [value]="null" class="tb-not-found">\n <div class="tb-not-found-content" (click)="$event.stopPropagation()">\n <div *ngIf="!textIsNotEmpty(searchText); else searchNotEmpty">\n <span translate>tb.rulenode.no-message-types-found</span>\n </div>\n <ng-template #searchNotEmpty>\n <span>\n {{ \'tb.rulenode.no-message-type-matching\' | translate :\n {messageType: truncate.transform(searchText, true, 6, &apos;...&apos;)}\n }}\n </span>\n </ng-template>\n <span>\n <a translate (click)="createMessageType($event, searchText)">tb.rulenode.create-new-message-type</a>\n </span>\n </div>\n </mat-option>\n </mat-autocomplete>\n <mat-icon class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon" matSuffix\n color="primary"\n matTooltip="{{ \'tb.rulenode.chip-help\' | translate: { inputName: \'tb.rulenode.message-type\' | translate } }}">help</mat-icon>\n <mat-error *ngIf="chipList.errorState">\n {{ \'tb.rulenode.select-message-types-required\' | translate }}\n </mat-error>\n</mat-form-field>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:je.MatAutocomplete,selector:"mat-autocomplete",inputs:["disableRipple","hideSingleSelectionIndicator"],exportAs:["matAutocomplete"]},{kind:"directive",type:je.MatAutocompleteTrigger,selector:"input[matAutocomplete], textarea[matAutocomplete]",exportAs:["matAutocompleteTrigger"]},{kind:"directive",type:je.MatAutocompleteOrigin,selector:"[matAutocompleteOrigin]",exportAs:["matAutocompleteOrigin"]},{kind:"component",type:Ie.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:Ie.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:Ie.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:Ie.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:U.AsyncPipe,name:"async"},{kind:"pipe",type:$e.HighlightPipe,name:"highlight"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_n,decorators:[{type:n,args:[{selector:"tb-message-types-config",providers:[{provide:B,useExisting:c((()=>_n)),multi:!0}],template:'<mat-form-field [formGroup]="messageTypeConfigForm" style="width: 100%;">\n <mat-label *ngIf="label">{{ label }}</mat-label>\n <mat-chip-grid #chipList [required]="required">\n <mat-chip-row\n *ngFor="let messageType of messageTypes"\n [removable]="true"\n (removed)="remove(messageType)">\n {{messageType.name}}\n <mat-icon matChipRemove>close</mat-icon>\n </mat-chip-row>\n <input matInput type="text" placeholder="{{ placeholder | translate }}"\n #messageTypeInput\n (focusin)="onFocus()"\n formControlName="messageType"\n matAutocompleteOrigin\n #origin="matAutocompleteOrigin"\n [matAutocompleteConnectedTo]="origin"\n [matAutocomplete]="messageTypeAutocomplete"\n [matChipInputFor]="chipList"\n [matChipInputSeparatorKeyCodes]="separatorKeysCodes"\n (matChipInputTokenEnd)="add($event)">\n </mat-chip-grid>\n <mat-autocomplete #messageTypeAutocomplete="matAutocomplete"\n class="tb-autocomplete"\n (optionSelected)="selected($event)"\n [displayWith]="displayMessageTypeFn">\n <mat-option *ngFor="let messageType of filteredMessageTypes | async" [value]="messageType">\n <span [innerHTML]="messageType.name | highlight:searchText"></span>\n </mat-option>\n <mat-option *ngIf="(filteredMessageTypes | async)?.length === 0" [value]="null" class="tb-not-found">\n <div class="tb-not-found-content" (click)="$event.stopPropagation()">\n <div *ngIf="!textIsNotEmpty(searchText); else searchNotEmpty">\n <span translate>tb.rulenode.no-message-types-found</span>\n </div>\n <ng-template #searchNotEmpty>\n <span>\n {{ \'tb.rulenode.no-message-type-matching\' | translate :\n {messageType: truncate.transform(searchText, true, 6, &apos;...&apos;)}\n }}\n </span>\n </ng-template>\n <span>\n <a translate (click)="createMessageType($event, searchText)">tb.rulenode.create-new-message-type</a>\n </span>\n </div>\n </mat-option>\n </mat-autocomplete>\n <mat-icon class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon" matSuffix\n color="primary"\n matTooltip="{{ \'tb.rulenode.chip-help\' | translate: { inputName: \'tb.rulenode.message-type\' | translate } }}">help</mat-icon>\n <mat-error *ngIf="chipList.errorState">\n {{ \'tb.rulenode.select-message-types-required\' | translate }}\n </mat-error>\n</mat-form-field>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:S.TruncatePipe},{type:R.FormBuilder}]},propDecorators:{required:[{type:m}],label:[{type:m}],placeholder:[{type:m}],disabled:[{type:m}],chipList:[{type:u,args:["chipList",{static:!1}]}],matAutocomplete:[{type:u,args:["messageTypeAutocomplete",{static:!1}]}],messageTypeInput:[{type:u,args:["messageTypeInput",{static:!1}]}]}});class Bn extends k{get required(){return this.requiredValue}set required(e){this.requiredValue=Ee(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.subscriptions=[],this.disableCertPemCredentials=!1,this.passwordFieldRequired=!0,this.allCredentialsTypes=Qt,this.credentialsTypeTranslationsMap=Yt,this.propagateChange=e=>{}}ngOnInit(){this.credentialsConfigFormGroup=this.fb.group({type:[null,[O.required]],username:[null,[]],password:[null,[]],caCert:[null,[]],caCertFileName:[null,[]],privateKey:[null,[]],privateKeyFileName:[null,[]],cert:[null,[]],certFileName:[null,[]]}),this.subscriptions.push(this.credentialsConfigFormGroup.valueChanges.subscribe((()=>{this.updateView()}))),this.subscriptions.push(this.credentialsConfigFormGroup.get("type").valueChanges.subscribe((()=>{this.credentialsTypeChanged()})))}ngOnChanges(e){for(const t of Object.keys(e)){const n=e[t];if(!n.firstChange&&n.currentValue!==n.previousValue&&n.currentValue&&"disableCertPemCredentials"===t){"cert.PEM"===this.credentialsConfigFormGroup.get("type").value&&setTimeout((()=>{this.credentialsConfigFormGroup.get("type").patchValue("anonymous",{emitEvent:!0})}))}}}ngOnDestroy(){this.subscriptions.forEach((e=>e.unsubscribe()))}writeValue(e){fe(e)&&(this.credentialsConfigFormGroup.reset(e,{emitEvent:!1}),this.updateValidators())}setDisabledState(e){e?this.credentialsConfigFormGroup.disable({emitEvent:!1}):(this.credentialsConfigFormGroup.enable({emitEvent:!1}),this.updateValidators())}updateView(){let e=this.credentialsConfigFormGroup.value;const t=e.type;switch(t){case"anonymous":e={type:t};break;case"basic":e={type:t,username:e.username,password:e.password};break;case"cert.PEM":delete e.username}this.propagateChange(e)}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}validate(e){return this.credentialsConfigFormGroup.valid?null:{credentialsConfig:{valid:!1}}}credentialsTypeChanged(){this.credentialsConfigFormGroup.patchValue({username:null,password:null,caCert:null,caCertFileName:null,privateKey:null,privateKeyFileName:null,cert:null,certFileName:null}),this.updateValidators()}updateValidators(e=!1){const t=this.credentialsConfigFormGroup.get("type").value;switch(e&&this.credentialsConfigFormGroup.reset({type:t},{emitEvent:!1}),this.credentialsConfigFormGroup.setValidators([]),this.credentialsConfigFormGroup.get("username").setValidators([]),this.credentialsConfigFormGroup.get("password").setValidators([]),t){case"anonymous":break;case"basic":this.credentialsConfigFormGroup.get("username").setValidators([O.required]),this.credentialsConfigFormGroup.get("password").setValidators(this.passwordFieldRequired?[O.required]:[]);break;case"cert.PEM":this.credentialsConfigFormGroup.setValidators([this.requiredFilesSelected(O.required,[["caCert","caCertFileName"],["privateKey","privateKeyFileName","cert","certFileName"]])])}this.credentialsConfigFormGroup.get("username").updateValueAndValidity({emitEvent:e}),this.credentialsConfigFormGroup.get("password").updateValueAndValidity({emitEvent:e}),this.credentialsConfigFormGroup.updateValueAndValidity({emitEvent:e})}requiredFilesSelected(e,t=null){return n=>{t||(t=[Object.keys(n.controls)]);return n?.controls&&t.some((t=>t.every((t=>!e(n.controls[t])))))?null:{notAllRequiredFilesSelected:!0}}}}e("CredentialsConfigComponent",Bn),Bn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Bn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Bn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Bn,selector:"tb-credentials-config",inputs:{required:"required",disableCertPemCredentials:"disableCertPemCredentials",passwordFieldRequired:"passwordFieldRequired"},providers:[{provide:B,useExisting:c((()=>Bn)),multi:!0},{provide:K,useExisting:c((()=>Bn)),multi:!0}],usesInheritance:!0,usesOnChanges:!0,ngImport:t,template:'<section [formGroup]="credentialsConfigFormGroup" fxLayout="column">\n <mat-expansion-panel class="tb-credentials-config-panel-group">\n <mat-expansion-panel-header>\n <mat-panel-title translate>tb.rulenode.credentials</mat-panel-title>\n <mat-panel-description>\n {{ credentialsTypeTranslationsMap.get(credentialsConfigFormGroup.get(\'type\').value) | translate }}\n </mat-panel-description>\n </mat-expansion-panel-header>\n <ng-template matExpansionPanelContent>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.credentials-type</mat-label>\n <mat-select formControlName="type" required>\n <mat-option *ngFor="let credentialsType of allCredentialsTypes" [value]="credentialsType"\n [disabled]="credentialsType === \'cert.PEM\' && disableCertPemCredentials">\n {{ credentialsTypeTranslationsMap.get(credentialsType) | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf="credentialsConfigFormGroup.get(\'type\').hasError(\'required\')">\n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <section fxLayout="column" [ngSwitch]="credentialsConfigFormGroup.get(\'type\').value">\n <ng-template ngSwitchCase="anonymous">\n </ng-template>\n <ng-template ngSwitchCase="basic">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.username</mat-label>\n <input required matInput formControlName="username">\n <mat-error *ngIf="credentialsConfigFormGroup.get(\'username\').hasError(\'required\')">\n {{ \'tb.rulenode.username-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.password</mat-label>\n <input type="password" [required]="passwordFieldRequired" matInput formControlName="password">\n <tb-toggle-password matSuffix></tb-toggle-password>\n <mat-error *ngIf="credentialsConfigFormGroup.get(\'password\').hasError(\'required\')">\n {{ \'tb.rulenode.password-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </ng-template>\n <ng-template ngSwitchCase="cert.PEM">\n <div class="tb-hint">{{ \'tb.rulenode.credentials-pem-hint\' | translate }}</div>\n <tb-file-input formControlName="caCert"\n inputId="caCertSelect"\n [existingFileName]="credentialsConfigFormGroup.get(\'caCertFileName\').value"\n (fileNameChanged)="credentialsConfigFormGroup.get(\'caCertFileName\').setValue($event)"\n label="{{\'tb.rulenode.ca-cert\' | translate}}"\n noFileText="tb.rulenode.no-file"\n dropLabel="{{\'tb.rulenode.drop-file\' | translate}}">\n </tb-file-input>\n <tb-file-input formControlName="cert"\n inputId="CertSelect"\n [existingFileName]="credentialsConfigFormGroup.get(\'certFileName\').value"\n (fileNameChanged)="credentialsConfigFormGroup.get(\'certFileName\').setValue($event)"\n label="{{\'tb.rulenode.cert\' | translate}}"\n noFileText="tb.rulenode.no-file"\n dropLabel="{{\'tb.rulenode.drop-file\' | translate}}">\n </tb-file-input>\n <tb-file-input style="padding-bottom: 8px;"\n formControlName="privateKey"\n inputId="privateKeySelect"\n [existingFileName]="credentialsConfigFormGroup.get(\'privateKeyFileName\').value"\n (fileNameChanged)="credentialsConfigFormGroup.get(\'privateKeyFileName\').setValue($event)"\n label="{{\'tb.rulenode.private-key\' | translate}}"\n noFileText="tb.rulenode.no-file"\n dropLabel="{{\'tb.rulenode.drop-file\' | translate}}">\n </tb-file-input>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.private-key-password</mat-label>\n <input type="password" matInput formControlName="password">\n <tb-toggle-password matSuffix></tb-toggle-password>\n </mat-form-field>\n </ng-template>\n </section>\n </ng-template>\n </mat-expansion-panel>\n</section>\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:U.NgSwitch,selector:"[ngSwitch]",inputs:["ngSwitch"]},{kind:"directive",type:U.NgSwitchCase,selector:"[ngSwitchCase]",inputs:["ngSwitchCase"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:oe.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:oe.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:oe.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:oe.MatExpansionPanelDescription,selector:"mat-panel-description"},{kind:"directive",type:oe.MatExpansionPanelContent,selector:"ng-template[matExpansionPanelContent]"},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ze.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Xe.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Bn,decorators:[{type:n,args:[{selector:"tb-credentials-config",providers:[{provide:B,useExisting:c((()=>Bn)),multi:!0},{provide:K,useExisting:c((()=>Bn)),multi:!0}],template:'<section [formGroup]="credentialsConfigFormGroup" fxLayout="column">\n <mat-expansion-panel class="tb-credentials-config-panel-group">\n <mat-expansion-panel-header>\n <mat-panel-title translate>tb.rulenode.credentials</mat-panel-title>\n <mat-panel-description>\n {{ credentialsTypeTranslationsMap.get(credentialsConfigFormGroup.get(\'type\').value) | translate }}\n </mat-panel-description>\n </mat-expansion-panel-header>\n <ng-template matExpansionPanelContent>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.credentials-type</mat-label>\n <mat-select formControlName="type" required>\n <mat-option *ngFor="let credentialsType of allCredentialsTypes" [value]="credentialsType"\n [disabled]="credentialsType === \'cert.PEM\' && disableCertPemCredentials">\n {{ credentialsTypeTranslationsMap.get(credentialsType) | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf="credentialsConfigFormGroup.get(\'type\').hasError(\'required\')">\n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <section fxLayout="column" [ngSwitch]="credentialsConfigFormGroup.get(\'type\').value">\n <ng-template ngSwitchCase="anonymous">\n </ng-template>\n <ng-template ngSwitchCase="basic">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.username</mat-label>\n <input required matInput formControlName="username">\n <mat-error *ngIf="credentialsConfigFormGroup.get(\'username\').hasError(\'required\')">\n {{ \'tb.rulenode.username-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.password</mat-label>\n <input type="password" [required]="passwordFieldRequired" matInput formControlName="password">\n <tb-toggle-password matSuffix></tb-toggle-password>\n <mat-error *ngIf="credentialsConfigFormGroup.get(\'password\').hasError(\'required\')">\n {{ \'tb.rulenode.password-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </ng-template>\n <ng-template ngSwitchCase="cert.PEM">\n <div class="tb-hint">{{ \'tb.rulenode.credentials-pem-hint\' | translate }}</div>\n <tb-file-input formControlName="caCert"\n inputId="caCertSelect"\n [existingFileName]="credentialsConfigFormGroup.get(\'caCertFileName\').value"\n (fileNameChanged)="credentialsConfigFormGroup.get(\'caCertFileName\').setValue($event)"\n label="{{\'tb.rulenode.ca-cert\' | translate}}"\n noFileText="tb.rulenode.no-file"\n dropLabel="{{\'tb.rulenode.drop-file\' | translate}}">\n </tb-file-input>\n <tb-file-input formControlName="cert"\n inputId="CertSelect"\n [existingFileName]="credentialsConfigFormGroup.get(\'certFileName\').value"\n (fileNameChanged)="credentialsConfigFormGroup.get(\'certFileName\').setValue($event)"\n label="{{\'tb.rulenode.cert\' | translate}}"\n noFileText="tb.rulenode.no-file"\n dropLabel="{{\'tb.rulenode.drop-file\' | translate}}">\n </tb-file-input>\n <tb-file-input style="padding-bottom: 8px;"\n formControlName="privateKey"\n inputId="privateKeySelect"\n [existingFileName]="credentialsConfigFormGroup.get(\'privateKeyFileName\').value"\n (fileNameChanged)="credentialsConfigFormGroup.get(\'privateKeyFileName\').setValue($event)"\n label="{{\'tb.rulenode.private-key\' | translate}}"\n noFileText="tb.rulenode.no-file"\n dropLabel="{{\'tb.rulenode.drop-file\' | translate}}">\n </tb-file-input>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.private-key-password</mat-label>\n <input type="password" matInput formControlName="password">\n <tb-toggle-password matSuffix></tb-toggle-password>\n </mat-form-field>\n </ng-template>\n </section>\n </ng-template>\n </mat-expansion-panel>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{required:[{type:m}],disableCertPemCredentials:[{type:m}],passwordFieldRequired:[{type:m}]}});class Kn{set required(e){this.requiredValue!==e&&(this.requiredValue=e,this.updateValidators())}get required(){return this.requiredValue}constructor(e){this.fb=e,this.subscriptSizing="fixed",this.messageTypes=[{name:"Post attributes",value:"POST_ATTRIBUTES_REQUEST"},{name:"Post telemetry",value:"POST_TELEMETRY_REQUEST"},{name:"Custom",value:""}],this.propagateChange=()=>{},this.destroy$=new ae,this.messageTypeFormGroup=this.fb.group({messageTypeAlias:[null,[O.required]],messageType:[{value:null,disabled:!0},[O.maxLength(255)]]}),this.messageTypeFormGroup.get("messageTypeAlias").valueChanges.pipe(ie(this.destroy$)).subscribe((e=>this.updateMessageTypeValue(e))),this.messageTypeFormGroup.valueChanges.pipe(ie(this.destroy$)).subscribe((()=>this.updateView()))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}registerOnTouched(e){}registerOnChange(e){this.propagateChange=e}writeValue(e){this.modelValue=e;let t=this.messageTypes.find((t=>t.value===e));t||(t=this.messageTypes.find((e=>""===e.value))),this.messageTypeFormGroup.get("messageTypeAlias").patchValue(t,{emitEvent:!1}),this.messageTypeFormGroup.get("messageType").patchValue(e,{emitEvent:!1})}validate(){return this.messageTypeFormGroup.valid?null:{messageTypeInvalid:!0}}setDisabledState(e){this.disabled=e,e?this.messageTypeFormGroup.disable({emitEvent:!1}):(this.messageTypeFormGroup.enable({emitEvent:!1}),"Custom"!==this.messageTypeFormGroup.get("messageTypeAlias").value?.name&&this.messageTypeFormGroup.get("messageType").disable({emitEvent:!1}))}updateView(){const e=this.messageTypeFormGroup.getRawValue().messageType;this.modelValue!==e&&(this.modelValue=e,this.propagateChange(this.modelValue))}updateValidators(){this.messageTypeFormGroup.get("messageType").setValidators(this.required?[O.required,O.maxLength(255)]:[O.maxLength(255)]),this.messageTypeFormGroup.get("messageType").updateValueAndValidity({emitEvent:!1})}updateMessageTypeValue(e){"Custom"!==e?.name?this.messageTypeFormGroup.get("messageType").disable({emitEvent:!1}):this.messageTypeFormGroup.get("messageType").enable({emitEvent:!1}),this.messageTypeFormGroup.get("messageType").patchValue(e.value??null)}}e("OutputMessageTypeAutocompleteComponent",Kn),Kn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kn,deps:[{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Kn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Kn,selector:"tb-output-message-type-autocomplete",inputs:{subscriptSizing:"subscriptSizing",disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:c((()=>Kn)),multi:!0},{provide:K,useExisting:c((()=>Kn)),multi:!0}],ngImport:t,template:'<section class="tb-form-row no-border no-padding tb-standard-fields column-xs" [formGroup]="messageTypeFormGroup">\n <mat-form-field class="flex" subscriptSizing="{{ subscriptSizing }}" hideRequiredMarker>\n <mat-label>{{\'tb.rulenode.output-message-type\' | translate}}</mat-label>\n <mat-select formControlName="messageTypeAlias">\n <mat-option *ngFor="let msgType of messageTypes" [value]="msgType">\n {{msgType.name}}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="flex" subscriptSizing="{{ subscriptSizing }}" [hideRequiredMarker]="messageTypeFormGroup.get(\'messageType\').disabled">\n <mat-label>{{\'tb.rulenode.message-type-value\' | translate}}</mat-label>\n <input matInput type="text" formControlName="messageType">\n <button type="button"\n matSuffix\n mat-icon-button\n aria-label="Copy"\n *ngIf="messageTypeFormGroup.get(\'messageType\').value"\n ngxClipboard\n [cbContent]="messageTypeFormGroup.get(\'messageType\').value"\n matTooltip="{{ \'tb.rulenode.copy-message-type\' | translate }}">\n <mat-icon aria-hidden="false"\n aria-label="help-icon">content_copy\n </mat-icon>\n </button>\n <mat-error *ngIf="messageTypeFormGroup.get(\'messageType\').hasError(\'required\')">\n {{ \'tb.rulenode.message-type-value-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="messageTypeFormGroup.get(\'messageType\').hasError(\'maxlength\')">\n {{ \'tb.rulenode.message-type-value-max-length\' | translate }}\n </mat-error>\n </mat-form-field>\n</section>\n\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:ft,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),Qe([I()],Kn.prototype,"disabled",void 0),Qe([I()],Kn.prototype,"required",null),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kn,decorators:[{type:n,args:[{selector:"tb-output-message-type-autocomplete",providers:[{provide:B,useExisting:c((()=>Kn)),multi:!0},{provide:K,useExisting:c((()=>Kn)),multi:!0}],template:'<section class="tb-form-row no-border no-padding tb-standard-fields column-xs" [formGroup]="messageTypeFormGroup">\n <mat-form-field class="flex" subscriptSizing="{{ subscriptSizing }}" hideRequiredMarker>\n <mat-label>{{\'tb.rulenode.output-message-type\' | translate}}</mat-label>\n <mat-select formControlName="messageTypeAlias">\n <mat-option *ngFor="let msgType of messageTypes" [value]="msgType">\n {{msgType.name}}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="flex" subscriptSizing="{{ subscriptSizing }}" [hideRequiredMarker]="messageTypeFormGroup.get(\'messageType\').disabled">\n <mat-label>{{\'tb.rulenode.message-type-value\' | translate}}</mat-label>\n <input matInput type="text" formControlName="messageType">\n <button type="button"\n matSuffix\n mat-icon-button\n aria-label="Copy"\n *ngIf="messageTypeFormGroup.get(\'messageType\').value"\n ngxClipboard\n [cbContent]="messageTypeFormGroup.get(\'messageType\').value"\n matTooltip="{{ \'tb.rulenode.copy-message-type\' | translate }}">\n <mat-icon aria-hidden="false"\n aria-label="help-icon">content_copy\n </mat-icon>\n </button>\n <mat-error *ngIf="messageTypeFormGroup.get(\'messageType\').hasError(\'required\')">\n {{ \'tb.rulenode.message-type-value-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="messageTypeFormGroup.get(\'messageType\').hasError(\'maxlength\')">\n {{ \'tb.rulenode.message-type-value-max-length\' | translate }}\n </mat-error>\n </mat-form-field>\n</section>\n\n'}]}],ctorParameters:function(){return[{type:R.FormBuilder}]},propDecorators:{subscriptSizing:[{type:m}],disabled:[{type:m}],required:[{type:m}]}});class zn{constructor(e,t){this.fb=e,this.translate=t,this.translation=mn,this.propagateChange=()=>{},this.destroy$=new ae,this.selectOptions=[]}ngOnInit(){this.initOptions(),this.chipControlGroup=this.fb.group({chipControl:[null,[]]}),this.chipControlGroup.get("chipControl").valueChanges.pipe(He(this.destroy$)).subscribe((e=>{e&&this.propagateChange(e)}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}initOptions(){for(const e of this.translation.keys())this.selectOptions.push({value:e,name:this.translate.instant(this.translation.get(e))})}writeValue(e){this.chipControlGroup.get("chipControl").patchValue(e,{emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){e?this.chipControlGroup.disable({emitEvent:!1}):this.chipControlGroup.enable({emitEvent:!1})}}e("MsgMetadataChipComponent",zn),zn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zn,deps:[{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),zn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:zn,selector:"tb-msg-metadata-chip",inputs:{labelText:"labelText",translation:"translation"},providers:[{provide:B,useExisting:c((()=>zn)),multi:!0}],ngImport:t,template:'<div [formGroup]="chipControlGroup" class="tb-form-row space-between">\n <div class="fixed-title-width">{{ labelText }}</div>\n <mat-chip-listbox formControlName="chipControl">\n <mat-chip-option *ngFor="let option of selectOptions"\n selectable="{{ chipControlGroup.get(\'chipControl\').value !== option.value }}"\n color="primary"\n [value]="option.value">{{ option.name }}</mat-chip-option>\n </mat-chip-listbox>\n</div>\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Ie.MatChipListbox,selector:"mat-chip-listbox",inputs:["tabIndex","multiple","aria-orientation","selectable","compareWith","required","hideSingleSelectionIndicator","value"],outputs:["change"]},{kind:"component",type:Ie.MatChipOption,selector:"mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]",inputs:["color","disabled","disableRipple","tabIndex","selectable","selected"],outputs:["selectionChange"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zn,decorators:[{type:n,args:[{selector:"tb-msg-metadata-chip",providers:[{provide:B,useExisting:c((()=>zn)),multi:!0}],template:'<div [formGroup]="chipControlGroup" class="tb-form-row space-between">\n <div class="fixed-title-width">{{ labelText }}</div>\n <mat-chip-listbox formControlName="chipControl">\n <mat-chip-option *ngFor="let option of selectOptions"\n selectable="{{ chipControlGroup.get(\'chipControl\').value !== option.value }}"\n color="primary"\n [value]="option.value">{{ option.name }}</mat-chip-option>\n </mat-chip-listbox>\n</div>\n'}]}],ctorParameters:function(){return[{type:R.FormBuilder},{type:Z.TranslateService}]},propDecorators:{labelText:[{type:m}],translation:[{type:m}]}});class Hn extends k{constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.injector=n,this.fb=r,this.destroy$=new ae,this.sourceFieldSubcritption=[],this.propagateChange=null,this.disabled=!1,this.required=!1,this.oneMapRequiredValidator=e=>e.get("keyVals").value.length,this.propagateNestedErrors=e=>{if(this.svListFormGroup&&this.svListFormGroup.get("keyVals")&&"VALID"===this.svListFormGroup.get("keyVals")?.status)return null;const t={};if(this.svListFormGroup&&this.svListFormGroup.setErrors(null),e instanceof z||e instanceof H){if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;for(const n of Object.keys(e.controls)){const r=this.propagateNestedErrors(e.controls[n]);if(r&&Object.keys(r).length)for(const e of Object.keys(r))t[e]=!0}return t}if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;return ye(t,{})?null:t}}ngOnInit(){this.ngControl=this.injector.get(_),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.svListFormGroup=this.fb.group({keyVals:this.fb.array([])},{validators:[this.propagateNestedErrors,this.oneMapRequiredValidator]}),this.svListFormGroup.valueChanges.pipe(He(this.destroy$)).subscribe((()=>{this.updateModel()}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}keyValsFormArray(){return this.svListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.svListFormGroup.disable({emitEvent:!1}):this.svListFormGroup.enable({emitEvent:!1})}writeValue(e){const t=Object.keys(e).map((t=>({key:t,value:e[t]})));if(this.keyValsFormArray().length===t.length)this.keyValsFormArray().patchValue(t,{emitEvent:!1});else{const e=[];t.forEach((t=>{e.push(this.fb.group({key:[t.key,[O.required]],value:[t.value,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]}))})),this.svListFormGroup.setControl("keyVals",this.fb.array(e,this.propagateNestedErrors),{emitEvent:!1});for(const e of this.keyValsFormArray().controls)this.keyChangeSubscribe(e)}}filterSelectOptions(e){const t=[];for(const e of this.svListFormGroup.get("keyVals").value){const n=this.selectOptions.find((t=>t.value===e.key));n&&t.push(n)}const n=[];for(const r of this.selectOptions)fe(t.find((e=>e.value===r.value)))&&r.value!==e?.get("key").value||n.push(r);return n}removeKeyVal(e){this.keyValsFormArray().removeAt(e),this.sourceFieldSubcritption[e].unsubscribe(),this.sourceFieldSubcritption.splice(e,1)}addKeyVal(){this.keyValsFormArray().push(this.fb.group({key:["",[O.required]],value:["",[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]})),this.keyChangeSubscribe(this.keyValsFormArray().at(this.keyValsFormArray().length-1))}keyChangeSubscribe(e){this.sourceFieldSubcritption.push(e.get("key").valueChanges.pipe(He(this.destroy$)).subscribe((t=>{const n=At.get(t);e.get("value").patchValue(this.targetKeyPrefix+n[0].toUpperCase()+n.slice(1))})))}validate(e){return!this.svListFormGroup.get("keyVals").value.length&&this.required?{svMapRequired:!0}:this.svListFormGroup.valid?null:{svFieldsRequired:!0}}updateModel(){const e=this.svListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.svListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("SvMapConfigComponent",Hn),Hn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hn,deps:[{token:P.Store},{token:Z.TranslateService},{token:t.Injector},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Hn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Hn,selector:"tb-sv-map-config",inputs:{selectOptions:"selectOptions",disabled:"disabled",labelText:"labelText",requiredText:"requiredText",targetKeyPrefix:"targetKeyPrefix",selectText:"selectText",selectRequiredText:"selectRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",popupHelpLink:"popupHelpLink",required:"required"},providers:[{provide:B,useExisting:c((()=>Hn)),multi:!0},{provide:K,useExisting:c((()=>Hn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'<section [formGroup]="svListFormGroup" class="tb-form-panel stroked">\n <div class="tb-form-row no-padding no-border space-between">\n <div class="tb-form-panel-title">{{ labelText }}</div>\n <div class="tb-form-panel-hint tb-error" translate *ngIf="svListFormGroup.hasError(\'required\')">\n tb.rulenode.map-fields-required\n </div>\n <div class="tb-form-panel-hint tb-error" translate *ngIf="svListFormGroup.hasError(\'svMapRequired\')">\n {{ requiredText }}\n </div>\n </div>\n <div class="tb-form-panel no-border no-padding">\n <div class="tb-form-table">\n <div class="tb-form-table-header">\n <div class="tb-form-table-header-cell field-space">{{ selectText }}</div>\n <div class="tb-form-table-header-cell field-space">{{ valText }}</div>\n <div class="tb-form-table-header-cell actions-header"></div>\n </div>\n <div class="tb-form-table-body">\n <div class="tb-form-table-row"\n *ngFor="let keyValControl of keyValsFormArray().controls; let $index = index;">\n <mat-form-field class="tb-inline-field field-space" appearance="outline" subscriptSizing="dynamic">\n <mat-select [placeholder]="selectText" [formControl]="keyValControl.get(\'key\')" required>\n <mat-option *ngFor="let option of filterSelectOptions(keyValControl)" [value]="option.value">\n {{option.name}}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="tb-inline-field field-space" appearance="outline" subscriptSizing="dynamic">\n <input [placeholder]="valText" [formControl]="keyValControl.get(\'value\')" matInput/>\n </mat-form-field>\n <div class="tb-form-table-row-cell-buttons">\n <button [ngClass]="{\'tb-hidden\': keyValsFormArray().controls.length === 1}"\n type="button"\n mat-icon-button\n (click)="removeKeyVal($index)"\n [disabled]="isLoading$ | async"\n matTooltip="{{ \'tb.key-val.remove-mapping-entry\' | translate }}"\n matTooltipPosition="above">\n <mat-icon>delete</mat-icon>\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n <div>\n <button [disabled]="(isLoading$ | async) || keyValsFormArray().length >= selectOptions.length"\n type="button" mat-stroked-button color="primary" (click)="addKeyVal()">\n {{ \'tb.key-val.add-mapping-entry\' | translate }}\n </button>\n </div>\n <tb-example-hint [hintText]="hintText" [popupHelpLink]="popupHelpLink"></tb-example-hint>\n</section>\n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgClass,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:Ve.DefaultClassDirective,selector:" [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl], [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl], [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]",inputs:["ngClass","ngClass.xs","ngClass.sm","ngClass.md","ngClass.lg","ngClass.xl","ngClass.lt-sm","ngClass.lt-md","ngClass.lt-lg","ngClass.lt-xl","ngClass.gt-xs","ngClass.gt-sm","ngClass.gt-md","ngClass.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:U.AsyncPipe,name:"async"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),Qe([I()],Hn.prototype,"disabled",void 0),Qe([I()],Hn.prototype,"required",void 0),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hn,decorators:[{type:n,args:[{selector:"tb-sv-map-config",providers:[{provide:B,useExisting:c((()=>Hn)),multi:!0},{provide:K,useExisting:c((()=>Hn)),multi:!0}],template:'<section [formGroup]="svListFormGroup" class="tb-form-panel stroked">\n <div class="tb-form-row no-padding no-border space-between">\n <div class="tb-form-panel-title">{{ labelText }}</div>\n <div class="tb-form-panel-hint tb-error" translate *ngIf="svListFormGroup.hasError(\'required\')">\n tb.rulenode.map-fields-required\n </div>\n <div class="tb-form-panel-hint tb-error" translate *ngIf="svListFormGroup.hasError(\'svMapRequired\')">\n {{ requiredText }}\n </div>\n </div>\n <div class="tb-form-panel no-border no-padding">\n <div class="tb-form-table">\n <div class="tb-form-table-header">\n <div class="tb-form-table-header-cell field-space">{{ selectText }}</div>\n <div class="tb-form-table-header-cell field-space">{{ valText }}</div>\n <div class="tb-form-table-header-cell actions-header"></div>\n </div>\n <div class="tb-form-table-body">\n <div class="tb-form-table-row"\n *ngFor="let keyValControl of keyValsFormArray().controls; let $index = index;">\n <mat-form-field class="tb-inline-field field-space" appearance="outline" subscriptSizing="dynamic">\n <mat-select [placeholder]="selectText" [formControl]="keyValControl.get(\'key\')" required>\n <mat-option *ngFor="let option of filterSelectOptions(keyValControl)" [value]="option.value">\n {{option.name}}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="tb-inline-field field-space" appearance="outline" subscriptSizing="dynamic">\n <input [placeholder]="valText" [formControl]="keyValControl.get(\'value\')" matInput/>\n </mat-form-field>\n <div class="tb-form-table-row-cell-buttons">\n <button [ngClass]="{\'tb-hidden\': keyValsFormArray().controls.length === 1}"\n type="button"\n mat-icon-button\n (click)="removeKeyVal($index)"\n [disabled]="isLoading$ | async"\n matTooltip="{{ \'tb.key-val.remove-mapping-entry\' | translate }}"\n matTooltipPosition="above">\n <mat-icon>delete</mat-icon>\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n <div>\n <button [disabled]="(isLoading$ | async) || keyValsFormArray().length >= selectOptions.length"\n type="button" mat-stroked-button color="primary" (click)="addKeyVal()">\n {{ \'tb.key-val.add-mapping-entry\' | translate }}\n </button>\n </div>\n <tb-example-hint [hintText]="hintText" [popupHelpLink]="popupHelpLink"></tb-example-hint>\n</section>\n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:t.Injector},{type:R.FormBuilder}]},propDecorators:{selectOptions:[{type:m}],disabled:[{type:m}],labelText:[{type:m}],requiredText:[{type:m}],targetKeyPrefix:[{type:m}],selectText:[{type:m}],selectRequiredText:[{type:m}],valText:[{type:m}],valRequiredText:[{type:m}],hintText:[{type:m}],popupHelpLink:[{type:m}],required:[{type:m}]}});class Un extends k{get required(){return this.requiredValue}set required(e){this.requiredValue=Ee(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=N,this.propagateChange=null}ngOnInit(){this.relationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[O.required]],maxLevel:[null,[]],filters:[null]}),this.relationsQueryFormGroup.valueChanges.subscribe((e=>{this.relationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.relationsQueryFormGroup.disable({emitEvent:!1}):this.relationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.relationsQueryFormGroup.reset(e||{},{emitEvent:!1})}}e("RelationsQueryConfigOldComponent",Un),Un.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Un,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Un.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Un,selector:"tb-relations-query-config-old",inputs:{disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:c((()=>Un)),multi:!0}],usesInheritance:!0,ngImport:t,template:'<section fxLayout="column" [formGroup]="relationsQueryFormGroup">\n <mat-checkbox formControlName="fetchLastLevelOnly">\n {{ \'alias.last-level-relation\' | translate }}\n </mat-checkbox>\n <div fxLayoutGap="8px" fxLayout="row">\n <mat-form-field class="mat-block" style="min-width: 100px;">\n <mat-label translate>relation.direction</mat-label>\n <mat-select required matInput formControlName="direction">\n <mat-option *ngFor="let type of directionTypes" [value]="type">\n {{ directionTypeTranslations.get(type) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field fxFlex floatLabel="always" class="mat-block">\n <mat-label translate>tb.rulenode.max-relation-level</mat-label>\n <input matInput\n type="number"\n min="1"\n step="1"\n placeholder="{{ \'tb.rulenode.unlimited-level\' | translate }}"\n formControlName="maxLevel">\n </mat-form-field>\n </div>\n <div class="mat-caption" style="color: #6e6e6e;" translate>relation.relation-filters</div>\n <tb-relation-filters\n formControlName="filters"\n ></tb-relation-filters>\n</section>\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:We.RelationFiltersComponent,selector:"tb-relation-filters",inputs:["disabled","allowedEntityTypes"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Un,decorators:[{type:n,args:[{selector:"tb-relations-query-config-old",providers:[{provide:B,useExisting:c((()=>Un)),multi:!0}],template:'<section fxLayout="column" [formGroup]="relationsQueryFormGroup">\n <mat-checkbox formControlName="fetchLastLevelOnly">\n {{ \'alias.last-level-relation\' | translate }}\n </mat-checkbox>\n <div fxLayoutGap="8px" fxLayout="row">\n <mat-form-field class="mat-block" style="min-width: 100px;">\n <mat-label translate>relation.direction</mat-label>\n <mat-select required matInput formControlName="direction">\n <mat-option *ngFor="let type of directionTypes" [value]="type">\n {{ directionTypeTranslations.get(type) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field fxFlex floatLabel="always" class="mat-block">\n <mat-label translate>tb.rulenode.max-relation-level</mat-label>\n <input matInput\n type="number"\n min="1"\n step="1"\n placeholder="{{ \'tb.rulenode.unlimited-level\' | translate }}"\n formControlName="maxLevel">\n </mat-form-field>\n </div>\n <div class="mat-caption" style="color: #6e6e6e;" translate>relation.relation-filters</div>\n <tb-relation-filters\n formControlName="filters"\n ></tb-relation-filters>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:m}],required:[{type:m}]}});class jn{constructor(e,t){this.translate=e,this.fb=t,this.propagateChange=e=>{},this.destroy$=new ae,this.separatorKeysCodes=[Fe,ke,Te],this.onTouched=()=>{}}ngOnInit(){this.attributeControlGroup=this.fb.group({clientAttributeNames:[[],[]],sharedAttributeNames:[[],[]],serverAttributeNames:[[],[]],latestTsKeyNames:[[],[]],getLatestValueWithTs:[!1,[]]},{validators:this.atLeastOne(O.required,["clientAttributeNames","sharedAttributeNames","serverAttributeNames","latestTsKeyNames"])}),this.attributeControlGroup.valueChanges.pipe(He(this.destroy$)).subscribe((e=>{this.propagateChange(this.preparePropagateValue(e))}))}preparePropagateValue(e){const t={};for(const n in e)t[n]="getLatestValueWithTs"===n||fe(e[n])?e[n]:[];return t}validate(){return this.attributeControlGroup.valid?null:{atLeastOneRequired:!0}}atLeastOne(e,t=null){return n=>{t||(t=Object.keys(n.controls));return n?.controls&&t.some((t=>!e(n.controls[t])))?null:{atLeastOne:!0}}}writeValue(e){this.attributeControlGroup.setValue(e,{emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){this.onTouched=e}setDisabledState(e){e?this.attributeControlGroup.disable({emitEvent:!1}):this.attributeControlGroup.enable({emitEvent:!1})}ngOnDestroy(){this.destroy$.next(null),this.destroy$.complete()}}e("SelectAttributesComponent",jn),jn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jn,deps:[{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),jn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:jn,selector:"tb-select-attributes",inputs:{popupHelpLink:"popupHelpLink"},providers:[{provide:B,useExisting:c((()=>jn)),multi:!0},{provide:K,useExisting:jn,multi:!0}],ngImport:t,template:'<div class="tb-form-panel no-padding no-border" [formGroup]="attributeControlGroup">\n <tb-example-hint [hintText]="\'tb.rulenode.kv-map-pattern-hint\' | translate"\n [popupHelpLink]="popupHelpLink"></tb-example-hint>\n <tb-string-items-list subscriptSizing="dynamic" class="mat-block" editable\n (focusout)="onTouched()"\n [placeholder]="\'tb.rulenode.add-attribute-key\' | translate"\n [label]="\'tb.rulenode.client-attributes\' | translate" formControlName="clientAttributeNames">\n <ng-container matSuffix *ngTemplateOutlet="helpIcon"></ng-container>\n </tb-string-items-list>\n <tb-string-items-list subscriptSizing="dynamic" class="mat-block" editable\n (focusout)="onTouched()"\n [placeholder]="\'tb.rulenode.add-attribute-key\' | translate"\n [label]="\'tb.rulenode.shared-attributes\' | translate" formControlName="sharedAttributeNames">\n <ng-container matSuffix *ngTemplateOutlet="helpIcon"></ng-container>\n </tb-string-items-list>\n <tb-string-items-list subscriptSizing="dynamic" class="mat-block" editable\n (focusout)="onTouched()"\n [placeholder]="\'tb.rulenode.add-attribute-key\' | translate"\n [label]="\'tb.rulenode.server-attributes\' | translate" formControlName="serverAttributeNames">\n <ng-container matSuffix *ngTemplateOutlet="helpIcon"></ng-container>\n </tb-string-items-list>\n <tb-string-items-list subscriptSizing="dynamic" editable class="mat-block"\n (focusout)="onTouched()"\n [placeholder]="\'tb.rulenode.add-telemetry-key\' | translate"\n [label]="\'tb.rulenode.latest-telemetry\' | translate" formControlName="latestTsKeyNames">\n <ng-container matSuffix *ngTemplateOutlet="helpIcon"></ng-container>\n </tb-string-items-list>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.fetch-latest-telemetry-with-timestamp-tooltip\' | translate:\n { latestTsKeyName: attributeControlGroup.get(\'latestTsKeyNames\').value[0]} }}"\n *ngIf="attributeControlGroup.get(\'latestTsKeyNames\').value?.length > 0"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="getLatestValueWithTs">\n {{ \'tb.rulenode.fetch-latest-telemetry-with-timestamp\' | translate }}\n </mat-slide-toggle>\n </div>\n</div>\n\n<ng-template #helpIcon>\n <mat-icon class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.chip-help\' | translate: { inputName: \'tb.rulenode.field-name\' | translate } }}">help</mat-icon>\n</ng-template>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:U.NgTemplateOutlet,selector:"[ngTemplateOutlet]",inputs:["ngTemplateOutletContext","ngTemplateOutlet","ngTemplateOutletInjector"]},{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jn,decorators:[{type:n,args:[{selector:"tb-select-attributes",providers:[{provide:B,useExisting:c((()=>jn)),multi:!0},{provide:K,useExisting:jn,multi:!0}],template:'<div class="tb-form-panel no-padding no-border" [formGroup]="attributeControlGroup">\n <tb-example-hint [hintText]="\'tb.rulenode.kv-map-pattern-hint\' | translate"\n [popupHelpLink]="popupHelpLink"></tb-example-hint>\n <tb-string-items-list subscriptSizing="dynamic" class="mat-block" editable\n (focusout)="onTouched()"\n [placeholder]="\'tb.rulenode.add-attribute-key\' | translate"\n [label]="\'tb.rulenode.client-attributes\' | translate" formControlName="clientAttributeNames">\n <ng-container matSuffix *ngTemplateOutlet="helpIcon"></ng-container>\n </tb-string-items-list>\n <tb-string-items-list subscriptSizing="dynamic" class="mat-block" editable\n (focusout)="onTouched()"\n [placeholder]="\'tb.rulenode.add-attribute-key\' | translate"\n [label]="\'tb.rulenode.shared-attributes\' | translate" formControlName="sharedAttributeNames">\n <ng-container matSuffix *ngTemplateOutlet="helpIcon"></ng-container>\n </tb-string-items-list>\n <tb-string-items-list subscriptSizing="dynamic" class="mat-block" editable\n (focusout)="onTouched()"\n [placeholder]="\'tb.rulenode.add-attribute-key\' | translate"\n [label]="\'tb.rulenode.server-attributes\' | translate" formControlName="serverAttributeNames">\n <ng-container matSuffix *ngTemplateOutlet="helpIcon"></ng-container>\n </tb-string-items-list>\n <tb-string-items-list subscriptSizing="dynamic" editable class="mat-block"\n (focusout)="onTouched()"\n [placeholder]="\'tb.rulenode.add-telemetry-key\' | translate"\n [label]="\'tb.rulenode.latest-telemetry\' | translate" formControlName="latestTsKeyNames">\n <ng-container matSuffix *ngTemplateOutlet="helpIcon"></ng-container>\n </tb-string-items-list>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.fetch-latest-telemetry-with-timestamp-tooltip\' | translate:\n { latestTsKeyName: attributeControlGroup.get(\'latestTsKeyNames\').value[0]} }}"\n *ngIf="attributeControlGroup.get(\'latestTsKeyNames\').value?.length > 0"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="getLatestValueWithTs">\n {{ \'tb.rulenode.fetch-latest-telemetry-with-timestamp\' | translate }}\n </mat-slide-toggle>\n </div>\n</div>\n\n<ng-template #helpIcon>\n <mat-icon class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.chip-help\' | translate: { inputName: \'tb.rulenode.field-name\' | translate } }}">help</mat-icon>\n</ng-template>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:Z.TranslateService},{type:R.FormBuilder}]},propDecorators:{popupHelpLink:[{type:m}]}});class $n extends k{constructor(e,t){super(e),this.store=e,this.fb=t,this.propagateChange=null,this.destroy$=new ae,this.alarmStatus=q,this.alarmStatusTranslations=A}ngOnInit(){this.alarmStatusGroup=this.fb.group({alarmStatus:[null,[]]}),this.alarmStatusGroup.get("alarmStatus").valueChanges.pipe(He(this.destroy$)).subscribe((e=>{this.propagateChange(e)}))}setDisabledState(e){e?this.alarmStatusGroup.disable({emitEvent:!1}):this.alarmStatusGroup.enable({emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}writeValue(e){this.alarmStatusGroup.get("alarmStatus").patchValue(e,{emitEvent:!1})}}e("AlarmStatusSelectComponent",$n),$n.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$n,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),$n.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:$n,selector:"tb-alarm-status-select",providers:[{provide:B,useExisting:c((()=>$n)),multi:!0}],usesInheritance:!0,ngImport:t,template:'<section [formGroup]="alarmStatusGroup" fxLayout="column" fxLayoutAlign="center center">\n <mat-chip-listbox multiple formControlName="alarmStatus" class="chip-listbox" fxLayout="column">\n <div class="toggle-column">\n <mat-chip-option fxFlex class="option" [value]="alarmStatus.ACTIVE_UNACK">\n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_UNACK) | translate }}\n </mat-chip-option>\n <mat-chip-option fxFlex class="option" [value]="alarmStatus.ACTIVE_ACK">\n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_ACK) | translate }}\n </mat-chip-option>\n </div>\n <div class="toggle-column">\n <mat-chip-option fxFlex class="option" [value]="alarmStatus.CLEARED_UNACK">\n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_UNACK) | translate }}\n </mat-chip-option>\n <mat-chip-option fxFlex class="option" [value]="alarmStatus.CLEARED_ACK">\n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_ACK) | translate }}\n </mat-chip-option>\n </div>\n </mat-chip-listbox>\n</section>\n',styles:[":host .chip-listbox{max-width:460px;width:100%}:host .chip-listbox .toggle-column{display:flex;flex:1 1 100%;gap:8px}:host .chip-listbox .option{margin:0}@media screen and (max-width: 959px){:host .chip-listbox{max-width:360px}:host .chip-listbox .toggle-column{flex-direction:column}}:host ::ng-deep .chip-listbox .mdc-evolution-chip-set__chips{gap:8px}:host ::ng-deep .chip-listbox .option button{flex-basis:100%;justify-content:start}:host ::ng-deep .chip-listbox .option .mdc-evolution-chip__graphic{flex-grow:0}\n"],dependencies:[{kind:"component",type:Ie.MatChipListbox,selector:"mat-chip-listbox",inputs:["tabIndex","multiple","aria-orientation","selectable","compareWith","required","hideSingleSelectionIndicator","value"],outputs:["change"]},{kind:"component",type:Ie.MatChipOption,selector:"mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]",inputs:["color","disabled","disableRipple","tabIndex","selectable","selected"],outputs:["selectionChange"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$n,decorators:[{type:n,args:[{selector:"tb-alarm-status-select",providers:[{provide:B,useExisting:c((()=>$n)),multi:!0}],template:'<section [formGroup]="alarmStatusGroup" fxLayout="column" fxLayoutAlign="center center">\n <mat-chip-listbox multiple formControlName="alarmStatus" class="chip-listbox" fxLayout="column">\n <div class="toggle-column">\n <mat-chip-option fxFlex class="option" [value]="alarmStatus.ACTIVE_UNACK">\n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_UNACK) | translate }}\n </mat-chip-option>\n <mat-chip-option fxFlex class="option" [value]="alarmStatus.ACTIVE_ACK">\n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_ACK) | translate }}\n </mat-chip-option>\n </div>\n <div class="toggle-column">\n <mat-chip-option fxFlex class="option" [value]="alarmStatus.CLEARED_UNACK">\n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_UNACK) | translate }}\n </mat-chip-option>\n <mat-chip-option fxFlex class="option" [value]="alarmStatus.CLEARED_ACK">\n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_ACK) | translate }}\n </mat-chip-option>\n </div>\n </mat-chip-listbox>\n</section>\n',styles:[":host .chip-listbox{max-width:460px;width:100%}:host .chip-listbox .toggle-column{display:flex;flex:1 1 100%;gap:8px}:host .chip-listbox .option{margin:0}@media screen and (max-width: 959px){:host .chip-listbox{max-width:360px}:host .chip-listbox .toggle-column{flex-direction:column}}:host ::ng-deep .chip-listbox .mdc-evolution-chip-set__chips{gap:8px}:host ::ng-deep .chip-listbox .option button{flex-basis:100%;justify-content:start}:host ::ng-deep .chip-listbox .option .mdc-evolution-chip__graphic{flex-grow:0}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Jn{}e("RulenodeCoreConfigCommonModule",Jn),Jn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jn,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Jn.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Jn,declarations:[Pn,Rn,On,_n,Bn,Gn,wn,Kn,Nn,zn,Hn,Un,jn,$n,xt],imports:[$,M,Je],exports:[Pn,Rn,On,_n,Bn,Gn,wn,Kn,Nn,zn,Hn,Un,jn,$n,xt]}),Jn.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jn,imports:[$,M,Je]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jn,decorators:[{type:d,args:[{declarations:[Pn,Rn,On,_n,Bn,Gn,wn,Kn,Nn,zn,Hn,Un,jn,$n,xt],imports:[$,M,Je],exports:[Pn,Rn,On,_n,Bn,Gn,wn,Kn,Nn,zn,Hn,Un,jn,$n,xt]}]}]});class Qn{}e("RuleNodeCoreConfigActionModule",Qn),Qn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Qn.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Qn,declarations:[En,ht,qn,In,vn,ut,vt,Ct,Ft,Fn,kt,Lt,hn,Cn,Ln,Sn,An,Mn,Tt,Tn,kn,Dn,Vn],imports:[$,M,Je,Jn],exports:[En,ht,qn,In,vn,ut,vt,Ct,Ft,Fn,kt,Lt,hn,Cn,Ln,Sn,An,Mn,Tt,Tn,kn,Dn,Vn]}),Qn.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,imports:[$,M,Je,Jn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,decorators:[{type:d,args:[{declarations:[En,ht,qn,In,vn,ut,vt,Ct,Ft,Fn,kt,Lt,hn,Cn,Ln,Sn,An,Mn,Tt,Tn,kn,Dn,Vn],imports:[$,M,Je,Jn],exports:[En,ht,qn,In,vn,ut,vt,Ct,Ft,Fn,kt,Lt,hn,Cn,Ln,Sn,An,Mn,Tt,Tn,kn,Dn,Vn]}]}]});class Yn extends g{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.separatorKeysCodes=[Fe,ke,Te]}configForm(){return this.calculateDeltaConfigForm}onConfigurationSet(e){this.calculateDeltaConfigForm=this.fb.group({inputValueKey:[e.inputValueKey,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],outputValueKey:[e.outputValueKey,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],useCache:[e.useCache,[]],addPeriodBetweenMsgs:[e.addPeriodBetweenMsgs,[]],periodValueKey:[e.periodValueKey,[]],round:[e.round,[O.min(0),O.max(15)]],tellFailureIfDeltaIsNegative:[e.tellFailureIfDeltaIsNegative,[]],excludeZeroDeltas:[e.excludeZeroDeltas,[]]})}prepareInputConfig(e){return{inputValueKey:fe(e?.inputValueKey)?e.inputValueKey:null,outputValueKey:fe(e?.outputValueKey)?e.outputValueKey:null,useCache:!fe(e?.useCache)||e.useCache,addPeriodBetweenMsgs:!!fe(e?.addPeriodBetweenMsgs)&&e.addPeriodBetweenMsgs,periodValueKey:fe(e?.periodValueKey)?e.periodValueKey:null,round:fe(e?.round)?e.round:null,tellFailureIfDeltaIsNegative:!fe(e?.tellFailureIfDeltaIsNegative)||e.tellFailureIfDeltaIsNegative,excludeZeroDeltas:!!fe(e?.excludeZeroDeltas)&&e.excludeZeroDeltas}}prepareOutputConfig(e){return be(e)}updateValidators(e){this.calculateDeltaConfigForm.get("addPeriodBetweenMsgs").value?this.calculateDeltaConfigForm.get("periodValueKey").setValidators([O.required]):this.calculateDeltaConfigForm.get("periodValueKey").setValidators([]),this.calculateDeltaConfigForm.get("periodValueKey").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["addPeriodBetweenMsgs"]}}e("CalculateDeltaConfigComponent",Yn),Yn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Yn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Yn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Yn,selector:"tb-enrichment-node-calculate-delta-config",usesInheritance:!0,ngImport:t,template:"<section [formGroup]=\"calculateDeltaConfigForm\">\n <div fxLayout.gt-sm=\"row\" fxLayoutGap.gt-sm=\"22px\">\n <mat-form-field class=\"mat-block\" fxFlex>\n <mat-label>{{ 'tb.rulenode.input-value-key' | translate }}</mat-label>\n <input matInput formControlName=\"inputValueKey\">\n <mat-error *ngIf=\"calculateDeltaConfigForm.get('inputValueKey').hasError('required') ||\n calculateDeltaConfigForm.get('inputValueKey').hasError('pattern')\">\n {{ 'tb.rulenode.input-value-key-required' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class=\"mat-block\" fxFlex>\n <mat-label>{{ 'tb.rulenode.output-value-key' | translate }}</mat-label>\n <input matInput formControlName=\"outputValueKey\">\n <mat-error *ngIf=\"calculateDeltaConfigForm.get('outputValueKey').hasError('required') ||\n calculateDeltaConfigForm.get('outputValueKey').hasError('pattern')\">\n {{ 'tb.rulenode.output-value-key-required' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <mat-form-field class=\"mat-block\" fxFlex>\n <mat-label>{{ 'tb.rulenode.number-of-digits-after-floating-point' | translate }}</mat-label>\n <input type=\"number\" min=\"0\" max=\"15\" step=\"1\" matInput formControlName=\"round\">\n <mat-error *ngIf=\"calculateDeltaConfigForm.get('round').hasError('min')\">\n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n </mat-error>\n <mat-error *ngIf=\"calculateDeltaConfigForm.get('round').hasError('max')\">\n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n </mat-error>\n </mat-form-field>\n <div class=\"tb-form-panel no-padding no-border\">\n <div tb-hint-tooltip-icon=\"{{ 'tb.rulenode.failure-if-delta-negative-tooltip' | translate }}\"\n class=\"tb-form-row same-padding\">\n <mat-slide-toggle class=\"mat-slide margin\" formControlName=\"tellFailureIfDeltaIsNegative\">\n {{ 'tb.rulenode.failure-if-delta-negative' | translate }}\n </mat-slide-toggle>\n </div>\n <div tb-hint-tooltip-icon=\"{{ 'tb.rulenode.use-caching-tooltip' | translate :\n { inputValueKey: calculateDeltaConfigForm.get('inputValueKey').valid ?\n calculateDeltaConfigForm.get('inputValueKey').value : 'tb.rulenode.input-value-key' | translate } }}\"\n class=\"tb-form-row same-padding\">\n <mat-slide-toggle class=\"mat-slide margin\" formControlName=\"useCache\">\n {{ 'tb.rulenode.use-caching' | translate }}\n </mat-slide-toggle>\n </div>\n <div class=\"tb-form-panel stroked\" [class.no-padding-bottom]=\"calculateDeltaConfigForm.get('addPeriodBetweenMsgs').value\">\n <div tb-hint-tooltip-icon=\"{{ 'tb.rulenode.add-time-difference-between-readings-tooltip' | translate:\n { periodValueKey: (calculateDeltaConfigForm.get('periodValueKey').valid &&\n calculateDeltaConfigForm.get('addPeriodBetweenMsgs').value) ? calculateDeltaConfigForm.get('periodValueKey').value :\n 'periodInMs' } }}\"\n class=\"tb-form-row no-border no-padding\">\n <mat-slide-toggle class=\"mat-slide\" formControlName=\"addPeriodBetweenMsgs\">\n {{ 'tb.rulenode.add-time-difference-between-readings' | translate:\n { inputValueKey: calculateDeltaConfigForm.get('inputValueKey').valid ?\n calculateDeltaConfigForm.get('inputValueKey').value : 'tb.rulenode.input-value-key' | translate } }}\n </mat-slide-toggle>\n </div>\n <mat-form-field class=\"mat-block\" *ngIf=\"calculateDeltaConfigForm.get('addPeriodBetweenMsgs').value\">\n <mat-label>{{ 'tb.rulenode.period-value-key' | translate }}</mat-label>\n <input required matInput formControlName=\"periodValueKey\">\n <mat-error *ngIf=\"calculateDeltaConfigForm.get('periodValueKey').hasError('required')\">\n {{ 'tb.rulenode.period-value-key-required' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <div tb-hint-tooltip-icon=\"{{ calculateDeltaConfigForm.get('addPeriodBetweenMsgs').value ? ('tb.rulenode.exclude-zero-deltas-time-difference-hint' | translate :{\n outputValueKey: calculateDeltaConfigForm.get('outputValueKey').valid ? calculateDeltaConfigForm.get('outputValueKey').value : 'tb.rulenode.output-value-key' | translate,\n periodValueKey: calculateDeltaConfigForm.get('periodValueKey').valid ? calculateDeltaConfigForm.get('periodValueKey').value : 'tb.rulenode.period-value-key' | translate\n }) : ('tb.rulenode.exclude-zero-deltas-hint' | translate :{ outputValueKey: calculateDeltaConfigForm.get('outputValueKey').valid ? calculateDeltaConfigForm.get('outputValueKey').value : 'tb.rulenode.output-value-key' | translate }) }}\"\n class=\"tb-form-row same-padding\">\n <mat-slide-toggle class=\"mat-slide margin\" formControlName=\"excludeZeroDeltas\">\n {{ 'tb.rulenode.exclude-zero-deltas' | translate }}\n </mat-slide-toggle>\n </div>\n </div>\n</section>\n",dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Yn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-calculate-delta-config",template:"<section [formGroup]=\"calculateDeltaConfigForm\">\n <div fxLayout.gt-sm=\"row\" fxLayoutGap.gt-sm=\"22px\">\n <mat-form-field class=\"mat-block\" fxFlex>\n <mat-label>{{ 'tb.rulenode.input-value-key' | translate }}</mat-label>\n <input matInput formControlName=\"inputValueKey\">\n <mat-error *ngIf=\"calculateDeltaConfigForm.get('inputValueKey').hasError('required') ||\n calculateDeltaConfigForm.get('inputValueKey').hasError('pattern')\">\n {{ 'tb.rulenode.input-value-key-required' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class=\"mat-block\" fxFlex>\n <mat-label>{{ 'tb.rulenode.output-value-key' | translate }}</mat-label>\n <input matInput formControlName=\"outputValueKey\">\n <mat-error *ngIf=\"calculateDeltaConfigForm.get('outputValueKey').hasError('required') ||\n calculateDeltaConfigForm.get('outputValueKey').hasError('pattern')\">\n {{ 'tb.rulenode.output-value-key-required' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <mat-form-field class=\"mat-block\" fxFlex>\n <mat-label>{{ 'tb.rulenode.number-of-digits-after-floating-point' | translate }}</mat-label>\n <input type=\"number\" min=\"0\" max=\"15\" step=\"1\" matInput formControlName=\"round\">\n <mat-error *ngIf=\"calculateDeltaConfigForm.get('round').hasError('min')\">\n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n </mat-error>\n <mat-error *ngIf=\"calculateDeltaConfigForm.get('round').hasError('max')\">\n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n </mat-error>\n </mat-form-field>\n <div class=\"tb-form-panel no-padding no-border\">\n <div tb-hint-tooltip-icon=\"{{ 'tb.rulenode.failure-if-delta-negative-tooltip' | translate }}\"\n class=\"tb-form-row same-padding\">\n <mat-slide-toggle class=\"mat-slide margin\" formControlName=\"tellFailureIfDeltaIsNegative\">\n {{ 'tb.rulenode.failure-if-delta-negative' | translate }}\n </mat-slide-toggle>\n </div>\n <div tb-hint-tooltip-icon=\"{{ 'tb.rulenode.use-caching-tooltip' | translate :\n { inputValueKey: calculateDeltaConfigForm.get('inputValueKey').valid ?\n calculateDeltaConfigForm.get('inputValueKey').value : 'tb.rulenode.input-value-key' | translate } }}\"\n class=\"tb-form-row same-padding\">\n <mat-slide-toggle class=\"mat-slide margin\" formControlName=\"useCache\">\n {{ 'tb.rulenode.use-caching' | translate }}\n </mat-slide-toggle>\n </div>\n <div class=\"tb-form-panel stroked\" [class.no-padding-bottom]=\"calculateDeltaConfigForm.get('addPeriodBetweenMsgs').value\">\n <div tb-hint-tooltip-icon=\"{{ 'tb.rulenode.add-time-difference-between-readings-tooltip' | translate:\n { periodValueKey: (calculateDeltaConfigForm.get('periodValueKey').valid &&\n calculateDeltaConfigForm.get('addPeriodBetweenMsgs').value) ? calculateDeltaConfigForm.get('periodValueKey').value :\n 'periodInMs' } }}\"\n class=\"tb-form-row no-border no-padding\">\n <mat-slide-toggle class=\"mat-slide\" formControlName=\"addPeriodBetweenMsgs\">\n {{ 'tb.rulenode.add-time-difference-between-readings' | translate:\n { inputValueKey: calculateDeltaConfigForm.get('inputValueKey').valid ?\n calculateDeltaConfigForm.get('inputValueKey').value : 'tb.rulenode.input-value-key' | translate } }}\n </mat-slide-toggle>\n </div>\n <mat-form-field class=\"mat-block\" *ngIf=\"calculateDeltaConfigForm.get('addPeriodBetweenMsgs').value\">\n <mat-label>{{ 'tb.rulenode.period-value-key' | translate }}</mat-label>\n <input required matInput formControlName=\"periodValueKey\">\n <mat-error *ngIf=\"calculateDeltaConfigForm.get('periodValueKey').hasError('required')\">\n {{ 'tb.rulenode.period-value-key-required' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <div tb-hint-tooltip-icon=\"{{ calculateDeltaConfigForm.get('addPeriodBetweenMsgs').value ? ('tb.rulenode.exclude-zero-deltas-time-difference-hint' | translate :{\n outputValueKey: calculateDeltaConfigForm.get('outputValueKey').valid ? calculateDeltaConfigForm.get('outputValueKey').value : 'tb.rulenode.output-value-key' | translate,\n periodValueKey: calculateDeltaConfigForm.get('periodValueKey').valid ? calculateDeltaConfigForm.get('periodValueKey').value : 'tb.rulenode.period-value-key' | translate\n }) : ('tb.rulenode.exclude-zero-deltas-hint' | translate :{ outputValueKey: calculateDeltaConfigForm.get('outputValueKey').valid ? calculateDeltaConfigForm.get('outputValueKey').value : 'tb.rulenode.output-value-key' | translate }) }}\"\n class=\"tb-form-row same-padding\">\n <mat-slide-toggle class=\"mat-slide margin\" formControlName=\"excludeZeroDeltas\">\n {{ 'tb.rulenode.exclude-zero-deltas' | translate }}\n </mat-slide-toggle>\n </div>\n </div>\n</section>\n"}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class Wn extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.fetchToData=[],this.DataToFetch=zt;for(const e of Ht.keys())e!==zt.FIELDS&&this.fetchToData.push({value:e,name:this.translate.instant(Ht.get(e))})}configForm(){return this.customerAttributesConfigForm}prepareOutputConfig(e){const t={};for(const n of Object.keys(e.dataMapping))t[n.trim()]=e.dataMapping[n];return e.dataMapping=t,be(e)}prepareInputConfig(e){let t,n;return t=fe(e?.telemetry)?e.telemetry?zt.LATEST_TELEMETRY:zt.ATTRIBUTES:fe(e?.dataToFetch)?e.dataToFetch:zt.ATTRIBUTES,n=fe(e?.attrMapping)?e.attrMapping:fe(e?.dataMapping)?e.dataMapping:null,{dataToFetch:t,dataMapping:n,fetchTo:fe(e?.fetchTo)?e.fetchTo:ln.METADATA}}selectTranslation(e,t){return this.customerAttributesConfigForm.get("dataToFetch").value===zt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.customerAttributesConfigForm=this.fb.group({dataToFetch:[e.dataToFetch,[]],dataMapping:[e.dataMapping,[O.required]],fetchTo:[e.fetchTo]})}}e("CustomerAttributesConfigComponent",Wn),Wn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Wn,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Wn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Wn,selector:"tb-enrichment-node-customer-attributes-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="customerAttributesConfigForm" class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.mapping-of-customers</div>\n <div fxFlex fxLayoutAlign="center center">\n <div class="fetch-to-data-toggle">\n <tb-toggle-select class="fetch-to-data-toggle" formControlName="dataToFetch" appearance="fill">\n <tb-toggle-option *ngFor="let data of fetchToData" [value]="data.value">\n {{ data.name }}\n </tb-toggle-option>\n </tb-toggle-select>\n </div>\n </div>\n <tb-kv-map-config\n required\n formControlName="dataMapping"\n [requiredText]="\'tb.rulenode.attr-mapping-required\' | translate"\n [labelText]="selectTranslation(\'tb.rulenode.latest-telemetry-mapping\',\'tb.rulenode.attributes-mapping\') | translate"\n [keyText]="selectTranslation(\'tb.rulenode.source-telemetry\',\'tb.rulenode.source-attribute\') | translate"\n [keyRequiredText]="selectTranslation(\'tb.rulenode.source-telemetry-required\',\'tb.rulenode.source-attribute-required\') | translate"\n [valText]="\'tb.rulenode.target-key\' | translate"\n [valRequiredText]="\'tb.rulenode.target-key-required\' | translate"\n [hintText]="\'tb.rulenode.kv-map-pattern-hint\'"\n popupHelpLink="rulenode/customer_attributes_node_fields_templatization">\n </tb-kv-map-config>\n <tb-msg-metadata-chip\n [labelText]="customerAttributesConfigForm.get(\'dataToFetch\').value === DataToFetch.LATEST_TELEMETRY ?\n (\'tb.rulenode.add-mapped-latest-telemetry-to\' | translate) : (\'tb.rulenode.add-mapped-attribute-to\' | translate)"\n formControlName="fetchTo">\n </tb-msg-metadata-chip>\n</section>\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Ae.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Me.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Pn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Wn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-customer-attributes-config",template:'<section [formGroup]="customerAttributesConfigForm" class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.mapping-of-customers</div>\n <div fxFlex fxLayoutAlign="center center">\n <div class="fetch-to-data-toggle">\n <tb-toggle-select class="fetch-to-data-toggle" formControlName="dataToFetch" appearance="fill">\n <tb-toggle-option *ngFor="let data of fetchToData" [value]="data.value">\n {{ data.name }}\n </tb-toggle-option>\n </tb-toggle-select>\n </div>\n </div>\n <tb-kv-map-config\n required\n formControlName="dataMapping"\n [requiredText]="\'tb.rulenode.attr-mapping-required\' | translate"\n [labelText]="selectTranslation(\'tb.rulenode.latest-telemetry-mapping\',\'tb.rulenode.attributes-mapping\') | translate"\n [keyText]="selectTranslation(\'tb.rulenode.source-telemetry\',\'tb.rulenode.source-attribute\') | translate"\n [keyRequiredText]="selectTranslation(\'tb.rulenode.source-telemetry-required\',\'tb.rulenode.source-attribute-required\') | translate"\n [valText]="\'tb.rulenode.target-key\' | translate"\n [valRequiredText]="\'tb.rulenode.target-key-required\' | translate"\n [hintText]="\'tb.rulenode.kv-map-pattern-hint\'"\n popupHelpLink="rulenode/customer_attributes_node_fields_templatization">\n </tb-kv-map-config>\n <tb-msg-metadata-chip\n [labelText]="customerAttributesConfigForm.get(\'dataToFetch\').value === DataToFetch.LATEST_TELEMETRY ?\n (\'tb.rulenode.add-mapped-latest-telemetry-to\' | translate) : (\'tb.rulenode.add-mapped-attribute-to\' | translate)"\n formControlName="fetchTo">\n </tb-msg-metadata-chip>\n</section>\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Zn extends g{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n}configForm(){return this.deviceAttributesConfigForm}onConfigurationSet(e){this.deviceAttributesConfigForm=this.fb.group({deviceRelationsQuery:[e.deviceRelationsQuery,[O.required]],tellFailureIfAbsent:[e.tellFailureIfAbsent,[]],fetchTo:[e.fetchTo,[]],attributesControl:[e.attributesControl,[]]})}prepareInputConfig(e){return xe(e)&&(e.attributesControl={clientAttributeNames:fe(e?.clientAttributeNames)?e.clientAttributeNames:[],latestTsKeyNames:fe(e?.latestTsKeyNames)?e.latestTsKeyNames:[],serverAttributeNames:fe(e?.serverAttributeNames)?e.serverAttributeNames:[],sharedAttributeNames:fe(e?.sharedAttributeNames)?e.sharedAttributeNames:[],getLatestValueWithTs:!!fe(e?.getLatestValueWithTs)&&e.getLatestValueWithTs}),{deviceRelationsQuery:fe(e?.deviceRelationsQuery)?e.deviceRelationsQuery:null,tellFailureIfAbsent:!fe(e?.tellFailureIfAbsent)||e.tellFailureIfAbsent,fetchTo:fe(e?.fetchTo)?e.fetchTo:ln.METADATA,attributesControl:e?e.attributesControl:null}}prepareOutputConfig(e){for(const t of Object.keys(e.attributesControl))e[t]=e.attributesControl[t];return delete e.attributesControl,e}}e("DeviceAttributesConfigComponent",Zn),Zn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Zn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Zn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Zn,selector:"tb-enrichment-node-device-attributes-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="deviceAttributesConfigForm" class="tb-form-panel no-padding no-border">\n <div class="tb-form-panel stroked no-padding-bottom">\n <div class="tb-form-panel-title" translate>tb.rulenode.device-relations-query</div>\n <tb-device-relations-query-config\n required\n formControlName="deviceRelationsQuery">\n </tb-device-relations-query-config>\n </div>\n <div class="tb-form-panel stroked">\n <div class="tb-form-row no-padding no-border space-between">\n <div class="tb-form-panel-title tb-required" translate>tb.rulenode.related-device-attributes</div>\n <div class="tb-form-panel-hint tb-error" translate\n [hidden]="!(deviceAttributesConfigForm.get(\'attributesControl\').touched &&\n deviceAttributesConfigForm.get(\'attributesControl\').hasError(\'atLeastOneRequired\'))">\n tb.rulenode.at-least-one-field-required\n </div>\n </div>\n <tb-select-attributes formControlName="attributesControl"\n popupHelpLink="rulenode/related_device_attributes_node_fields_templatization"></tb-select-attributes>\n <tb-msg-metadata-chip formControlName="fetchTo"\n [labelText]="\'tb.rulenode.add-selected-attributes-to\' | translate"></tb-msg-metadata-chip>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.tell-failure-tooltip\' | translate }}"\n class="tb-form-row same-padding">\n <mat-slide-toggle class="mat-slide margin" formControlName="tellFailureIfAbsent">\n {{ \'tb.rulenode.tell-failure\' | translate }}\n </mat-slide-toggle>\n </div>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:Rn,selector:"tb-device-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:jn,selector:"tb-select-attributes",inputs:["popupHelpLink"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Zn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-device-attributes-config",template:'<section [formGroup]="deviceAttributesConfigForm" class="tb-form-panel no-padding no-border">\n <div class="tb-form-panel stroked no-padding-bottom">\n <div class="tb-form-panel-title" translate>tb.rulenode.device-relations-query</div>\n <tb-device-relations-query-config\n required\n formControlName="deviceRelationsQuery">\n </tb-device-relations-query-config>\n </div>\n <div class="tb-form-panel stroked">\n <div class="tb-form-row no-padding no-border space-between">\n <div class="tb-form-panel-title tb-required" translate>tb.rulenode.related-device-attributes</div>\n <div class="tb-form-panel-hint tb-error" translate\n [hidden]="!(deviceAttributesConfigForm.get(\'attributesControl\').touched &&\n deviceAttributesConfigForm.get(\'attributesControl\').hasError(\'atLeastOneRequired\'))">\n tb.rulenode.at-least-one-field-required\n </div>\n </div>\n <tb-select-attributes formControlName="attributesControl"\n popupHelpLink="rulenode/related_device_attributes_node_fields_templatization"></tb-select-attributes>\n <tb-msg-metadata-chip formControlName="fetchTo"\n [labelText]="\'tb.rulenode.add-selected-attributes-to\' | translate"></tb-msg-metadata-chip>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.tell-failure-tooltip\' | translate }}"\n class="tb-form-row same-padding">\n <mat-slide-toggle class="mat-slide margin" formControlName="tellFailureIfAbsent">\n {{ \'tb.rulenode.tell-failure\' | translate }}\n </mat-slide-toggle>\n </div>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class Xn extends g{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.predefinedValues=[];for(const e of Object.keys(Pt))this.predefinedValues.push({value:Pt[e],name:this.translate.instant(Rt.get(Pt[e]))})}ngOnInit(){super.ngOnInit()}configForm(){return this.entityDetailsConfigForm}prepareInputConfig(e){let t;return t=fe(e?.addToMetadata)?e.addToMetadata?ln.METADATA:ln.DATA:e?.fetchTo?e.fetchTo:ln.DATA,{detailsList:fe(e?.detailsList)?e.detailsList:null,fetchTo:t}}onConfigurationSet(e){this.entityDetailsConfigForm=this.fb.group({detailsList:[e.detailsList,[O.required]],fetchTo:[e.fetchTo,[]]})}}e("EntityDetailsConfigComponent",Xn),Xn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Xn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Xn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Xn,selector:"tb-enrichment-node-entity-details-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="entityDetailsConfigForm">\n <tb-string-items-list [predefinedValues]="predefinedValues"\n class="mat-block" required\n [label]="\'tb.rulenode.select-details\' | translate"\n [placeholder]="\'tb.rulenode.add-detail\' | translate"\n [requiredText]="\'tb.rulenode.entity-details-list-empty\' | translate"\n formControlName="detailsList">\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.chip-help\' | translate: { inputName: \'tb.rulenode.detail\' | translate } }}">\n help\n </mat-icon>\n </tb-string-items-list>\n <tb-msg-metadata-chip\n [labelText]="\'tb.rulenode.add-selected-details-to\' | translate"\n formControlName="fetchTo">\n </tb-msg-metadata-chip>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Xn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-entity-details-config",template:'<section [formGroup]="entityDetailsConfigForm">\n <tb-string-items-list [predefinedValues]="predefinedValues"\n class="mat-block" required\n [label]="\'tb.rulenode.select-details\' | translate"\n [placeholder]="\'tb.rulenode.add-detail\' | translate"\n [requiredText]="\'tb.rulenode.entity-details-list-empty\' | translate"\n formControlName="detailsList">\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.chip-help\' | translate: { inputName: \'tb.rulenode.detail\' | translate } }}">\n help\n </mat-icon>\n </tb-string-items-list>\n <tb-msg-metadata-chip\n [labelText]="\'tb.rulenode.add-selected-details-to\' | translate"\n formControlName="fetchTo">\n </tb-msg-metadata-chip>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class er extends g{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.separatorKeysCodes=[Fe,ke,Te],this.aggregationTypes=E,this.aggregations=Object.values(E),this.aggregationTypesTranslations=G,this.fetchMode=Ot,this.samplingOrders=Object.values(Kt),this.samplingOrdersTranslate=jt,this.timeUnits=Object.values(Gt),this.timeUnitsTranslationMap=wt,this.deduplicationStrategiesHintTranslations=Bt,this.headerOptions=[],this.timeUnitMap={[Gt.MILLISECONDS]:1,[Gt.SECONDS]:1e3,[Gt.MINUTES]:6e4,[Gt.HOURS]:36e5,[Gt.DAYS]:864e5},this.intervalValidator=()=>e=>e.get("startInterval").value*this.timeUnitMap[e.get("startIntervalTimeUnit").value]<=e.get("endInterval").value*this.timeUnitMap[e.get("endIntervalTimeUnit").value]?{intervalError:!0}:null;for(const e of _t.keys())this.headerOptions.push({value:e,name:this.translate.instant(_t.get(e))})}configForm(){return this.getTelemetryFromDatabaseConfigForm}onConfigurationSet(e){this.getTelemetryFromDatabaseConfigForm=this.fb.group({latestTsKeyNames:[e.latestTsKeyNames,[O.required]],aggregation:[e.aggregation,[O.required]],fetchMode:[e.fetchMode,[O.required]],orderBy:[e.orderBy,[]],limit:[e.limit,[]],useMetadataIntervalPatterns:[e.useMetadataIntervalPatterns,[]],interval:this.fb.group({startInterval:[e.interval.startInterval,[]],startIntervalTimeUnit:[e.interval.startIntervalTimeUnit,[]],endInterval:[e.interval.endInterval,[]],endIntervalTimeUnit:[e.interval.endIntervalTimeUnit,[]]}),startIntervalPattern:[e.startIntervalPattern,[]],endIntervalPattern:[e.endIntervalPattern,[]]})}validatorTriggers(){return["fetchMode","useMetadataIntervalPatterns"]}toggleChange(e){this.getTelemetryFromDatabaseConfigForm.get("fetchMode").patchValue(e,{emitEvent:!0})}prepareOutputConfig(e){return e.startInterval=e.interval.startInterval,e.startIntervalTimeUnit=e.interval.startIntervalTimeUnit,e.endInterval=e.interval.endInterval,e.endIntervalTimeUnit=e.interval.endIntervalTimeUnit,delete e.interval,be(e)}prepareInputConfig(e){return xe(e)&&(e.interval={startInterval:e.startInterval,startIntervalTimeUnit:e.startIntervalTimeUnit,endInterval:e.endInterval,endIntervalTimeUnit:e.endIntervalTimeUnit}),{latestTsKeyNames:fe(e?.latestTsKeyNames)?e.latestTsKeyNames:null,aggregation:fe(e?.aggregation)?e.aggregation:E.NONE,fetchMode:fe(e?.fetchMode)?e.fetchMode:Ot.FIRST,orderBy:fe(e?.orderBy)?e.orderBy:Kt.ASC,limit:fe(e?.limit)?e.limit:1e3,useMetadataIntervalPatterns:!!fe(e?.useMetadataIntervalPatterns)&&e.useMetadataIntervalPatterns,interval:{startInterval:fe(e?.interval?.startInterval)?e.interval.startInterval:2,startIntervalTimeUnit:fe(e?.interval?.startIntervalTimeUnit)?e.interval.startIntervalTimeUnit:Gt.MINUTES,endInterval:fe(e?.interval?.endInterval)?e.interval.endInterval:1,endIntervalTimeUnit:fe(e?.interval?.endIntervalTimeUnit)?e.interval.endIntervalTimeUnit:Gt.MINUTES},startIntervalPattern:fe(e?.startIntervalPattern)?e.startIntervalPattern:null,endIntervalPattern:fe(e?.endIntervalPattern)?e.endIntervalPattern:null}}updateValidators(e){const t=this.getTelemetryFromDatabaseConfigForm.get("fetchMode").value,n=this.getTelemetryFromDatabaseConfigForm.get("useMetadataIntervalPatterns").value;t&&t===Ot.ALL?(this.getTelemetryFromDatabaseConfigForm.get("aggregation").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("orderBy").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("limit").setValidators([O.required,O.min(2),O.max(1e3)])):(this.getTelemetryFromDatabaseConfigForm.get("aggregation").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("orderBy").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("limit").setValidators([])),n?(this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").setValidators([O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").setValidators([O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)])):(this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").setValidators([O.required,O.min(1),O.max(2147483647)]),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").setValidators([O.required,O.min(1),O.max(2147483647)]),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("interval").setValidators([this.intervalValidator()]),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").setValidators([])),this.getTelemetryFromDatabaseConfigForm.get("aggregation").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("orderBy").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("limit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").updateValueAndValidity({emitEvent:e})}removeKey(e,t){const n=this.getTelemetryFromDatabaseConfigForm.get(t).value,r=n.indexOf(e);r>=0&&(n.splice(r,1),this.getTelemetryFromDatabaseConfigForm.get(t).setValue(n,{emitEvent:!0}))}clearChipGrid(){this.getTelemetryFromDatabaseConfigForm.get("latestTsKeyNames").patchValue([],{emitEvent:!0})}addKey(e,t){const n=e.input;let r=e.value;if((r||"").trim()){r=r.trim();let e=this.getTelemetryFromDatabaseConfigForm.get(t).value;e&&-1!==e.indexOf(r)||(e||(e=[]),e.push(r),this.getTelemetryFromDatabaseConfigForm.get(t).setValue(e,{emitEvent:!0}))}n&&(n.value="")}defaultPaddingEnable(){return this.getTelemetryFromDatabaseConfigForm.get("fetchMode").value===Ot.ALL&&this.getTelemetryFromDatabaseConfigForm.get("aggregation").value===E.NONE}}e("GetTelemetryFromDatabaseConfigComponent",er),er.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:er,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),er.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:er,selector:"tb-enrichment-node-get-telemetry-from-database",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="getTelemetryFromDatabaseConfigForm" class="tb-form-panel no-padding no-border">\n <tb-string-items-list class="mat-block" editable [placeholder]="\'tb.rulenode.add-timeseries-key\' | translate"\n subscriptSizing="dynamic" required\n [requiredText]="\'tb.rulenode.timeseries-keys-required\' | translate"\n [label]="\'tb.rulenode.timeseries-keys\' | translate" formControlName="latestTsKeyNames"\n [hint]="\'tb.rulenode.general-pattern-hint\' | translate">\n <div matHintEnd class="see-example" tb-help-popup="{{\'rulenode/originator_telemetry_node_fields_templatization\'}}"\n hintMode\n tb-help-popup-placement="right"\n trigger-style="letter-spacing:0.25px; font-size:12px"\n [tb-help-popup-style]="{maxWidth: \'820px\'}"\n trigger-text="{{ \'tb.key-val.see-examples\' | translate }}"></div>\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon" color="primary"\n matTooltip="{{ \'tb.rulenode.chip-help\' | translate: { inputName: \'tb.rulenode.timeseries-key\' | translate } }}">help\n </mat-icon>\n </tb-string-items-list>\n <div class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.fetch-interval</div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.use-metadata-dynamic-interval-tooltip\' | translate }}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="useMetadataIntervalPatterns">\n {{ \'tb.rulenode.use-metadata-dynamic-interval\' | translate }}\n </mat-slide-toggle>\n </div>\n <div formGroupName="interval" fxLayout="column"\n *ngIf="getTelemetryFromDatabaseConfigForm.get(\'useMetadataIntervalPatterns\').value === false; else intervalPattern">\n <div fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="0" fxLayoutGap.gt-sm="16px">\n <mat-form-field fxFlex="50" class="mat-block">\n <mat-label>{{ \'tb.rulenode.interval-start\' | translate }}</mat-label>\n <input type="number" step="1" min="1" max="2147483647" matInput formControlName="startInterval" required>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').hasError(\'required\')">\n {{ \'tb.rulenode.start-interval-value-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').hasError(\'min\')">\n {{ \'tb.rulenode.time-value-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').hasError(\'max\')">\n {{ \'tb.rulenode.time-value-range\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex="50" class="mat-block" hideRequiredMarker>\n <mat-label>{{ \'tb.rulenode.time-unit\' | translate }}</mat-label>\n <mat-select formControlName="startIntervalTimeUnit" required>\n <mat-option *ngFor="let timeUnit of timeUnits" [value]="timeUnit">\n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="0" fxLayoutGap.gt-sm="16px">\n <mat-form-field fxFlex="50" class="mat-block">\n <mat-label>{{ \'tb.rulenode.interval-end\' | translate }}</mat-label>\n <input type="number" step="1" min="1" max="2147483647" matInput formControlName="endInterval" required>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').hasError(\'required\')">\n {{ \'tb.rulenode.end-interval-value-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').hasError(\'min\')">\n {{ \'tb.rulenode.time-value-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').hasError(\'max\')">\n {{ \'tb.rulenode.time-value-range\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex="50" class="mat-block" hideRequiredMarker>\n <mat-label>{{ \'tb.rulenode.time-unit\' | translate }}</mat-label>\n <mat-select formControlName="endIntervalTimeUnit" required>\n <mat-option *ngFor="let timeUnit of timeUnits" [value]="timeUnit">\n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div class="description-block tb-primary-fill" [class.error]="getTelemetryFromDatabaseConfigForm.get(\'interval\').invalid">\n <mat-icon class="description-icon">error_outline</mat-icon>\n <div class="description-text">\n <ng-container *ngIf="getTelemetryFromDatabaseConfigForm.get(\'interval\').valid; else invalidText">\n {{ \'tb.rulenode.fetch-timeseries-from-to\' | translate:\n {\n startInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').value,\n endInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').value,\n startIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.startIntervalTimeUnit\').value.toLowerCase(),\n endIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.endIntervalTimeUnit\').value.toLowerCase()\n } }}\n </ng-container>\n <ng-template #invalidText>\n {{ "tb.rulenode.fetch-timeseries-from-to-invalid" | translate }}\n </ng-template>\n </div>\n </div>\n </div>\n <ng-template #intervalPattern>\n <div fxLayout="column" class="input-block">\n <mat-form-field fxFlex class="mat-block">\n <mat-label>{{ \'tb.rulenode.start-interval\' | translate }}</mat-label>\n <input matInput formControlName="startIntervalPattern" required>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'startIntervalPattern\').hasError(\'required\') ||\n getTelemetryFromDatabaseConfigForm.get(\'startIntervalPattern\').hasError(\'pattern\')">\n {{ \'tb.rulenode.start-interval-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex class="mat-block">\n <mat-label>{{ \'tb.rulenode.end-interval\' | translate }}</mat-label>\n <input matInput formControlName="endIntervalPattern" required>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'endIntervalPattern\').hasError(\'required\') ||\n getTelemetryFromDatabaseConfigForm.get(\'endIntervalPattern\').hasError(\'pattern\')">\n {{ \'tb.rulenode.end-interval-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <tb-example-hint [hintText]="\'tb.rulenode.metadata-dynamic-interval-hint\' | translate"\n popupHelpLink="rulenode/originator_telemetry_node_fields_templatization">\n </tb-example-hint>\n </div>\n </ng-template>\n </div>\n <div class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.fetch-strategy</div>\n <div class="tb-form-panel no-border no-padding item-center">\n <div class="fetch-mod-toggle">\n <tb-toggle-select formControlName="fetchMode" appearance="fill">\n <tb-toggle-option *ngFor="let data of headerOptions" [value]="data.value">\n {{ data.name }}\n </tb-toggle-option>\n </tb-toggle-select>\n </div>\n <div class="tb-form-hint tb-primary-fill hint-container">\n {{ deduplicationStrategiesHintTranslations.get(getTelemetryFromDatabaseConfigForm.get(\'fetchMode\').value) | translate }}\n </div>\n </div>\n <div *ngIf="getTelemetryFromDatabaseConfigForm.get(\'fetchMode\').value === fetchMode.ALL">\n <mat-form-field class="mat-block" hideRequiredMarker\n [subscriptSizing]="defaultPaddingEnable() ? \'fixed\' : \'dynamic\'">\n <mat-label>{{ \'aggregation.function\' | translate }}</mat-label>\n <mat-select formControlName="aggregation" required>\n <mat-option *ngFor="let aggregation of aggregations" [value]="aggregation">\n {{ aggregationTypesTranslations.get(aggregationTypes[aggregation]) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <div *ngIf="getTelemetryFromDatabaseConfigForm.get(\'aggregation\').value === aggregationTypes.NONE">\n <mat-form-field class="mat-block" hideRequiredMarker>\n <mat-label> {{ "tb.rulenode.order-by-timestamp" | translate }} </mat-label>\n <mat-select formControlName="orderBy" required>\n <mat-option *ngFor="let order of samplingOrders" [value]="order">\n {{ samplingOrdersTranslate.get(order) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label>{{ "tb.rulenode.limit" | translate }}</mat-label>\n <input type="number" min="2" max="1000" step="1" matInput formControlName="limit" required>\n <mat-hint>{{ "tb.rulenode.limit-hint" | translate }}</mat-hint>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'limit\').hasError(\'required\')">\n {{ \'tb.rulenode.limit-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'limit\').hasError(\'min\')">\n {{ \'tb.rulenode.limit-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'limit\').hasError(\'max\')">\n {{ \'tb.rulenode.limit-range\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n </div>\n </div>\n</section>\n',styles:[":host .see-example{display:inline-block}:host .description-block{display:flex;align-items:center;border-radius:6px;border:1px solid #EAEAEA}:host .description-block .description-icon{font-size:24px;height:24px;min-height:24px;width:24px;min-width:24px;line-height:24px;color:#d9d9d9;margin:4px}:host .description-block .description-text{font-size:12px;line-height:16px;letter-spacing:.25px;margin:6px}:host .description-block.error{color:var(--mdc-theme-error, #f44336)}:host .description-block.error .description-icon{color:var(--mdc-theme-error, #f44336)}:host .item-center{align-items:center}:host .item-center .fetch-mod-toggle{width:100%}:host .hint-container{width:100%}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:R.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Ae.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Me.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:er,decorators:[{type:n,args:[{selector:"tb-enrichment-node-get-telemetry-from-database",template:'<section [formGroup]="getTelemetryFromDatabaseConfigForm" class="tb-form-panel no-padding no-border">\n <tb-string-items-list class="mat-block" editable [placeholder]="\'tb.rulenode.add-timeseries-key\' | translate"\n subscriptSizing="dynamic" required\n [requiredText]="\'tb.rulenode.timeseries-keys-required\' | translate"\n [label]="\'tb.rulenode.timeseries-keys\' | translate" formControlName="latestTsKeyNames"\n [hint]="\'tb.rulenode.general-pattern-hint\' | translate">\n <div matHintEnd class="see-example" tb-help-popup="{{\'rulenode/originator_telemetry_node_fields_templatization\'}}"\n hintMode\n tb-help-popup-placement="right"\n trigger-style="letter-spacing:0.25px; font-size:12px"\n [tb-help-popup-style]="{maxWidth: \'820px\'}"\n trigger-text="{{ \'tb.key-val.see-examples\' | translate }}"></div>\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon" color="primary"\n matTooltip="{{ \'tb.rulenode.chip-help\' | translate: { inputName: \'tb.rulenode.timeseries-key\' | translate } }}">help\n </mat-icon>\n </tb-string-items-list>\n <div class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.fetch-interval</div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.use-metadata-dynamic-interval-tooltip\' | translate }}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="useMetadataIntervalPatterns">\n {{ \'tb.rulenode.use-metadata-dynamic-interval\' | translate }}\n </mat-slide-toggle>\n </div>\n <div formGroupName="interval" fxLayout="column"\n *ngIf="getTelemetryFromDatabaseConfigForm.get(\'useMetadataIntervalPatterns\').value === false; else intervalPattern">\n <div fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="0" fxLayoutGap.gt-sm="16px">\n <mat-form-field fxFlex="50" class="mat-block">\n <mat-label>{{ \'tb.rulenode.interval-start\' | translate }}</mat-label>\n <input type="number" step="1" min="1" max="2147483647" matInput formControlName="startInterval" required>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').hasError(\'required\')">\n {{ \'tb.rulenode.start-interval-value-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').hasError(\'min\')">\n {{ \'tb.rulenode.time-value-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').hasError(\'max\')">\n {{ \'tb.rulenode.time-value-range\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex="50" class="mat-block" hideRequiredMarker>\n <mat-label>{{ \'tb.rulenode.time-unit\' | translate }}</mat-label>\n <mat-select formControlName="startIntervalTimeUnit" required>\n <mat-option *ngFor="let timeUnit of timeUnits" [value]="timeUnit">\n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="0" fxLayoutGap.gt-sm="16px">\n <mat-form-field fxFlex="50" class="mat-block">\n <mat-label>{{ \'tb.rulenode.interval-end\' | translate }}</mat-label>\n <input type="number" step="1" min="1" max="2147483647" matInput formControlName="endInterval" required>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').hasError(\'required\')">\n {{ \'tb.rulenode.end-interval-value-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').hasError(\'min\')">\n {{ \'tb.rulenode.time-value-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').hasError(\'max\')">\n {{ \'tb.rulenode.time-value-range\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex="50" class="mat-block" hideRequiredMarker>\n <mat-label>{{ \'tb.rulenode.time-unit\' | translate }}</mat-label>\n <mat-select formControlName="endIntervalTimeUnit" required>\n <mat-option *ngFor="let timeUnit of timeUnits" [value]="timeUnit">\n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div class="description-block tb-primary-fill" [class.error]="getTelemetryFromDatabaseConfigForm.get(\'interval\').invalid">\n <mat-icon class="description-icon">error_outline</mat-icon>\n <div class="description-text">\n <ng-container *ngIf="getTelemetryFromDatabaseConfigForm.get(\'interval\').valid; else invalidText">\n {{ \'tb.rulenode.fetch-timeseries-from-to\' | translate:\n {\n startInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').value,\n endInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').value,\n startIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.startIntervalTimeUnit\').value.toLowerCase(),\n endIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.endIntervalTimeUnit\').value.toLowerCase()\n } }}\n </ng-container>\n <ng-template #invalidText>\n {{ "tb.rulenode.fetch-timeseries-from-to-invalid" | translate }}\n </ng-template>\n </div>\n </div>\n </div>\n <ng-template #intervalPattern>\n <div fxLayout="column" class="input-block">\n <mat-form-field fxFlex class="mat-block">\n <mat-label>{{ \'tb.rulenode.start-interval\' | translate }}</mat-label>\n <input matInput formControlName="startIntervalPattern" required>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'startIntervalPattern\').hasError(\'required\') ||\n getTelemetryFromDatabaseConfigForm.get(\'startIntervalPattern\').hasError(\'pattern\')">\n {{ \'tb.rulenode.start-interval-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex class="mat-block">\n <mat-label>{{ \'tb.rulenode.end-interval\' | translate }}</mat-label>\n <input matInput formControlName="endIntervalPattern" required>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'endIntervalPattern\').hasError(\'required\') ||\n getTelemetryFromDatabaseConfigForm.get(\'endIntervalPattern\').hasError(\'pattern\')">\n {{ \'tb.rulenode.end-interval-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <tb-example-hint [hintText]="\'tb.rulenode.metadata-dynamic-interval-hint\' | translate"\n popupHelpLink="rulenode/originator_telemetry_node_fields_templatization">\n </tb-example-hint>\n </div>\n </ng-template>\n </div>\n <div class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.fetch-strategy</div>\n <div class="tb-form-panel no-border no-padding item-center">\n <div class="fetch-mod-toggle">\n <tb-toggle-select formControlName="fetchMode" appearance="fill">\n <tb-toggle-option *ngFor="let data of headerOptions" [value]="data.value">\n {{ data.name }}\n </tb-toggle-option>\n </tb-toggle-select>\n </div>\n <div class="tb-form-hint tb-primary-fill hint-container">\n {{ deduplicationStrategiesHintTranslations.get(getTelemetryFromDatabaseConfigForm.get(\'fetchMode\').value) | translate }}\n </div>\n </div>\n <div *ngIf="getTelemetryFromDatabaseConfigForm.get(\'fetchMode\').value === fetchMode.ALL">\n <mat-form-field class="mat-block" hideRequiredMarker\n [subscriptSizing]="defaultPaddingEnable() ? \'fixed\' : \'dynamic\'">\n <mat-label>{{ \'aggregation.function\' | translate }}</mat-label>\n <mat-select formControlName="aggregation" required>\n <mat-option *ngFor="let aggregation of aggregations" [value]="aggregation">\n {{ aggregationTypesTranslations.get(aggregationTypes[aggregation]) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <div *ngIf="getTelemetryFromDatabaseConfigForm.get(\'aggregation\').value === aggregationTypes.NONE">\n <mat-form-field class="mat-block" hideRequiredMarker>\n <mat-label> {{ "tb.rulenode.order-by-timestamp" | translate }} </mat-label>\n <mat-select formControlName="orderBy" required>\n <mat-option *ngFor="let order of samplingOrders" [value]="order">\n {{ samplingOrdersTranslate.get(order) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label>{{ "tb.rulenode.limit" | translate }}</mat-label>\n <input type="number" min="2" max="1000" step="1" matInput formControlName="limit" required>\n <mat-hint>{{ "tb.rulenode.limit-hint" | translate }}</mat-hint>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'limit\').hasError(\'required\')">\n {{ \'tb.rulenode.limit-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'limit\').hasError(\'min\')">\n {{ \'tb.rulenode.limit-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'limit\').hasError(\'max\')">\n {{ \'tb.rulenode.limit-range\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n </div>\n </div>\n</section>\n',styles:[":host .see-example{display:inline-block}:host .description-block{display:flex;align-items:center;border-radius:6px;border:1px solid #EAEAEA}:host .description-block .description-icon{font-size:24px;height:24px;min-height:24px;width:24px;min-width:24px;line-height:24px;color:#d9d9d9;margin:4px}:host .description-block .description-text{font-size:12px;line-height:16px;letter-spacing:.25px;margin:6px}:host .description-block.error{color:var(--mdc-theme-error, #f44336)}:host .description-block.error .description-icon{color:var(--mdc-theme-error, #f44336)}:host .item-center{align-items:center}:host .item-center .fetch-mod-toggle{width:100%}:host .hint-container{width:100%}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class tr extends g{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n}configForm(){return this.originatorAttributesConfigForm}onConfigurationSet(e){this.originatorAttributesConfigForm=this.fb.group({tellFailureIfAbsent:[e.tellFailureIfAbsent,[]],fetchTo:[e.fetchTo,[]],attributesControl:[e.attributesControl,[]]})}prepareInputConfig(e){return xe(e)&&(e.attributesControl={clientAttributeNames:fe(e?.clientAttributeNames)?e.clientAttributeNames:[],latestTsKeyNames:fe(e?.latestTsKeyNames)?e.latestTsKeyNames:[],serverAttributeNames:fe(e?.serverAttributeNames)?e.serverAttributeNames:[],sharedAttributeNames:fe(e?.sharedAttributeNames)?e.sharedAttributeNames:[],getLatestValueWithTs:!!fe(e?.getLatestValueWithTs)&&e.getLatestValueWithTs}),{fetchTo:fe(e?.fetchTo)?e.fetchTo:ln.METADATA,tellFailureIfAbsent:!!fe(e?.tellFailureIfAbsent)&&e.tellFailureIfAbsent,attributesControl:fe(e?.attributesControl)?e.attributesControl:null}}prepareOutputConfig(e){for(const t of Object.keys(e.attributesControl))e[t]=e.attributesControl[t];return delete e.attributesControl,e}}e("OriginatorAttributesConfigComponent",tr),tr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:tr,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),tr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:tr,selector:"tb-enrichment-node-originator-attributes-config",usesInheritance:!0,ngImport:t,template:'<section class="tb-form-panel no-padding no-border" [formGroup]="originatorAttributesConfigForm">\n <div class="tb-form-panel stroked">\n <div class="tb-form-row no-padding no-border space-between">\n <div class="tb-form-panel-title tb-required" translate>tb.rulenode.originator-attributes</div>\n <div class="tb-form-panel-hint tb-error" translate\n [hidden]="!(originatorAttributesConfigForm.get(\'attributesControl\').touched &&\n originatorAttributesConfigForm.get(\'attributesControl\').hasError(\'atLeastOneRequired\'))">\n tb.rulenode.at-least-one-field-required\n </div>\n </div>\n <tb-select-attributes formControlName="attributesControl"\n popupHelpLink="rulenode/originator_attributes_node_fields_templatization">\n </tb-select-attributes>\n <tb-msg-metadata-chip [labelText]="\'tb.rulenode.add-originator-attributes-to\' | translate"\n formControlName="fetchTo">\n </tb-msg-metadata-chip>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.tell-failure-tooltip\' | translate }}" class="tb-form-row same-padding">\n <mat-slide-toggle class="mat-slide margin" formControlName="tellFailureIfAbsent">\n {{ \'tb.rulenode.tell-failure\' | translate }}\n </mat-slide-toggle>\n </div>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:jn,selector:"tb-select-attributes",inputs:["popupHelpLink"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:tr,decorators:[{type:n,args:[{selector:"tb-enrichment-node-originator-attributes-config",template:'<section class="tb-form-panel no-padding no-border" [formGroup]="originatorAttributesConfigForm">\n <div class="tb-form-panel stroked">\n <div class="tb-form-row no-padding no-border space-between">\n <div class="tb-form-panel-title tb-required" translate>tb.rulenode.originator-attributes</div>\n <div class="tb-form-panel-hint tb-error" translate\n [hidden]="!(originatorAttributesConfigForm.get(\'attributesControl\').touched &&\n originatorAttributesConfigForm.get(\'attributesControl\').hasError(\'atLeastOneRequired\'))">\n tb.rulenode.at-least-one-field-required\n </div>\n </div>\n <tb-select-attributes formControlName="attributesControl"\n popupHelpLink="rulenode/originator_attributes_node_fields_templatization">\n </tb-select-attributes>\n <tb-msg-metadata-chip [labelText]="\'tb.rulenode.add-originator-attributes-to\' | translate"\n formControlName="fetchTo">\n </tb-msg-metadata-chip>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.tell-failure-tooltip\' | translate }}" class="tb-form-row same-padding">\n <mat-slide-toggle class="mat-slide margin" formControlName="tellFailureIfAbsent">\n {{ \'tb.rulenode.tell-failure\' | translate }}\n </mat-slide-toggle>\n </div>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class nr extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.originatorFields=[];for(const e of qt)this.originatorFields.push({value:e.value,name:this.translate.instant(e.name)})}configForm(){return this.originatorFieldsConfigForm}prepareOutputConfig(e){return be(e)}prepareInputConfig(e){return{dataMapping:fe(e?.dataMapping)?e.dataMapping:null,ignoreNullStrings:fe(e?.ignoreNullStrings)?e.ignoreNullStrings:null,fetchTo:fe(e?.fetchTo)?e.fetchTo:ln.METADATA}}onConfigurationSet(e){this.originatorFieldsConfigForm=this.fb.group({dataMapping:[e.dataMapping,[O.required]],ignoreNullStrings:[e.ignoreNullStrings,[]],fetchTo:[e.fetchTo,[]]})}}e("OriginatorFieldsConfigComponent",nr),nr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:nr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),nr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:nr,selector:"tb-enrichment-node-originator-fields-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="originatorFieldsConfigForm" class="tb-form-panel no-padding no-border">\n <tb-sv-map-config\n required\n [selectOptions]="originatorFields"\n targetKeyPrefix="originator"\n formControlName="dataMapping"\n [requiredText]="\'tb.rulenode.attr-mapping-required\' | translate"\n [labelText]="\'tb.rulenode.originator-fields-mapping\' | translate"\n [selectText]="\'tb.rulenode.source-field\' | translate"\n [selectRequiredText]="\'tb.rulenode.source-field-required\' | translate"\n [valText]="\'tb.rulenode.target-key\' | translate"\n [valRequiredText]="\'tb.rulenode.target-key-required\' | translate"\n [hintText]="\'tb.rulenode.originator-fields-sv-map-hint\' | translate"\n popupHelpLink="rulenode/originator_fields_node_fields_templatization">\n </tb-sv-map-config>\n <tb-msg-metadata-chip [labelText]="\'tb.rulenode.add-mapped-originator-fields-to\' | translate"\n formControlName="fetchTo">\n </tb-msg-metadata-chip>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.skip-empty-fields-tooltip\' | translate }}" class="tb-form-row same-padding">\n <mat-slide-toggle class="mat-slide margin" formControlName="ignoreNullStrings">\n {{ \'tb.rulenode.skip-empty-fields\' | translate }}\n </mat-slide-toggle>\n </div>\n</section>\n',dependencies:[{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:Hn,selector:"tb-sv-map-config",inputs:["selectOptions","disabled","labelText","requiredText","targetKeyPrefix","selectText","selectRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:nr,decorators:[{type:n,args:[{selector:"tb-enrichment-node-originator-fields-config",template:'<section [formGroup]="originatorFieldsConfigForm" class="tb-form-panel no-padding no-border">\n <tb-sv-map-config\n required\n [selectOptions]="originatorFields"\n targetKeyPrefix="originator"\n formControlName="dataMapping"\n [requiredText]="\'tb.rulenode.attr-mapping-required\' | translate"\n [labelText]="\'tb.rulenode.originator-fields-mapping\' | translate"\n [selectText]="\'tb.rulenode.source-field\' | translate"\n [selectRequiredText]="\'tb.rulenode.source-field-required\' | translate"\n [valText]="\'tb.rulenode.target-key\' | translate"\n [valRequiredText]="\'tb.rulenode.target-key-required\' | translate"\n [hintText]="\'tb.rulenode.originator-fields-sv-map-hint\' | translate"\n popupHelpLink="rulenode/originator_fields_node_fields_templatization">\n </tb-sv-map-config>\n <tb-msg-metadata-chip [labelText]="\'tb.rulenode.add-mapped-originator-fields-to\' | translate"\n formControlName="fetchTo">\n </tb-msg-metadata-chip>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.skip-empty-fields-tooltip\' | translate }}" class="tb-form-row same-padding">\n <mat-slide-toggle class="mat-slide margin" formControlName="ignoreNullStrings">\n {{ \'tb.rulenode.skip-empty-fields\' | translate }}\n </mat-slide-toggle>\n </div>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class rr extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.DataToFetch=zt,this.msgMetadataLabelTranslations=Ut,this.originatorFields=[],this.fetchToData=[];for(const e of Object.keys(qt))this.originatorFields.push({value:qt[e].value,name:this.translate.instant(qt[e].name)});for(const e of Ht.keys())this.fetchToData.push({value:e,name:this.translate.instant(Ht.get(e))})}configForm(){return this.relatedAttributesConfigForm}prepareOutputConfig(e){e.dataToFetch===zt.FIELDS?(e.dataMapping=e.svMap,delete e.svMap):(e.dataMapping=e.kvMap,delete e.kvMap);const t={};if(e&&e.dataMapping)for(const n of Object.keys(e.dataMapping))t[n.trim()]=e.dataMapping[n];return e.dataMapping=t,delete e.svMap,delete e.kvMap,be(e)}prepareInputConfig(e){let t,n,r={[F.name.value]:`relatedEntity${this.translate.instant(F.name.name)}`},o={serialNumber:"sn"};return t=fe(e?.telemetry)?e.telemetry?zt.LATEST_TELEMETRY:zt.ATTRIBUTES:fe(e?.dataToFetch)?e.dataToFetch:zt.ATTRIBUTES,n=fe(e?.attrMapping)?e.attrMapping:fe(e?.dataMapping)?e.dataMapping:null,t===zt.FIELDS?r=n:o=n,{relationsQuery:fe(e?.relationsQuery)?e.relationsQuery:null,dataToFetch:t,svMap:r,kvMap:o,fetchTo:fe(e?.fetchTo)?e.fetchTo:ln.METADATA}}selectTranslation(e,t){return this.relatedAttributesConfigForm.get("dataToFetch").value===zt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.relatedAttributesConfigForm=this.fb.group({relationsQuery:[e.relationsQuery,[O.required]],dataToFetch:[e.dataToFetch,[]],kvMap:[e.kvMap,[O.required]],svMap:[e.svMap,[O.required]],fetchTo:[e.fetchTo,[]]})}validatorTriggers(){return["dataToFetch"]}updateValidators(e){this.relatedAttributesConfigForm.get("dataToFetch").value===zt.FIELDS?(this.relatedAttributesConfigForm.get("svMap").enable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").disable({emitEvent:!1}),this.relatedAttributesConfigForm.get("svMap").updateValueAndValidity()):(this.relatedAttributesConfigForm.get("svMap").disable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").enable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").updateValueAndValidity())}}e("RelatedAttributesConfigComponent",rr),rr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:rr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),rr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:rr,selector:"tb-enrichment-node-related-attributes-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="relatedAttributesConfigForm" class="tb-form-panel no-padding no-border">\n <tb-relations-query-config\n required\n formControlName="relationsQuery">\n </tb-relations-query-config>\n <div class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.data-to-fetch</div>\n <tb-toggle-select formControlName="dataToFetch" appearance="fill">\n <tb-toggle-option *ngFor="let data of fetchToData" [value]="data.value">\n {{ data.name }}\n </tb-toggle-option>\n </tb-toggle-select>\n <tb-kv-map-config\n [hidden]="relatedAttributesConfigForm.get(\'dataToFetch\').value === DataToFetch.FIELDS"\n required\n formControlName="kvMap"\n [requiredText]="\'tb.rulenode.attr-mapping-required\' | translate"\n [labelText]="selectTranslation(\'tb.rulenode.latest-telemetry-mapping\',\'tb.rulenode.attributes-mapping\') | translate"\n [keyText]="selectTranslation(\'tb.rulenode.source-telemetry\',\'tb.rulenode.source-attribute\') | translate"\n [keyRequiredText]="selectTranslation(\'tb.rulenode.source-telemetry-required\',\'tb.rulenode.source-attribute-required\') | translate"\n [valText]="\'tb.rulenode.target-key\' | translate"\n [valRequiredText]="\'tb.rulenode.target-key-required\' | translate"\n [hintText]="\'tb.rulenode.kv-map-pattern-hint\'"\n popupHelpLink="rulenode/related_entity_data_node_fields_templatization">\n </tb-kv-map-config>\n <tb-sv-map-config\n [hidden]="relatedAttributesConfigForm.get(\'dataToFetch\').value !== DataToFetch.FIELDS"\n required\n [labelText]="\'tb.rulenode.fields-mapping\' | translate"\n targetKeyPrefix="relatedEntity"\n [selectOptions]="originatorFields"\n formControlName="svMap"\n [requiredText]="\'tb.rulenode.attr-mapping-required\' | translate"\n [selectText]="\'tb.rulenode.source-field\' | translate"\n [selectRequiredText]="\'tb.rulenode.source-field-required\' | translate"\n [valText]="\'tb.rulenode.target-key\' | translate"\n [valRequiredText]="\'tb.rulenode.target-key-required\' | translate"\n [hintText]="\'tb.rulenode.sv-map-hint\' | translate"\n popupHelpLink="rulenode/related_entity_data_node_fields_templatization">\n </tb-sv-map-config>\n <tb-msg-metadata-chip formControlName="fetchTo"\n [labelText]="msgMetadataLabelTranslations.get(relatedAttributesConfigForm.get(\'dataToFetch\').value) | translate">\n </tb-msg-metadata-chip>\n </div>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Ae.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Me.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Pn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:On,selector:"tb-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:Hn,selector:"tb-sv-map-config",inputs:["selectOptions","disabled","labelText","requiredText","targetKeyPrefix","selectText","selectRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:rr,decorators:[{type:n,args:[{selector:"tb-enrichment-node-related-attributes-config",template:'<section [formGroup]="relatedAttributesConfigForm" class="tb-form-panel no-padding no-border">\n <tb-relations-query-config\n required\n formControlName="relationsQuery">\n </tb-relations-query-config>\n <div class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.data-to-fetch</div>\n <tb-toggle-select formControlName="dataToFetch" appearance="fill">\n <tb-toggle-option *ngFor="let data of fetchToData" [value]="data.value">\n {{ data.name }}\n </tb-toggle-option>\n </tb-toggle-select>\n <tb-kv-map-config\n [hidden]="relatedAttributesConfigForm.get(\'dataToFetch\').value === DataToFetch.FIELDS"\n required\n formControlName="kvMap"\n [requiredText]="\'tb.rulenode.attr-mapping-required\' | translate"\n [labelText]="selectTranslation(\'tb.rulenode.latest-telemetry-mapping\',\'tb.rulenode.attributes-mapping\') | translate"\n [keyText]="selectTranslation(\'tb.rulenode.source-telemetry\',\'tb.rulenode.source-attribute\') | translate"\n [keyRequiredText]="selectTranslation(\'tb.rulenode.source-telemetry-required\',\'tb.rulenode.source-attribute-required\') | translate"\n [valText]="\'tb.rulenode.target-key\' | translate"\n [valRequiredText]="\'tb.rulenode.target-key-required\' | translate"\n [hintText]="\'tb.rulenode.kv-map-pattern-hint\'"\n popupHelpLink="rulenode/related_entity_data_node_fields_templatization">\n </tb-kv-map-config>\n <tb-sv-map-config\n [hidden]="relatedAttributesConfigForm.get(\'dataToFetch\').value !== DataToFetch.FIELDS"\n required\n [labelText]="\'tb.rulenode.fields-mapping\' | translate"\n targetKeyPrefix="relatedEntity"\n [selectOptions]="originatorFields"\n formControlName="svMap"\n [requiredText]="\'tb.rulenode.attr-mapping-required\' | translate"\n [selectText]="\'tb.rulenode.source-field\' | translate"\n [selectRequiredText]="\'tb.rulenode.source-field-required\' | translate"\n [valText]="\'tb.rulenode.target-key\' | translate"\n [valRequiredText]="\'tb.rulenode.target-key-required\' | translate"\n [hintText]="\'tb.rulenode.sv-map-hint\' | translate"\n popupHelpLink="rulenode/related_entity_data_node_fields_templatization">\n </tb-sv-map-config>\n <tb-msg-metadata-chip formControlName="fetchTo"\n [labelText]="msgMetadataLabelTranslations.get(relatedAttributesConfigForm.get(\'dataToFetch\').value) | translate">\n </tb-msg-metadata-chip>\n </div>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class or extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.fetchToData=[],this.DataToFetch=zt;for(const e of Ht.keys())e!==zt.FIELDS&&this.fetchToData.push({value:e,name:this.translate.instant(Ht.get(e))})}configForm(){return this.tenantAttributesConfigForm}prepareInputConfig(e){let t,n;return t=fe(e?.telemetry)?e.telemetry?zt.LATEST_TELEMETRY:zt.ATTRIBUTES:fe(e?.dataToFetch)?e.dataToFetch:zt.ATTRIBUTES,n=fe(e?.attrMapping)?e.attrMapping:fe(e?.dataMapping)?e.dataMapping:null,{dataToFetch:t,dataMapping:n,fetchTo:fe(e?.fetchTo)?e.fetchTo:ln.METADATA}}selectTranslation(e,t){return this.tenantAttributesConfigForm.get("dataToFetch").value===zt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.tenantAttributesConfigForm=this.fb.group({dataToFetch:[e.dataToFetch,[]],dataMapping:[e.dataMapping,[O.required]],fetchTo:[e.fetchTo,[]]})}}e("TenantAttributesConfigComponent",or),or.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:or,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),or.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:or,selector:"tb-enrichment-node-tenant-attributes-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="tenantAttributesConfigForm" class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.mapping-of-tenant</div>\n <div fxFlex fxLayoutAlign="center center">\n <div class="fetch-to-data-toggle">\n <tb-toggle-select class="fetch-to-data-toggle" formControlName="dataToFetch" appearance="fill">\n <tb-toggle-option *ngFor="let data of fetchToData" [value]="data.value">\n {{ data.name }}\n </tb-toggle-option>\n </tb-toggle-select>\n </div>\n </div>\n <tb-kv-map-config\n required\n formControlName="dataMapping"\n [requiredText]="\'tb.rulenode.attr-mapping-required\' | translate"\n [labelText]="selectTranslation(\'tb.rulenode.latest-telemetry-mapping\', \'tb.rulenode.attributes-mapping\') | translate"\n [keyText]="selectTranslation(\'tb.rulenode.source-telemetry\', \'tb.rulenode.source-attribute\') | translate"\n [keyRequiredText]="selectTranslation(\'tb.rulenode.source-telemetry-required\', \'tb.rulenode.source-attribute-required\') | translate"\n [valText]="\'tb.rulenode.target-key\' | translate"\n [valRequiredText]="\'tb.rulenode.target-key-required\' | translate"\n [hintText]="\'tb.rulenode.kv-map-pattern-hint\'"\n popupHelpLink="rulenode/tenant_attributes_node_fields_templatization">\n </tb-kv-map-config>\n <tb-msg-metadata-chip formControlName="fetchTo"\n [labelText]="tenantAttributesConfigForm.get(\'dataToFetch\').value === DataToFetch.LATEST_TELEMETRY ?\n (\'tb.rulenode.add-mapped-latest-telemetry-to\' | translate) : (\'tb.rulenode.add-mapped-attribute-to\' | translate)">\n </tb-msg-metadata-chip>\n</section>\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Ae.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Me.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Pn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:or,decorators:[{type:n,args:[{selector:"tb-enrichment-node-tenant-attributes-config",template:'<section [formGroup]="tenantAttributesConfigForm" class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.mapping-of-tenant</div>\n <div fxFlex fxLayoutAlign="center center">\n <div class="fetch-to-data-toggle">\n <tb-toggle-select class="fetch-to-data-toggle" formControlName="dataToFetch" appearance="fill">\n <tb-toggle-option *ngFor="let data of fetchToData" [value]="data.value">\n {{ data.name }}\n </tb-toggle-option>\n </tb-toggle-select>\n </div>\n </div>\n <tb-kv-map-config\n required\n formControlName="dataMapping"\n [requiredText]="\'tb.rulenode.attr-mapping-required\' | translate"\n [labelText]="selectTranslation(\'tb.rulenode.latest-telemetry-mapping\', \'tb.rulenode.attributes-mapping\') | translate"\n [keyText]="selectTranslation(\'tb.rulenode.source-telemetry\', \'tb.rulenode.source-attribute\') | translate"\n [keyRequiredText]="selectTranslation(\'tb.rulenode.source-telemetry-required\', \'tb.rulenode.source-attribute-required\') | translate"\n [valText]="\'tb.rulenode.target-key\' | translate"\n [valRequiredText]="\'tb.rulenode.target-key-required\' | translate"\n [hintText]="\'tb.rulenode.kv-map-pattern-hint\'"\n popupHelpLink="rulenode/tenant_attributes_node_fields_templatization">\n </tb-kv-map-config>\n <tb-msg-metadata-chip formControlName="fetchTo"\n [labelText]="tenantAttributesConfigForm.get(\'dataToFetch\').value === DataToFetch.LATEST_TELEMETRY ?\n (\'tb.rulenode.add-mapped-latest-telemetry-to\' | translate) : (\'tb.rulenode.add-mapped-attribute-to\' | translate)">\n </tb-msg-metadata-chip>\n</section>\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class ar extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.fetchDeviceCredentialsConfigForm}prepareInputConfig(e){return{fetchTo:fe(e?.fetchTo)?e.fetchTo:ln.METADATA}}onConfigurationSet(e){this.fetchDeviceCredentialsConfigForm=this.fb.group({fetchTo:[e.fetchTo,[]]})}}e("FetchDeviceCredentialsConfigComponent",ar),ar.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ar,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),ar.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ar,selector:"./tb-enrichment-node-fetch-device-credentials-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="fetchDeviceCredentialsConfigForm">\n <tb-msg-metadata-chip\n [labelText]="\'tb.rulenode.fetch-credentials-to\' | translate"\n formControlName="fetchTo">\n </tb-msg-metadata-chip>\n</section>\n',dependencies:[{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ar,decorators:[{type:n,args:[{selector:"./tb-enrichment-node-fetch-device-credentials-config",template:'<section [formGroup]="fetchDeviceCredentialsConfigForm">\n <tb-msg-metadata-chip\n [labelText]="\'tb.rulenode.fetch-credentials-to\' | translate"\n formControlName="fetchTo">\n </tb-msg-metadata-chip>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class ir{}e("RulenodeCoreConfigEnrichmentModule",ir),ir.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ir,deps:[],target:t.ɵɵFactoryTarget.NgModule}),ir.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:ir,declarations:[Wn,Xn,Zn,tr,nr,er,rr,or,Yn,ar],imports:[$,M,Jn],exports:[Wn,Xn,Zn,tr,nr,er,rr,or,Yn,ar]}),ir.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ir,imports:[$,M,Jn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ir,decorators:[{type:d,args:[{declarations:[Wn,Xn,Zn,tr,nr,er,rr,or,Yn,ar],imports:[$,M,Jn],exports:[Wn,Xn,Zn,tr,nr,er,rr,or,Yn,ar]}]}]});class lr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.allAzureIotHubCredentialsTypes=Wt,this.azureIotHubCredentialsTypeTranslationsMap=Zt}configForm(){return this.azureIotHubConfigForm}onConfigurationSet(e){this.azureIotHubConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[O.required]],host:[e?e.host:null,[O.required]],port:[e?e.port:null,[O.required,O.min(1),O.max(65535)]],connectTimeoutSec:[e?e.connectTimeoutSec:null,[O.required,O.min(1),O.max(200)]],clientId:[e?e.clientId:null,[O.required]],cleanSession:[!!e&&e.cleanSession,[]],ssl:[!!e&&e.ssl,[]],credentials:this.fb.group({type:[e&&e.credentials?e.credentials.type:null,[O.required]],sasKey:[e&&e.credentials?e.credentials.sasKey:null,[]],caCert:[e&&e.credentials?e.credentials.caCert:null,[]],caCertFileName:[e&&e.credentials?e.credentials.caCertFileName:null,[]],privateKey:[e&&e.credentials?e.credentials.privateKey:null,[]],privateKeyFileName:[e&&e.credentials?e.credentials.privateKeyFileName:null,[]],cert:[e&&e.credentials?e.credentials.cert:null,[]],certFileName:[e&&e.credentials?e.credentials.certFileName:null,[]],password:[e&&e.credentials?e.credentials.password:null,[]]})})}prepareOutputConfig(e){const t=e.credentials.type;return"sas"===t&&(e.credentials={type:t,sasKey:e.credentials.sasKey,caCert:e.credentials.caCert,caCertFileName:e.credentials.caCertFileName}),e}validatorTriggers(){return["credentials.type"]}updateValidators(e){const t=this.azureIotHubConfigForm.get("credentials"),n=t.get("type").value;switch(e&&t.reset({type:n},{emitEvent:!1}),t.get("sasKey").setValidators([]),t.get("privateKey").setValidators([]),t.get("privateKeyFileName").setValidators([]),t.get("cert").setValidators([]),t.get("certFileName").setValidators([]),n){case"sas":t.get("sasKey").setValidators([O.required]);break;case"cert.PEM":t.get("privateKey").setValidators([O.required]),t.get("privateKeyFileName").setValidators([O.required]),t.get("cert").setValidators([O.required]),t.get("certFileName").setValidators([O.required])}t.get("sasKey").updateValueAndValidity({emitEvent:e}),t.get("privateKey").updateValueAndValidity({emitEvent:e}),t.get("privateKeyFileName").updateValueAndValidity({emitEvent:e}),t.get("cert").updateValueAndValidity({emitEvent:e}),t.get("certFileName").updateValueAndValidity({emitEvent:e})}}e("AzureIotHubConfigComponent",lr),lr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:lr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),lr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:lr,selector:"tb-external-node-azure-iot-hub-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="azureIotHubConfigForm" fxLayout="column">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.topic</mat-label>\n <input required matInput formControlName="topicPattern">\n <mat-error *ngIf="azureIotHubConfigForm.get(\'topicPattern\').hasError(\'required\')">\n {{ \'tb.rulenode.topic-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.hostname</mat-label>\n <input required matInput formControlName="host">\n <mat-error *ngIf="azureIotHubConfigForm.get(\'host\').hasError(\'required\')">\n {{ \'tb.rulenode.hostname-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.device-id</mat-label>\n <input required matInput formControlName="clientId" autocomplete="new-clientId">\n <mat-error *ngIf="azureIotHubConfigForm.get(\'clientId\').hasError(\'required\')">\n {{ \'tb.rulenode.device-id-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-accordion>\n <mat-expansion-panel class="tb-mqtt-credentials-panel-group">\n <mat-expansion-panel-header>\n <mat-panel-title class="tb-required" translate>tb.rulenode.credentials</mat-panel-title>\n <mat-panel-description>\n {{ azureIotHubCredentialsTypeTranslationsMap.get(azureIotHubConfigForm.get(\'credentials.type\').value) | translate }}\n </mat-panel-description>\n </mat-expansion-panel-header>\n <section formGroupName="credentials" fxLayout="column">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.credentials-type</mat-label>\n <mat-select formControlName="type" required>\n <mat-option *ngFor="let credentialsType of allAzureIotHubCredentialsTypes" [value]="credentialsType">\n {{ azureIotHubCredentialsTypeTranslationsMap.get(credentialsType) | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf="azureIotHubConfigForm.get(\'credentials.type\').hasError(\'required\')">\n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <section fxLayout="column" [ngSwitch]="azureIotHubConfigForm.get(\'credentials.type\').value">\n <ng-template ngSwitchCase="anonymous">\n </ng-template>\n <ng-template ngSwitchCase="sas">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.sas-key</mat-label>\n <input type="password" required matInput formControlName="sasKey" autocomplete="new-password">\n <tb-toggle-password matSuffix></tb-toggle-password>\n <mat-error *ngIf="azureIotHubConfigForm.get(\'credentials.sasKey\').hasError(\'required\')">\n {{ \'tb.rulenode.sas-key-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <tb-file-input formControlName="caCert"\n inputId="caCertSelect"\n [existingFileName]="azureIotHubConfigForm.get(\'credentials.caCertFileName\').value"\n (fileNameChanged)="azureIotHubConfigForm.get(\'credentials.caCertFileName\').setValue($event)"\n label="{{\'tb.rulenode.azure-ca-cert\' | translate}}"\n noFileText="tb.rulenode.no-file"\n dropLabel="{{\'tb.rulenode.drop-file\' | translate}}">\n </tb-file-input>\n </ng-template>\n <ng-template ngSwitchCase="cert.PEM">\n <tb-file-input formControlName="caCert"\n inputId="caCertSelect"\n [existingFileName]="azureIotHubConfigForm.get(\'credentials.caCertFileName\').value"\n (fileNameChanged)="azureIotHubConfigForm.get(\'credentials.caCertFileName\').setValue($event)"\n label="{{\'tb.rulenode.azure-ca-cert\' | translate}}"\n noFileText="tb.rulenode.no-file"\n dropLabel="{{\'tb.rulenode.drop-file\' | translate}}">\n </tb-file-input>\n <tb-file-input formControlName="cert"\n inputId="CertSelect"\n [existingFileName]="azureIotHubConfigForm.get(\'credentials.certFileName\').value"\n (fileNameChanged)="azureIotHubConfigForm.get(\'credentials.certFileName\').setValue($event)"\n required\n requiredAsError\n label="{{\'tb.rulenode.cert\' | translate}}"\n noFileText="tb.rulenode.no-file"\n dropLabel="{{\'tb.rulenode.drop-file\' | translate}}">\n </tb-file-input>\n <tb-file-input style="padding-bottom: 8px;"\n formControlName="privateKey"\n inputId="privateKeySelect"\n [existingFileName]="azureIotHubConfigForm.get(\'credentials.privateKeyFileName\').value"\n (fileNameChanged)="azureIotHubConfigForm.get(\'credentials.privateKeyFileName\').setValue($event)"\n required\n requiredAsError\n label="{{\'tb.rulenode.private-key\' | translate}}"\n noFileText="tb.rulenode.no-file"\n dropLabel="{{\'tb.rulenode.drop-file\' | translate}}">\n </tb-file-input>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.private-key-password</mat-label>\n <input type="password" matInput formControlName="password" autocomplete="new-password">\n <tb-toggle-password matSuffix></tb-toggle-password>\n </mat-form-field>\n </ng-template>\n </section>\n </section>\n </mat-expansion-panel>\n </mat-accordion>\n</section>\n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:U.NgSwitch,selector:"[ngSwitch]",inputs:["ngSwitch"]},{kind:"directive",type:U.NgSwitchCase,selector:"[ngSwitchCase]",inputs:["ngSwitchCase"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:oe.MatAccordion,selector:"mat-accordion",inputs:["multi","hideToggle","displayMode","togglePosition"],exportAs:["matAccordion"]},{kind:"component",type:oe.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:oe.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:oe.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:oe.MatExpansionPanelDescription,selector:"mat-panel-description"},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:R.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"component",type:Ze.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Xe.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:lr,decorators:[{type:n,args:[{selector:"tb-external-node-azure-iot-hub-config",template:'<section [formGroup]="azureIotHubConfigForm" fxLayout="column">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.topic</mat-label>\n <input required matInput formControlName="topicPattern">\n <mat-error *ngIf="azureIotHubConfigForm.get(\'topicPattern\').hasError(\'required\')">\n {{ \'tb.rulenode.topic-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.hostname</mat-label>\n <input required matInput formControlName="host">\n <mat-error *ngIf="azureIotHubConfigForm.get(\'host\').hasError(\'required\')">\n {{ \'tb.rulenode.hostname-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.device-id</mat-label>\n <input required matInput formControlName="clientId" autocomplete="new-clientId">\n <mat-error *ngIf="azureIotHubConfigForm.get(\'clientId\').hasError(\'required\')">\n {{ \'tb.rulenode.device-id-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-accordion>\n <mat-expansion-panel class="tb-mqtt-credentials-panel-group">\n <mat-expansion-panel-header>\n <mat-panel-title class="tb-required" translate>tb.rulenode.credentials</mat-panel-title>\n <mat-panel-description>\n {{ azureIotHubCredentialsTypeTranslationsMap.get(azureIotHubConfigForm.get(\'credentials.type\').value) | translate }}\n </mat-panel-description>\n </mat-expansion-panel-header>\n <section formGroupName="credentials" fxLayout="column">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.credentials-type</mat-label>\n <mat-select formControlName="type" required>\n <mat-option *ngFor="let credentialsType of allAzureIotHubCredentialsTypes" [value]="credentialsType">\n {{ azureIotHubCredentialsTypeTranslationsMap.get(credentialsType) | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf="azureIotHubConfigForm.get(\'credentials.type\').hasError(\'required\')">\n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <section fxLayout="column" [ngSwitch]="azureIotHubConfigForm.get(\'credentials.type\').value">\n <ng-template ngSwitchCase="anonymous">\n </ng-template>\n <ng-template ngSwitchCase="sas">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.sas-key</mat-label>\n <input type="password" required matInput formControlName="sasKey" autocomplete="new-password">\n <tb-toggle-password matSuffix></tb-toggle-password>\n <mat-error *ngIf="azureIotHubConfigForm.get(\'credentials.sasKey\').hasError(\'required\')">\n {{ \'tb.rulenode.sas-key-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <tb-file-input formControlName="caCert"\n inputId="caCertSelect"\n [existingFileName]="azureIotHubConfigForm.get(\'credentials.caCertFileName\').value"\n (fileNameChanged)="azureIotHubConfigForm.get(\'credentials.caCertFileName\').setValue($event)"\n label="{{\'tb.rulenode.azure-ca-cert\' | translate}}"\n noFileText="tb.rulenode.no-file"\n dropLabel="{{\'tb.rulenode.drop-file\' | translate}}">\n </tb-file-input>\n </ng-template>\n <ng-template ngSwitchCase="cert.PEM">\n <tb-file-input formControlName="caCert"\n inputId="caCertSelect"\n [existingFileName]="azureIotHubConfigForm.get(\'credentials.caCertFileName\').value"\n (fileNameChanged)="azureIotHubConfigForm.get(\'credentials.caCertFileName\').setValue($event)"\n label="{{\'tb.rulenode.azure-ca-cert\' | translate}}"\n noFileText="tb.rulenode.no-file"\n dropLabel="{{\'tb.rulenode.drop-file\' | translate}}">\n </tb-file-input>\n <tb-file-input formControlName="cert"\n inputId="CertSelect"\n [existingFileName]="azureIotHubConfigForm.get(\'credentials.certFileName\').value"\n (fileNameChanged)="azureIotHubConfigForm.get(\'credentials.certFileName\').setValue($event)"\n required\n requiredAsError\n label="{{\'tb.rulenode.cert\' | translate}}"\n noFileText="tb.rulenode.no-file"\n dropLabel="{{\'tb.rulenode.drop-file\' | translate}}">\n </tb-file-input>\n <tb-file-input style="padding-bottom: 8px;"\n formControlName="privateKey"\n inputId="privateKeySelect"\n [existingFileName]="azureIotHubConfigForm.get(\'credentials.privateKeyFileName\').value"\n (fileNameChanged)="azureIotHubConfigForm.get(\'credentials.privateKeyFileName\').setValue($event)"\n required\n requiredAsError\n label="{{\'tb.rulenode.private-key\' | translate}}"\n noFileText="tb.rulenode.no-file"\n dropLabel="{{\'tb.rulenode.drop-file\' | translate}}">\n </tb-file-input>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.private-key-password</mat-label>\n <input type="password" matInput formControlName="password" autocomplete="new-password">\n <tb-toggle-password matSuffix></tb-toggle-password>\n </mat-form-field>\n </ng-template>\n </section>\n </section>\n </mat-expansion-panel>\n </mat-accordion>\n</section>\n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class sr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.ackValues=["all","-1","0","1"],this.ToByteStandartCharsetTypesValues=en,this.ToByteStandartCharsetTypeTranslationMap=tn}configForm(){return this.kafkaConfigForm}onConfigurationSet(e){this.kafkaConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[O.required]],keyPattern:[e?e.keyPattern:null],bootstrapServers:[e?e.bootstrapServers:null,[O.required]],retries:[e?e.retries:null,[O.min(0)]],batchSize:[e?e.batchSize:null,[O.min(0)]],linger:[e?e.linger:null,[O.min(0)]],bufferMemory:[e?e.bufferMemory:null,[O.min(0)]],acks:[e?e.acks:null,[O.required]],keySerializer:[e?e.keySerializer:null,[O.required]],valueSerializer:[e?e.valueSerializer:null,[O.required]],otherProperties:[e?e.otherProperties:null,[]],addMetadataKeyValuesAsKafkaHeaders:[!!e&&e.addMetadataKeyValuesAsKafkaHeaders,[]],kafkaHeadersCharset:[e?e.kafkaHeadersCharset:null,[]]})}validatorTriggers(){return["addMetadataKeyValuesAsKafkaHeaders"]}updateValidators(e){this.kafkaConfigForm.get("addMetadataKeyValuesAsKafkaHeaders").value?this.kafkaConfigForm.get("kafkaHeadersCharset").setValidators([O.required]):this.kafkaConfigForm.get("kafkaHeadersCharset").setValidators([]),this.kafkaConfigForm.get("kafkaHeadersCharset").updateValueAndValidity({emitEvent:e})}}e("KafkaConfigComponent",sr),sr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:sr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),sr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:sr,selector:"tb-external-node-kafka-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="kafkaConfigForm" fxLayout="column">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.topic-pattern</mat-label>\n <input required matInput formControlName="topicPattern">\n <mat-error *ngIf="kafkaConfigForm.get(\'topicPattern\').hasError(\'required\')">\n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.key-pattern</mat-label>\n <input matInput formControlName="keyPattern">\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <div class="tb-hint" translate>tb.rulenode.key-pattern-hint</div>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.bootstrap-servers</mat-label>\n <input required matInput formControlName="bootstrapServers">\n <mat-error *ngIf="kafkaConfigForm.get(\'bootstrapServers\').hasError(\'required\')">\n {{ \'tb.rulenode.bootstrap-servers-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.retries</mat-label>\n <input type="number" step="1" min="0" matInput formControlName="retries">\n <mat-error *ngIf="kafkaConfigForm.get(\'retries\').hasError(\'min\')">\n {{ \'tb.rulenode.min-retries-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.batch-size-bytes</mat-label>\n <input type="number" step="1" min="0" matInput formControlName="batchSize">\n <mat-error *ngIf="kafkaConfigForm.get(\'batchSize\').hasError(\'min\')">\n {{ \'tb.rulenode.min-batch-size-bytes-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.linger-ms</mat-label>\n <input type="number" step="1" min="0" matInput formControlName="linger">\n <mat-error *ngIf="kafkaConfigForm.get(\'linger\').hasError(\'min\')">\n {{ \'tb.rulenode.min-linger-ms-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.buffer-memory-bytes</mat-label>\n <input type="number" step="1" min="0" matInput formControlName="bufferMemory">\n <mat-error *ngIf="kafkaConfigForm.get(\'bufferMemory\').hasError(\'min\')">\n {{ \'tb.rulenode.min-buffer-memory-bytes-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.acks</mat-label>\n <mat-select formControlName="acks" required>\n <mat-option *ngFor="let ackValue of ackValues" [value]="ackValue">\n {{ ackValue }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.key-serializer</mat-label>\n <input required matInput formControlName="keySerializer">\n <mat-error *ngIf="kafkaConfigForm.get(\'keySerializer\').hasError(\'required\')">\n {{ \'tb.rulenode.key-serializer-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.value-serializer</mat-label>\n <input required matInput formControlName="valueSerializer">\n <mat-error *ngIf="kafkaConfigForm.get(\'valueSerializer\').hasError(\'required\')">\n {{ \'tb.rulenode.value-serializer-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <label translate class="tb-title">tb.rulenode.other-properties</label>\n <tb-kv-map-config-old\n required="false"\n formControlName="otherProperties"\n keyText="tb.rulenode.key"\n keyRequiredText="tb.rulenode.key-required"\n valText="tb.rulenode.value"\n valRequiredText="tb.rulenode.value-required">\n </tb-kv-map-config-old>\n <mat-checkbox fxFlex formControlName="addMetadataKeyValuesAsKafkaHeaders">\n {{ \'tb.rulenode.add-metadata-key-values-as-kafka-headers\' | translate }}\n </mat-checkbox>\n <div class="tb-hint" translate>tb.rulenode.add-metadata-key-values-as-kafka-headers-hint</div>\n <mat-form-field fxFlex class="mat-block" *ngIf="kafkaConfigForm.get(\'addMetadataKeyValuesAsKafkaHeaders\').value">\n <mat-label translate>tb.rulenode.charset-encoding</mat-label>\n <mat-select formControlName="kafkaHeadersCharset" required>\n <mat-option *ngFor="let charset of ToByteStandartCharsetTypesValues" [value]="charset">\n {{ ToByteStandartCharsetTypeTranslationMap.get(charset) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n</section>\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:sr,decorators:[{type:n,args:[{selector:"tb-external-node-kafka-config",template:'<section [formGroup]="kafkaConfigForm" fxLayout="column">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.topic-pattern</mat-label>\n <input required matInput formControlName="topicPattern">\n <mat-error *ngIf="kafkaConfigForm.get(\'topicPattern\').hasError(\'required\')">\n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.key-pattern</mat-label>\n <input matInput formControlName="keyPattern">\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <div class="tb-hint" translate>tb.rulenode.key-pattern-hint</div>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.bootstrap-servers</mat-label>\n <input required matInput formControlName="bootstrapServers">\n <mat-error *ngIf="kafkaConfigForm.get(\'bootstrapServers\').hasError(\'required\')">\n {{ \'tb.rulenode.bootstrap-servers-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.retries</mat-label>\n <input type="number" step="1" min="0" matInput formControlName="retries">\n <mat-error *ngIf="kafkaConfigForm.get(\'retries\').hasError(\'min\')">\n {{ \'tb.rulenode.min-retries-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.batch-size-bytes</mat-label>\n <input type="number" step="1" min="0" matInput formControlName="batchSize">\n <mat-error *ngIf="kafkaConfigForm.get(\'batchSize\').hasError(\'min\')">\n {{ \'tb.rulenode.min-batch-size-bytes-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.linger-ms</mat-label>\n <input type="number" step="1" min="0" matInput formControlName="linger">\n <mat-error *ngIf="kafkaConfigForm.get(\'linger\').hasError(\'min\')">\n {{ \'tb.rulenode.min-linger-ms-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.buffer-memory-bytes</mat-label>\n <input type="number" step="1" min="0" matInput formControlName="bufferMemory">\n <mat-error *ngIf="kafkaConfigForm.get(\'bufferMemory\').hasError(\'min\')">\n {{ \'tb.rulenode.min-buffer-memory-bytes-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.acks</mat-label>\n <mat-select formControlName="acks" required>\n <mat-option *ngFor="let ackValue of ackValues" [value]="ackValue">\n {{ ackValue }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.key-serializer</mat-label>\n <input required matInput formControlName="keySerializer">\n <mat-error *ngIf="kafkaConfigForm.get(\'keySerializer\').hasError(\'required\')">\n {{ \'tb.rulenode.key-serializer-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.value-serializer</mat-label>\n <input required matInput formControlName="valueSerializer">\n <mat-error *ngIf="kafkaConfigForm.get(\'valueSerializer\').hasError(\'required\')">\n {{ \'tb.rulenode.value-serializer-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <label translate class="tb-title">tb.rulenode.other-properties</label>\n <tb-kv-map-config-old\n required="false"\n formControlName="otherProperties"\n keyText="tb.rulenode.key"\n keyRequiredText="tb.rulenode.key-required"\n valText="tb.rulenode.value"\n valRequiredText="tb.rulenode.value-required">\n </tb-kv-map-config-old>\n <mat-checkbox fxFlex formControlName="addMetadataKeyValuesAsKafkaHeaders">\n {{ \'tb.rulenode.add-metadata-key-values-as-kafka-headers\' | translate }}\n </mat-checkbox>\n <div class="tb-hint" translate>tb.rulenode.add-metadata-key-values-as-kafka-headers-hint</div>\n <mat-form-field fxFlex class="mat-block" *ngIf="kafkaConfigForm.get(\'addMetadataKeyValuesAsKafkaHeaders\').value">\n <mat-label translate>tb.rulenode.charset-encoding</mat-label>\n <mat-select formControlName="kafkaHeadersCharset" required>\n <mat-option *ngFor="let charset of ToByteStandartCharsetTypesValues" [value]="charset">\n {{ ToByteStandartCharsetTypeTranslationMap.get(charset) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class mr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.mqttConfigForm}onConfigurationSet(e){this.mqttConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[O.required]],host:[e?e.host:null,[O.required]],port:[e?e.port:null,[O.required,O.min(1),O.max(65535)]],connectTimeoutSec:[e?e.connectTimeoutSec:null,[O.required,O.min(1),O.max(200)]],clientId:[e?e.clientId:null,[]],appendClientIdSuffix:[{value:!!e&&e.appendClientIdSuffix,disabled:!(e&&he(e.clientId))},[]],parseToPlainText:[!!e&&e.parseToPlainText,[]],cleanSession:[!!e&&e.cleanSession,[]],retainedMessage:[!!e&&e.retainedMessage,[]],ssl:[!!e&&e.ssl,[]],credentials:[e?e.credentials:null,[]]})}updateValidators(e){he(this.mqttConfigForm.get("clientId").value)?this.mqttConfigForm.get("appendClientIdSuffix").enable({emitEvent:!1}):this.mqttConfigForm.get("appendClientIdSuffix").disable({emitEvent:!1}),this.mqttConfigForm.get("appendClientIdSuffix").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["clientId"]}}e("MqttConfigComponent",mr),mr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:mr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),mr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:mr,selector:"tb-external-node-mqtt-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="mqttConfigForm" fxLayout="column">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.topic-pattern</mat-label>\n <input required matInput formControlName="topicPattern">\n <mat-error *ngIf="mqttConfigForm.get(\'topicPattern\').hasError(\'required\')">\n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <div fxFlex fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap.gt-sm="8px">\n <mat-form-field fxFlex="60" class="mat-block">\n <mat-label translate>tb.rulenode.host</mat-label>\n <input required matInput formControlName="host">\n <mat-error *ngIf="mqttConfigForm.get(\'host\').hasError(\'required\')">\n {{ \'tb.rulenode.host-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex="40" class="mat-block">\n <mat-label translate>tb.rulenode.port</mat-label>\n <input required type="number" step="1" min="1" max="65535" matInput formControlName="port">\n <mat-error *ngIf="mqttConfigForm.get(\'port\').hasError(\'required\')">\n {{ \'tb.rulenode.port-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="mqttConfigForm.get(\'port\').hasError(\'min\')">\n {{ \'tb.rulenode.port-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="mqttConfigForm.get(\'port\').hasError(\'max\')">\n {{ \'tb.rulenode.port-range\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex="40" class="mat-block">\n <mat-label translate>tb.rulenode.connect-timeout</mat-label>\n <input required type="number" step="1" min="1" max="200" matInput formControlName="connectTimeoutSec">\n <mat-error *ngIf="mqttConfigForm.get(\'connectTimeoutSec\').hasError(\'required\')">\n {{ \'tb.rulenode.connect-timeout-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="mqttConfigForm.get(\'connectTimeoutSec\').hasError(\'min\')">\n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="mqttConfigForm.get(\'connectTimeoutSec\').hasError(\'max\')">\n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.client-id</mat-label>\n <input matInput formControlName="clientId">\n <mat-hint>{{\'tb.rulenode.client-id-hint\' | translate}}</mat-hint>\n </mat-form-field>\n <mat-checkbox formControlName="appendClientIdSuffix">\n {{ \'tb.rulenode.append-client-id-suffix\' | translate }}\n </mat-checkbox>\n <div class="tb-hint">{{ "tb.rulenode.client-id-suffix-hint" | translate }}</div>\n <mat-checkbox formControlName="parseToPlainText">\n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n </mat-checkbox>\n <div class="tb-hint">{{ "tb.rulenode.parse-to-plain-text-hint" | translate }}</div>\n <mat-checkbox formControlName="cleanSession">\n {{ \'tb.rulenode.clean-session\' | translate }}\n </mat-checkbox>\n <mat-checkbox formControlName="retainedMessage">\n {{ "tb.rulenode.retained-message" | translate }}\n </mat-checkbox>\n <mat-checkbox formControlName="ssl">\n {{ \'tb.rulenode.enable-ssl\' | translate }}\n </mat-checkbox>\n <tb-credentials-config formControlName="credentials" [passwordFieldRequired]="false"></tb-credentials-config>\n</section>\n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n"],dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Bn,selector:"tb-credentials-config",inputs:["required","disableCertPemCredentials","passwordFieldRequired"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:mr,decorators:[{type:n,args:[{selector:"tb-external-node-mqtt-config",template:'<section [formGroup]="mqttConfigForm" fxLayout="column">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.topic-pattern</mat-label>\n <input required matInput formControlName="topicPattern">\n <mat-error *ngIf="mqttConfigForm.get(\'topicPattern\').hasError(\'required\')">\n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <div fxFlex fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap.gt-sm="8px">\n <mat-form-field fxFlex="60" class="mat-block">\n <mat-label translate>tb.rulenode.host</mat-label>\n <input required matInput formControlName="host">\n <mat-error *ngIf="mqttConfigForm.get(\'host\').hasError(\'required\')">\n {{ \'tb.rulenode.host-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex="40" class="mat-block">\n <mat-label translate>tb.rulenode.port</mat-label>\n <input required type="number" step="1" min="1" max="65535" matInput formControlName="port">\n <mat-error *ngIf="mqttConfigForm.get(\'port\').hasError(\'required\')">\n {{ \'tb.rulenode.port-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="mqttConfigForm.get(\'port\').hasError(\'min\')">\n {{ \'tb.rulenode.port-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="mqttConfigForm.get(\'port\').hasError(\'max\')">\n {{ \'tb.rulenode.port-range\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex="40" class="mat-block">\n <mat-label translate>tb.rulenode.connect-timeout</mat-label>\n <input required type="number" step="1" min="1" max="200" matInput formControlName="connectTimeoutSec">\n <mat-error *ngIf="mqttConfigForm.get(\'connectTimeoutSec\').hasError(\'required\')">\n {{ \'tb.rulenode.connect-timeout-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="mqttConfigForm.get(\'connectTimeoutSec\').hasError(\'min\')">\n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="mqttConfigForm.get(\'connectTimeoutSec\').hasError(\'max\')">\n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.client-id</mat-label>\n <input matInput formControlName="clientId">\n <mat-hint>{{\'tb.rulenode.client-id-hint\' | translate}}</mat-hint>\n </mat-form-field>\n <mat-checkbox formControlName="appendClientIdSuffix">\n {{ \'tb.rulenode.append-client-id-suffix\' | translate }}\n </mat-checkbox>\n <div class="tb-hint">{{ "tb.rulenode.client-id-suffix-hint" | translate }}</div>\n <mat-checkbox formControlName="parseToPlainText">\n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n </mat-checkbox>\n <div class="tb-hint">{{ "tb.rulenode.parse-to-plain-text-hint" | translate }}</div>\n <mat-checkbox formControlName="cleanSession">\n {{ \'tb.rulenode.clean-session\' | translate }}\n </mat-checkbox>\n <mat-checkbox formControlName="retainedMessage">\n {{ "tb.rulenode.retained-message" | translate }}\n </mat-checkbox>\n <mat-checkbox formControlName="ssl">\n {{ \'tb.rulenode.enable-ssl\' | translate }}\n </mat-checkbox>\n <tb-credentials-config formControlName="credentials" [passwordFieldRequired]="false"></tb-credentials-config>\n</section>\n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class pr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.notificationType=w,this.entityType=C}configForm(){return this.notificationConfigForm}onConfigurationSet(e){this.notificationConfigForm=this.fb.group({templateId:[e?e.templateId:null,[O.required]],targets:[e?e.targets:[],[O.required]]})}}e("NotificationConfigComponent",pr),pr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:pr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),pr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:pr,selector:"tb-external-node-notification-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="notificationConfigForm" fxLayout="column">\n <tb-template-autocomplete\n required\n allowCreate\n formControlName="templateId"\n [notificationTypes]="notificationType.RULE_NODE">\n </tb-template-autocomplete>\n <tb-entity-list\n required\n formControlName="targets"\n labelText="{{ \'notification.recipients\' | translate }}"\n placeholderText="{{ \'notification.recipient\' | translate }}"\n requiredText="{{ \'notification.recipients-required\' | translate }}"\n entityType="{{ entityType.NOTIFICATION_TARGET }}"\n subType="{{ notificationType.RULE_NODE }}">\n </tb-entity-list>\n</section>\n',dependencies:[{kind:"component",type:tt.EntityListComponent,selector:"tb-entity-list",inputs:["entityType","subType","labelText","placeholderText","requiredText","required","disabled","subscriptSizing","hint"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:nt.TemplateAutocompleteComponent,selector:"tb-template-autocomplete",inputs:["required","allowCreate","allowEdit","disabled","notificationTypes"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:pr,decorators:[{type:n,args:[{selector:"tb-external-node-notification-config",template:'<section [formGroup]="notificationConfigForm" fxLayout="column">\n <tb-template-autocomplete\n required\n allowCreate\n formControlName="templateId"\n [notificationTypes]="notificationType.RULE_NODE">\n </tb-template-autocomplete>\n <tb-entity-list\n required\n formControlName="targets"\n labelText="{{ \'notification.recipients\' | translate }}"\n placeholderText="{{ \'notification.recipient\' | translate }}"\n requiredText="{{ \'notification.recipients-required\' | translate }}"\n entityType="{{ entityType.NOTIFICATION_TARGET }}"\n subType="{{ notificationType.RULE_NODE }}">\n </tb-entity-list>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class dr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.pubSubConfigForm}onConfigurationSet(e){this.pubSubConfigForm=this.fb.group({projectId:[e?e.projectId:null,[O.required]],topicName:[e?e.topicName:null,[O.required]],serviceAccountKey:[e?e.serviceAccountKey:null,[O.required]],serviceAccountKeyFileName:[e?e.serviceAccountKeyFileName:null,[O.required]],messageAttributes:[e?e.messageAttributes:null,[]]})}}e("PubSubConfigComponent",dr),dr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),dr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:dr,selector:"tb-external-node-pub-sub-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="pubSubConfigForm" fxLayout="column">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.gcp-project-id</mat-label>\n <input required matInput formControlName="projectId">\n <mat-error *ngIf="pubSubConfigForm.get(\'projectId\').hasError(\'required\')">\n {{ \'tb.rulenode.gcp-project-id-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.pubsub-topic-name</mat-label>\n <input required matInput formControlName="topicName">\n <mat-error *ngIf="pubSubConfigForm.get(\'topicName\').hasError(\'required\')">\n {{ \'tb.rulenode.pubsub-topic-name-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <tb-file-input style="padding-bottom: 24px;"\n formControlName="serviceAccountKey"\n [existingFileName]="pubSubConfigForm.get(\'serviceAccountKeyFileName\').value"\n (fileNameChanged)="pubSubConfigForm.get(\'serviceAccountKeyFileName\').setValue($event)"\n required\n requiredAsError\n label="{{\'tb.rulenode.gcp-service-account-key\' | translate}}"\n noFileText="tb.rulenode.no-file"\n dropLabel="{{\'tb.rulenode.drop-file\' | translate}}">\n </tb-file-input>\n <label translate class="tb-title">tb.rulenode.message-attributes</label>\n <div class="tb-hint" [innerHTML]="\'tb.rulenode.message-attributes-hint\' | translate | safe: \'html\'"></div>\n <tb-kv-map-config-old\n required="false"\n formControlName="messageAttributes"\n keyText="tb.rulenode.name"\n keyRequiredText="tb.rulenode.name-required"\n valText="tb.rulenode.value"\n valRequiredText="tb.rulenode.value-required">\n </tb-kv-map-config-old>\n</section>\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ze.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:ue.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dr,decorators:[{type:n,args:[{selector:"tb-external-node-pub-sub-config",template:'<section [formGroup]="pubSubConfigForm" fxLayout="column">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.gcp-project-id</mat-label>\n <input required matInput formControlName="projectId">\n <mat-error *ngIf="pubSubConfigForm.get(\'projectId\').hasError(\'required\')">\n {{ \'tb.rulenode.gcp-project-id-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.pubsub-topic-name</mat-label>\n <input required matInput formControlName="topicName">\n <mat-error *ngIf="pubSubConfigForm.get(\'topicName\').hasError(\'required\')">\n {{ \'tb.rulenode.pubsub-topic-name-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <tb-file-input style="padding-bottom: 24px;"\n formControlName="serviceAccountKey"\n [existingFileName]="pubSubConfigForm.get(\'serviceAccountKeyFileName\').value"\n (fileNameChanged)="pubSubConfigForm.get(\'serviceAccountKeyFileName\').setValue($event)"\n required\n requiredAsError\n label="{{\'tb.rulenode.gcp-service-account-key\' | translate}}"\n noFileText="tb.rulenode.no-file"\n dropLabel="{{\'tb.rulenode.drop-file\' | translate}}">\n </tb-file-input>\n <label translate class="tb-title">tb.rulenode.message-attributes</label>\n <div class="tb-hint" [innerHTML]="\'tb.rulenode.message-attributes-hint\' | translate | safe: \'html\'"></div>\n <tb-kv-map-config-old\n required="false"\n formControlName="messageAttributes"\n keyText="tb.rulenode.name"\n keyRequiredText="tb.rulenode.name-required"\n valText="tb.rulenode.value"\n valRequiredText="tb.rulenode.value-required">\n </tb-kv-map-config-old>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ur extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.messageProperties=[null,"BASIC","TEXT_PLAIN","MINIMAL_BASIC","MINIMAL_PERSISTENT_BASIC","PERSISTENT_BASIC","PERSISTENT_TEXT_PLAIN"]}configForm(){return this.rabbitMqConfigForm}onConfigurationSet(e){this.rabbitMqConfigForm=this.fb.group({exchangeNamePattern:[e?e.exchangeNamePattern:null,[]],routingKeyPattern:[e?e.routingKeyPattern:null,[]],messageProperties:[e?e.messageProperties:null,[]],host:[e?e.host:null,[O.required]],port:[e?e.port:null,[O.required,O.min(1),O.max(65535)]],virtualHost:[e?e.virtualHost:null,[]],username:[e?e.username:null,[]],password:[e?e.password:null,[]],automaticRecoveryEnabled:[!!e&&e.automaticRecoveryEnabled,[]],connectionTimeout:[e?e.connectionTimeout:null,[O.min(0)]],handshakeTimeout:[e?e.handshakeTimeout:null,[O.min(0)]],clientProperties:[e?e.clientProperties:null,[]]})}}e("RabbitMqConfigComponent",ur),ur.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ur,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ur.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ur,selector:"tb-external-node-rabbit-mq-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="rabbitMqConfigForm" fxLayout="column">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.exchange-name-pattern</mat-label>\n <input matInput formControlName="exchangeNamePattern">\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.routing-key-pattern</mat-label>\n <input matInput formControlName="routingKeyPattern">\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.message-properties</mat-label>\n <mat-select formControlName="messageProperties">\n <mat-option *ngFor="let property of messageProperties" [value]="property">\n {{ property }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <div fxLayout.gt-sm="row" fxLayoutGap.gt-sm="8px">\n <mat-form-field fxFlex="100" fxFlex.gt-sm="60" class="mat-block">\n <mat-label translate>tb.rulenode.host</mat-label>\n <input required matInput formControlName="host">\n <mat-error *ngIf="rabbitMqConfigForm.get(\'host\').hasError(\'required\')">\n {{ \'tb.rulenode.host-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex="100" fxFlex.gt-sm="40" class="mat-block">\n <mat-label translate>tb.rulenode.port</mat-label>\n <input required type="number" step="1" min="1" max="65535" matInput formControlName="port">\n <mat-error *ngIf="rabbitMqConfigForm.get(\'port\').hasError(\'required\')">\n {{ \'tb.rulenode.port-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="rabbitMqConfigForm.get(\'port\').hasError(\'min\')">\n {{ \'tb.rulenode.port-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="rabbitMqConfigForm.get(\'port\').hasError(\'max\')">\n {{ \'tb.rulenode.port-range\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.virtual-host</mat-label>\n <input matInput formControlName="virtualHost">\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.username</mat-label>\n <input matInput formControlName="username">\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.password</mat-label>\n <input type="password" matInput formControlName="password">\n <tb-toggle-password matSuffix></tb-toggle-password>\n </mat-form-field>\n <mat-checkbox formControlName="automaticRecoveryEnabled">\n {{ \'tb.rulenode.automatic-recovery\' | translate }}\n </mat-checkbox>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.connection-timeout-ms</mat-label>\n <input type="number" step="1" min="0" matInput formControlName="connectionTimeout">\n <mat-error *ngIf="rabbitMqConfigForm.get(\'connectionTimeout\').hasError(\'min\')">\n {{ \'tb.rulenode.min-connection-timeout-ms-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.handshake-timeout-ms</mat-label>\n <input type="number" step="1" min="0" matInput formControlName="handshakeTimeout">\n <mat-error *ngIf="rabbitMqConfigForm.get(\'handshakeTimeout\').hasError(\'min\')">\n {{ \'tb.rulenode.min-handshake-timeout-ms-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <label translate class="tb-title">tb.rulenode.client-properties</label>\n <tb-kv-map-config-old\n required="false"\n formControlName="clientProperties"\n keyText="tb.rulenode.key"\n keyRequiredText="tb.rulenode.key-required"\n valText="tb.rulenode.value"\n valRequiredText="tb.rulenode.value-required">\n </tb-kv-map-config-old>\n</section>\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Xe.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ur,decorators:[{type:n,args:[{selector:"tb-external-node-rabbit-mq-config",template:'<section [formGroup]="rabbitMqConfigForm" fxLayout="column">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.exchange-name-pattern</mat-label>\n <input matInput formControlName="exchangeNamePattern">\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.routing-key-pattern</mat-label>\n <input matInput formControlName="routingKeyPattern">\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.message-properties</mat-label>\n <mat-select formControlName="messageProperties">\n <mat-option *ngFor="let property of messageProperties" [value]="property">\n {{ property }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <div fxLayout.gt-sm="row" fxLayoutGap.gt-sm="8px">\n <mat-form-field fxFlex="100" fxFlex.gt-sm="60" class="mat-block">\n <mat-label translate>tb.rulenode.host</mat-label>\n <input required matInput formControlName="host">\n <mat-error *ngIf="rabbitMqConfigForm.get(\'host\').hasError(\'required\')">\n {{ \'tb.rulenode.host-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex="100" fxFlex.gt-sm="40" class="mat-block">\n <mat-label translate>tb.rulenode.port</mat-label>\n <input required type="number" step="1" min="1" max="65535" matInput formControlName="port">\n <mat-error *ngIf="rabbitMqConfigForm.get(\'port\').hasError(\'required\')">\n {{ \'tb.rulenode.port-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="rabbitMqConfigForm.get(\'port\').hasError(\'min\')">\n {{ \'tb.rulenode.port-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="rabbitMqConfigForm.get(\'port\').hasError(\'max\')">\n {{ \'tb.rulenode.port-range\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.virtual-host</mat-label>\n <input matInput formControlName="virtualHost">\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.username</mat-label>\n <input matInput formControlName="username">\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.password</mat-label>\n <input type="password" matInput formControlName="password">\n <tb-toggle-password matSuffix></tb-toggle-password>\n </mat-form-field>\n <mat-checkbox formControlName="automaticRecoveryEnabled">\n {{ \'tb.rulenode.automatic-recovery\' | translate }}\n </mat-checkbox>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.connection-timeout-ms</mat-label>\n <input type="number" step="1" min="0" matInput formControlName="connectionTimeout">\n <mat-error *ngIf="rabbitMqConfigForm.get(\'connectionTimeout\').hasError(\'min\')">\n {{ \'tb.rulenode.min-connection-timeout-ms-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.handshake-timeout-ms</mat-label>\n <input type="number" step="1" min="0" matInput formControlName="handshakeTimeout">\n <mat-error *ngIf="rabbitMqConfigForm.get(\'handshakeTimeout\').hasError(\'min\')">\n {{ \'tb.rulenode.min-handshake-timeout-ms-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <label translate class="tb-title">tb.rulenode.client-properties</label>\n <tb-kv-map-config-old\n required="false"\n formControlName="clientProperties"\n keyText="tb.rulenode.key"\n keyRequiredText="tb.rulenode.key-required"\n valText="tb.rulenode.value"\n valRequiredText="tb.rulenode.value-required">\n </tb-kv-map-config-old>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class cr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.proxySchemes=["http","https"],this.httpRequestTypes=Object.keys(Xt)}configForm(){return this.restApiCallConfigForm}onConfigurationSet(e){this.restApiCallConfigForm=this.fb.group({restEndpointUrlPattern:[e?e.restEndpointUrlPattern:null,[O.required]],requestMethod:[e?e.requestMethod:null,[O.required]],useSimpleClientHttpFactory:[!!e&&e.useSimpleClientHttpFactory,[]],parseToPlainText:[!!e&&e.parseToPlainText,[]],ignoreRequestBody:[!!e&&e.ignoreRequestBody,[]],enableProxy:[!!e&&e.enableProxy,[]],useSystemProxyProperties:[!!e&&e.enableProxy,[]],proxyScheme:[e?e.proxyHost:null,[]],proxyHost:[e?e.proxyHost:null,[]],proxyPort:[e?e.proxyPort:null,[]],proxyUser:[e?e.proxyUser:null,[]],proxyPassword:[e?e.proxyPassword:null,[]],readTimeoutMs:[e?e.readTimeoutMs:null,[]],maxParallelRequestsCount:[e?e.maxParallelRequestsCount:null,[O.min(0)]],headers:[e?e.headers:null,[]],credentials:[e?e.credentials:null,[]]})}validatorTriggers(){return["useSimpleClientHttpFactory","enableProxy","useSystemProxyProperties"]}updateValidators(e){const t=this.restApiCallConfigForm.get("useSimpleClientHttpFactory").value,n=this.restApiCallConfigForm.get("enableProxy").value,r=this.restApiCallConfigForm.get("useSystemProxyProperties").value;n&&!r?(this.restApiCallConfigForm.get("proxyHost").setValidators(n?[O.required]:[]),this.restApiCallConfigForm.get("proxyPort").setValidators(n?[O.required,O.min(1),O.max(65535)]:[])):(this.restApiCallConfigForm.get("proxyHost").setValidators([]),this.restApiCallConfigForm.get("proxyPort").setValidators([]),t?this.restApiCallConfigForm.get("readTimeoutMs").setValidators([]):this.restApiCallConfigForm.get("readTimeoutMs").setValidators([O.min(0)])),this.restApiCallConfigForm.get("readTimeoutMs").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("proxyHost").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("proxyPort").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("credentials").updateValueAndValidity({emitEvent:e})}}e("RestApiCallConfigComponent",cr),cr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),cr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:cr,selector:"tb-external-node-rest-api-call-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="restApiCallConfigForm" fxLayout="column">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.endpoint-url-pattern</mat-label>\n <input required matInput formControlName="restEndpointUrlPattern">\n <mat-error *ngIf="restApiCallConfigForm.get(\'restEndpointUrlPattern\').hasError(\'required\')">\n {{ \'tb.rulenode.endpoint-url-pattern-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.request-method</mat-label>\n <mat-select formControlName="requestMethod">\n <mat-option *ngFor="let requestType of httpRequestTypes" [value]="requestType">\n {{ requestType }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-checkbox formControlName="enableProxy">\n {{ \'tb.rulenode.enable-proxy\' | translate }}\n </mat-checkbox>\n <mat-checkbox *ngIf="!restApiCallConfigForm.get(\'enableProxy\').value" formControlName="useSimpleClientHttpFactory">\n {{ \'tb.rulenode.use-simple-client-http-factory\' | translate }}\n </mat-checkbox>\n <mat-checkbox formControlName="parseToPlainText">\n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n </mat-checkbox>\n <div class="tb-hint" style="padding-bottom: 5px;" translate>tb.rulenode.parse-to-plain-text-hint</div>\n <mat-checkbox formControlName="ignoreRequestBody">\n {{ \'tb.rulenode.ignore-request-body\' | translate }}\n </mat-checkbox>\n <div *ngIf="restApiCallConfigForm.get(\'enableProxy\').value">\n <mat-checkbox formControlName="useSystemProxyProperties">\n {{ \'tb.rulenode.use-system-proxy-properties\' | translate }}\n </mat-checkbox>\n <div *ngIf="!restApiCallConfigForm.get(\'useSystemProxyProperties\').value">\n <div fxLayout.gt-sm="row" fxLayoutGap.gt-sm="8px">\n <mat-form-field class="mat-block" fxFlex="100" fxFlex.gt-sm="10">\n <mat-label translate>tb.rulenode.proxy-scheme</mat-label>\n <mat-select formControlName="proxyScheme">\n <mat-option *ngFor="let proxyScheme of proxySchemes" [value]="proxyScheme">\n {{ proxyScheme }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="md-block" fxFlex="100" fxFlex.gt-sm="50">\n <mat-label translate>tb.rulenode.proxy-host</mat-label>\n <input matInput required formControlName="proxyHost">\n <mat-error *ngIf="restApiCallConfigForm.get(\'proxyHost\').hasError(\'required\')">\n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block" fxFlex="100" fxFlex.gt-sm="40">\n <mat-label translate>tb.rulenode.proxy-port</mat-label>\n <input matInput required formControlName="proxyPort" type="number" step="1">\n <mat-error *ngIf="restApiCallConfigForm.get(\'proxyPort\').hasError(\'required\')">\n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n </mat-error>\n <mat-error\n *ngIf="restApiCallConfigForm.get(\'proxyPort\').hasError(\'min\') || restApiCallConfigForm.get(\'proxyPort\').hasError(\'max\')">\n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.proxy-user</mat-label>\n <input matInput formControlName="proxyUser">\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.proxy-password</mat-label>\n <input matInput formControlName="proxyPassword">\n </mat-form-field>\n </div>\n </div>\n <mat-form-field *ngIf="!restApiCallConfigForm.get(\'useSimpleClientHttpFactory\').value || restApiCallConfigForm.get(\'enableProxy\').value" class="mat-block"\n subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.read-timeout</mat-label>\n <input type="number" step="1" min="0" matInput formControlName="readTimeoutMs">\n <mat-hint translate>tb.rulenode.read-timeout-hint</mat-hint>\n </mat-form-field>\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.max-parallel-requests-count</mat-label>\n <input type="number" step="1" min="0" matInput formControlName="maxParallelRequestsCount">\n <mat-hint translate>tb.rulenode.max-parallel-requests-count-hint</mat-hint>\n </mat-form-field>\n <label translate class="tb-title">tb.rulenode.headers</label>\n <div class="tb-hint" [innerHTML]="\'tb.rulenode.headers-hint\' | translate | safe: \'html\'"> </div>\n <tb-kv-map-config-old\n required="false"\n formControlName="headers"\n keyText="tb.rulenode.header"\n keyRequiredText="tb.rulenode.header-required"\n valText="tb.rulenode.value"\n valRequiredText="tb.rulenode.value-required">\n </tb-kv-map-config-old>\n <tb-credentials-config formControlName="credentials" [disableCertPemCredentials]="restApiCallConfigForm.get(\'useSimpleClientHttpFactory\').value"></tb-credentials-config>\n</section>\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Bn,selector:"tb-credentials-config",inputs:["required","disableCertPemCredentials","passwordFieldRequired"]},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:ue.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cr,decorators:[{type:n,args:[{selector:"tb-external-node-rest-api-call-config",template:'<section [formGroup]="restApiCallConfigForm" fxLayout="column">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.endpoint-url-pattern</mat-label>\n <input required matInput formControlName="restEndpointUrlPattern">\n <mat-error *ngIf="restApiCallConfigForm.get(\'restEndpointUrlPattern\').hasError(\'required\')">\n {{ \'tb.rulenode.endpoint-url-pattern-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.request-method</mat-label>\n <mat-select formControlName="requestMethod">\n <mat-option *ngFor="let requestType of httpRequestTypes" [value]="requestType">\n {{ requestType }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-checkbox formControlName="enableProxy">\n {{ \'tb.rulenode.enable-proxy\' | translate }}\n </mat-checkbox>\n <mat-checkbox *ngIf="!restApiCallConfigForm.get(\'enableProxy\').value" formControlName="useSimpleClientHttpFactory">\n {{ \'tb.rulenode.use-simple-client-http-factory\' | translate }}\n </mat-checkbox>\n <mat-checkbox formControlName="parseToPlainText">\n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n </mat-checkbox>\n <div class="tb-hint" style="padding-bottom: 5px;" translate>tb.rulenode.parse-to-plain-text-hint</div>\n <mat-checkbox formControlName="ignoreRequestBody">\n {{ \'tb.rulenode.ignore-request-body\' | translate }}\n </mat-checkbox>\n <div *ngIf="restApiCallConfigForm.get(\'enableProxy\').value">\n <mat-checkbox formControlName="useSystemProxyProperties">\n {{ \'tb.rulenode.use-system-proxy-properties\' | translate }}\n </mat-checkbox>\n <div *ngIf="!restApiCallConfigForm.get(\'useSystemProxyProperties\').value">\n <div fxLayout.gt-sm="row" fxLayoutGap.gt-sm="8px">\n <mat-form-field class="mat-block" fxFlex="100" fxFlex.gt-sm="10">\n <mat-label translate>tb.rulenode.proxy-scheme</mat-label>\n <mat-select formControlName="proxyScheme">\n <mat-option *ngFor="let proxyScheme of proxySchemes" [value]="proxyScheme">\n {{ proxyScheme }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="md-block" fxFlex="100" fxFlex.gt-sm="50">\n <mat-label translate>tb.rulenode.proxy-host</mat-label>\n <input matInput required formControlName="proxyHost">\n <mat-error *ngIf="restApiCallConfigForm.get(\'proxyHost\').hasError(\'required\')">\n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block" fxFlex="100" fxFlex.gt-sm="40">\n <mat-label translate>tb.rulenode.proxy-port</mat-label>\n <input matInput required formControlName="proxyPort" type="number" step="1">\n <mat-error *ngIf="restApiCallConfigForm.get(\'proxyPort\').hasError(\'required\')">\n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n </mat-error>\n <mat-error\n *ngIf="restApiCallConfigForm.get(\'proxyPort\').hasError(\'min\') || restApiCallConfigForm.get(\'proxyPort\').hasError(\'max\')">\n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.proxy-user</mat-label>\n <input matInput formControlName="proxyUser">\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.proxy-password</mat-label>\n <input matInput formControlName="proxyPassword">\n </mat-form-field>\n </div>\n </div>\n <mat-form-field *ngIf="!restApiCallConfigForm.get(\'useSimpleClientHttpFactory\').value || restApiCallConfigForm.get(\'enableProxy\').value" class="mat-block"\n subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.read-timeout</mat-label>\n <input type="number" step="1" min="0" matInput formControlName="readTimeoutMs">\n <mat-hint translate>tb.rulenode.read-timeout-hint</mat-hint>\n </mat-form-field>\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.max-parallel-requests-count</mat-label>\n <input type="number" step="1" min="0" matInput formControlName="maxParallelRequestsCount">\n <mat-hint translate>tb.rulenode.max-parallel-requests-count-hint</mat-hint>\n </mat-form-field>\n <label translate class="tb-title">tb.rulenode.headers</label>\n <div class="tb-hint" [innerHTML]="\'tb.rulenode.headers-hint\' | translate | safe: \'html\'"> </div>\n <tb-kv-map-config-old\n required="false"\n formControlName="headers"\n keyText="tb.rulenode.header"\n keyRequiredText="tb.rulenode.header-required"\n valText="tb.rulenode.value"\n valRequiredText="tb.rulenode.value-required">\n </tb-kv-map-config-old>\n <tb-credentials-config formControlName="credentials" [disableCertPemCredentials]="restApiCallConfigForm.get(\'useSimpleClientHttpFactory\').value"></tb-credentials-config>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class gr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.smtpProtocols=["smtp","smtps"],this.tlsVersions=["TLSv1","TLSv1.1","TLSv1.2","TLSv1.3"]}configForm(){return this.sendEmailConfigForm}onConfigurationSet(e){this.sendEmailConfigForm=this.fb.group({useSystemSmtpSettings:[!!e&&e.useSystemSmtpSettings,[]],smtpProtocol:[e?e.smtpProtocol:null,[]],smtpHost:[e?e.smtpHost:null,[]],smtpPort:[e?e.smtpPort:null,[]],timeout:[e?e.timeout:null,[]],enableTls:[!!e&&e.enableTls,[]],tlsVersion:[e?e.tlsVersion:null,[]],enableProxy:[!!e&&e.enableProxy,[]],proxyHost:[e?e.proxyHost:null,[]],proxyPort:[e?e.proxyPort:null,[]],proxyUser:[e?e.proxyUser:null,[]],proxyPassword:[e?e.proxyPassword:null,[]],username:[e?e.username:null,[]],password:[e?e.password:null,[]]})}validatorTriggers(){return["useSystemSmtpSettings","enableProxy"]}updateValidators(e){const t=this.sendEmailConfigForm.get("useSystemSmtpSettings").value,n=this.sendEmailConfigForm.get("enableProxy").value;t?(this.sendEmailConfigForm.get("smtpProtocol").setValidators([]),this.sendEmailConfigForm.get("smtpHost").setValidators([]),this.sendEmailConfigForm.get("smtpPort").setValidators([]),this.sendEmailConfigForm.get("timeout").setValidators([]),this.sendEmailConfigForm.get("proxyHost").setValidators([]),this.sendEmailConfigForm.get("proxyPort").setValidators([])):(this.sendEmailConfigForm.get("smtpProtocol").setValidators([O.required]),this.sendEmailConfigForm.get("smtpHost").setValidators([O.required]),this.sendEmailConfigForm.get("smtpPort").setValidators([O.required,O.min(1),O.max(65535)]),this.sendEmailConfigForm.get("timeout").setValidators([O.required,O.min(0)]),this.sendEmailConfigForm.get("proxyHost").setValidators(n?[O.required]:[]),this.sendEmailConfigForm.get("proxyPort").setValidators(n?[O.required,O.min(1),O.max(65535)]:[])),this.sendEmailConfigForm.get("smtpProtocol").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("smtpHost").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("smtpPort").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("timeout").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("proxyHost").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("proxyPort").updateValueAndValidity({emitEvent:e})}}e("SendEmailConfigComponent",gr),gr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),gr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:gr,selector:"tb-external-node-send-email-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="sendEmailConfigForm" fxLayout="column">\n <mat-checkbox formControlName="useSystemSmtpSettings">\n {{ \'tb.rulenode.use-system-smtp-settings\' | translate }}\n </mat-checkbox>\n <section fxLayout="column" *ngIf="sendEmailConfigForm.get(\'useSystemSmtpSettings\').value === false">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.smtp-protocol</mat-label>\n <mat-select formControlName="smtpProtocol">\n <mat-option *ngFor="let smtpProtocol of smtpProtocols" [value]="smtpProtocol">\n {{ smtpProtocol.toUpperCase() }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <div fxLayout.gt-sm="row" fxLayoutGap.gt-sm="8px">\n <mat-form-field fxFlex="100" fxFlex.gt-sm="60" class="mat-block">\n <mat-label translate>tb.rulenode.smtp-host</mat-label>\n <input required matInput formControlName="smtpHost">\n <mat-error *ngIf="sendEmailConfigForm.get(\'smtpHost\').hasError(\'required\')">\n {{ \'tb.rulenode.smtp-host-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex="100" fxFlex.gt-sm="40" class="mat-block">\n <mat-label translate>tb.rulenode.smtp-port</mat-label>\n <input required type="number" step="1" min="1" max="65535" matInput formControlName="smtpPort">\n <mat-error *ngIf="sendEmailConfigForm.get(\'smtpPort\').hasError(\'required\')">\n {{ \'tb.rulenode.smtp-port-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="sendEmailConfigForm.get(\'smtpPort\').hasError(\'min\')">\n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="sendEmailConfigForm.get(\'smtpPort\').hasError(\'max\')">\n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.timeout-msec</mat-label>\n <input required type="number" step="1" min="0" matInput formControlName="timeout">\n <mat-error *ngIf="sendEmailConfigForm.get(\'timeout\').hasError(\'required\')">\n {{ \'tb.rulenode.timeout-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="sendEmailConfigForm.get(\'timeout\').hasError(\'min\')">\n {{ \'tb.rulenode.min-timeout-msec-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-checkbox formControlName="enableTls">\n {{ \'tb.rulenode.enable-tls\' | translate }}\n </mat-checkbox>\n <mat-form-field class="mat-block" *ngIf="sendEmailConfigForm.get(\'enableTls\').value === true">\n <mat-label translate>tb.rulenode.tls-version</mat-label>\n <mat-select formControlName="tlsVersion">\n <mat-option *ngFor="let tlsVersion of tlsVersions" [value]="tlsVersion">\n {{ tlsVersion }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <tb-checkbox formControlName="enableProxy">\n {{ \'tb.rulenode.enable-proxy\' | translate }}\n </tb-checkbox>\n <div *ngIf="sendEmailConfigForm.get(\'enableProxy\').value">\n <div fxLayout.gt-sm="row" fxLayoutGap.gt-sm="8px">\n <mat-form-field class="mat-block" fxFlex="100" fxFlex.gt-sm="60">\n <mat-label translate>tb.rulenode.proxy-host</mat-label>\n <input matInput required formControlName="proxyHost">\n <mat-error *ngIf="sendEmailConfigForm.get(\'proxyHost\').hasError(\'required\')">\n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block" fxFlex="100" fxFlex.gt-sm="40">\n <mat-label translate>tb.rulenode.proxy-port</mat-label>\n <input matInput required formControlName="proxyPort" type="number" step="1" min="1" max="65535">\n <mat-error *ngIf="sendEmailConfigForm.get(\'proxyPort\').hasError(\'required\')">\n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="sendEmailConfigForm.get(\'proxyPort\').hasError(\'min\') || sendEmailConfigForm.get(\'proxyPort\').hasError(\'max\')">\n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.proxy-user</mat-label>\n <input matInput formControlName="proxyUser">\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.proxy-password</mat-label>\n <input matInput formControlName="proxyPassword">\n </mat-form-field>\n </div>\n <mat-form-field class="mat-block" floatLabel="always">\n <mat-label translate>tb.rulenode.username</mat-label>\n <input matInput placeholder="{{ \'tb.rulenode.enter-username\' | translate }}" formControlName="username">\n </mat-form-field>\n <mat-form-field class="mat-block" floatLabel="always">\n <mat-label translate>tb.rulenode.password</mat-label>\n <input matInput type="password" placeholder="{{ \'tb.rulenode.enter-password\' | translate }}" formControlName="password">\n <tb-toggle-password matSuffix></tb-toggle-password>\n </mat-form-field>\n </section>\n</section>\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:rt.TbCheckboxComponent,selector:"tb-checkbox",inputs:["disabled","trueValue","falseValue"],outputs:["valueChange"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Xe.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gr,decorators:[{type:n,args:[{selector:"tb-external-node-send-email-config",template:'<section [formGroup]="sendEmailConfigForm" fxLayout="column">\n <mat-checkbox formControlName="useSystemSmtpSettings">\n {{ \'tb.rulenode.use-system-smtp-settings\' | translate }}\n </mat-checkbox>\n <section fxLayout="column" *ngIf="sendEmailConfigForm.get(\'useSystemSmtpSettings\').value === false">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.smtp-protocol</mat-label>\n <mat-select formControlName="smtpProtocol">\n <mat-option *ngFor="let smtpProtocol of smtpProtocols" [value]="smtpProtocol">\n {{ smtpProtocol.toUpperCase() }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <div fxLayout.gt-sm="row" fxLayoutGap.gt-sm="8px">\n <mat-form-field fxFlex="100" fxFlex.gt-sm="60" class="mat-block">\n <mat-label translate>tb.rulenode.smtp-host</mat-label>\n <input required matInput formControlName="smtpHost">\n <mat-error *ngIf="sendEmailConfigForm.get(\'smtpHost\').hasError(\'required\')">\n {{ \'tb.rulenode.smtp-host-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex="100" fxFlex.gt-sm="40" class="mat-block">\n <mat-label translate>tb.rulenode.smtp-port</mat-label>\n <input required type="number" step="1" min="1" max="65535" matInput formControlName="smtpPort">\n <mat-error *ngIf="sendEmailConfigForm.get(\'smtpPort\').hasError(\'required\')">\n {{ \'tb.rulenode.smtp-port-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="sendEmailConfigForm.get(\'smtpPort\').hasError(\'min\')">\n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="sendEmailConfigForm.get(\'smtpPort\').hasError(\'max\')">\n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.timeout-msec</mat-label>\n <input required type="number" step="1" min="0" matInput formControlName="timeout">\n <mat-error *ngIf="sendEmailConfigForm.get(\'timeout\').hasError(\'required\')">\n {{ \'tb.rulenode.timeout-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="sendEmailConfigForm.get(\'timeout\').hasError(\'min\')">\n {{ \'tb.rulenode.min-timeout-msec-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-checkbox formControlName="enableTls">\n {{ \'tb.rulenode.enable-tls\' | translate }}\n </mat-checkbox>\n <mat-form-field class="mat-block" *ngIf="sendEmailConfigForm.get(\'enableTls\').value === true">\n <mat-label translate>tb.rulenode.tls-version</mat-label>\n <mat-select formControlName="tlsVersion">\n <mat-option *ngFor="let tlsVersion of tlsVersions" [value]="tlsVersion">\n {{ tlsVersion }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <tb-checkbox formControlName="enableProxy">\n {{ \'tb.rulenode.enable-proxy\' | translate }}\n </tb-checkbox>\n <div *ngIf="sendEmailConfigForm.get(\'enableProxy\').value">\n <div fxLayout.gt-sm="row" fxLayoutGap.gt-sm="8px">\n <mat-form-field class="mat-block" fxFlex="100" fxFlex.gt-sm="60">\n <mat-label translate>tb.rulenode.proxy-host</mat-label>\n <input matInput required formControlName="proxyHost">\n <mat-error *ngIf="sendEmailConfigForm.get(\'proxyHost\').hasError(\'required\')">\n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block" fxFlex="100" fxFlex.gt-sm="40">\n <mat-label translate>tb.rulenode.proxy-port</mat-label>\n <input matInput required formControlName="proxyPort" type="number" step="1" min="1" max="65535">\n <mat-error *ngIf="sendEmailConfigForm.get(\'proxyPort\').hasError(\'required\')">\n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="sendEmailConfigForm.get(\'proxyPort\').hasError(\'min\') || sendEmailConfigForm.get(\'proxyPort\').hasError(\'max\')">\n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.proxy-user</mat-label>\n <input matInput formControlName="proxyUser">\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.proxy-password</mat-label>\n <input matInput formControlName="proxyPassword">\n </mat-form-field>\n </div>\n <mat-form-field class="mat-block" floatLabel="always">\n <mat-label translate>tb.rulenode.username</mat-label>\n <input matInput placeholder="{{ \'tb.rulenode.enter-username\' | translate }}" formControlName="username">\n </mat-form-field>\n <mat-form-field class="mat-block" floatLabel="always">\n <mat-label translate>tb.rulenode.password</mat-label>\n <input matInput type="password" placeholder="{{ \'tb.rulenode.enter-password\' | translate }}" formControlName="password">\n <tb-toggle-password matSuffix></tb-toggle-password>\n </mat-form-field>\n </section>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class fr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.sendSmsConfigForm}onConfigurationSet(e){this.sendSmsConfigForm=this.fb.group({numbersToTemplate:[e?e.numbersToTemplate:null,[O.required]],smsMessageTemplate:[e?e.smsMessageTemplate:null,[O.required]],useSystemSmsSettings:[!!e&&e.useSystemSmsSettings,[]],smsProviderConfiguration:[e?e.smsProviderConfiguration:null,[]]})}validatorTriggers(){return["useSystemSmsSettings"]}updateValidators(e){this.sendSmsConfigForm.get("useSystemSmsSettings").value?this.sendSmsConfigForm.get("smsProviderConfiguration").setValidators([]):this.sendSmsConfigForm.get("smsProviderConfiguration").setValidators([O.required]),this.sendSmsConfigForm.get("smsProviderConfiguration").updateValueAndValidity({emitEvent:e})}}e("SendSmsConfigComponent",fr),fr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),fr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:fr,selector:"tb-external-node-send-sms-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="sendSmsConfigForm" fxLayout="column">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.numbers-to-template</mat-label>\n <input required matInput formControlName="numbersToTemplate">\n <mat-error *ngIf="sendSmsConfigForm.get(\'numbersToTemplate\').hasError(\'required\')">\n {{ \'tb.rulenode.numbers-to-template-required\' | translate }}\n </mat-error>\n <mat-hint [innerHTML]="\'tb.rulenode.numbers-to-template-hint\' | translate | safe: \'html\'"></mat-hint>\n </mat-form-field>\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.sms-message-template</mat-label>\n <textarea required matInput formControlName="smsMessageTemplate" rows="6"></textarea>\n <mat-error *ngIf="sendSmsConfigForm.get(\'smsMessageTemplate\').hasError(\'required\')">\n {{ \'tb.rulenode.sms-message-template-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <mat-checkbox formControlName="useSystemSmsSettings">\n {{ \'tb.rulenode.use-system-sms-settings\' | translate }}\n </mat-checkbox>\n <tb-sms-provider-configuration\n *ngIf="sendSmsConfigForm.get(\'useSystemSmsSettings\').value === false"\n formControlName="smsProviderConfiguration"\n required>\n </tb-sms-provider-configuration>\n</section>\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ot.SmsProviderConfigurationComponent,selector:"tb-sms-provider-configuration",inputs:["required","disabled"]},{kind:"pipe",type:ue.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fr,decorators:[{type:n,args:[{selector:"tb-external-node-send-sms-config",template:'<section [formGroup]="sendSmsConfigForm" fxLayout="column">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.numbers-to-template</mat-label>\n <input required matInput formControlName="numbersToTemplate">\n <mat-error *ngIf="sendSmsConfigForm.get(\'numbersToTemplate\').hasError(\'required\')">\n {{ \'tb.rulenode.numbers-to-template-required\' | translate }}\n </mat-error>\n <mat-hint [innerHTML]="\'tb.rulenode.numbers-to-template-hint\' | translate | safe: \'html\'"></mat-hint>\n </mat-form-field>\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.sms-message-template</mat-label>\n <textarea required matInput formControlName="smsMessageTemplate" rows="6"></textarea>\n <mat-error *ngIf="sendSmsConfigForm.get(\'smsMessageTemplate\').hasError(\'required\')">\n {{ \'tb.rulenode.sms-message-template-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <mat-checkbox formControlName="useSystemSmsSettings">\n {{ \'tb.rulenode.use-system-sms-settings\' | translate }}\n </mat-checkbox>\n <tb-sms-provider-configuration\n *ngIf="sendSmsConfigForm.get(\'useSystemSmsSettings\').value === false"\n formControlName="smsProviderConfiguration"\n required>\n </tb-sms-provider-configuration>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class yr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.slackChanelTypes=Object.keys(D),this.slackChanelTypesTranslateMap=V}configForm(){return this.slackConfigForm}onConfigurationSet(e){this.slackConfigForm=this.fb.group({botToken:[e?e.botToken:null],useSystemSettings:[!!e&&e.useSystemSettings],messageTemplate:[e?e.messageTemplate:null,[O.required]],conversationType:[e?e.conversationType:null,[O.required]],conversation:[e?e.conversation:null,[O.required]]})}validatorTriggers(){return["useSystemSettings"]}updateValidators(e){this.slackConfigForm.get("useSystemSettings").value?this.slackConfigForm.get("botToken").clearValidators():this.slackConfigForm.get("botToken").setValidators([O.required]),this.slackConfigForm.get("botToken").updateValueAndValidity({emitEvent:e})}}e("SlackConfigComponent",yr),yr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),yr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:yr,selector:"tb-external-node-slack-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="slackConfigForm" fxLayout="column">\n <mat-form-field fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.message-template</mat-label>\n <input required matInput formControlName="messageTemplate">\n <mat-error *ngIf="slackConfigForm.get(\'messageTemplate\').hasError(\'required\')">\n {{ \'tb.rulenode.message-template-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <mat-checkbox formControlName="useSystemSettings">\n {{ \'tb.rulenode.use-system-slack-settings\' | translate }}\n </mat-checkbox>\n <mat-form-field *ngIf="!slackConfigForm.get(\'useSystemSettings\').value" class="mat-block">\n <mat-label translate>tb.rulenode.slack-api-token</mat-label>\n <input required matInput formControlName="botToken">\n <mat-error *ngIf="slackConfigForm.get(\'botToken\').hasError(\'required\')">\n {{ \'tb.rulenode.slack-api-token-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <label class="tb-title">{{ \'notification.slack-chanel-type\' | translate }}</label>\n <mat-radio-group formControlName="conversationType">\n <mat-radio-button *ngFor="let slackChanelType of slackChanelTypes" [value]="slackChanelType">\n {{ slackChanelTypesTranslateMap.get(slackChanelType) | translate }}\n </mat-radio-button>\n </mat-radio-group>\n <tb-slack-conversation-autocomplete\n formControlName="conversation"\n required\n [token]="slackConfigForm.get(\'useSystemSettings\').value ? \'\' : slackConfigForm.get(\'botToken\').value"\n [slackChanelType]="slackConfigForm.get(\'conversationType\').value">\n </tb-slack-conversation-autocomplete>\n</section>\n',styles:[":host .tb-title{display:block;padding-bottom:6px}:host ::ng-deep .mat-mdc-radio-group{display:flex;flex-direction:row;margin-bottom:22px;gap:12px}:host ::ng-deep .mat-mdc-radio-group .mat-mdc-radio-button{flex:1 1 100%;padding:4px;border:1px solid rgba(0,0,0,.12);border-radius:6px}@media screen and (max-width: 599px){:host ::ng-deep .mat-mdc-radio-group{flex-direction:column}}\n"],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:at.MatRadioGroup,selector:"mat-radio-group",exportAs:["matRadioGroup"]},{kind:"component",type:at.MatRadioButton,selector:"mat-radio-button",inputs:["disableRipple","tabIndex"],exportAs:["matRadioButton"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:it.SlackConversationAutocompleteComponent,selector:"tb-slack-conversation-autocomplete",inputs:["labelText","requiredText","required","disabled","slackChanelType","token"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yr,decorators:[{type:n,args:[{selector:"tb-external-node-slack-config",template:'<section [formGroup]="slackConfigForm" fxLayout="column">\n <mat-form-field fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.message-template</mat-label>\n <input required matInput formControlName="messageTemplate">\n <mat-error *ngIf="slackConfigForm.get(\'messageTemplate\').hasError(\'required\')">\n {{ \'tb.rulenode.message-template-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <mat-checkbox formControlName="useSystemSettings">\n {{ \'tb.rulenode.use-system-slack-settings\' | translate }}\n </mat-checkbox>\n <mat-form-field *ngIf="!slackConfigForm.get(\'useSystemSettings\').value" class="mat-block">\n <mat-label translate>tb.rulenode.slack-api-token</mat-label>\n <input required matInput formControlName="botToken">\n <mat-error *ngIf="slackConfigForm.get(\'botToken\').hasError(\'required\')">\n {{ \'tb.rulenode.slack-api-token-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <label class="tb-title">{{ \'notification.slack-chanel-type\' | translate }}</label>\n <mat-radio-group formControlName="conversationType">\n <mat-radio-button *ngFor="let slackChanelType of slackChanelTypes" [value]="slackChanelType">\n {{ slackChanelTypesTranslateMap.get(slackChanelType) | translate }}\n </mat-radio-button>\n </mat-radio-group>\n <tb-slack-conversation-autocomplete\n formControlName="conversation"\n required\n [token]="slackConfigForm.get(\'useSystemSettings\').value ? \'\' : slackConfigForm.get(\'botToken\').value"\n [slackChanelType]="slackConfigForm.get(\'conversationType\').value">\n </tb-slack-conversation-autocomplete>\n</section>\n',styles:[":host .tb-title{display:block;padding-bottom:6px}:host ::ng-deep .mat-mdc-radio-group{display:flex;flex-direction:row;margin-bottom:22px;gap:12px}:host ::ng-deep .mat-mdc-radio-group .mat-mdc-radio-button{flex:1 1 100%;padding:4px;border:1px solid rgba(0,0,0,.12);border-radius:6px}@media screen and (max-width: 599px){:host ::ng-deep .mat-mdc-radio-group{flex-direction:column}}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class br extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.snsConfigForm}onConfigurationSet(e){this.snsConfigForm=this.fb.group({topicArnPattern:[e?e.topicArnPattern:null,[O.required]],accessKeyId:[e?e.accessKeyId:null,[O.required]],secretAccessKey:[e?e.secretAccessKey:null,[O.required]],region:[e?e.region:null,[O.required]]})}}e("SnsConfigComponent",br),br.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:br,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),br.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:br,selector:"tb-external-node-sns-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="snsConfigForm" fxLayout="column">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.topic-arn-pattern</mat-label>\n <input required matInput formControlName="topicArnPattern">\n <mat-error *ngIf="snsConfigForm.get(\'topicArnPattern\').hasError(\'required\')">\n {{ \'tb.rulenode.topic-arn-pattern-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-access-key-id</mat-label>\n <input required matInput formControlName="accessKeyId">\n <mat-error *ngIf="snsConfigForm.get(\'accessKeyId\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-secret-access-key</mat-label>\n <input required matInput formControlName="secretAccessKey">\n <mat-error *ngIf="snsConfigForm.get(\'secretAccessKey\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-region</mat-label>\n <input required matInput formControlName="region">\n <mat-error *ngIf="snsConfigForm.get(\'region\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-region-required\' | translate }}\n </mat-error>\n </mat-form-field>\n</section>\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:br,decorators:[{type:n,args:[{selector:"tb-external-node-sns-config",template:'<section [formGroup]="snsConfigForm" fxLayout="column">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.topic-arn-pattern</mat-label>\n <input required matInput formControlName="topicArnPattern">\n <mat-error *ngIf="snsConfigForm.get(\'topicArnPattern\').hasError(\'required\')">\n {{ \'tb.rulenode.topic-arn-pattern-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-access-key-id</mat-label>\n <input required matInput formControlName="accessKeyId">\n <mat-error *ngIf="snsConfigForm.get(\'accessKeyId\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-secret-access-key</mat-label>\n <input required matInput formControlName="secretAccessKey">\n <mat-error *ngIf="snsConfigForm.get(\'secretAccessKey\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-region</mat-label>\n <input required matInput formControlName="region">\n <mat-error *ngIf="snsConfigForm.get(\'region\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-region-required\' | translate }}\n </mat-error>\n </mat-form-field>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class xr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.sqsQueueType=$t,this.sqsQueueTypes=Object.keys($t),this.sqsQueueTypeTranslationsMap=Jt}configForm(){return this.sqsConfigForm}onConfigurationSet(e){this.sqsConfigForm=this.fb.group({queueType:[e?e.queueType:null,[O.required]],queueUrlPattern:[e?e.queueUrlPattern:null,[O.required]],delaySeconds:[e?e.delaySeconds:null,[O.min(0),O.max(900)]],messageAttributes:[e?e.messageAttributes:null,[]],accessKeyId:[e?e.accessKeyId:null,[O.required]],secretAccessKey:[e?e.secretAccessKey:null,[O.required]],region:[e?e.region:null,[O.required]]})}}e("SqsConfigComponent",xr),xr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),xr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:xr,selector:"tb-external-node-sqs-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="sqsConfigForm" fxLayout="column">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.queue-type</mat-label>\n <mat-select formControlName="queueType" required>\n <mat-option *ngFor="let type of sqsQueueTypes" [value]="type">\n {{ sqsQueueTypeTranslationsMap.get(type) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.queue-url-pattern</mat-label>\n <input required matInput formControlName="queueUrlPattern">\n <mat-error *ngIf="sqsConfigForm.get(\'queueUrlPattern\').hasError(\'required\')">\n {{ \'tb.rulenode.queue-url-pattern-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <mat-form-field *ngIf="sqsConfigForm.get(\'queueType\').value === sqsQueueType.STANDARD" class="mat-block">\n <mat-label translate>tb.rulenode.delay-seconds</mat-label>\n <input required type="number" min="0" max="900" step="1" matInput formControlName="delaySeconds">\n <mat-error *ngIf="sqsConfigForm.get(\'delaySeconds\').hasError(\'min\')">\n {{ \'tb.rulenode.min-delay-seconds-message\' | translate }}\n </mat-error>\n <mat-error *ngIf="sqsConfigForm.get(\'delaySeconds\').hasError(\'max\')">\n {{ \'tb.rulenode.max-delay-seconds-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <label translate class="tb-title">tb.rulenode.message-attributes</label>\n <div class="tb-hint" [innerHTML]="\'tb.rulenode.message-attributes-hint\' | translate | safe: \'html\'"></div>\n <tb-kv-map-config-old\n required="false"\n formControlName="messageAttributes"\n keyText="tb.rulenode.name"\n keyRequiredText="tb.rulenode.name-required"\n valText="tb.rulenode.value"\n valRequiredText="tb.rulenode.value-required">\n </tb-kv-map-config-old>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-access-key-id</mat-label>\n <input required matInput formControlName="accessKeyId">\n <mat-error *ngIf="sqsConfigForm.get(\'accessKeyId\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-secret-access-key</mat-label>\n <input required matInput formControlName="secretAccessKey">\n <mat-error *ngIf="sqsConfigForm.get(\'secretAccessKey\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-region</mat-label>\n <input required matInput formControlName="region">\n <mat-error *ngIf="sqsConfigForm.get(\'region\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-region-required\' | translate }}\n </mat-error>\n </mat-form-field>\n</section>\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:ue.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xr,decorators:[{type:n,args:[{selector:"tb-external-node-sqs-config",template:'<section [formGroup]="sqsConfigForm" fxLayout="column">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.queue-type</mat-label>\n <mat-select formControlName="queueType" required>\n <mat-option *ngFor="let type of sqsQueueTypes" [value]="type">\n {{ sqsQueueTypeTranslationsMap.get(type) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.queue-url-pattern</mat-label>\n <input required matInput formControlName="queueUrlPattern">\n <mat-error *ngIf="sqsConfigForm.get(\'queueUrlPattern\').hasError(\'required\')">\n {{ \'tb.rulenode.queue-url-pattern-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <mat-form-field *ngIf="sqsConfigForm.get(\'queueType\').value === sqsQueueType.STANDARD" class="mat-block">\n <mat-label translate>tb.rulenode.delay-seconds</mat-label>\n <input required type="number" min="0" max="900" step="1" matInput formControlName="delaySeconds">\n <mat-error *ngIf="sqsConfigForm.get(\'delaySeconds\').hasError(\'min\')">\n {{ \'tb.rulenode.min-delay-seconds-message\' | translate }}\n </mat-error>\n <mat-error *ngIf="sqsConfigForm.get(\'delaySeconds\').hasError(\'max\')">\n {{ \'tb.rulenode.max-delay-seconds-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <label translate class="tb-title">tb.rulenode.message-attributes</label>\n <div class="tb-hint" [innerHTML]="\'tb.rulenode.message-attributes-hint\' | translate | safe: \'html\'"></div>\n <tb-kv-map-config-old\n required="false"\n formControlName="messageAttributes"\n keyText="tb.rulenode.name"\n keyRequiredText="tb.rulenode.name-required"\n valText="tb.rulenode.value"\n valRequiredText="tb.rulenode.value-required">\n </tb-kv-map-config-old>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-access-key-id</mat-label>\n <input required matInput formControlName="accessKeyId">\n <mat-error *ngIf="sqsConfigForm.get(\'accessKeyId\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-secret-access-key</mat-label>\n <input required matInput formControlName="secretAccessKey">\n <mat-error *ngIf="sqsConfigForm.get(\'secretAccessKey\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-region</mat-label>\n <input required matInput formControlName="region">\n <mat-error *ngIf="sqsConfigForm.get(\'region\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-region-required\' | translate }}\n </mat-error>\n </mat-form-field>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class hr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.lambdaConfigForm}onConfigurationSet(e){this.lambdaConfigForm=this.fb.group({functionName:[e?e.functionName:null,[O.required]],qualifier:[e?e.qualifier:null,[]],accessKey:[e?e.accessKey:null,[O.required]],secretKey:[e?e.secretKey:null,[O.required]],region:[e?e.region:null,[O.required]],connectionTimeout:[e?e.connectionTimeout:null,[O.required,O.min(0)]],requestTimeout:[e?e.requestTimeout:null,[O.required,O.min(0)]],tellFailureIfFuncThrowsExc:[!!e&&e.tellFailureIfFuncThrowsExc,[]]})}}e("LambdaConfigComponent",hr),hr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),hr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:hr,selector:"tb-external-node-lambda-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="lambdaConfigForm" class="tb-form-panel no-padding no-border">\n <div class="tb-form-panel stroked">\n <div class="tb-form-row no-padding no-border">\n <div class="tb-form-panel-title tb-required" translate>tb.rulenode.function-configuration</div>\n </div>\n <tb-example-hint [hintText]="\'tb.rulenode.template-rules-hint\'"\n popupHelpLink="rulenode/node-templatization-doc">\n </tb-example-hint>\n <div class="tb-standard-fields">\n <mat-form-field class="mat-block">\n <mat-label>{{\'tb.rulenode.function-name\' | translate}}</mat-label>\n <input required matInput formControlName="functionName">\n <mat-error *ngIf="lambdaConfigForm.get(\'functionName\').hasError(\'required\')">\n {{\'tb.rulenode.function-name-required\' | translate}}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label>{{\'tb.rulenode.qualifier\' | translate}}</mat-label>\n <input required matInput formControlName="qualifier">\n <mat-hint translate>tb.rulenode.qualifier-hint</mat-hint>\n </mat-form-field>\n </div>\n </div>\n\n <div class="tb-form-panel stroked">\n <mat-expansion-panel class="tb-settings" expanded>\n <mat-expansion-panel-header>\n <mat-panel-title class="tb-form-panel-title tb-required" translate>tb.rulenode.aws-credentials</mat-panel-title>\n </mat-expansion-panel-header>\n <div class="tb-standard-fields">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-access-key-id</mat-label>\n <input required matInput formControlName="accessKey">\n <mat-error *ngIf="lambdaConfigForm.get(\'accessKey\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-secret-access-key</mat-label>\n <input required matInput formControlName="secretKey">\n <mat-error *ngIf="lambdaConfigForm.get(\'secretKey\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-region</mat-label>\n <input required matInput formControlName="region">\n <mat-error *ngIf="lambdaConfigForm.get(\'region\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-region-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n </mat-expansion-panel>\n </div>\n <div class="tb-form-panel stroked no-padding">\n <mat-expansion-panel class="tb-settings">\n <mat-expansion-panel-header style="padding: 16px">\n <mat-panel-title translate>tb.rulenode.advanced-settings</mat-panel-title>\n </mat-expansion-panel-header>\n <div class="tb-form-panel no-border no-padding no-gap" style="margin-top: 0">\n <div class="tb-form-row no-border same-padding tb-standard-fields">\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.connection-timeout</mat-label>\n <input type="number" required min="0" matInput formControlName="connectionTimeout">\n <mat-error *ngIf="lambdaConfigForm.get(\'connectionTimeout\').hasError(\'required\')">\n {{ \'tb.rulenode.connection-timeout-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="lambdaConfigForm.get(\'connectionTimeout\').hasError(\'min\')">\n {{ \'tb.rulenode.connection-timeout-min\' | translate }}\n </mat-error>\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.connection-timeout-hint\' | translate }}">help</mat-icon>\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.request-timeout</mat-label>\n <input type="number" required min="0" matInput formControlName="requestTimeout">\n <mat-error *ngIf="lambdaConfigForm.get(\'requestTimeout\').hasError(\'required\')">\n {{ \'tb.rulenode.request-timeout-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="lambdaConfigForm.get(\'requestTimeout\').hasError(\'min\')">\n {{ \'tb.rulenode.request-timeout-min\' | translate }}\n </mat-error>\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.request-timeout-hint\' | translate }}">help</mat-icon>\n </mat-form-field>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.tell-failure-aws-lambda-hint\' | translate }}"\n class="tb-form-row no-border" style="margin-bottom: 16px">\n <mat-slide-toggle class="mat-slide" formControlName="tellFailureIfFuncThrowsExc">\n {{ \'tb.rulenode.tell-failure-aws-lambda\' | translate }}\n </mat-slide-toggle>\n </div>\n </div>\n </mat-expansion-panel>\n </div>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"component",type:oe.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:oe.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:oe.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hr,decorators:[{type:n,args:[{selector:"tb-external-node-lambda-config",template:'<section [formGroup]="lambdaConfigForm" class="tb-form-panel no-padding no-border">\n <div class="tb-form-panel stroked">\n <div class="tb-form-row no-padding no-border">\n <div class="tb-form-panel-title tb-required" translate>tb.rulenode.function-configuration</div>\n </div>\n <tb-example-hint [hintText]="\'tb.rulenode.template-rules-hint\'"\n popupHelpLink="rulenode/node-templatization-doc">\n </tb-example-hint>\n <div class="tb-standard-fields">\n <mat-form-field class="mat-block">\n <mat-label>{{\'tb.rulenode.function-name\' | translate}}</mat-label>\n <input required matInput formControlName="functionName">\n <mat-error *ngIf="lambdaConfigForm.get(\'functionName\').hasError(\'required\')">\n {{\'tb.rulenode.function-name-required\' | translate}}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label>{{\'tb.rulenode.qualifier\' | translate}}</mat-label>\n <input required matInput formControlName="qualifier">\n <mat-hint translate>tb.rulenode.qualifier-hint</mat-hint>\n </mat-form-field>\n </div>\n </div>\n\n <div class="tb-form-panel stroked">\n <mat-expansion-panel class="tb-settings" expanded>\n <mat-expansion-panel-header>\n <mat-panel-title class="tb-form-panel-title tb-required" translate>tb.rulenode.aws-credentials</mat-panel-title>\n </mat-expansion-panel-header>\n <div class="tb-standard-fields">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-access-key-id</mat-label>\n <input required matInput formControlName="accessKey">\n <mat-error *ngIf="lambdaConfigForm.get(\'accessKey\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-secret-access-key</mat-label>\n <input required matInput formControlName="secretKey">\n <mat-error *ngIf="lambdaConfigForm.get(\'secretKey\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-region</mat-label>\n <input required matInput formControlName="region">\n <mat-error *ngIf="lambdaConfigForm.get(\'region\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-region-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n </mat-expansion-panel>\n </div>\n <div class="tb-form-panel stroked no-padding">\n <mat-expansion-panel class="tb-settings">\n <mat-expansion-panel-header style="padding: 16px">\n <mat-panel-title translate>tb.rulenode.advanced-settings</mat-panel-title>\n </mat-expansion-panel-header>\n <div class="tb-form-panel no-border no-padding no-gap" style="margin-top: 0">\n <div class="tb-form-row no-border same-padding tb-standard-fields">\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.connection-timeout</mat-label>\n <input type="number" required min="0" matInput formControlName="connectionTimeout">\n <mat-error *ngIf="lambdaConfigForm.get(\'connectionTimeout\').hasError(\'required\')">\n {{ \'tb.rulenode.connection-timeout-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="lambdaConfigForm.get(\'connectionTimeout\').hasError(\'min\')">\n {{ \'tb.rulenode.connection-timeout-min\' | translate }}\n </mat-error>\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.connection-timeout-hint\' | translate }}">help</mat-icon>\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.request-timeout</mat-label>\n <input type="number" required min="0" matInput formControlName="requestTimeout">\n <mat-error *ngIf="lambdaConfigForm.get(\'requestTimeout\').hasError(\'required\')">\n {{ \'tb.rulenode.request-timeout-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="lambdaConfigForm.get(\'requestTimeout\').hasError(\'min\')">\n {{ \'tb.rulenode.request-timeout-min\' | translate }}\n </mat-error>\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.request-timeout-hint\' | translate }}">help</mat-icon>\n </mat-form-field>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.tell-failure-aws-lambda-hint\' | translate }}"\n class="tb-form-row no-border" style="margin-bottom: 16px">\n <mat-slide-toggle class="mat-slide" formControlName="tellFailureIfFuncThrowsExc">\n {{ \'tb.rulenode.tell-failure-aws-lambda\' | translate }}\n </mat-slide-toggle>\n </div>\n </div>\n </mat-expansion-panel>\n </div>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class vr{}e("RulenodeCoreConfigExternalModule",vr),vr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),vr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:vr,declarations:[br,xr,hr,dr,sr,mr,pr,ur,cr,gr,lr,fr,yr],imports:[$,M,Je,Jn],exports:[br,xr,hr,dr,sr,mr,pr,ur,cr,gr,lr,fr,yr]}),vr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vr,imports:[$,M,Je,Jn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vr,decorators:[{type:d,args:[{declarations:[br,xr,hr,dr,sr,mr,pr,ur,cr,gr,lr,fr,yr],imports:[$,M,Je,Jn],exports:[br,xr,hr,dr,sr,mr,pr,ur,cr,gr,lr,fr,yr]}]}]});class Cr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.searchText=""}configForm(){return this.alarmStatusConfigForm}prepareInputConfig(e){return{alarmStatusList:fe(e?.alarmStatusList)?e.alarmStatusList:null}}onConfigurationSet(e){this.alarmStatusConfigForm=this.fb.group({alarmStatusList:[e.alarmStatusList,[O.required]]})}}e("CheckAlarmStatusComponent",Cr),Cr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Cr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Cr,selector:"tb-filter-node-check-alarm-status-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="alarmStatusConfigForm" class="tb-form-panel stroked">\n <div class="tb-form-row no-padding no-border space-between">\n <div class="tb-form-panel-title tb-required" translate>tb.rulenode.alarm-status</div>\n <div class="tb-form-panel-hint tb-error" translate [hidden]="alarmStatusConfigForm.get(\'alarmStatusList\').valid">\n tb.rulenode.alarm-required\n </div>\n </div>\n <tb-alarm-status-select formControlName="alarmStatusList"></tb-alarm-status-select>\n</section>\n\n\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:$n,selector:"tb-alarm-status-select"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-alarm-status-config",template:'<section [formGroup]="alarmStatusConfigForm" class="tb-form-panel stroked">\n <div class="tb-form-row no-padding no-border space-between">\n <div class="tb-form-panel-title tb-required" translate>tb.rulenode.alarm-status</div>\n <div class="tb-form-panel-hint tb-error" translate [hidden]="alarmStatusConfigForm.get(\'alarmStatusList\').valid">\n tb.rulenode.alarm-required\n </div>\n </div>\n <tb-alarm-status-select formControlName="alarmStatusList"></tb-alarm-status-select>\n</section>\n\n\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Fr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.checkMessageConfigForm}prepareInputConfig(e){return{messageNames:fe(e?.messageNames)?e.messageNames:[],metadataNames:fe(e?.metadataNames)?e.metadataNames:[],checkAllKeys:!!fe(e?.checkAllKeys)&&e.checkAllKeys}}prepareOutputConfig(e){return{messageNames:fe(e?.messageNames)?e.messageNames:[],metadataNames:fe(e?.metadataNames)?e.metadataNames:[],checkAllKeys:e.checkAllKeys}}atLeastOne(e,t=null){return n=>{t||(t=Object.keys(n.controls));return n?.controls&&t.some((t=>!e(n.controls[t])))?null:{atLeastOne:!0}}}onConfigurationSet(e){this.checkMessageConfigForm=this.fb.group({messageNames:[e.messageNames,[]],metadataNames:[e.metadataNames,[]],checkAllKeys:[e.checkAllKeys,[]]},{validators:this.atLeastOne(O.required,["messageNames","metadataNames"])})}get touchedValidationControl(){return["messageNames","metadataNames"].some((e=>this.checkMessageConfigForm.get(e).touched))}}e("CheckMessageConfigComponent",Fr),Fr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Fr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Fr,selector:"tb-filter-node-check-message-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="checkMessageConfigForm" class="tb-form-panel stroked">\n <div class="tb-form-row no-padding no-border space-between">\n <div class="tb-form-panel-title tb-required" translate>tb.rulenode.fields-to-check</div>\n <div class="tb-form-panel-hint tb-error" translate [hidden]="!(touchedValidationControl && checkMessageConfigForm.hasError(\'atLeastOne\'))">\n tb.rulenode.at-least-one-field-required\n </div>\n </div>\n <tb-string-items-list editable subscriptSizing="dynamic"\n [label]="\'tb.rulenode.data-keys\' | translate"\n [placeholder]="\'tb.rulenode.add-message-field\' | translate"\n formControlName="messageNames">\n <mat-icon matSuffix color="primary" class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n matTooltip="{{ \'tb.rulenode.chip-help\' | translate: { inputName: \'tb.rulenode.field-name\' | translate } }}">help</mat-icon>\n </tb-string-items-list>\n <tb-string-items-list editable subscriptSizing="dynamic"\n [label]="\'tb.rulenode.metadata-keys\' | translate"\n [placeholder]="\'tb.rulenode.add-metadata-field\' | translate"\n formControlName="metadataNames">\n <mat-icon matSuffix color="primary" class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n matTooltip="{{ \'tb.rulenode.chip-help\' | translate: { inputName: \'tb.rulenode.field-name\' | translate } }}">help</mat-icon>\n </tb-string-items-list>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.check-all-keys-tooltip\' | translate }}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="checkAllKeys">\n {{ \'tb.rulenode.check-all-keys\' | translate }}\n </mat-slide-toggle>\n </div>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-message-config",template:'<section [formGroup]="checkMessageConfigForm" class="tb-form-panel stroked">\n <div class="tb-form-row no-padding no-border space-between">\n <div class="tb-form-panel-title tb-required" translate>tb.rulenode.fields-to-check</div>\n <div class="tb-form-panel-hint tb-error" translate [hidden]="!(touchedValidationControl && checkMessageConfigForm.hasError(\'atLeastOne\'))">\n tb.rulenode.at-least-one-field-required\n </div>\n </div>\n <tb-string-items-list editable subscriptSizing="dynamic"\n [label]="\'tb.rulenode.data-keys\' | translate"\n [placeholder]="\'tb.rulenode.add-message-field\' | translate"\n formControlName="messageNames">\n <mat-icon matSuffix color="primary" class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n matTooltip="{{ \'tb.rulenode.chip-help\' | translate: { inputName: \'tb.rulenode.field-name\' | translate } }}">help</mat-icon>\n </tb-string-items-list>\n <tb-string-items-list editable subscriptSizing="dynamic"\n [label]="\'tb.rulenode.metadata-keys\' | translate"\n [placeholder]="\'tb.rulenode.add-metadata-field\' | translate"\n formControlName="metadataNames">\n <mat-icon matSuffix color="primary" class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n matTooltip="{{ \'tb.rulenode.chip-help\' | translate: { inputName: \'tb.rulenode.field-name\' | translate } }}">help</mat-icon>\n </tb-string-items-list>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.check-all-keys-tooltip\' | translate }}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="checkAllKeys">\n {{ \'tb.rulenode.check-all-keys\' | translate }}\n </mat-slide-toggle>\n </div>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class kr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.entitySearchDirection=Object.values(v),this.entitySearchDirectionTranslationsMap=N}configForm(){return this.checkRelationConfigForm}prepareInputConfig(e){return{checkForSingleEntity:!!fe(e?.checkForSingleEntity)&&e.checkForSingleEntity,direction:fe(e?.direction)?e.direction:null,entityType:fe(e?.entityType)?e.entityType:null,entityId:fe(e?.entityId)?e.entityId:null,relationType:fe(e?.relationType)?e.relationType:null}}onConfigurationSet(e){this.checkRelationConfigForm=this.fb.group({checkForSingleEntity:[e.checkForSingleEntity,[]],direction:[e.direction,[]],entityType:[e.entityType,e&&e.checkForSingleEntity?[O.required]:[]],entityId:[e.entityId,e&&e.checkForSingleEntity?[O.required]:[]],relationType:[e.relationType,[O.required]]})}validatorTriggers(){return["checkForSingleEntity"]}updateValidators(e){const t=this.checkRelationConfigForm.get("checkForSingleEntity").value;this.checkRelationConfigForm.get("entityType").setValidators(t?[O.required]:[]),this.checkRelationConfigForm.get("entityType").updateValueAndValidity({emitEvent:e}),this.checkRelationConfigForm.get("entityId").setValidators(t?[O.required]:[]),this.checkRelationConfigForm.get("entityId").updateValueAndValidity({emitEvent:e})}}e("CheckRelationConfigComponent",kr),kr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),kr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:kr,selector:"tb-filter-node-check-relation-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="checkRelationConfigForm" class="tb-form-panel stroked no-padding-bottom">\n <div class="tb-form-panel-title" translate>tb.rulenode.relation-search-parameters</div>\n <div fxLayout="column">\n <mat-form-field class="mat-block" hideRequiredMarker>\n <mat-label>{{ \'relation.direction\' | translate }}</mat-label>\n <mat-select formControlName="direction" required>\n <mat-option *ngFor="let direction of entitySearchDirection" [value]="direction">\n {{ entitySearchDirectionTranslationsMap.get(direction) | translate }} <span translate>tb.rulenode.relations-query-config-direction-suffix</span>\n </mat-option>\n </mat-select>\n </mat-form-field>\n <tb-relation-type-autocomplete\n required\n formControlName="relationType">\n </tb-relation-type-autocomplete>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.check-relation-to-specific-entity-tooltip\' | translate }}"\n class="tb-form-row no-border no-padding slide-toggle">\n <mat-slide-toggle class="mat-slide" formControlName="checkForSingleEntity">\n {{ \'tb.rulenode.check-relation-to-specific-entity\' | translate }}\n </mat-slide-toggle>\n </div>\n <div *ngIf="checkRelationConfigForm.get(\'checkForSingleEntity\').value" class="same-width-component-row">\n <tb-entity-type-select\n style="min-width: 100px; flex: 1;"\n showLabel\n required\n formControlName="entityType">\n </tb-entity-type-select>\n <tb-entity-autocomplete\n fxFlex\n required\n *ngIf="checkRelationConfigForm.get(\'entityType\').value"\n [entityType]="checkRelationConfigForm.get(\'entityType\').value"\n formControlName="entityId">\n </tb-entity-autocomplete>\n </div>\n </div>\n</section>\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:lt.EntityAutocompleteComponent,selector:"tb-entity-autocomplete",inputs:["entityType","entitySubtype","excludeEntityIds","labelText","requiredText","useFullEntityId","appearance","required","disabled"],outputs:["entityChanged"]},{kind:"component",type:Ne.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"component",type:Se.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-relation-config",template:'<section [formGroup]="checkRelationConfigForm" class="tb-form-panel stroked no-padding-bottom">\n <div class="tb-form-panel-title" translate>tb.rulenode.relation-search-parameters</div>\n <div fxLayout="column">\n <mat-form-field class="mat-block" hideRequiredMarker>\n <mat-label>{{ \'relation.direction\' | translate }}</mat-label>\n <mat-select formControlName="direction" required>\n <mat-option *ngFor="let direction of entitySearchDirection" [value]="direction">\n {{ entitySearchDirectionTranslationsMap.get(direction) | translate }} <span translate>tb.rulenode.relations-query-config-direction-suffix</span>\n </mat-option>\n </mat-select>\n </mat-form-field>\n <tb-relation-type-autocomplete\n required\n formControlName="relationType">\n </tb-relation-type-autocomplete>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.check-relation-to-specific-entity-tooltip\' | translate }}"\n class="tb-form-row no-border no-padding slide-toggle">\n <mat-slide-toggle class="mat-slide" formControlName="checkForSingleEntity">\n {{ \'tb.rulenode.check-relation-to-specific-entity\' | translate }}\n </mat-slide-toggle>\n </div>\n <div *ngIf="checkRelationConfigForm.get(\'checkForSingleEntity\').value" class="same-width-component-row">\n <tb-entity-type-select\n style="min-width: 100px; flex: 1;"\n showLabel\n required\n formControlName="entityType">\n </tb-entity-type-select>\n <tb-entity-autocomplete\n fxFlex\n required\n *ngIf="checkRelationConfigForm.get(\'entityType\').value"\n [entityType]="checkRelationConfigForm.get(\'entityType\').value"\n formControlName="entityId">\n </tb-entity-autocomplete>\n </div>\n </div>\n</section>\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Tr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.perimeterType=Mt,this.perimeterTypes=Object.values(Mt),this.perimeterTypeTranslationMap=Et,this.rangeUnits=Object.values(Dt),this.rangeUnitTranslationMap=Vt,this.defaultPaddingEnable=!0}configForm(){return this.geoFilterConfigForm}prepareInputConfig(e){return{latitudeKeyName:fe(e?.latitudeKeyName)?e.latitudeKeyName:null,longitudeKeyName:fe(e?.longitudeKeyName)?e.longitudeKeyName:null,perimeterType:fe(e?.perimeterType)?e.perimeterType:null,fetchPerimeterInfoFromMessageMetadata:!!fe(e?.fetchPerimeterInfoFromMessageMetadata)&&e.fetchPerimeterInfoFromMessageMetadata,perimeterKeyName:fe(e?.perimeterKeyName)?e.perimeterKeyName:null,centerLatitude:fe(e?.centerLatitude)?e.centerLatitude:null,centerLongitude:fe(e?.centerLongitude)?e.centerLongitude:null,range:fe(e?.range)?e.range:null,rangeUnit:fe(e?.rangeUnit)?e.rangeUnit:null,polygonsDefinition:fe(e?.polygonsDefinition)?e.polygonsDefinition:null}}onConfigurationSet(e){this.geoFilterConfigForm=this.fb.group({latitudeKeyName:[e.latitudeKeyName,[O.required]],longitudeKeyName:[e.longitudeKeyName,[O.required]],perimeterType:[e.perimeterType,[O.required]],fetchPerimeterInfoFromMessageMetadata:[e.fetchPerimeterInfoFromMessageMetadata,[]],perimeterKeyName:[e.perimeterKeyName,[]],centerLatitude:[e.centerLatitude,[]],centerLongitude:[e.centerLongitude,[]],range:[e.range,[]],rangeUnit:[e.rangeUnit,[]],polygonsDefinition:[e.polygonsDefinition,[]]})}validatorTriggers(){return["fetchPerimeterInfoFromMessageMetadata","perimeterType"]}updateValidators(e){const t=this.geoFilterConfigForm.get("fetchPerimeterInfoFromMessageMetadata").value,n=this.geoFilterConfigForm.get("perimeterType").value;t?this.geoFilterConfigForm.get("perimeterKeyName").setValidators([O.required]):this.geoFilterConfigForm.get("perimeterKeyName").setValidators([]),t||n!==Mt.CIRCLE?(this.geoFilterConfigForm.get("centerLatitude").setValidators([]),this.geoFilterConfigForm.get("centerLongitude").setValidators([]),this.geoFilterConfigForm.get("range").setValidators([]),this.geoFilterConfigForm.get("rangeUnit").setValidators([]),this.defaultPaddingEnable=!0):(this.geoFilterConfigForm.get("centerLatitude").setValidators([O.required,O.min(-90),O.max(90)]),this.geoFilterConfigForm.get("centerLongitude").setValidators([O.required,O.min(-180),O.max(180)]),this.geoFilterConfigForm.get("range").setValidators([O.required,O.min(0)]),this.geoFilterConfigForm.get("rangeUnit").setValidators([O.required]),this.defaultPaddingEnable=!1),t||n!==Mt.POLYGON?this.geoFilterConfigForm.get("polygonsDefinition").setValidators([]):this.geoFilterConfigForm.get("polygonsDefinition").setValidators([O.required]),this.geoFilterConfigForm.get("perimeterKeyName").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("centerLatitude").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("centerLongitude").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("range").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("rangeUnit").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("polygonsDefinition").updateValueAndValidity({emitEvent:e})}}e("GpsGeoFilterConfigComponent",Tr),Tr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Tr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Tr,selector:"tb-filter-node-gps-geofencing-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="geoFilterConfigForm" class="tb-form-panel no-border no-padding">\n <section class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.coordinate-field-names</div>\n <section>\n <div fxLayout="row" fxLayoutGap="16px">\n <mat-form-field fxFlex="50" class="mat-block">\n <mat-label>{{ \'tb.rulenode.latitude-field-name\' | translate }}</mat-label>\n <input matInput formControlName="latitudeKeyName" required>\n <mat-error *ngIf="geoFilterConfigForm.get(\'latitudeKeyName\').hasError(\'required\')">\n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex="50" class="mat-block">\n <mat-label>{{ \'tb.rulenode.longitude-field-name\' | translate }}</mat-label>\n <input matInput formControlName="longitudeKeyName" required>\n <mat-error *ngIf="geoFilterConfigForm.get(\'longitudeKeyName\').hasError(\'required\')">\n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <div class="tb-form-hint tb-primary-fill" translate>tb.rulenode.coordinate-field-hint</div>\n </section>\n </section>\n <section class="tb-form-panel stroked" [class.no-padding-bottom]="!defaultPaddingEnable">\n <div class="tb-form-panel-title" translate>tb.rulenode.geofence-configuration</div>\n <section fxLayout="column">\n <mat-form-field fxFlex class="mat-block" hideRequiredMarker>\n <mat-label>{{ \'tb.rulenode.perimeter-type\' | translate }}</mat-label>\n <mat-select formControlName="perimeterType">\n <mat-option *ngFor="let type of perimeterTypes" [value]="type">\n {{ perimeterTypeTranslationMap.get(type) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <div tb-hint-tooltip-icon="{{ geoFilterConfigForm.get(\'perimeterType\').value === perimeterType.CIRCLE\n ? (\'tb.rulenode.fetch-circle-parameter-info-from-metadata-hint\'\n | translate : { perimeterKeyName: geoFilterConfigForm.get(\'perimeterKeyName\').valid\n ? geoFilterConfigForm.get(\'perimeterKeyName\').value\n : \'ss_perimeter\'})\n : (\'tb.rulenode.fetch-poligon-parameter-info-from-metadata-hint\'\n | translate : { perimeterKeyName: geoFilterConfigForm.get(\'perimeterKeyName\').valid\n ? geoFilterConfigForm.get(\'perimeterKeyName\').value\n : \'ss_perimeter\'}) }}"\n class="tb-form-row no-border no-padding slide-toggle">\n <mat-slide-toggle class="mat-slide" formControlName="fetchPerimeterInfoFromMessageMetadata">\n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n </mat-slide-toggle>\n </div>\n <mat-form-field *ngIf="geoFilterConfigForm.get(\'fetchPerimeterInfoFromMessageMetadata\').value" class="mat-block">\n <mat-label>{{ \'tb.rulenode.perimeter-key-name\' | translate }}</mat-label>\n <input matInput formControlName="perimeterKeyName" required>\n <mat-error *ngIf="geoFilterConfigForm.get(\'perimeterKeyName\').hasError(\'required\')">\n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n </mat-error>\n <mat-hint>{{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}</mat-hint>\n </mat-form-field>\n <div fxLayout="column"\n *ngIf="geoFilterConfigForm.get(\'perimeterType\').value === perimeterType.CIRCLE &&\n !geoFilterConfigForm.get(\'fetchPerimeterInfoFromMessageMetadata\').value">\n <div fxLayout="row" fxLayoutGap="16px">\n <mat-form-field fxFlex>\n <mat-label>{{ \'tb.rulenode.circle-center-latitude\' | translate }}</mat-label>\n <input type="number" min="-90" max="90" step="0.1" matInput formControlName="centerLatitude" required>\n <mat-error *ngIf="geoFilterConfigForm.get(\'centerLatitude\').hasError(\'required\')">\n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex>\n <mat-label>{{ \'tb.rulenode.circle-center-longitude\' | translate }}</mat-label>\n <input type="number" min="-180" max="180" step="0.1" matInput formControlName="centerLongitude" required>\n <mat-error *ngIf="geoFilterConfigForm.get(\'centerLongitude\').hasError(\'required\')">\n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <div fxLayout="row" fxLayoutGap="16px">\n <mat-form-field fxFlex>\n <mat-label>{{ \'tb.rulenode.range\' | translate }}</mat-label>\n <input type="number" min="0" step="0.1" matInput formControlName="range" required>\n <mat-error *ngIf="geoFilterConfigForm.get(\'range\').hasError(\'required\')">\n {{ \'tb.rulenode.range-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex>\n <mat-label>{{ \'tb.rulenode.range-units\' | translate }}</mat-label>\n <mat-select formControlName="rangeUnit" required>\n <mat-option *ngFor="let type of rangeUnits" [value]="type">\n {{ rangeUnitTranslationMap.get(type) | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf="geoFilterConfigForm.get(\'rangeUnit\').hasError(\'required\')">\n {{ \'tb.rulenode.range-units-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n </div>\n <mat-form-field class="mat-block" subscriptSizing="dynamic"\n *ngIf="geoFilterConfigForm.get(\'perimeterType\').value === perimeterType.POLYGON &&\n !geoFilterConfigForm.get(\'fetchPerimeterInfoFromMessageMetadata\').value">\n <mat-label>{{ \'tb.rulenode.polygon-definition\' | translate }}</mat-label>\n <input matInput formControlName="polygonsDefinition" required>\n <mat-hint>{{ \'tb.rulenode.polygon-definition-hint\' | translate }}</mat-hint>\n <mat-error *ngIf="geoFilterConfigForm.get(\'polygonsDefinition\').hasError(\'required\')">\n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </section>\n </section>\n</section>\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tr,decorators:[{type:n,args:[{selector:"tb-filter-node-gps-geofencing-config",template:'<section [formGroup]="geoFilterConfigForm" class="tb-form-panel no-border no-padding">\n <section class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.coordinate-field-names</div>\n <section>\n <div fxLayout="row" fxLayoutGap="16px">\n <mat-form-field fxFlex="50" class="mat-block">\n <mat-label>{{ \'tb.rulenode.latitude-field-name\' | translate }}</mat-label>\n <input matInput formControlName="latitudeKeyName" required>\n <mat-error *ngIf="geoFilterConfigForm.get(\'latitudeKeyName\').hasError(\'required\')">\n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex="50" class="mat-block">\n <mat-label>{{ \'tb.rulenode.longitude-field-name\' | translate }}</mat-label>\n <input matInput formControlName="longitudeKeyName" required>\n <mat-error *ngIf="geoFilterConfigForm.get(\'longitudeKeyName\').hasError(\'required\')">\n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <div class="tb-form-hint tb-primary-fill" translate>tb.rulenode.coordinate-field-hint</div>\n </section>\n </section>\n <section class="tb-form-panel stroked" [class.no-padding-bottom]="!defaultPaddingEnable">\n <div class="tb-form-panel-title" translate>tb.rulenode.geofence-configuration</div>\n <section fxLayout="column">\n <mat-form-field fxFlex class="mat-block" hideRequiredMarker>\n <mat-label>{{ \'tb.rulenode.perimeter-type\' | translate }}</mat-label>\n <mat-select formControlName="perimeterType">\n <mat-option *ngFor="let type of perimeterTypes" [value]="type">\n {{ perimeterTypeTranslationMap.get(type) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <div tb-hint-tooltip-icon="{{ geoFilterConfigForm.get(\'perimeterType\').value === perimeterType.CIRCLE\n ? (\'tb.rulenode.fetch-circle-parameter-info-from-metadata-hint\'\n | translate : { perimeterKeyName: geoFilterConfigForm.get(\'perimeterKeyName\').valid\n ? geoFilterConfigForm.get(\'perimeterKeyName\').value\n : \'ss_perimeter\'})\n : (\'tb.rulenode.fetch-poligon-parameter-info-from-metadata-hint\'\n | translate : { perimeterKeyName: geoFilterConfigForm.get(\'perimeterKeyName\').valid\n ? geoFilterConfigForm.get(\'perimeterKeyName\').value\n : \'ss_perimeter\'}) }}"\n class="tb-form-row no-border no-padding slide-toggle">\n <mat-slide-toggle class="mat-slide" formControlName="fetchPerimeterInfoFromMessageMetadata">\n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n </mat-slide-toggle>\n </div>\n <mat-form-field *ngIf="geoFilterConfigForm.get(\'fetchPerimeterInfoFromMessageMetadata\').value" class="mat-block">\n <mat-label>{{ \'tb.rulenode.perimeter-key-name\' | translate }}</mat-label>\n <input matInput formControlName="perimeterKeyName" required>\n <mat-error *ngIf="geoFilterConfigForm.get(\'perimeterKeyName\').hasError(\'required\')">\n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n </mat-error>\n <mat-hint>{{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}</mat-hint>\n </mat-form-field>\n <div fxLayout="column"\n *ngIf="geoFilterConfigForm.get(\'perimeterType\').value === perimeterType.CIRCLE &&\n !geoFilterConfigForm.get(\'fetchPerimeterInfoFromMessageMetadata\').value">\n <div fxLayout="row" fxLayoutGap="16px">\n <mat-form-field fxFlex>\n <mat-label>{{ \'tb.rulenode.circle-center-latitude\' | translate }}</mat-label>\n <input type="number" min="-90" max="90" step="0.1" matInput formControlName="centerLatitude" required>\n <mat-error *ngIf="geoFilterConfigForm.get(\'centerLatitude\').hasError(\'required\')">\n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex>\n <mat-label>{{ \'tb.rulenode.circle-center-longitude\' | translate }}</mat-label>\n <input type="number" min="-180" max="180" step="0.1" matInput formControlName="centerLongitude" required>\n <mat-error *ngIf="geoFilterConfigForm.get(\'centerLongitude\').hasError(\'required\')">\n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <div fxLayout="row" fxLayoutGap="16px">\n <mat-form-field fxFlex>\n <mat-label>{{ \'tb.rulenode.range\' | translate }}</mat-label>\n <input type="number" min="0" step="0.1" matInput formControlName="range" required>\n <mat-error *ngIf="geoFilterConfigForm.get(\'range\').hasError(\'required\')">\n {{ \'tb.rulenode.range-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex>\n <mat-label>{{ \'tb.rulenode.range-units\' | translate }}</mat-label>\n <mat-select formControlName="rangeUnit" required>\n <mat-option *ngFor="let type of rangeUnits" [value]="type">\n {{ rangeUnitTranslationMap.get(type) | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf="geoFilterConfigForm.get(\'rangeUnit\').hasError(\'required\')">\n {{ \'tb.rulenode.range-units-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n </div>\n <mat-form-field class="mat-block" subscriptSizing="dynamic"\n *ngIf="geoFilterConfigForm.get(\'perimeterType\').value === perimeterType.POLYGON &&\n !geoFilterConfigForm.get(\'fetchPerimeterInfoFromMessageMetadata\').value">\n <mat-label>{{ \'tb.rulenode.polygon-definition\' | translate }}</mat-label>\n <input matInput formControlName="polygonsDefinition" required>\n <mat-hint>{{ \'tb.rulenode.polygon-definition-hint\' | translate }}</mat-hint>\n <mat-error *ngIf="geoFilterConfigForm.get(\'polygonsDefinition\').hasError(\'required\')">\n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </section>\n </section>\n</section>\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Lr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.messageTypeConfigForm}prepareInputConfig(e){return{messageTypes:fe(e?.messageTypes)?e.messageTypes:null}}onConfigurationSet(e){this.messageTypeConfigForm=this.fb.group({messageTypes:[e.messageTypes,[O.required]]})}}e("MessageTypeConfigComponent",Lr),Lr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Lr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Lr,selector:"tb-filter-node-message-type-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="messageTypeConfigForm">\n <tb-message-types-config\n required\n [label]="\'tb.rulenode.select-message-types\' | translate"\n formControlName="messageTypes">\n </tb-message-types-config>\n</section>\n',dependencies:[{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:_n,selector:"tb-message-types-config",inputs:["required","label","placeholder","disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lr,decorators:[{type:n,args:[{selector:"tb-filter-node-message-type-config",template:'<section [formGroup]="messageTypeConfigForm">\n <tb-message-types-config\n required\n [label]="\'tb.rulenode.select-message-types\' | translate"\n formControlName="messageTypes">\n </tb-message-types-config>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Ir extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.allowedEntityTypes=[C.DEVICE,C.ASSET,C.ENTITY_VIEW,C.TENANT,C.CUSTOMER,C.USER,C.DASHBOARD,C.RULE_CHAIN,C.RULE_NODE,C.EDGE]}configForm(){return this.originatorTypeConfigForm}prepareInputConfig(e){return{originatorTypes:fe(e?.originatorTypes)?e.originatorTypes:null}}onConfigurationSet(e){this.originatorTypeConfigForm=this.fb.group({originatorTypes:[e.originatorTypes,[O.required]]})}}e("OriginatorTypeConfigComponent",Ir),Ir.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ir,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Ir.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ir,selector:"tb-filter-node-originator-type-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="originatorTypeConfigForm">\n <tb-entity-type-list fxFlex\n formControlName="originatorTypes"\n [allowedEntityTypes]="allowedEntityTypes"\n [ignoreAuthorityFilter]="true"\n [emptyInputPlaceholder]="\'tb.rulenode.add-entity-type\' | translate"\n [filledInputPlaceholder]="\'tb.rulenode.add-entity-type\' | translate"\n [label]="\'tb.rulenode.select-entity-types\' | translate"\n required>\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.chip-help\' | translate: { inputName: \'tb.rulenode.entity-type\' | translate } }}">help</mat-icon>\n </tb-entity-type-list>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:st.EntityTypeListComponent,selector:"tb-entity-type-list",inputs:["required","additionalClasses","appearance","label","floatLabel","disabled","subscriptSizing","allowedEntityTypes","emptyInputPlaceholder","filledInputPlaceholder","ignoreAuthorityFilter"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ir,decorators:[{type:n,args:[{selector:"tb-filter-node-originator-type-config",template:'<section [formGroup]="originatorTypeConfigForm">\n <tb-entity-type-list fxFlex\n formControlName="originatorTypes"\n [allowedEntityTypes]="allowedEntityTypes"\n [ignoreAuthorityFilter]="true"\n [emptyInputPlaceholder]="\'tb.rulenode.add-entity-type\' | translate"\n [filledInputPlaceholder]="\'tb.rulenode.add-entity-type\' | translate"\n [label]="\'tb.rulenode.select-entity-types\' | translate"\n required>\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.chip-help\' | translate: { inputName: \'tb.rulenode.entity-type\' | translate } }}">help</mat-icon>\n </tb-entity-type-list>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Nr extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ce(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-filter-function"}configForm(){return this.scriptConfigForm}onConfigurationSet(e){this.scriptConfigForm=this.fb.group({scriptLang:[e.scriptLang,[O.required]],jsScript:[e.jsScript,[]],tbelScript:[e.tbelScript,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.scriptConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.scriptConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.scriptConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.scriptConfigForm.get("jsScript").setValidators(t===b.JS?[O.required]:[]),this.scriptConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.scriptConfigForm.get("tbelScript").setValidators(t===b.TBEL?[O.required]:[]),this.scriptConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),{scriptLang:fe(e?.scriptLang)?e.scriptLang:b.JS,jsScript:fe(e?.jsScript)?e.jsScript:null,tbelScript:fe(e?.tbelScript)?e.tbelScript:null}}testScript(e){const t=this.scriptConfigForm.get("scriptLang").value,n=t===b.JS?"jsScript":"tbelScript",r=t===b.JS?"rulenode/filter_node_script_fn":"rulenode/tbel/filter_node_script_fn",o=this.scriptConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"filter",this.translate.instant("tb.rulenode.filter"),"Filter",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.scriptConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.scriptConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}e("ScriptConfigComponent",Nr),Nr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nr,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:ge.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Nr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Nr,selector:"tb-filter-node-script-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'<section [formGroup]="scriptConfigForm">\n <tb-script-lang formControlName="scriptLang" *ngIf="tbelEnabled"></tb-script-lang>\n <tb-js-func *ngIf="scriptConfigForm.get(\'scriptLang\').value === scriptLanguage.JS"\n #jsFuncComponent\n formControlName="jsScript"\n functionName="Filter"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n helpId="rulenode/filter_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <tb-js-func *ngIf="scriptConfigForm.get(\'scriptLang\').value === scriptLanguage.TBEL"\n #tbelFuncComponent\n formControlName="tbelScript"\n functionName="Filter"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n [disableUndefinedCheck]="true"\n [scriptLanguage]="scriptLanguage.TBEL"\n helpId="rulenode/tbel/filter_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <button mat-button mat-raised-button color="primary" (click)="testScript()">\n {{ testScriptLabel | translate }}\n </button>\n</section>\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ce.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nr,decorators:[{type:n,args:[{selector:"tb-filter-node-script-config",template:'<section [formGroup]="scriptConfigForm">\n <tb-script-lang formControlName="scriptLang" *ngIf="tbelEnabled"></tb-script-lang>\n <tb-js-func *ngIf="scriptConfigForm.get(\'scriptLang\').value === scriptLanguage.JS"\n #jsFuncComponent\n formControlName="jsScript"\n functionName="Filter"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n helpId="rulenode/filter_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <tb-js-func *ngIf="scriptConfigForm.get(\'scriptLang\').value === scriptLanguage.TBEL"\n #tbelFuncComponent\n formControlName="tbelScript"\n functionName="Filter"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n [disableUndefinedCheck]="true"\n [scriptLanguage]="scriptLanguage.TBEL"\n helpId="rulenode/tbel/filter_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <button mat-button mat-raised-button color="primary" (click)="testScript()">\n {{ testScriptLabel | translate }}\n </button>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:ge.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}});class Sr extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ce(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-switch-function"}configForm(){return this.switchConfigForm}onConfigurationSet(e){this.switchConfigForm=this.fb.group({scriptLang:[e.scriptLang,[O.required]],jsScript:[e.jsScript,[]],tbelScript:[e.tbelScript,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.switchConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.switchConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.switchConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.switchConfigForm.get("jsScript").setValidators(t===b.JS?[O.required]:[]),this.switchConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.switchConfigForm.get("tbelScript").setValidators(t===b.TBEL?[O.required]:[]),this.switchConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),{scriptLang:fe(e?.scriptLang)?e.scriptLang:b.JS,jsScript:fe(e?.jsScript)?e.jsScript:null,tbelScript:fe(e?.tbelScript)?e.tbelScript:null}}testScript(e){const t=this.switchConfigForm.get("scriptLang").value,n=t===b.JS?"jsScript":"tbelScript",r=t===b.JS?"rulenode/switch_node_script_fn":"rulenode/tbel/switch_node_script_fn",o=this.switchConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"switch",this.translate.instant("tb.rulenode.switch"),"Switch",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.switchConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.switchConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}e("SwitchConfigComponent",Sr),Sr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sr,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:ge.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Sr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Sr,selector:"tb-filter-node-switch-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'<section [formGroup]="switchConfigForm">\n <tb-script-lang formControlName="scriptLang" *ngIf="tbelEnabled"></tb-script-lang>\n <tb-js-func *ngIf="switchConfigForm.get(\'scriptLang\').value === scriptLanguage.JS"\n #jsFuncComponent\n formControlName="jsScript"\n functionName="Switch"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n helpId="rulenode/switch_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <tb-js-func *ngIf="switchConfigForm.get(\'scriptLang\').value === scriptLanguage.TBEL"\n #tbelFuncComponent\n formControlName="tbelScript"\n functionName="Switch"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n [disableUndefinedCheck]="true"\n [scriptLanguage]="scriptLanguage.TBEL"\n helpId="rulenode/tbel/switch_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <button mat-button mat-raised-button color="primary" (click)="testScript()">\n {{ testScriptLabel | translate }}\n </button>\n</section>\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ce.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sr,decorators:[{type:n,args:[{selector:"tb-filter-node-switch-config",template:'<section [formGroup]="switchConfigForm">\n <tb-script-lang formControlName="scriptLang" *ngIf="tbelEnabled"></tb-script-lang>\n <tb-js-func *ngIf="switchConfigForm.get(\'scriptLang\').value === scriptLanguage.JS"\n #jsFuncComponent\n formControlName="jsScript"\n functionName="Switch"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n helpId="rulenode/switch_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <tb-js-func *ngIf="switchConfigForm.get(\'scriptLang\').value === scriptLanguage.TBEL"\n #tbelFuncComponent\n formControlName="tbelScript"\n functionName="Switch"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n [disableUndefinedCheck]="true"\n [scriptLanguage]="scriptLanguage.TBEL"\n helpId="rulenode/tbel/switch_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <button mat-button mat-raised-button color="primary" (click)="testScript()">\n {{ testScriptLabel | translate }}\n </button>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:ge.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}});class qr{}e("RuleNodeCoreConfigFilterModule",qr),qr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),qr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:qr,declarations:[Fr,kr,Tr,Lr,Ir,Nr,Sr,Cr],imports:[$,M,Jn],exports:[Fr,kr,Tr,Lr,Ir,Nr,Sr,Cr]}),qr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qr,imports:[$,M,Jn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qr,decorators:[{type:d,args:[{declarations:[Fr,kr,Tr,Lr,Ir,Nr,Sr,Cr],imports:[$,M,Jn],exports:[Fr,kr,Tr,Lr,Ir,Nr,Sr,Cr]}]}]});class Ar extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.originatorSource=It,this.originatorSources=Object.keys(It),this.originatorSourceTranslationMap=Nt,this.originatorSourceDescTranslationMap=St,this.allowedEntityTypes=[C.DEVICE,C.ASSET,C.ENTITY_VIEW,C.USER,C.EDGE]}configForm(){return this.changeOriginatorConfigForm}onConfigurationSet(e){this.changeOriginatorConfigForm=this.fb.group({originatorSource:[e?e.originatorSource:null,[O.required]],entityType:[e?e.entityType:null,[]],entityNamePattern:[e?e.entityNamePattern:null,[]],relationsQuery:[e?e.relationsQuery:null,[]]})}validatorTriggers(){return["originatorSource"]}updateValidators(e){const t=this.changeOriginatorConfigForm.get("originatorSource").value;t===It.RELATED?this.changeOriginatorConfigForm.get("relationsQuery").setValidators([O.required]):this.changeOriginatorConfigForm.get("relationsQuery").setValidators([]),t===It.ENTITY?(this.changeOriginatorConfigForm.get("entityType").setValidators([O.required]),this.changeOriginatorConfigForm.get("entityNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)])):(this.changeOriginatorConfigForm.get("entityType").patchValue(null,{emitEvent:e}),this.changeOriginatorConfigForm.get("entityNamePattern").patchValue(null,{emitEvent:e}),this.changeOriginatorConfigForm.get("entityType").setValidators([]),this.changeOriginatorConfigForm.get("entityNamePattern").setValidators([])),this.changeOriginatorConfigForm.get("relationsQuery").updateValueAndValidity({emitEvent:e}),this.changeOriginatorConfigForm.get("entityType").updateValueAndValidity({emitEvent:e}),this.changeOriginatorConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e})}}e("ChangeOriginatorConfigComponent",Ar),Ar.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ar,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Ar.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ar,selector:"tb-transformation-node-change-originator-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="changeOriginatorConfigForm" class="tb-form-panel no-border no-padding">\n <mat-form-field class="mat-block" subscriptSizing="dynamic" hideRequiredMarker>\n <mat-label translate>tb.rulenode.new-originator</mat-label>\n <mat-select formControlName="originatorSource" required>\n <mat-select-trigger>\n <span *ngIf="originatorSourceTranslationMap.get(changeOriginatorConfigForm.get(\'originatorSource\').value)">\n {{ originatorSourceTranslationMap.get(changeOriginatorConfigForm.get(\'originatorSource\').value) | translate }}\n </span>\n </mat-select-trigger>\n <mat-option *ngFor="let source of originatorSources" [value]="source">\n <span matListItemTitle>\n {{ originatorSourceTranslationMap.get(source) | translate }}\n </span>\n <br>\n <small matListItemMeta style="color: inherit">\n {{ originatorSourceDescTranslationMap.get(source) | translate }}\n </small>\n </mat-option>\n </mat-select>\n </mat-form-field>\n <div class="tb-form-panel stroked no-padding-bottom"\n *ngIf="changeOriginatorConfigForm.get(\'originatorSource\').value === \'ENTITY\'">\n <tb-example-hint [hintText]="\'tb.rulenode.entity-name-pattern-hint\'"\n popupHelpLink="rulenode/change_originator_node_fields_templatization">\n </tb-example-hint>\n <div class="tb-form-row no-border no-padding tb-standard-fields">\n <tb-entity-type-select\n showLabel\n required\n [allowedEntityTypes] = "allowedEntityTypes"\n formControlName="entityType"\n class="mat-mdc-form-field flex">\n </tb-entity-type-select>\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.entity-name-pattern</mat-label>\n <input required matInput formControlName="entityNamePattern">\n <mat-error *ngIf="changeOriginatorConfigForm.get(\'entityNamePattern\').hasError(\'required\') ||\n changeOriginatorConfigForm.get(\'entityNamePattern\').hasError(\'pattern\')">\n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n </div>\n <tb-relations-query-config\n required\n *ngIf="changeOriginatorConfigForm.get(\'originatorSource\').value === originatorSource.RELATED"\n formControlName="relationsQuery">\n </tb-relations-query-config>\n</section>\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ne.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:te.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:Pe.MatListItemTitle,selector:"[matListItemTitle]"},{kind:"directive",type:Pe.MatListItemMeta,selector:"[matListItemMeta]"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:On,selector:"tb-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ar,decorators:[{type:n,args:[{selector:"tb-transformation-node-change-originator-config",template:'<section [formGroup]="changeOriginatorConfigForm" class="tb-form-panel no-border no-padding">\n <mat-form-field class="mat-block" subscriptSizing="dynamic" hideRequiredMarker>\n <mat-label translate>tb.rulenode.new-originator</mat-label>\n <mat-select formControlName="originatorSource" required>\n <mat-select-trigger>\n <span *ngIf="originatorSourceTranslationMap.get(changeOriginatorConfigForm.get(\'originatorSource\').value)">\n {{ originatorSourceTranslationMap.get(changeOriginatorConfigForm.get(\'originatorSource\').value) | translate }}\n </span>\n </mat-select-trigger>\n <mat-option *ngFor="let source of originatorSources" [value]="source">\n <span matListItemTitle>\n {{ originatorSourceTranslationMap.get(source) | translate }}\n </span>\n <br>\n <small matListItemMeta style="color: inherit">\n {{ originatorSourceDescTranslationMap.get(source) | translate }}\n </small>\n </mat-option>\n </mat-select>\n </mat-form-field>\n <div class="tb-form-panel stroked no-padding-bottom"\n *ngIf="changeOriginatorConfigForm.get(\'originatorSource\').value === \'ENTITY\'">\n <tb-example-hint [hintText]="\'tb.rulenode.entity-name-pattern-hint\'"\n popupHelpLink="rulenode/change_originator_node_fields_templatization">\n </tb-example-hint>\n <div class="tb-form-row no-border no-padding tb-standard-fields">\n <tb-entity-type-select\n showLabel\n required\n [allowedEntityTypes] = "allowedEntityTypes"\n formControlName="entityType"\n class="mat-mdc-form-field flex">\n </tb-entity-type-select>\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.entity-name-pattern</mat-label>\n <input required matInput formControlName="entityNamePattern">\n <mat-error *ngIf="changeOriginatorConfigForm.get(\'entityNamePattern\').hasError(\'required\') ||\n changeOriginatorConfigForm.get(\'entityNamePattern\').hasError(\'pattern\')">\n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n </div>\n <tb-relations-query-config\n required\n *ngIf="changeOriginatorConfigForm.get(\'originatorSource\').value === originatorSource.RELATED"\n formControlName="relationsQuery">\n </tb-relations-query-config>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Mr extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ce(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-transformer-function"}configForm(){return this.scriptConfigForm}onConfigurationSet(e){this.scriptConfigForm=this.fb.group({scriptLang:[e?e.scriptLang:b.JS,[O.required]],jsScript:[e?e.jsScript:null,[O.required]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.scriptConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.scriptConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.scriptConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.scriptConfigForm.get("jsScript").setValidators(t===b.JS?[O.required]:[]),this.scriptConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.scriptConfigForm.get("tbelScript").setValidators(t===b.TBEL?[O.required]:[]),this.scriptConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),e}testScript(e){const t=this.scriptConfigForm.get("scriptLang").value,n=t===b.JS?"jsScript":"tbelScript",r=t===b.JS?"rulenode/transformation_node_script_fn":"rulenode/tbel/transformation_node_script_fn",o=this.scriptConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"update",this.translate.instant("tb.rulenode.transformer"),"Transform",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.scriptConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.scriptConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}e("TransformScriptConfigComponent",Mr),Mr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mr,deps:[{token:P.Store},{token:R.FormBuilder},{token:ge.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Mr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Mr,selector:"tb-transformation-node-script-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'<section [formGroup]="scriptConfigForm">\n <tb-script-lang formControlName="scriptLang" *ngIf="tbelEnabled"></tb-script-lang>\n <tb-js-func *ngIf="scriptConfigForm.get(\'scriptLang\').value === scriptLanguage.JS"\n #jsFuncComponent\n formControlName="jsScript"\n functionName="Transform"\n helpId="rulenode/transformation_node_script_fn"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <tb-js-func *ngIf="scriptConfigForm.get(\'scriptLang\').value === scriptLanguage.TBEL"\n #tbelFuncComponent\n formControlName="tbelScript"\n functionName="Transform"\n helpId="rulenode/tbel/transformation_node_script_fn"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n [disableUndefinedCheck]="true"\n [scriptLanguage]="scriptLanguage.TBEL"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <div>\n <button mat-button mat-raised-button color="primary" (click)="testScript()">\n {{ testScriptLabel | translate }}\n </button>\n </div>\n</section>\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ce.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mr,decorators:[{type:n,args:[{selector:"tb-transformation-node-script-config",template:'<section [formGroup]="scriptConfigForm">\n <tb-script-lang formControlName="scriptLang" *ngIf="tbelEnabled"></tb-script-lang>\n <tb-js-func *ngIf="scriptConfigForm.get(\'scriptLang\').value === scriptLanguage.JS"\n #jsFuncComponent\n formControlName="jsScript"\n functionName="Transform"\n helpId="rulenode/transformation_node_script_fn"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <tb-js-func *ngIf="scriptConfigForm.get(\'scriptLang\').value === scriptLanguage.TBEL"\n #tbelFuncComponent\n formControlName="tbelScript"\n functionName="Transform"\n helpId="rulenode/tbel/transformation_node_script_fn"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n [disableUndefinedCheck]="true"\n [scriptLanguage]="scriptLanguage.TBEL"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <div>\n <button mat-button mat-raised-button color="primary" (click)="testScript()">\n {{ testScriptLabel | translate }}\n </button>\n </div>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:ge.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}}); - /** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - const Er=mt({passive:!0});class Gr{constructor(e,t){this._platform=e,this._ngZone=t,this._monitoredElements=new Map}monitor(e){if(!this._platform.isBrowser)return se;const t=Ge(e),n=this._monitoredElements.get(t);if(n)return n.subject;const r=new ae,o="cdk-text-field-autofilled",a=e=>{"cdk-text-field-autofill-start"!==e.animationName||t.classList.contains(o)?"cdk-text-field-autofill-end"===e.animationName&&t.classList.contains(o)&&(t.classList.remove(o),this._ngZone.run((()=>r.next({target:e.target,isAutofilled:!1})))):(t.classList.add(o),this._ngZone.run((()=>r.next({target:e.target,isAutofilled:!0}))))};return this._ngZone.runOutsideAngular((()=>{t.addEventListener("animationstart",a,Er),t.classList.add("cdk-text-field-autofill-monitored")})),this._monitoredElements.set(t,{subject:r,unlisten:()=>{t.removeEventListener("animationstart",a,Er)}}),r}stopMonitoring(e){const t=Ge(e),n=this._monitoredElements.get(t);n&&(n.unlisten(),n.subject.complete(),t.classList.remove("cdk-text-field-autofill-monitored"),t.classList.remove("cdk-text-field-autofilled"),this._monitoredElements.delete(t))}ngOnDestroy(){this._monitoredElements.forEach(((e,t)=>this.stopMonitoring(t)))}}Gr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Gr,deps:[{token:pt.Platform},{token:t.NgZone}],target:t.ɵɵFactoryTarget.Injectable}),Gr.ɵprov=t.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Gr,providedIn:"root"}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Gr,decorators:[{type:o,args:[{providedIn:"root"}]}],ctorParameters:function(){return[{type:pt.Platform},{type:t.NgZone}]}});class wr{constructor(e,t){this._elementRef=e,this._autofillMonitor=t,this.cdkAutofill=new l}ngOnInit(){this._autofillMonitor.monitor(this._elementRef).subscribe((e=>this.cdkAutofill.emit(e)))}ngOnDestroy(){this._autofillMonitor.stopMonitoring(this._elementRef)}}wr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:wr,deps:[{token:t.ElementRef},{token:Gr}],target:t.ɵɵFactoryTarget.Directive}),wr.ɵdir=t.ɵɵngDeclareDirective({minVersion:"14.0.0",version:"15.2.0-rc.0",type:wr,selector:"[cdkAutofill]",outputs:{cdkAutofill:"cdkAutofill"},ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:wr,decorators:[{type:s,args:[{selector:"[cdkAutofill]"}]}],ctorParameters:function(){return[{type:t.ElementRef},{type:Gr}]},propDecorators:{cdkAutofill:[{type:p}]}}); - /** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - class Dr{get minRows(){return this._minRows}set minRows(e){this._minRows=we(e),this._setMinHeight()}get maxRows(){return this._maxRows}set maxRows(e){this._maxRows=we(e),this._setMaxHeight()}get enabled(){return this._enabled}set enabled(e){e=Ee(e),this._enabled!==e&&((this._enabled=e)?this.resizeToFitContent(!0):this.reset())}get placeholder(){return this._textareaElement.placeholder}set placeholder(e){this._cachedPlaceholderHeight=void 0,e?this._textareaElement.setAttribute("placeholder",e):this._textareaElement.removeAttribute("placeholder"),this._cacheTextareaPlaceholderHeight()}constructor(e,t,n,r){this._elementRef=e,this._platform=t,this._ngZone=n,this._destroyed=new ae,this._enabled=!0,this._previousMinRows=-1,this._isViewInited=!1,this._handleFocusEvent=e=>{this._hasFocus="focus"===e.type},this._document=r,this._textareaElement=this._elementRef.nativeElement}_setMinHeight(){const e=this.minRows&&this._cachedLineHeight?this.minRows*this._cachedLineHeight+"px":null;e&&(this._textareaElement.style.minHeight=e)}_setMaxHeight(){const e=this.maxRows&&this._cachedLineHeight?this.maxRows*this._cachedLineHeight+"px":null;e&&(this._textareaElement.style.maxHeight=e)}ngAfterViewInit(){this._platform.isBrowser&&(this._initialHeight=this._textareaElement.style.height,this.resizeToFitContent(),this._ngZone.runOutsideAngular((()=>{const e=this._getWindow();me(e,"resize").pipe(Ue(16),He(this._destroyed)).subscribe((()=>this.resizeToFitContent(!0))),this._textareaElement.addEventListener("focus",this._handleFocusEvent),this._textareaElement.addEventListener("blur",this._handleFocusEvent)})),this._isViewInited=!0,this.resizeToFitContent(!0))}ngOnDestroy(){this._textareaElement.removeEventListener("focus",this._handleFocusEvent),this._textareaElement.removeEventListener("blur",this._handleFocusEvent),this._destroyed.next(),this._destroyed.complete()}_cacheTextareaLineHeight(){if(this._cachedLineHeight)return;let e=this._textareaElement.cloneNode(!1);e.rows=1,e.style.position="absolute",e.style.visibility="hidden",e.style.border="none",e.style.padding="0",e.style.height="",e.style.minHeight="",e.style.maxHeight="",e.style.overflow="hidden",this._textareaElement.parentNode.appendChild(e),this._cachedLineHeight=e.clientHeight,e.remove(),this._setMinHeight(),this._setMaxHeight()}_measureScrollHeight(){const e=this._textareaElement,t=e.style.marginBottom||"",n=this._platform.FIREFOX,r=n&&this._hasFocus,o=n?"cdk-textarea-autosize-measuring-firefox":"cdk-textarea-autosize-measuring";r&&(e.style.marginBottom=`${e.clientHeight}px`),e.classList.add(o);const a=e.scrollHeight-4;return e.classList.remove(o),r&&(e.style.marginBottom=t),a}_cacheTextareaPlaceholderHeight(){if(!this._isViewInited||null!=this._cachedPlaceholderHeight)return;if(!this.placeholder)return void(this._cachedPlaceholderHeight=0);const e=this._textareaElement.value;this._textareaElement.value=this._textareaElement.placeholder,this._cachedPlaceholderHeight=this._measureScrollHeight(),this._textareaElement.value=e}ngDoCheck(){this._platform.isBrowser&&this.resizeToFitContent()}resizeToFitContent(e=!1){if(!this._enabled)return;if(this._cacheTextareaLineHeight(),this._cacheTextareaPlaceholderHeight(),!this._cachedLineHeight)return;const t=this._elementRef.nativeElement,n=t.value;if(!e&&this._minRows===this._previousMinRows&&n===this._previousValue)return;const r=this._measureScrollHeight(),o=Math.max(r,this._cachedPlaceholderHeight||0);t.style.height=`${o}px`,this._ngZone.runOutsideAngular((()=>{"undefined"!=typeof requestAnimationFrame?requestAnimationFrame((()=>this._scrollToCaretPosition(t))):setTimeout((()=>this._scrollToCaretPosition(t)))})),this._previousValue=n,this._previousMinRows=this._minRows}reset(){void 0!==this._initialHeight&&(this._textareaElement.style.height=this._initialHeight)}_noopInputHandler(){}_getDocument(){return this._document||document}_getWindow(){return this._getDocument().defaultView||window}_scrollToCaretPosition(e){const{selectionStart:t,selectionEnd:n}=e;!this._destroyed.isStopped&&this._hasFocus&&e.setSelectionRange(t,n)}}Dr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Dr,deps:[{token:t.ElementRef},{token:pt.Platform},{token:t.NgZone},{token:j,optional:!0}],target:t.ɵɵFactoryTarget.Directive}),Dr.ɵdir=t.ɵɵngDeclareDirective({minVersion:"14.0.0",version:"15.2.0-rc.0",type:Dr,selector:"textarea[cdkTextareaAutosize]",inputs:{minRows:["cdkAutosizeMinRows","minRows"],maxRows:["cdkAutosizeMaxRows","maxRows"],enabled:["cdkTextareaAutosize","enabled"],placeholder:"placeholder"},host:{attributes:{rows:"1"},listeners:{input:"_noopInputHandler()"},classAttribute:"cdk-textarea-autosize"},exportAs:["cdkTextareaAutosize"],ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Dr,decorators:[{type:s,args:[{selector:"textarea[cdkTextareaAutosize]",exportAs:"cdkTextareaAutosize",host:{class:"cdk-textarea-autosize",rows:"1","(input)":"_noopInputHandler()"}}]}],ctorParameters:function(){return[{type:t.ElementRef},{type:pt.Platform},{type:t.NgZone},{type:void 0,decorators:[{type:i},{type:a,args:[j]}]}]},propDecorators:{minRows:[{type:m,args:["cdkAutosizeMinRows"]}],maxRows:[{type:m,args:["cdkAutosizeMaxRows"]}],enabled:[{type:m,args:["cdkTextareaAutosize"]}],placeholder:[{type:m}]}}); - /** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - class Vr{}Vr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Vr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Vr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.0-rc.0",ngImport:t,type:Vr,declarations:[wr,Dr],exports:[wr,Dr]}),Vr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Vr}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Vr,decorators:[{type:d,args:[{declarations:[wr,Dr],exports:[wr,Dr]}]}]});class Pr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.mailBodyTypes=[{name:"tb.mail-body-type.plain-text",description:"tb.mail-body-type.plain-text-description",value:"false"},{name:"tb.mail-body-type.html",description:"tb.mail-body-type.html-text-description",value:"true"},{name:"tb.mail-body-type.use-body-type-template",description:"tb.mail-body-type.dynamic-text-description",value:"dynamic"}]}configForm(){return this.toEmailConfigForm}onConfigurationSet(e){this.toEmailConfigForm=this.fb.group({fromTemplate:[e?e.fromTemplate:null,[O.required]],toTemplate:[e?e.toTemplate:null,[O.required]],ccTemplate:[e?e.ccTemplate:null,[]],bccTemplate:[e?e.bccTemplate:null,[]],subjectTemplate:[e?e.subjectTemplate:null,[O.required]],mailBodyType:[e?e.mailBodyType:null],isHtmlTemplate:[e?e.isHtmlTemplate:null,[O.required]],bodyTemplate:[e?e.bodyTemplate:null,[O.required]]})}prepareInputConfig(e){return{fromTemplate:fe(e?.fromTemplate)?e.fromTemplate:null,toTemplate:fe(e?.toTemplate)?e.toTemplate:null,ccTemplate:fe(e?.ccTemplate)?e.ccTemplate:null,bccTemplate:fe(e?.bccTemplate)?e.bccTemplate:null,subjectTemplate:fe(e?.subjectTemplate)?e.subjectTemplate:null,mailBodyType:fe(e?.mailBodyType)?e.mailBodyType:null,isHtmlTemplate:fe(e?.isHtmlTemplate)?e.isHtmlTemplate:null,bodyTemplate:fe(e?.bodyTemplate)?e.bodyTemplate:null}}updateValidators(e){"dynamic"===this.toEmailConfigForm.get("mailBodyType").value?this.toEmailConfigForm.get("isHtmlTemplate").enable({emitEvent:!1}):this.toEmailConfigForm.get("isHtmlTemplate").disable({emitEvent:!1}),this.toEmailConfigForm.get("isHtmlTemplate").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["mailBodyType"]}getBodyTypeName(){return this.mailBodyTypes.find((e=>e.value===this.toEmailConfigForm.get("mailBodyType").value)).name}}e("ToEmailConfigComponent",Pr),Pr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Pr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Pr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Pr,selector:"tb-transformation-node-to-email-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="toEmailConfigForm" class="tb-form-panel no-border no-padding">\n <div class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.email-sender</div>\n <div class="tb-form-row no-border no-padding tb-standard-fields">\n <mat-form-field class="flex" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.from-template</mat-label>\n <input required matInput formControlName="fromTemplate">\n <mat-hint align="start">\n {{ \'tb.rulenode.email-from-template-hint\' | translate }}\n </mat-hint>\n <mat-hint align="end">\n <div class="input-bottom-double-hint">\n <div class="see-example"\n hintMode\n tb-help-popup="{{\'rulenode/to_email_node_fields_templatization\'}}"\n tb-help-popup-placement="right"\n trigger-style="letter-spacing:0.25px; font-size:12px;"\n [tb-help-popup-style]="{maxWidth: \'820px\'}"\n trigger-text="{{ \'tb.key-val.see-examples\' | translate }}"></div>\n </div>\n </mat-hint>\n <mat-error *ngIf="toEmailConfigForm.get(\'fromTemplate\').hasError(\'required\')">\n {{ \'tb.rulenode.from-template-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n </div>\n <div class="tb-form-panel stroked">\n <div class="tb-form-panel no-padding no-border">\n <div class="tb-form-panel-title" translate>tb.rulenode.recipients</div>\n <tb-example-hint [hintText]="\'tb.rulenode.recipients-block-main-hint\' | translate"\n popupHelpLink="rulenode/to_email_node_fields_templatization">\n </tb-example-hint>\n </div>\n <div class="tb-form-row no-border no-padding tb-standard-fields">\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.to-template</mat-label>\n <textarea required\n matInput\n class="tb-enable-vertical-resize"\n formControlName="toTemplate"\n cdkTextareaAutosize\n cdkAutosizeMinRows="1"></textarea>\n <mat-error *ngIf="toEmailConfigForm.get(\'toTemplate\').hasError(\'required\')">\n {{ \'tb.rulenode.to-template-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.cc-template</mat-label>\n <textarea matInput\n formControlName="ccTemplate"\n class="tb-enable-vertical-resize"\n cdkTextareaAutosize\n cdkAutosizeMinRows="1"></textarea>\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.bcc-template</mat-label>\n <textarea matInput\n formControlName="bccTemplate"\n class="tb-enable-vertical-resize"\n cdkTextareaAutosize\n cdkAutosizeMinRows="1"></textarea>\n </mat-form-field>\n </div>\n </div>\n <div class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.message-subject-and-content</div>\n <tb-example-hint [hintText]="\'tb.rulenode.kv-map-pattern-hint\' | translate"\n popupHelpLink="rulenode/to_email_node_fields_templatization">\n </tb-example-hint>\n <section>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.subject-template</mat-label>\n <textarea required\n matInput\n formControlName="subjectTemplate"\n class="tb-enable-vertical-resize"\n cdkTextareaAutosize\n cdkAutosizeMinRows="1"></textarea>\n <mat-error *ngIf="toEmailConfigForm.get(\'subjectTemplate\').hasError(\'required\')">\n {{ \'tb.rulenode.subject-template-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.mail-body-type</mat-label>\n <mat-select formControlName="mailBodyType">\n <mat-select-trigger>\n <span *ngIf="toEmailConfigForm.get(\'mailBodyType\').value">\n {{ getBodyTypeName() | translate }}\n </span>\n </mat-select-trigger>\n <mat-option *ngFor="let type of mailBodyTypes" [value]="type.value">\n <span matListItemTitle>\n {{ type.name | translate }}\n </span>\n <br>\n <small matListItemMeta style="color: inherit">\n {{ type.description | translate }}\n </small>\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="mat-block" *ngIf="toEmailConfigForm.get(\'mailBodyType\').value === \'dynamic\'">\n <mat-label translate>tb.rulenode.body-type-template</mat-label>\n <input required matInput formControlName="isHtmlTemplate">\n <mat-hint translate>tb.mail-body-type.after-template-evaluation-hint</mat-hint>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.body-template</mat-label>\n <textarea required\n matInput\n formControlName="bodyTemplate"\n class="tb-enable-vertical-resize"\n cdkTextareaAutosize\n cdkAutosizeMinRows="2"></textarea>\n <mat-error *ngIf="toEmailConfigForm.get(\'bodyTemplate\').hasError(\'required\')">\n {{ \'tb.rulenode.body-template-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </section>\n </div>\n</section>\n',styles:[":host .input-bottom-double-hint{display:inline-flex}:host .input-bottom-double-hint .see-example{flex-shrink:0;padding-right:16px}:host textarea.tb-enable-vertical-resize{resize:vertical}\n"],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Dr,selector:"textarea[cdkTextareaAutosize]",inputs:["cdkAutosizeMinRows","cdkAutosizeMaxRows","cdkTextareaAutosize","placeholder"],exportAs:["cdkTextareaAutosize"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:te.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:Pe.MatListItemTitle,selector:"[matListItemTitle]"},{kind:"directive",type:Pe.MatListItemMeta,selector:"[matListItemMeta]"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Pr,decorators:[{type:n,args:[{selector:"tb-transformation-node-to-email-config",template:'<section [formGroup]="toEmailConfigForm" class="tb-form-panel no-border no-padding">\n <div class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.email-sender</div>\n <div class="tb-form-row no-border no-padding tb-standard-fields">\n <mat-form-field class="flex" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.from-template</mat-label>\n <input required matInput formControlName="fromTemplate">\n <mat-hint align="start">\n {{ \'tb.rulenode.email-from-template-hint\' | translate }}\n </mat-hint>\n <mat-hint align="end">\n <div class="input-bottom-double-hint">\n <div class="see-example"\n hintMode\n tb-help-popup="{{\'rulenode/to_email_node_fields_templatization\'}}"\n tb-help-popup-placement="right"\n trigger-style="letter-spacing:0.25px; font-size:12px;"\n [tb-help-popup-style]="{maxWidth: \'820px\'}"\n trigger-text="{{ \'tb.key-val.see-examples\' | translate }}"></div>\n </div>\n </mat-hint>\n <mat-error *ngIf="toEmailConfigForm.get(\'fromTemplate\').hasError(\'required\')">\n {{ \'tb.rulenode.from-template-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n </div>\n <div class="tb-form-panel stroked">\n <div class="tb-form-panel no-padding no-border">\n <div class="tb-form-panel-title" translate>tb.rulenode.recipients</div>\n <tb-example-hint [hintText]="\'tb.rulenode.recipients-block-main-hint\' | translate"\n popupHelpLink="rulenode/to_email_node_fields_templatization">\n </tb-example-hint>\n </div>\n <div class="tb-form-row no-border no-padding tb-standard-fields">\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.to-template</mat-label>\n <textarea required\n matInput\n class="tb-enable-vertical-resize"\n formControlName="toTemplate"\n cdkTextareaAutosize\n cdkAutosizeMinRows="1"></textarea>\n <mat-error *ngIf="toEmailConfigForm.get(\'toTemplate\').hasError(\'required\')">\n {{ \'tb.rulenode.to-template-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.cc-template</mat-label>\n <textarea matInput\n formControlName="ccTemplate"\n class="tb-enable-vertical-resize"\n cdkTextareaAutosize\n cdkAutosizeMinRows="1"></textarea>\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.bcc-template</mat-label>\n <textarea matInput\n formControlName="bccTemplate"\n class="tb-enable-vertical-resize"\n cdkTextareaAutosize\n cdkAutosizeMinRows="1"></textarea>\n </mat-form-field>\n </div>\n </div>\n <div class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.message-subject-and-content</div>\n <tb-example-hint [hintText]="\'tb.rulenode.kv-map-pattern-hint\' | translate"\n popupHelpLink="rulenode/to_email_node_fields_templatization">\n </tb-example-hint>\n <section>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.subject-template</mat-label>\n <textarea required\n matInput\n formControlName="subjectTemplate"\n class="tb-enable-vertical-resize"\n cdkTextareaAutosize\n cdkAutosizeMinRows="1"></textarea>\n <mat-error *ngIf="toEmailConfigForm.get(\'subjectTemplate\').hasError(\'required\')">\n {{ \'tb.rulenode.subject-template-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.mail-body-type</mat-label>\n <mat-select formControlName="mailBodyType">\n <mat-select-trigger>\n <span *ngIf="toEmailConfigForm.get(\'mailBodyType\').value">\n {{ getBodyTypeName() | translate }}\n </span>\n </mat-select-trigger>\n <mat-option *ngFor="let type of mailBodyTypes" [value]="type.value">\n <span matListItemTitle>\n {{ type.name | translate }}\n </span>\n <br>\n <small matListItemMeta style="color: inherit">\n {{ type.description | translate }}\n </small>\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="mat-block" *ngIf="toEmailConfigForm.get(\'mailBodyType\').value === \'dynamic\'">\n <mat-label translate>tb.rulenode.body-type-template</mat-label>\n <input required matInput formControlName="isHtmlTemplate">\n <mat-hint translate>tb.mail-body-type.after-template-evaluation-hint</mat-hint>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.body-template</mat-label>\n <textarea required\n matInput\n formControlName="bodyTemplate"\n class="tb-enable-vertical-resize"\n cdkTextareaAutosize\n cdkAutosizeMinRows="2"></textarea>\n <mat-error *ngIf="toEmailConfigForm.get(\'bodyTemplate\').hasError(\'required\')">\n {{ \'tb.rulenode.body-template-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </section>\n </div>\n</section>\n',styles:[":host .input-bottom-double-hint{display:inline-flex}:host .input-bottom-double-hint .see-example{flex-shrink:0;padding-right:16px}:host textarea.tb-enable-vertical-resize{resize:vertical}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Rr extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.copyFrom=[],this.translation=sn;for(const e of this.translation.keys())this.copyFrom.push({value:e,name:this.translate.instant(this.translation.get(e))})}onConfigurationSet(e){this.copyKeysConfigForm=this.fb.group({copyFrom:[e.copyFrom,[O.required]],keys:[e?e.keys:null,[O.required]]})}configForm(){return this.copyKeysConfigForm}prepareInputConfig(e){let t;return t=fe(e?.fromMetadata)?e.copyFrom?ln.METADATA:ln.DATA:fe(e?.copyFrom)?e.copyFrom:ln.DATA,{keys:fe(e?.keys)?e.keys:null,copyFrom:t}}}e("CopyKeysConfigComponent",Rr),Rr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Rr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Rr,selector:"tb-transformation-node-copy-keys-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="copyKeysConfigForm" class="tb-form-panel no-padding no-border">\n <tb-msg-metadata-chip\n [labelText]="(\'tb.key-val.copy-key-values-from\' | translate)"\n [translation]="translation"\n formControlName="copyFrom">\n </tb-msg-metadata-chip>\n <tb-string-items-list class="mat-block"\n required\n [label]="\'tb.rulenode.keys\' | translate"\n [placeholder]="\'tb.rulenode.add-key\' | translate"\n [requiredText]="\'tb.key-val.at-least-one-key-error\' | translate"\n formControlName="keys">\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.use-regular-expression-hint\' | translate }}">\n help\n </mat-icon>\n </tb-string-items-list>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rr,decorators:[{type:n,args:[{selector:"tb-transformation-node-copy-keys-config",template:'<section [formGroup]="copyKeysConfigForm" class="tb-form-panel no-padding no-border">\n <tb-msg-metadata-chip\n [labelText]="(\'tb.key-val.copy-key-values-from\' | translate)"\n [translation]="translation"\n formControlName="copyFrom">\n </tb-msg-metadata-chip>\n <tb-string-items-list class="mat-block"\n required\n [label]="\'tb.rulenode.keys\' | translate"\n [placeholder]="\'tb.rulenode.add-key\' | translate"\n [requiredText]="\'tb.key-val.at-least-one-key-error\' | translate"\n formControlName="keys">\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.use-regular-expression-hint\' | translate }}">\n help\n </mat-icon>\n </tb-string-items-list>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Or extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.renameIn=[],this.translation=pn;for(const e of this.translation.keys())this.renameIn.push({value:e,name:this.translate.instant(this.translation.get(e))})}configForm(){return this.renameKeysConfigForm}onConfigurationSet(e){this.renameKeysConfigForm=this.fb.group({renameIn:[e?e.renameIn:null,[O.required]],renameKeysMapping:[e?e.renameKeysMapping:null,[O.required]]})}prepareInputConfig(e){let t;return t=fe(e?.fromMetadata)?e.fromMetadata?ln.METADATA:ln.DATA:fe(e?.renameIn)?e?.renameIn:ln.DATA,{renameKeysMapping:fe(e?.renameKeysMapping)?e.renameKeysMapping:null,renameIn:t}}}e("RenameKeysConfigComponent",Or),Or.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Or,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Or.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Or,selector:"tb-transformation-node-rename-keys-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="renameKeysConfigForm" class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.rename-keys-in</div>\n <div class="fx-centered">\n <div class="fetch-to-data-toggle">\n <tb-toggle-select class="fetch-to-data-toggle" formControlName="renameIn" appearance="fill">\n <tb-toggle-option *ngFor="let data of renameIn" [value]="data.value">\n {{ data.name }}\n </tb-toggle-option>\n </tb-toggle-select>\n </div>\n </div>\n <tb-kv-map-config\n required\n labelText="{{ translation.get(renameKeysConfigForm.get(\'renameIn\').value) | translate }} {{\'tb.rulenode.keys-mapping\' | translate}}"\n formControlName="renameKeysMapping"\n uniqueKeyValuePairValidator\n requiredText="{{\'tb.rulenode.attr-mapping-required\' | translate}}"\n keyText="{{\'tb.rulenode.current-key-name\' | translate}}"\n keyRequiredText="{{\'tb.rulenode.key-name-required\' | translate}}"\n valText="{{\'tb.rulenode.new-key-name\' | translate}}"\n valRequiredText="{{\'tb.rulenode.new-key-name-required\' | translate}}">\n </tb-kv-map-config>\n</section>\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}:host .fx-centered{display:flex;width:100%;justify-content:space-around}\n"],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Ae.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Me.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Pn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Or,decorators:[{type:n,args:[{selector:"tb-transformation-node-rename-keys-config",template:'<section [formGroup]="renameKeysConfigForm" class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.rename-keys-in</div>\n <div class="fx-centered">\n <div class="fetch-to-data-toggle">\n <tb-toggle-select class="fetch-to-data-toggle" formControlName="renameIn" appearance="fill">\n <tb-toggle-option *ngFor="let data of renameIn" [value]="data.value">\n {{ data.name }}\n </tb-toggle-option>\n </tb-toggle-select>\n </div>\n </div>\n <tb-kv-map-config\n required\n labelText="{{ translation.get(renameKeysConfigForm.get(\'renameIn\').value) | translate }} {{\'tb.rulenode.keys-mapping\' | translate}}"\n formControlName="renameKeysMapping"\n uniqueKeyValuePairValidator\n requiredText="{{\'tb.rulenode.attr-mapping-required\' | translate}}"\n keyText="{{\'tb.rulenode.current-key-name\' | translate}}"\n keyRequiredText="{{\'tb.rulenode.key-name-required\' | translate}}"\n valText="{{\'tb.rulenode.new-key-name\' | translate}}"\n valRequiredText="{{\'tb.rulenode.new-key-name-required\' | translate}}">\n </tb-kv-map-config>\n</section>\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}:host .fx-centered{display:flex;width:100%;justify-content:space-around}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class _r extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.jsonPathConfigForm}onConfigurationSet(e){this.jsonPathConfigForm=this.fb.group({jsonPath:[e?e.jsonPath:null,[O.required]]})}}e("NodeJsonPathConfigComponent",_r),_r.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_r,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),_r.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:_r,selector:"tb-transformation-node-json-path-config",usesInheritance:!0,ngImport:t,template:"<section [formGroup]=\"jsonPathConfigForm\">\n <mat-form-field subscriptSizing=\"dynamic\" class=\"mat-block\">\n <mat-label>{{ 'tb.rulenode.json-path-expression' | translate }}</mat-label>\n <input matInput formControlName=\"jsonPath\" required/>\n <mat-hint>{{ 'tb.rulenode.json-path-expression-hint' | translate }}</mat-hint>\n <mat-error *ngIf=\"jsonPathConfigForm.get('jsonPath').hasError('required')\">{{ 'tb.rulenode.json-path-expression-required' | translate }}</mat-error>\n </mat-form-field>\n</section>\n",dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_r,decorators:[{type:n,args:[{selector:"tb-transformation-node-json-path-config",template:"<section [formGroup]=\"jsonPathConfigForm\">\n <mat-form-field subscriptSizing=\"dynamic\" class=\"mat-block\">\n <mat-label>{{ 'tb.rulenode.json-path-expression' | translate }}</mat-label>\n <input matInput formControlName=\"jsonPath\" required/>\n <mat-hint>{{ 'tb.rulenode.json-path-expression-hint' | translate }}</mat-hint>\n <mat-error *ngIf=\"jsonPathConfigForm.get('jsonPath').hasError('required')\">{{ 'tb.rulenode.json-path-expression-required' | translate }}</mat-error>\n </mat-form-field>\n</section>\n"}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Br extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.deleteFrom=[],this.translation=mn;for(const e of this.translation.keys())this.deleteFrom.push({value:e,name:this.translate.instant(this.translation.get(e))})}onConfigurationSet(e){this.deleteKeysConfigForm=this.fb.group({deleteFrom:[e.deleteFrom,[O.required]],keys:[e?e.keys:null,[O.required]]})}prepareInputConfig(e){let t;return t=fe(e?.fromMetadata)?e.fromMetadata?ln.METADATA:ln.DATA:fe(e?.deleteFrom)?e?.deleteFrom:ln.DATA,{keys:fe(e?.keys)?e.keys:null,deleteFrom:t}}configForm(){return this.deleteKeysConfigForm}}e("DeleteKeysConfigComponent",Br),Br.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Br,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Br.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Br,selector:"tb-transformation-node-delete-keys-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="deleteKeysConfigForm" class="tb-form-panel no-border no-padding">\n <tb-msg-metadata-chip\n [labelText]="(\'tb.key-val.delete-key-values-from\' | translate)"\n formControlName="deleteFrom">\n </tb-msg-metadata-chip>\n <tb-string-items-list class="mat-block"\n required\n [label]="\'tb.rulenode.keys\' | translate"\n [placeholder]="\'tb.rulenode.add-key\' | translate"\n [requiredText]="\'tb.key-val.at-least-one-key-error\' | translate"\n formControlName="keys">\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.use-regular-expression-delete-hint\' | translate }}">\n help\n </mat-icon>\n </tb-string-items-list>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Br,decorators:[{type:n,args:[{selector:"tb-transformation-node-delete-keys-config",template:'<section [formGroup]="deleteKeysConfigForm" class="tb-form-panel no-border no-padding">\n <tb-msg-metadata-chip\n [labelText]="(\'tb.key-val.delete-key-values-from\' | translate)"\n formControlName="deleteFrom">\n </tb-msg-metadata-chip>\n <tb-string-items-list class="mat-block"\n required\n [label]="\'tb.rulenode.keys\' | translate"\n [placeholder]="\'tb.rulenode.add-key\' | translate"\n [requiredText]="\'tb.key-val.at-least-one-key-error\' | translate"\n formControlName="keys">\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.use-regular-expression-delete-hint\' | translate }}">\n help\n </mat-icon>\n </tb-string-items-list>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Kr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.deduplicationStrategie=Ot,this.deduplicationStrategies=Object.keys(this.deduplicationStrategie),this.deduplicationStrategiesTranslations=_t}configForm(){return this.deduplicationConfigForm}onConfigurationSet(e){this.deduplicationConfigForm=this.fb.group({interval:[fe(e?.interval)?e.interval:null,[O.required,O.min(1)]],strategy:[fe(e?.strategy)?e.strategy:null,[O.required]],outMsgType:[fe(e?.outMsgType)?e.outMsgType:null,[O.required]],maxPendingMsgs:[fe(e?.maxPendingMsgs)?e.maxPendingMsgs:null,[O.required,O.min(1),O.max(1e3)]],maxRetries:[fe(e?.maxRetries)?e.maxRetries:null,[O.required,O.min(0),O.max(100)]]})}prepareInputConfig(e){return e||(e={}),e.outMsgType||(e.outMsgType="POST_TELEMETRY_REQUEST"),super.prepareInputConfig(e)}updateValidators(e){this.deduplicationConfigForm.get("strategy").value===this.deduplicationStrategie.ALL?this.deduplicationConfigForm.get("outMsgType").enable({emitEvent:!1}):this.deduplicationConfigForm.get("outMsgType").disable({emitEvent:!1}),this.deduplicationConfigForm.get("outMsgType").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["strategy"]}}e("DeduplicationConfigComponent",Kr),Kr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Kr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Kr,selector:"tb-action-node-msg-deduplication-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="deduplicationConfigForm">\n <mat-form-field class="mat-block">\n <mat-label>{{\'tb.rulenode.interval\' | translate}}</mat-label>\n <input type=\'number\' required matInput formControlName="interval">\n <mat-error *ngIf="deduplicationConfigForm.get(\'interval\').hasError(\'required\')">\n {{\'tb.rulenode.interval-required\' | translate}}\n </mat-error>\n <mat-error *ngIf="deduplicationConfigForm.get(\'interval\').hasError(\'min\')">\n {{\'tb.rulenode.interval-min-error\' | translate}}\n </mat-error>\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.interval-hint\' | translate }}">help</mat-icon>\n </mat-form-field>\n <div class="tb-form-panel no-padding no-border">\n <div class="tb-form-panel stroked">\n <div class="tb-form-panel-title tb-required" translate>tb.rulenode.strategy</div>\n <tb-toggle-select class="fetch-to-data-toggle" formControlName="strategy" appearance="fill">\n <tb-toggle-option *ngFor="let strategy of deduplicationStrategies" [value]="strategy">\n {{ deduplicationStrategiesTranslations.get(strategy) | translate }}\n </tb-toggle-option>\n </tb-toggle-select>\n <tb-example-hint [hintText]="\'tb.rulenode.strategy-all-hint\' | translate"\n *ngIf="deduplicationConfigForm.get(\'strategy\').value === \'ALL\'">\n </tb-example-hint>\n <tb-example-hint [hintText]="\'tb.rulenode.strategy-first-hint\' | translate"\n textAlign="\'center\'"\n *ngIf="deduplicationConfigForm.get(\'strategy\').value === \'FIRST\'">\n </tb-example-hint>\n <tb-example-hint [hintText]="\'tb.rulenode.strategy-last-hint\' | translate"\n textAlign="\'center\'"\n *ngIf="deduplicationConfigForm.get(\'strategy\').value === \'LAST\'">\n </tb-example-hint>\n <div *ngIf="deduplicationConfigForm.get(\'strategy\').value === deduplicationStrategie.ALL">\n <tb-output-message-type-autocomplete\n required\n formControlName="outMsgType">\n </tb-output-message-type-autocomplete>\n </div>\n </div>\n <section class="tb-form-panel stroked">\n <mat-expansion-panel class="tb-settings">\n <mat-expansion-panel-header>\n <mat-panel-title translate>tb.rulenode.advanced-settings</mat-panel-title>\n </mat-expansion-panel-header>\n <div class="tb-form-row no-border no-padding tb-standard-fields">\n <mat-form-field class="flex">\n <mat-label>{{\'tb.rulenode.max-pending-msgs\' | translate}}</mat-label>\n <input type = \'number\' required matInput formControlName="maxPendingMsgs">\n <mat-error *ngIf="deduplicationConfigForm.get(\'maxPendingMsgs\').hasError(\'required\')">\n {{\'tb.rulenode.max-pending-msgs-required\' | translate}}\n </mat-error>\n <mat-error *ngIf="deduplicationConfigForm.get(\'maxPendingMsgs\').hasError(\'max\')">\n {{\'tb.rulenode.max-pending-msgs-max-error\' | translate}}\n </mat-error>\n <mat-error *ngIf="deduplicationConfigForm.get(\'maxPendingMsgs\').hasError(\'min\')">\n {{\'tb.rulenode.max-pending-msgs-min-error\' | translate}}\n </mat-error>\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.max-pending-msgs-hint\' | translate }}">help</mat-icon>\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label>{{\'tb.rulenode.max-retries\' | translate}}</mat-label>\n <input type = \'number\' required matInput formControlName="maxRetries">\n <mat-error *ngIf="deduplicationConfigForm.get(\'maxRetries\').hasError(\'required\')">\n {{\'tb.rulenode.max-retries-required\' | translate}}\n </mat-error>\n <mat-error *ngIf="deduplicationConfigForm.get(\'maxRetries\').hasError(\'max\')">\n {{\'tb.rulenode.max-retries-max-error\' | translate}}\n </mat-error>\n <mat-error *ngIf="deduplicationConfigForm.get(\'maxRetries\').hasError(\'min\')">\n {{\'tb.rulenode.max-retries-min-error\' | translate}}\n </mat-error>\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.max-retries-hint\' | translate }}">help</mat-icon>\n </mat-form-field>\n </div>\n </mat-expansion-panel>\n </section>\n </div>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:oe.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:oe.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:oe.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Ae.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Me.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Kn,selector:"tb-output-message-type-autocomplete",inputs:["subscriptSizing","disabled","required"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kr,decorators:[{type:n,args:[{selector:"tb-action-node-msg-deduplication-config",template:'<section [formGroup]="deduplicationConfigForm">\n <mat-form-field class="mat-block">\n <mat-label>{{\'tb.rulenode.interval\' | translate}}</mat-label>\n <input type=\'number\' required matInput formControlName="interval">\n <mat-error *ngIf="deduplicationConfigForm.get(\'interval\').hasError(\'required\')">\n {{\'tb.rulenode.interval-required\' | translate}}\n </mat-error>\n <mat-error *ngIf="deduplicationConfigForm.get(\'interval\').hasError(\'min\')">\n {{\'tb.rulenode.interval-min-error\' | translate}}\n </mat-error>\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.interval-hint\' | translate }}">help</mat-icon>\n </mat-form-field>\n <div class="tb-form-panel no-padding no-border">\n <div class="tb-form-panel stroked">\n <div class="tb-form-panel-title tb-required" translate>tb.rulenode.strategy</div>\n <tb-toggle-select class="fetch-to-data-toggle" formControlName="strategy" appearance="fill">\n <tb-toggle-option *ngFor="let strategy of deduplicationStrategies" [value]="strategy">\n {{ deduplicationStrategiesTranslations.get(strategy) | translate }}\n </tb-toggle-option>\n </tb-toggle-select>\n <tb-example-hint [hintText]="\'tb.rulenode.strategy-all-hint\' | translate"\n *ngIf="deduplicationConfigForm.get(\'strategy\').value === \'ALL\'">\n </tb-example-hint>\n <tb-example-hint [hintText]="\'tb.rulenode.strategy-first-hint\' | translate"\n textAlign="\'center\'"\n *ngIf="deduplicationConfigForm.get(\'strategy\').value === \'FIRST\'">\n </tb-example-hint>\n <tb-example-hint [hintText]="\'tb.rulenode.strategy-last-hint\' | translate"\n textAlign="\'center\'"\n *ngIf="deduplicationConfigForm.get(\'strategy\').value === \'LAST\'">\n </tb-example-hint>\n <div *ngIf="deduplicationConfigForm.get(\'strategy\').value === deduplicationStrategie.ALL">\n <tb-output-message-type-autocomplete\n required\n formControlName="outMsgType">\n </tb-output-message-type-autocomplete>\n </div>\n </div>\n <section class="tb-form-panel stroked">\n <mat-expansion-panel class="tb-settings">\n <mat-expansion-panel-header>\n <mat-panel-title translate>tb.rulenode.advanced-settings</mat-panel-title>\n </mat-expansion-panel-header>\n <div class="tb-form-row no-border no-padding tb-standard-fields">\n <mat-form-field class="flex">\n <mat-label>{{\'tb.rulenode.max-pending-msgs\' | translate}}</mat-label>\n <input type = \'number\' required matInput formControlName="maxPendingMsgs">\n <mat-error *ngIf="deduplicationConfigForm.get(\'maxPendingMsgs\').hasError(\'required\')">\n {{\'tb.rulenode.max-pending-msgs-required\' | translate}}\n </mat-error>\n <mat-error *ngIf="deduplicationConfigForm.get(\'maxPendingMsgs\').hasError(\'max\')">\n {{\'tb.rulenode.max-pending-msgs-max-error\' | translate}}\n </mat-error>\n <mat-error *ngIf="deduplicationConfigForm.get(\'maxPendingMsgs\').hasError(\'min\')">\n {{\'tb.rulenode.max-pending-msgs-min-error\' | translate}}\n </mat-error>\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.max-pending-msgs-hint\' | translate }}">help</mat-icon>\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label>{{\'tb.rulenode.max-retries\' | translate}}</mat-label>\n <input type = \'number\' required matInput formControlName="maxRetries">\n <mat-error *ngIf="deduplicationConfigForm.get(\'maxRetries\').hasError(\'required\')">\n {{\'tb.rulenode.max-retries-required\' | translate}}\n </mat-error>\n <mat-error *ngIf="deduplicationConfigForm.get(\'maxRetries\').hasError(\'max\')">\n {{\'tb.rulenode.max-retries-max-error\' | translate}}\n </mat-error>\n <mat-error *ngIf="deduplicationConfigForm.get(\'maxRetries\').hasError(\'min\')">\n {{\'tb.rulenode.max-retries-min-error\' | translate}}\n </mat-error>\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.max-retries-hint\' | translate }}">help</mat-icon>\n </mat-form-field>\n </div>\n </mat-expansion-panel>\n </section>\n </div>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class zr{}e("RulenodeCoreConfigTransformModule",zr),zr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),zr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:zr,declarations:[Ar,Mr,Pr,Rr,Or,_r,Br,Kr],imports:[$,M,Jn],exports:[Ar,Mr,Pr,Rr,Or,_r,Br,Kr]}),zr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zr,imports:[$,M,Jn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zr,decorators:[{type:d,args:[{declarations:[Ar,Mr,Pr,Rr,Or,_r,Br,Kr],imports:[$,M,Jn],exports:[Ar,Mr,Pr,Rr,Or,_r,Br,Kr]}]}]});class Hr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.entityType=C}configForm(){return this.ruleChainInputConfigForm}onConfigurationSet(e){this.ruleChainInputConfigForm=this.fb.group({forwardMsgToDefaultRuleChain:[!!e&&e?.forwardMsgToDefaultRuleChain,[]],ruleChainId:[e?e.ruleChainId:null,[O.required]]})}}e("RuleChainInputComponent",Hr),Hr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Hr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Hr,selector:"tb-flow-node-rule-chain-input-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="ruleChainInputConfigForm" fxLayout="column">\n <div class="tb-form-panel no-padding no-border">\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.forward-msg-default-rule-chain-tooltip\' | translate }}"\n class="tb-form-row no-border">\n <mat-slide-toggle class="mat-slide" formControlName="forwardMsgToDefaultRuleChain">\n {{ \'tb.rulenode.forward-msg-default-rule-chain\' | translate }}\n </mat-slide-toggle>\n </div>\n <tb-entity-autocomplete required\n [excludeEntityIds]="[ruleChainId]"\n [entityType]="entityType.RULE_CHAIN"\n [entitySubtype]="ruleChainType"\n formControlName="ruleChainId">\n </tb-entity-autocomplete>\n </div>\n</section>\n',dependencies:[{kind:"component",type:lt.EntityAutocompleteComponent,selector:"tb-entity-autocomplete",inputs:["entityType","entitySubtype","excludeEntityIds","labelText","requiredText","useFullEntityId","appearance","required","disabled"],outputs:["entityChanged"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hr,decorators:[{type:n,args:[{selector:"tb-flow-node-rule-chain-input-config",template:'<section [formGroup]="ruleChainInputConfigForm" fxLayout="column">\n <div class="tb-form-panel no-padding no-border">\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.forward-msg-default-rule-chain-tooltip\' | translate }}"\n class="tb-form-row no-border">\n <mat-slide-toggle class="mat-slide" formControlName="forwardMsgToDefaultRuleChain">\n {{ \'tb.rulenode.forward-msg-default-rule-chain\' | translate }}\n </mat-slide-toggle>\n </div>\n <tb-entity-autocomplete required\n [excludeEntityIds]="[ruleChainId]"\n [entityType]="entityType.RULE_CHAIN"\n [entitySubtype]="ruleChainType"\n formControlName="ruleChainId">\n </tb-entity-autocomplete>\n </div>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Ur extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.ruleChainOutputConfigForm}onConfigurationSet(e){this.ruleChainOutputConfigForm=this.fb.group({})}}e("RuleChainOutputComponent",Ur),Ur.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ur,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Ur.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ur,selector:"tb-flow-node-rule-chain-output-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="ruleChainOutputConfigForm" fxLayout="column">\n <div innerHTML="{{ \'tb.rulenode.output-node-name-hint\' | translate }}"></div>\n</section>\n',dependencies:[{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ur,decorators:[{type:n,args:[{selector:"tb-flow-node-rule-chain-output-config",template:'<section [formGroup]="ruleChainOutputConfigForm" fxLayout="column">\n <div innerHTML="{{ \'tb.rulenode.output-node-name-hint\' | translate }}"></div>\n</section>\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class jr{}e("RuleNodeCoreConfigFlowModule",jr),jr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),jr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:jr,declarations:[Hr,Ur],imports:[$,M,Jn],exports:[Hr,Ur]}),jr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jr,imports:[$,M,Jn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jr,decorators:[{type:d,args:[{declarations:[Hr,Ur],imports:[$,M,Jn],exports:[Hr,Ur]}]}]});class $r{constructor(e){!function(e){e.setTranslation("en_US",{tb:{rulenode:{id:"Id","additional-info":"Additional Info","advanced-settings":"Advanced settings","create-entity-if-not-exists":"Create new entity if it doesn't exist","create-entity-if-not-exists-hint":"If enabled, a new entity with specified parameters will be created unless it already exists. Existing entities will be used as is for relation.","select-device-connectivity-event":"Select device connectivity event","entity-name-pattern":"Name pattern","device-name-pattern":"Device name","asset-name-pattern":"Asset name","entity-view-name-pattern":"Entity view name","customer-title-pattern":"Customer title","dashboard-name-pattern":"Dashboard title","user-name-pattern":"User email","edge-name-pattern":"Edge name","entity-name-pattern-required":"Name pattern is required","entity-name-pattern-hint":"Name pattern field support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","copy-message-type":"Copy message type","entity-type-pattern":"Type pattern","entity-type-pattern-required":"Type pattern is required","message-type-value":"Message type value","message-type-value-required":"Message type value is required","message-type-value-max-length":"Message type value should be less than 256","output-message-type":"Output message type","entity-cache-expiration":"Entities cache expiration time (sec)","entity-cache-expiration-hint":"Specifies maximum time interval allowed to store found entity records. 0 value means that records will never expire.","entity-cache-expiration-required":"Entities cache expiration time is required.","entity-cache-expiration-range":"Entities cache expiration time should be greater than or equal to 0.","customer-name-pattern":"Customer title","customer-name-pattern-required":"Customer title is required","customer-name-pattern-hint":"Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","create-customer-if-not-exists":"Create new customer if it doesn't exist","unassign-from-customer":"Unassign from specific customer if originator is dashboard","unassign-from-customer-tooltip":"Only dashboards can be assigned to multiple customers at once. \nIf the message originator is a dashboard, you need to explicitly specify the customer's title to unassign from.","customer-cache-expiration":"Customers cache expiration time (sec)","customer-cache-expiration-hint":"Specifies maximum time interval allowed to store found customer records. 0 value means that records will never expire.","customer-cache-expiration-required":"Customers cache expiration time is required.","customer-cache-expiration-range":"Customers cache expiration time should be greater than or equal to 0.","interval-start":"Interval start","interval-end":"Interval end","time-unit":"Time unit","fetch-mode":"Fetch mode","order-by-timestamp":"Order by timestamp",limit:"Limit","limit-hint":"Min limit value is 2, max - 1000. If you want to fetch a single entry, select fetch mode 'First' or 'Last'.","limit-required":"Limit is required.","limit-range":"Limit should be in a range from 2 to 1000.","time-unit-milliseconds":"Milliseconds","time-unit-seconds":"Seconds","time-unit-minutes":"Minutes","time-unit-hours":"Hours","time-unit-days":"Days","time-value-range":"Allowing range from 1 to 2147483647.","start-interval-value-required":"Interval start is required.","end-interval-value-required":"Interval end is required.",filter:"Filter",switch:"Switch","math-templatization-tooltip":"This field support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","add-message-type":"Add message type","select-message-types-required":"At least one message type should be selected.","select-message-types":"Select message types","no-message-types-found":"No message types found","no-message-type-matching":"'{{messageType}}' not found.","create-new-message-type":"Create a new one.","message-types-required":"Message types are required.","client-attributes":"Client attributes","shared-attributes":"Shared attributes","server-attributes":"Server attributes","attributes-keys":"Attributes keys","attributes-keys-required":"Attributes keys are required","attributes-scope":"Attributes scope","attributes-scope-value":"Attributes scope value","attributes-scope-value-copy":"Copy attributes scope value","attributes-scope-hint":"Use the 'scope' metadata key to dynamically set the attribute scope per message. If provided, this overrides the scope set in the configuration.","notify-device":"Force notification to the device","send-attributes-updated-notification":"Send attributes updated notification","send-attributes-updated-notification-hint":"Send notification about updated attributes as a separate message to the rule engine queue.","send-attributes-deleted-notification":"Send attributes deleted notification","send-attributes-deleted-notification-hint":"Send notification about deleted attributes as a separate message to the rule engine queue.","update-attributes-only-on-value-change":"Save attributes only if the value changes","update-attributes-only-on-value-change-hint":"Updates the attributes on every incoming message disregarding if their value has changed. Increases API usage and reduces performance.","update-attributes-only-on-value-change-hint-enabled":"Updates the attributes only if their value has changed. If the value is not changed, no update to the attribute timestamp nor attribute change notification will be sent.","fetch-credentials-to-metadata":"Fetch credentials to metadata","notify-device-on-update-hint":"If enabled, force notification to the device about shared attributes update. If disabled, the notification behavior is controlled by the 'notifyDevice' parameter from the incoming message metadata. To turn off the notification, the message metadata must contain the 'notifyDevice' parameter set to 'false'. Any other case will trigger the notification to the device.","notify-device-on-delete-hint":"If enabled, force notification to the device about shared attributes removal. If disabled, the notification behavior is controlled by the 'notifyDevice' parameter from the incoming message metadata. To turn on the notification, the message metadata must contain the 'notifyDevice' parameter set to 'true'. In any other case, the notification will not be triggered to the device.","latest-timeseries":"Latest time series data keys","timeseries-keys":"Time series keys","timeseries-keys-required":"At least one time series key should be selected.","add-timeseries-key":"Add time series key","add-message-field":"Add message field","relation-search-parameters":"Relation search parameters","relation-parameters":"Relation parameters","add-metadata-field":"Add metadata field","data-keys":"Message field names","copy-from":"Copy from","data-to-metadata":"Data to metadata","metadata-to-data":"Metadata to data","use-regular-expression-hint":"Use regular expression to copy keys by pattern.\n\nTips & tricks:\nPress 'Enter' to complete field name input.\nPress 'Backspace' to delete field name. Multiple field names supported.",interval:"Interval","interval-required":"Interval is required","interval-hint":"Deduplication interval in seconds.","interval-min-error":"Min allowed value is 1","max-pending-msgs":"Max pending messages","max-pending-msgs-hint":"Maximum number of messages that are stored in memory for each unique deduplication id.","max-pending-msgs-required":"Max pending messages is required","max-pending-msgs-max-error":"Max allowed value is 1000","max-pending-msgs-min-error":"Min allowed value is 1","max-retries":"Max retries","max-retries-required":"Max retries is required","max-retries-hint":"Maximum number of retries to push the deduplicated messages into the queue. 10 seconds delay is used between retries","max-retries-max-error":"Max allowed value is 100","max-retries-min-error":"Min allowed value is 0",strategy:"Strategy","strategy-required":"Strategy is required","strategy-all-hint":"Return all messages that arrived during deduplication period as a single JSON array message. Where each element represents object with msg and metadata inner properties.","strategy-first-hint":"Return first message that arrived during deduplication period.","strategy-last-hint":"Return last message that arrived during deduplication period.",first:"First",last:"Last",all:"All","output-msg-type-hint":"The message type of the deduplication result.","queue-name-hint":"The queue name where the deduplication result will be published.",keys:"Keys","keys-required":"Keys are required","rename-keys-in":"Rename keys in",data:"Data",message:"Message",metadata:"Metadata","current-key-name":"Current key name","key-name-required":"Key name is required","new-key-name":"New key name","new-key-name-required":"New key name is required","metadata-keys":"Metadata field names","json-path-expression":"JSON path expression","json-path-expression-required":"JSON path expression is required","json-path-expression-hint":"JSONPath specifies a path to an element or a set of elements in a JSON structure. '$' represents the root object or array.","relations-query":"Relations query","device-relations-query":"Device relations query","max-relation-level":"Max relation level","max-relation-level-error":"Value should be greater than 0 or unspecified.","relation-type":"Relation type","relation-type-pattern":"Relation type pattern","relation-type-pattern-required":"Relation type pattern is required","relation-types-list":"Relation types to propagate","relation-types-list-hint":"If Propagate relation types are not selected, alarms will be propagated without filtering by relation type.","unlimited-level":"Unlimited level","latest-telemetry":"Latest telemetry","add-telemetry-key":"Add telemetry key","delete-from":"Delete from","use-regular-expression-delete-hint":"Use regular expression to delete keys by pattern.\n\nTips & tricks:\nPress 'Enter' to complete field name input.\nPress 'Backspace' to delete field name.\nMultiple field names supported.","fetch-into":"Fetch into","attr-mapping":"Attributes mapping:","source-attribute":"Source attribute key","source-attribute-required":"Source attribute key is required.","source-telemetry":"Source telemetry key","source-telemetry-required":"Source telemetry key is required.","target-key":"Target key","target-key-required":"Target key is required.","attr-mapping-required":"At least one mapping entry should be specified.","fields-mapping":"Fields mapping","relations-query-config-direction-suffix":"originator","profile-name":"Profile name","fetch-circle-parameter-info-from-metadata-hint":'Metadata field \'{{perimeterKeyName}}\' should be defined in next format: {"latitude":48.196, "longitude":24.6532, "radius":100.0, "radiusUnit":"METER"}',"fetch-poligon-parameter-info-from-metadata-hint":"Metadata field '{{perimeterKeyName}}' should be defined in next format: [[48.19736,24.65235],[48.19800,24.65060],...,[48.19849,24.65420]]","short-templatization-tooltip":"Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","fields-mapping-required":"At least one field mapping should be specified.","at-least-one-field-required":"At least one input field must have a value(s) provided.","originator-fields-sv-map-hint":"Target key fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","sv-map-hint":"Only target key fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","source-field":"Source field","source-field-required":"Source field is required.","originator-source":"Originator source","new-originator":"New originator","originator-customer":"Customer","originator-tenant":"Tenant","originator-related":"Related entity","originator-alarm-originator":"Alarm Originator","originator-entity":"Entity by name pattern","clone-message":"Clone message",transform:"Transform","default-ttl":"Default TTL in seconds","default-ttl-required":"Default TTL is required.","default-ttl-hint":"Rule node will fetch Time-to-Live (TTL) value from the message metadata. If no value is present, it defaults to the TTL specified in the configuration. If the value is set to 0, the TTL from the tenant profile configuration will be applied.","min-default-ttl-message":"Only 0 minimum TTL is allowed.","message-count":"Message count (0 - unlimited)","message-count-required":"Message count is required.","min-message-count-message":"Only 0 minimum message count is allowed.","period-seconds":"Period in seconds","period-seconds-required":"Period is required.","use-metadata-period-in-seconds-patterns":"Use period in seconds pattern","use-metadata-period-in-seconds-patterns-hint":"If selected, rule node use period in seconds interval pattern from message metadata or data assuming that intervals are in the seconds.","period-in-seconds-pattern":"Period in seconds pattern","period-in-seconds-pattern-required":"Period in seconds pattern is required","min-period-seconds-message":"Only 1 second minimum period is allowed.",originator:"Originator","message-body":"Message body","message-metadata":"Message metadata",generate:"Generate","test-generator-function":"Test generator function",generator:"Generator","test-filter-function":"Test filter function","test-switch-function":"Test switch function","test-transformer-function":"Test transformer function",transformer:"Transformer","alarm-create-condition":"Alarm create condition","test-condition-function":"Test condition function","alarm-clear-condition":"Alarm clear condition","alarm-details-builder":"Alarm details builder","test-details-function":"Test details function","alarm-type":"Alarm type","select-entity-types":"Select entity types","alarm-type-required":"Alarm type is required.","alarm-severity":"Alarm severity","alarm-severity-required":"Alarm severity is required","alarm-severity-pattern":"Alarm severity pattern","alarm-status-filter":"Alarm status filter","alarm-status-list-empty":"Alarm status list is empty","no-alarm-status-matching":"No alarm status matching were found.",propagate:"Propagate alarm to related entities","propagate-to-owner":"Propagate alarm to entity owner (Customer or Tenant)","propagate-to-tenant":"Propagate alarm to Tenant",condition:"Condition",details:"Details","to-string":"To string","test-to-string-function":"Test to string function","from-template":"From","from-template-required":"From is required","message-to-metadata":"Message to metadata","metadata-to-message":"Metadata to message","from-message":"From message","from-metadata":"From metadata","to-template":"To","to-template-required":"To Template is required","mail-address-list-template-hint":'Comma separated address list, use <code><span style="color: #000;">$&#123;</span>metadataKey<span style="color: #000;">&#125;</span></code> for value from metadata, <code><span style="color: #000;">$[</span>messageKey<span style="color: #000;">]</span></code> for value from message body',"cc-template":"Cc","bcc-template":"Bcc","subject-template":"Subject","subject-template-required":"Subject Template is required","body-template":"Body","body-template-required":"Body Template is required","dynamic-mail-body-type":"Dynamic mail body type","mail-body-type":"Mail body type","body-type-template":"Body type template","reply-routing-configuration":"Reply Routing Configuration","reply-routing-configuration-hint":"These configuration parameters specify the metadata key names used to identify the service and request for sending a reply back.","request-id-metadata-attribute":"Request Id","service-id-metadata-attribute":"Service Id","session-id-metadata-attribute":"Session Id","timeout-sec":"Timeout in seconds","timeout-required":"Timeout is required","min-timeout-message":"Only 0 minimum timeout value is allowed.","endpoint-url-pattern":"Endpoint URL pattern","endpoint-url-pattern-required":"Endpoint URL pattern is required","request-method":"Request method","use-simple-client-http-factory":"Use simple client HTTP factory","ignore-request-body":"Without request body","parse-to-plain-text":"Parse to plain text","parse-to-plain-text-hint":'If selected, request body message payload will be transformed from JSON string to plain text, e.g. msg = "Hello,\\t\\"world\\"" will be parsed to Hello, "world"',"read-timeout":"Read timeout in millis","read-timeout-hint":"The value of 0 means an infinite timeout","max-parallel-requests-count":"Max number of parallel requests","max-parallel-requests-count-hint":"The value of 0 specifies no limit in parallel processing",headers:"Headers","headers-hint":'Use <code><span style="color: #000;">$&#123;</span>metadataKey<span style="color: #000;">&#125;</span></code> for value from metadata, <code><span style="color: #000;">$[</span>messageKey<span style="color: #000;">]</span></code> for value from message body in header/value fields',header:"Header","header-required":"Header is required",value:"Value","value-required":"Value is required","topic-pattern":"Topic pattern","key-pattern":"Key pattern","key-pattern-hint":"Optional. If a valid partition number is specified, it will be used when sending the record. If no partition is specified, the key will be used instead. If neither is specified, a partition will be assigned in a round-robin fashion.","topic-pattern-required":"Topic pattern is required",topic:"Topic","topic-required":"Topic is required","bootstrap-servers":"Bootstrap servers","bootstrap-servers-required":"Bootstrap servers value is required","other-properties":"Other properties",key:"Key","key-required":"Key is required",retries:"Automatically retry times if fails","min-retries-message":"Only 0 minimum retries is allowed.","batch-size-bytes":"Produces batch size in bytes","min-batch-size-bytes-message":"Only 0 minimum batch size is allowed.","linger-ms":"Time to buffer locally (ms)","min-linger-ms-message":"Only 0 ms minimum value is allowed.","buffer-memory-bytes":"Client buffer max size in bytes","min-buffer-memory-message":"Only 0 minimum buffer size is allowed.",acks:"Number of acknowledgments","key-serializer":"Key serializer","key-serializer-required":"Key serializer is required","value-serializer":"Value serializer","value-serializer-required":"Value serializer is required","topic-arn-pattern":"Topic ARN pattern","topic-arn-pattern-required":"Topic ARN pattern is required","aws-access-key-id":"AWS Access Key ID","aws-access-key-id-required":"AWS Access Key ID is required","aws-secret-access-key":"AWS Secret Access Key","aws-secret-access-key-required":"AWS Secret Access Key is required","aws-region":"AWS Region","aws-region-required":"AWS Region is required","exchange-name-pattern":"Exchange name pattern","routing-key-pattern":"Routing key pattern","message-properties":"Message properties",host:"Host","host-required":"Host is required",port:"Port","port-required":"Port is required","port-range":"Port should be in a range from 1 to 65535.","virtual-host":"Virtual host",username:"Username",password:"Password","automatic-recovery":"Automatic recovery","connection-timeout-ms":"Connection timeout (ms)","min-connection-timeout-ms-message":"Only 0 ms minimum value is allowed.","handshake-timeout-ms":"Handshake timeout (ms)","min-handshake-timeout-ms-message":"Only 0 ms minimum value is allowed.","client-properties":"Client properties","queue-url-pattern":"Queue URL pattern","queue-url-pattern-required":"Queue URL pattern is required","delay-seconds":"Delay (seconds)","min-delay-seconds-message":"Only 0 seconds minimum value is allowed.","max-delay-seconds-message":"Only 900 seconds maximum value is allowed.",name:"Name","name-required":"Name is required","queue-type":"Queue type","sqs-queue-standard":"Standard","sqs-queue-fifo":"FIFO","gcp-project-id":"GCP project ID","gcp-project-id-required":"GCP project ID is required","gcp-service-account-key":"GCP service account key file","gcp-service-account-key-required":"GCP service account key file is required","pubsub-topic-name":"Topic name","pubsub-topic-name-required":"Topic name is required","message-attributes":"Message attributes","message-attributes-hint":'Use <code><span style="color: #000;">$&#123;</span>metadataKey<span style="color: #000000;">&#125;</span></code> for value from metadata, <code><span style="color: #000;">$[</span>messageKey<span style="color: #000;">]</span></code> for value from message body in name/value fields',"connect-timeout":"Connection timeout (sec)","connect-timeout-required":"Connection timeout is required.","connect-timeout-range":"Connection timeout should be in a range from 1 to 200.","client-id":"Client ID","client-id-hint":'Optional. Leave empty for auto-generated Client ID. Be careful when specifying the Client ID. Majority of the MQTT brokers will not allow multiple connections with the same Client ID. To connect to such brokers, your mqtt Client ID must be unique. When platform is running in a micro-services mode, the copy of rule node is launched in each micro-service. This will automatically lead to multiple mqtt clients with the same ID and may cause failures of the rule node. To avoid such failures enable "Add Service ID as suffix to Client ID" option below.',"append-client-id-suffix":"Add Service ID as suffix to Client ID","client-id-suffix-hint":'Optional. Applied when "Client ID" specified explicitly. If selected then Service ID will be added to Client ID as a suffix. Helps to avoid failures when platform is running in a micro-services mode.',"device-id":"Device ID","device-id-required":"Device ID is required.","clean-session":"Clean session","enable-ssl":"Enable SSL",credentials:"Credentials","credentials-type":"Credentials type","credentials-type-required":"Credentials type is required.","credentials-anonymous":"Anonymous","credentials-basic":"Basic","credentials-pem":"PEM","credentials-pem-hint":"At least Server CA certificate file or a pair of Client certificate and Client private key files are required","credentials-sas":"Shared Access Signature","sas-key":"SAS Key","sas-key-required":"SAS Key is required.",hostname:"Hostname","hostname-required":"Hostname is required.","azure-ca-cert":"CA certificate file","username-required":"Username is required.","password-required":"Password is required.","ca-cert":"Server CA certificate file","private-key":"Client private key file",cert:"Client certificate file","no-file":"No file selected.","drop-file":"Drop a file or click to select a file to upload.","private-key-password":"Private key password","use-system-smtp-settings":"Use system SMTP settings","use-metadata-dynamic-interval":"Use dynamic interval","metadata-dynamic-interval-hint":"Interval start and end input fields support templatization. Note that the substituted template value should be set in milliseconds. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","use-metadata-interval-patterns-hint":"If selected, rule node use start and end interval patterns from message metadata or data assuming that intervals are in the milliseconds.","use-message-alarm-data":"Use message alarm data","overwrite-alarm-details":"Overwrite alarm details","use-alarm-severity-pattern":"Use alarm severity pattern","check-all-keys":"Check that all specified fields are present","check-all-keys-hint":"If selected, checks that all specified keys are present in the message data and metadata.","check-relation-to-specific-entity":"Check relation to specific entity","check-relation-to-specific-entity-tooltip":"If enabled, checks the presence of relation with a specific entity otherwise, checks the presence of relation with any entity. In both cases, relation lookup is based on configured direction and type.","check-relation-hint":"Checks existence of relation to specific entity or to any entity based on direction and relation type.","delete-relation-with-specific-entity":"Delete relation with specific entity","delete-relation-with-specific-entity-hint":"If enabled, will delete the relation with just one specific entity. Otherwise, the relation will be removed with all matching entities.","delete-relation-hint":"Deletes relation from the originator of the incoming message to the specified entity or list of entities based on direction and type.","remove-current-relations":"Remove current relations","remove-current-relations-hint":"Removes current relations from the originator of the incoming message based on direction and type.","change-originator-to-related-entity":"Change originator to related entity","change-originator-to-related-entity-hint":"Used to process submitted message as a message from another entity.","start-interval":"Interval start","end-interval":"Interval end","start-interval-required":"Interval start is required.","end-interval-required":"Interval end is required.","smtp-protocol":"Protocol","smtp-host":"SMTP host","smtp-host-required":"SMTP host is required.","smtp-port":"SMTP port","smtp-port-required":"You must supply a smtp port.","smtp-port-range":"SMTP port should be in a range from 1 to 65535.","timeout-msec":"Timeout ms","min-timeout-msec-message":"Only 0 ms minimum value is allowed.","enter-username":"Enter username","enter-password":"Enter password","enable-tls":"Enable TLS","tls-version":"TLS version","enable-proxy":"Enable proxy","use-system-proxy-properties":"Use system proxy properties","proxy-host":"Proxy host","proxy-host-required":"Proxy host is required.","proxy-port":"Proxy port","proxy-port-required":"Proxy port is required.","proxy-port-range":"Proxy port should be in a range from 1 to 65535.","proxy-user":"Proxy user","proxy-password":"Proxy password","proxy-scheme":"Proxy scheme","numbers-to-template":"Phone Numbers To Template","numbers-to-template-required":"Phone Numbers To Template is required","numbers-to-template-hint":'Comma separated Phone Numbers, use <code><span style="color: #000;">$&#123;</span>metadataKey<span style="color: #000;">&#125;</span></code> for value from metadata, <code><span style="color: #000;">$[</span>messageKey<span style="color: #000;">]</span></code> for value from message body',"sms-message-template":"SMS message Template","sms-message-template-required":"SMS message Template is required","use-system-sms-settings":"Use system SMS provider settings","min-period-0-seconds-message":"Only 0 second minimum period is allowed.","max-pending-messages":"Maximum pending messages","max-pending-messages-required":"Maximum pending messages is required.","max-pending-messages-range":"Maximum pending messages should be in a range from 1 to 100000.","originator-types-filter":"Originator types filter","interval-seconds":"Interval in seconds","interval-seconds-required":"Interval is required.","min-interval-seconds-message":"Only 1 second minimum interval is allowed.","output-timeseries-key-prefix":"Output time series key prefix","output-timeseries-key-prefix-required":"Output time series key prefix required.","separator-hint":'Press "Enter" to complete field input.',"select-details":"Select details","entity-details-id":"Id","entity-details-title":"Title","entity-details-country":"Country","entity-details-state":"State","entity-details-city":"City","entity-details-zip":"Zip","entity-details-address":"Address","entity-details-address2":"Address2","entity-details-additional_info":"Additional Info","entity-details-phone":"Phone","entity-details-email":"Email","email-sender":"Email sender","fields-to-check":"Fields to check","add-detail":"Add detail","check-all-keys-tooltip":"If enabled, checks the presence of all fields listed in the message and metadata field names within the incoming message and its metadata.","fields-to-check-hint":'Press "Enter" to complete field name input. Multiple field names supported.',"entity-details-list-empty":"At least one detail should be selected.","alarm-status":"Alarm status","alarm-required":"At least one alarm status should be selected.","no-entity-details-matching":"No entity details matching were found.","custom-table-name":"Custom table name","custom-table-name-required":"Table Name is required","custom-table-hint":"Enter the table name without prefix 'cs_tb_'.","message-field":"Message field","message-field-required":"Message field is required.","table-col":"Table column","table-col-required":"Table column is required.","latitude-field-name":"Latitude field name","longitude-field-name":"Longitude field name","latitude-field-name-required":"Latitude field name is required.","longitude-field-name-required":"Longitude field name is required.","fetch-perimeter-info-from-metadata":"Fetch perimeter information from metadata","fetch-perimeter-info-from-metadata-tooltip":"If perimeter type is set to 'Polygon' the value of metadata field '{{perimeterKeyName}}' will be set as perimeter definition without additional parsing of the value. Otherwise, if perimeter type is set to 'Circle' the value of '{{perimeterKeyName}}' metadata field will be parsed to extract 'latitude', 'longitude', 'radius', 'radiusUnit' fields that uses for circle perimeter definition.","perimeter-key-name":"Perimeter key name","perimeter-key-name-hint":"Metadata field name that includes perimeter information.","perimeter-key-name-required":"Perimeter key name is required.","perimeter-circle":"Circle","perimeter-polygon":"Polygon","perimeter-type":"Perimeter type","circle-center-latitude":"Center latitude","circle-center-latitude-required":"Center latitude is required.","circle-center-longitude":"Center longitude","circle-center-longitude-required":"Center longitude is required.","range-unit-meter":"Meter","range-unit-kilometer":"Kilometer","range-unit-foot":"Foot","range-unit-mile":"Mile","range-unit-nautical-mile":"Nautical mile","range-units":"Range units","range-units-required":"Range units is required.",range:"Range","range-required":"Range is required.","polygon-definition":"Polygon definition","polygon-definition-required":"Polygon definition is required.","polygon-definition-hint":"Use the following format for manual definition of polygon: [[lat1,lon1],[lat2,lon2], ... ,[latN,lonN]].","min-inside-duration":"Minimal inside duration","min-inside-duration-value-required":"Minimal inside duration is required","min-inside-duration-time-unit":"Minimal inside duration time unit","min-outside-duration":"Minimal outside duration","min-outside-duration-value-required":"Minimal outside duration is required","min-outside-duration-time-unit":"Minimal outside duration time unit","tell-failure-if-absent":"Tell Failure","tell-failure-if-absent-hint":'If at least one selected key doesn\'t exist the outbound message will report "Failure".',"get-latest-value-with-ts":"Fetch timestamp for the latest telemetry values","get-latest-value-with-ts-hint":'If selected, the latest telemetry values will also include timestamp, e.g: "temp": "&#123;"ts":1574329385897, "value":42&#125;"',"ignore-null-strings":"Ignore null strings","ignore-null-strings-hint":"If selected rule node will ignore entity fields with empty value.","add-metadata-key-values-as-kafka-headers":"Add Message metadata key-value pairs to Kafka record headers","add-metadata-key-values-as-kafka-headers-hint":"If selected, key-value pairs from message metadata will be added to the outgoing records headers as byte arrays with predefined charset encoding.","charset-encoding":"Charset encoding","charset-encoding-required":"Charset encoding is required.","charset-us-ascii":"US-ASCII","charset-iso-8859-1":"ISO-8859-1","charset-utf-8":"UTF-8","charset-utf-16be":"UTF-16BE","charset-utf-16le":"UTF-16LE","charset-utf-16":"UTF-16","select-queue-hint":"The queue name can be selected from a drop-down list or add a custom name.","device-profile-node-hint":"Useful if you have duration or repeating conditions to ensure continuity of alarm state evaluation.","persist-alarm-rules":"Persist state of alarm rules","persist-alarm-rules-hint":"If enabled, the rule node will store the state of processing to the database.","fetch-alarm-rules":"Fetch state of alarm rules","fetch-alarm-rules-hint":"If enabled, the rule node will restore the state of processing on initialization and ensure that alarms are raised even after server restarts. Otherwise, the state will be restored when the first message from the device arrives.","input-value-key":"Input value key","input-value-key-required":"Input value key is required.","output-value-key":"Output value key","output-value-key-required":"Output value key is required.","number-of-digits-after-floating-point":"Number of digits after floating point","number-of-digits-after-floating-point-range":"Number of digits after floating point should be in a range from 0 to 15.","failure-if-delta-negative":"Tell Failure if delta is negative","failure-if-delta-negative-tooltip":"Rule node forces failure of message processing if delta value is negative.","use-caching":"Use caching","use-caching-tooltip":'Rule node will cache the value of "{{inputValueKey}}" that arrives from the incoming message to improve performance. Note that the cache will not be updated if you modify the "{{inputValueKey}}" value elsewhere.',"add-time-difference-between-readings":'Add the time difference between "{{inputValueKey}}" readings',"add-time-difference-between-readings-tooltip":'If enabled, the rule node will add the "{{periodValueKey}}" to the outbound message.',"period-value-key":"Period value key","period-value-key-required":"Period value key is required.","general-pattern-hint":"Use ${metadataKey} for value from metadata, $[messageKey] for value from message body.","alarm-severity-pattern-hint":'Use <code><span style="color: #000;">$&#123;</span>metadataKey<span style="color: #000;">&#125;</span></code> for value from metadata, <code><span style="color: #000;">$[</span>messageKey<span style="color: #000;">]</span></code> for value from message body. Alarm severity should be system (CRITICAL, MAJOR etc.)',"output-node-name-hint":"The <b>rule node name</b> corresponds to the <b>relation type</b> of the output message, and it is used to forward messages to other rule nodes in the caller rule chain.","skip-latest-persistence":"Skip latest persistence","skip-latest-persistence-hint":"Rule node will not update values for incoming keys for the latest time series data. Useful for highly loaded use-cases to decrease the pressure on the DB.","use-server-ts":"Use server ts","use-server-ts-hint":"Rule node will use the timestamp of message processing instead of the timestamp from the message. Useful for all sorts of sequential processing if you merge messages from multiple sources (devices, assets, etc).","kv-map-pattern-hint":"All input fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","kv-map-single-pattern-hint":"Input field support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","shared-scope":"Shared scope","server-scope":"Server scope","client-scope":"Client scope","attribute-type":"Attribute","constant-type":"Constant","time-series-type":"Time series","message-body-type":"Message","message-metadata-type":"Metadata","argument-tile":"Arguments","no-arguments-prompt":"No arguments configured","result-title":"Result","functions-field-input":"Functions","no-option-found":"No option found","argument-source-field-input":"Source","argument-source-field-input-required":"Argument source is required.","argument-key-field-input":"Key","argument-key-field-input-required":"Argument key is required.","constant-value-field-input":"Constant value","constant-value-field-input-required":"Constant value is required.","attribute-scope-field-input":"Attribute scope","attribute-scope-field-input-required":"Attribute scope os required.","default-value-field-input":"Default value","type-field-input":"Type","type-field-input-required":"Type is required.","key-field-input":"Key","add-entity-type":"Add entity type","add-device-profile":"Add device profile","key-field-input-required":"Key is required.","number-floating-point-field-input":"Number of digits after floating point","number-floating-point-field-input-hint":"Use <i>0</i> to convert result to integer","add-to-message-field-input":"Add to message","add-to-metadata-field-input":"Add to metadata","custom-expression-field-input":"Mathematical Expression","custom-expression-field-input-required":"Mathematical expression is required","custom-expression-field-input-hint":"Specify a mathematical expression to evaluate. Default expression demonstrates how to transform Fahrenheit to Celsius","retained-message":"Retained","attributes-mapping":"Attributes mapping","latest-telemetry-mapping":"Latest telemetry mapping","add-mapped-attribute-to":"Add mapped attributes to","add-mapped-latest-telemetry-to":"Add mapped latest telemetry to","add-mapped-fields-to":"Add mapped fields to","add-selected-details-to":"Add selected details to","clear-selected-types":"Clear selected types","clear-selected-details":"Clear selected details","clear-selected-fields":"Clear selected fields","clear-selected-keys":"Clear selected keys","geofence-configuration":"Geofence configuration","coordinate-field-names":"Coordinate field names","coordinate-field-hint":"Rule node tries to retrieve the specified fields from the message. If they are not present, it will look them up in the metadata.","presence-monitoring-strategy":"Presence monitoring strategy","presence-monitoring-strategy-on-first-message":"On first message","presence-monitoring-strategy-on-each-message":"On each message","presence-monitoring-strategy-on-first-message-hint":"Reports presence status 'Inside' or 'Outside' on the first message after the configured minimal duration has passed since previous presence status 'Entered' or 'Left' update.","presence-monitoring-strategy-on-each-message-hint":"Reports presence status 'Inside' or 'Outside' on each message after presence status 'Entered' or 'Left' update.","fetch-credentials-to":"Fetch credentials to","add-originator-attributes-to":"Add originator attributes to","originator-attributes":"Originator attributes","fetch-latest-telemetry-with-timestamp":"Fetch latest telemetry with timestamp","fetch-latest-telemetry-with-timestamp-tooltip":'If selected, latest telemetry values will be added to the outbound metadata with timestamp, e.g: "{{latestTsKeyName}}": "{"ts":1574329385897, "value":42}"',"tell-failure":"Tell failure if any of the attributes are missing","tell-failure-tooltip":'If at least one selected key doesn\'t exist the outbound message will report "Failure".',"created-time":"Created time","chip-help":"Press 'Enter' to complete {{inputName}} input. \nPress 'Backspace' to delete {{inputName}}. \nMultiple values supported.",detail:"detail","field-name":"field name","device-profile":"device profile","entity-type":"entity type","message-type":"message type","timeseries-key":"time series key",type:"Type","first-name":"First name","last-name":"Last name",label:"Label","originator-fields-mapping":"Originator fields mapping","add-mapped-originator-fields-to":"Add mapped originator fields to",fields:"Fields","skip-empty-fields":"Skip empty fields","skip-empty-fields-tooltip":"Fields with empty values will not be added to the output message/output metadata.","fetch-interval":"Fetch interval","fetch-strategy":"Fetch strategy","fetch-timeseries-from-to":"Fetch time series from {{startInterval}} {{startIntervalTimeUnit}} ago to {{endInterval}} {{endIntervalTimeUnit}} ago.","fetch-timeseries-from-to-invalid":'Fetch time series invalid ("Interval start" should be less than "Interval end").',"use-metadata-dynamic-interval-tooltip":"If selected, the rule node will use dynamic interval start and end based on the message and metadata patterns.","all-mode-hint":'If selected fetch mode "All" rule node will retrieve telemetry from the fetch interval with configurable query parameters.',"first-mode-hint":'If selected fetch mode "First" rule node will retrieve the closest telemetry to the fetch interval\'s start.',"last-mode-hint":'If selected fetch mode "Last" rule node will retrieve the closest telemetry to the fetch interval\'s end.',ascending:"Ascending",descending:"Descending",min:"Min",max:"Max",average:"Average",sum:"Sum",count:"Count",none:"None","last-level-relation-tooltip":"If selected, the rule node will search related entities only on the level set in the max relation level.","last-level-device-relation-tooltip":"If selected, the rule node will search related devices only on the level set in the max relation level.","data-to-fetch":"Data to fetch","mapping-of-customers":"Mapping of customer's","map-fields-required":"All mapping fields are required.",attributes:"Attributes","related-device-attributes":"Related device attributes","add-selected-attributes-to":"Add selected attributes to","device-profiles":"Device profiles","mapping-of-tenant":"Mapping of tenant's","add-attribute-key":"Add attribute key","message-template":"Message template","message-template-required":"Message template is required","use-system-slack-settings":"Use system slack settings","slack-api-token":"Slack API token","slack-api-token-required":"Slack API token is required","keys-mapping":"keys mapping","add-key":"Add key",recipients:"Recipients","message-subject-and-content":"Message subject and content","template-rules-hint":"Both input fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the message metadata.","originator-customer-desc":"Use customer of incoming message originator as new originator.","originator-tenant-desc":"Use current tenant as new originator.","originator-related-entity-desc":"Use related entity as new originator. Lookup based on configured relation type and direction.","originator-alarm-originator-desc":"Use alarm originator as new originator. Only if incoming message originator is alarm entity.","originator-entity-by-name-pattern-desc":"Use entity fetched from DB as new originator. Lookup based on entity type and specified name pattern.","email-from-template-hint":"Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","recipients-block-main-hint":"Comma-separated address list. All input fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","forward-msg-default-rule-chain":"Forward message to the originator's default rule chain","forward-msg-default-rule-chain-tooltip":"If enabled, message will be forwarded to the originator's default rule chain, or rule chain from configuration, if originator has no default rule chain defined in the entity profile.","exclude-zero-deltas":"Exclude zero deltas from outbound message","exclude-zero-deltas-hint":'If enabled, the "{{outputValueKey}}" output key will be added to the outbound message if its value is not zero.',"exclude-zero-deltas-time-difference-hint":'If enabled, the "{{outputValueKey}}" and "{{periodValueKey}}" output keys will be added to the outbound message only if the "{{outputValueKey}}" value is not zero.',"search-direction-from":"From originator to target entity","search-direction-to":"From target entity to originator","del-relation-direction-from":"From originator","del-relation-direction-to":"To originator","target-entity":"Target entity","function-configuration":"Function configuration","function-name":"Function name","function-name-required":"Function name is required.",qualifier:"Qualifier","qualifier-hint":'If the qualifier is not specified, the default qualifier "$LATEST" will be used.',"aws-credentials":"AWS Credentials","connection-timeout":"Connection timeout","connection-timeout-required":"Connection timeout is required.","connection-timeout-min":"Min connection timeout is 0.","connection-timeout-hint":"Rule node forces failure of message processing if AWS Lambda function execution raises exception.","request-timeout":"Request timeout","request-timeout-required":"Request timeout is required","request-timeout-min":"Min request timeout is 0","request-timeout-hint":"The amount of time to wait in seconds for the request to complete before giving up and timing out. A value of 0 means infinity, and is not recommended.","tell-failure-aws-lambda":"Tell Failure if AWS Lambda function execution raises exception","tell-failure-aws-lambda-hint":"Rule node forces failure of message processing if AWS Lambda function execution raises exception."},"key-val":{key:"Key",value:"Value","see-examples":"See examples.","remove-entry":"Remove entry","remove-mapping-entry":"Remove mapping entry","add-mapping-entry":"Add mapping","add-entry":"Add entry","copy-key-values-from":"Copy key-values from","delete-key-values":"Delete key-values","delete-key-values-from":"Delete key-values from","at-least-one-key-error":"At least one key should be selected.","unique-key-value-pair-error":"'{{keyText}}' must be different from the '{{valText}}'!"},"mail-body-type":{"plain-text":"Plain text",html:"HTML",dynamic:"Dynamic","use-body-type-template":"Use body type template","plain-text-description":"Simple, unformatted text with no special styling or formating.","html-text-description":"Allows you to use HTML tags for formatting, links and images in your mai body.","dynamic-text-description":"Allows to use Plain Text or HTML body type dynamically based on templatization feature.","after-template-evaluation-hint":"After template evaluation value should be true for HTML, and false for Plain text."}}},!0)}(e)}}e("RuleNodeCoreConfigModule",$r),$r.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$r,deps:[{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.NgModule}),$r.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:$r,declarations:[dt],imports:[$,M],exports:[Qn,qr,ir,vr,zr,jr,dt]}),$r.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$r,imports:[$,M,Qn,qr,ir,vr,zr,jr]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$r,decorators:[{type:d,args:[{declarations:[dt],imports:[$,M],exports:[Qn,qr,ir,vr,zr,jr,dt]}]}],ctorParameters:function(){return[{type:Z.TranslateService}]}})}}}));//# sourceMappingURL=rulenode-core-config.js.map +System.register(["@angular/core","@shared/public-api","@ngrx/store","@angular/forms","@angular/common","@angular/material/input","@angular/material/form-field","@angular/material/slide-toggle","@angular/flex-layout/flex","@ngx-translate/core","@angular/material/button","@angular/material/icon","@angular/material/select","@angular/material/core","@angular/material/tooltip","@angular/material/expansion","rxjs","@shared/components/hint-tooltip-icon.component","@shared/components/help-popup.component","@shared/pipe/safe.pipe","@core/public-api","@shared/components/js-func.component","@shared/components/script-lang.component","@angular/cdk/keycodes","@angular/material/checkbox","@angular/material/chips","@shared/components/entity/entity-type-select.component","@shared/components/relation/relation-type-autocomplete.component","@shared/components/entity/entity-select.component","@shared/components/toggle-header.component","@shared/components/toggle-select.component","@angular/cdk/coercion","@shared/components/tb-error.component","@angular/flex-layout/extended","@angular/material/list","@angular/cdk/drag-drop","rxjs/operators","@angular/material/autocomplete","@shared/pipe/highlight.pipe","@home/components/public-api","tslib","@shared/components/entity/entity-subtype-list.component","@home/components/relation/relation-filters.component","@shared/components/file-input.component","@shared/components/button/toggle-password.component","@shared/components/string-items-list.component","@shared/components/entity/entity-list.component","@shared/components/notification/template-autocomplete.component","@shared/components/tb-checkbox.component","@home/components/sms/sms-provider-configuration.component","@angular/material/radio","@shared/components/slack-conversation-autocomplete.component","@shared/components/entity/entity-autocomplete.component","@shared/components/entity/entity-type-list.component","@angular/cdk/platform"],(function(e){"use strict";var t,n,r,o,a,i,l,s,m,p,d,u,c,g,f,y,b,x,h,v,C,F,k,T,L,I,S,N,q,A,M,E,w,G,D,V,P,R,O,_,B,K,H,z,U,j,$,J,Q,Y,W,Z,X,ee,te,ne,re,oe,ae,ie,le,se,me,pe,de,ue,ce,ge,fe,ye,be,xe,he,ve,Ce,Fe,ke,Te,Le,Ie,Se,Ne,qe,Ae,Me,Ee,we,Ge,De,Ve,Pe,Re,Oe,_e,Be,Ke,He,ze,Ue,je,$e,Je,Qe,Ye,We,Ze,Xe,et,tt,nt,rt,ot,at,it,lt,st,mt,pt,dt;return{setters:[function(e){t=e,n=e.Component,r=e.InjectionToken,o=e.Injectable,a=e.Inject,i=e.Optional,l=e.EventEmitter,s=e.Directive,m=e.Input,p=e.Output,d=e.NgModule,u=e.ViewChild,c=e.forwardRef},function(e){g=e.RuleNodeConfigurationComponent,f=e.AttributeScope,y=e.telemetryTypeTranslations,b=e.ScriptLanguage,x=e.AlarmSeverity,h=e.alarmSeverityTranslations,v=e.EntitySearchDirection,C=e.EntityType,F=e.AliasEntityType,k=e.entityFields,T=e.PageComponent,L=e.messageTypeNames,I=e.MessageType,S=e.coerceBoolean,N=e.entitySearchDirectionTranslations,q=e,A=e.AlarmStatus,M=e.alarmStatusTranslations,E=e.SharedModule,w=e.AggregationType,G=e.aggregationTranslations,D=e.NotificationType,V=e.SlackChanelType,P=e.SlackChanelTypesTranslateMap},function(e){R=e},function(e){O=e,_=e.Validators,B=e.NgControl,K=e.NG_VALUE_ACCESSOR,H=e.NG_VALIDATORS,z=e.FormArray,U=e.FormGroup},function(e){j=e,$=e.DOCUMENT,J=e.CommonModule},function(e){Q=e},function(e){Y=e},function(e){W=e},function(e){Z=e},function(e){X=e},function(e){ee=e},function(e){te=e},function(e){ne=e},function(e){re=e},function(e){oe=e},function(e){ae=e},function(e){ie=e.Subject,le=e.takeUntil,se=e.of,me=e.EMPTY,pe=e.fromEvent},function(e){de=e},function(e){ue=e},function(e){ce=e},function(e){ge=e.getCurrentAuthState,fe=e,ye=e.isDefinedAndNotNull,be=e.isEqual,xe=e.deepTrim,he=e.isObject,ve=e.isNotEmptyStr},function(e){Ce=e},function(e){Fe=e},function(e){ke=e.ENTER,Te=e.COMMA,Le=e.SEMICOLON},function(e){Ie=e},function(e){Se=e},function(e){Ne=e},function(e){qe=e},function(e){Ae=e},function(e){Me=e},function(e){Ee=e},function(e){we=e.coerceBooleanProperty,Ge=e.coerceElement,De=e.coerceNumberProperty},function(e){Ve=e},function(e){Pe=e},function(e){Re=e},function(e){Oe=e},function(e){_e=e.tap,Be=e.map,Ke=e.startWith,He=e.mergeMap,ze=e.share,Ue=e.takeUntil,je=e.auditTime},function(e){$e=e},function(e){Je=e},function(e){Qe=e.HomeComponentsModule},function(e){Ye=e.__decorate},function(e){We=e},function(e){Ze=e},function(e){Xe=e},function(e){et=e},function(e){tt=e},function(e){nt=e},function(e){rt=e},function(e){ot=e},function(e){at=e},function(e){it=e},function(e){lt=e},function(e){st=e},function(e){mt=e},function(e){pt=e.normalizePassiveListenerOptions,dt=e}],execute:function(){class ut extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.emptyConfigForm}onConfigurationSet(e){this.emptyConfigForm=this.fb.group({})}}e("EmptyConfigComponent",ut),ut.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ut,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ut.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ut,selector:"tb-node-empty-config",usesInheritance:!0,ngImport:t,template:"<div></div>",isInline:!0}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ut,decorators:[{type:n,args:[{selector:"tb-node-empty-config",template:"<div></div>"}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class ct extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.assignCustomerConfigForm}onConfigurationSet(e){this.assignCustomerConfigForm=this.fb.group({customerNamePattern:[e?e.customerNamePattern:null,[_.required,_.pattern(/.*\S.*/)]],createCustomerIfNotExists:[!!e&&e.createCustomerIfNotExists,[]]})}prepareOutputConfig(e){return e.customerNamePattern=e.customerNamePattern.trim(),e}}e("AssignCustomerConfigComponent",ct),ct.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ct,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ct.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ct,selector:"tb-action-node-assign-to-customer-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="assignCustomerConfigForm" fxLayout="column">\n <div class="tb-form-panel no-padding no-border">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.customer-name-pattern</mat-label>\n <input required matInput formControlName="customerNamePattern">\n <mat-error *ngIf="assignCustomerConfigForm.get(\'customerNamePattern\').hasError(\'required\') ||\n assignCustomerConfigForm.get(\'customerNamePattern\').hasError(\'pattern\')">\n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.customer-name-pattern-hint</mat-hint>\n </mat-form-field>\n <div class="tb-form-row">\n <mat-slide-toggle class="mat-slide" formControlName="createCustomerIfNotExists">\n {{ \'tb.rulenode.create-customer-if-not-exists\' | translate }}\n </mat-slide-toggle>\n </div>\n </div>\n</section>\n',dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ct,decorators:[{type:n,args:[{selector:"tb-action-node-assign-to-customer-config",template:'<section [formGroup]="assignCustomerConfigForm" fxLayout="column">\n <div class="tb-form-panel no-padding no-border">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.customer-name-pattern</mat-label>\n <input required matInput formControlName="customerNamePattern">\n <mat-error *ngIf="assignCustomerConfigForm.get(\'customerNamePattern\').hasError(\'required\') ||\n assignCustomerConfigForm.get(\'customerNamePattern\').hasError(\'pattern\')">\n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.customer-name-pattern-hint</mat-hint>\n </mat-form-field>\n <div class="tb-form-row">\n <mat-slide-toggle class="mat-slide" formControlName="createCustomerIfNotExists">\n {{ \'tb.rulenode.create-customer-if-not-exists\' | translate }}\n </mat-slide-toggle>\n </div>\n </div>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});const gt=new r("WindowToken","undefined"!=typeof window&&window.document?{providedIn:"root",factory:()=>window}:{providedIn:"root",factory:()=>{}});class ft{constructor(e,t,n){this.ngZone=e,this.document=t,this.window=n,this.copySubject=new ie,this.copyResponse$=this.copySubject.asObservable(),this.config={}}configure(e){this.config=e}copy(e){if(!this.isSupported||!e)return this.pushCopyResponse({isSuccess:!1,content:e});const t=this.copyFromContent(e);return t?this.pushCopyResponse({content:e,isSuccess:t}):this.pushCopyResponse({isSuccess:!1,content:e})}get isSupported(){return!!this.document.queryCommandSupported&&!!this.document.queryCommandSupported("copy")&&!!this.window}isTargetValid(e){if(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement){if(e.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');return!0}throw new Error("Target should be input or textarea")}copyFromInputElement(e,t=!0){try{this.selectTarget(e);const n=this.copyText();return this.clearSelection(t?e:void 0,this.window),n&&this.isCopySuccessInIE11()}catch(e){return!1}}isCopySuccessInIE11(){const e=this.window.clipboardData;return!(e&&e.getData&&!e.getData("Text"))}copyFromContent(e,t=this.document.body){if(this.tempTextArea&&!t.contains(this.tempTextArea)&&this.destroy(this.tempTextArea.parentElement||void 0),!this.tempTextArea){this.tempTextArea=this.createTempTextArea(this.document,this.window);try{t.appendChild(this.tempTextArea)}catch(e){throw new Error("Container should be a Dom element")}}this.tempTextArea.value=e;const n=this.copyFromInputElement(this.tempTextArea,!1);return this.config.cleanUpAfterCopy&&this.destroy(this.tempTextArea.parentElement||void 0),n}destroy(e=this.document.body){this.tempTextArea&&(e.removeChild(this.tempTextArea),this.tempTextArea=void 0)}selectTarget(e){return e.select(),e.setSelectionRange(0,e.value.length),e.value.length}copyText(){return this.document.execCommand("copy")}clearSelection(e,t){e&&e.focus(),t.getSelection()?.removeAllRanges()}createTempTextArea(e,t){const n="rtl"===e.documentElement.getAttribute("dir");let r;r=e.createElement("textarea"),r.style.fontSize="12pt",r.style.border="0",r.style.padding="0",r.style.margin="0",r.style.position="absolute",r.style[n?"right":"left"]="-9999px";const o=t.pageYOffset||e.documentElement.scrollTop;return r.style.top=o+"px",r.setAttribute("readonly",""),r}pushCopyResponse(e){this.copySubject.observers.length>0&&this.ngZone.run((()=>{this.copySubject.next(e)}))}pushCopyReponse(e){this.pushCopyResponse(e)}}ft.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:ft,deps:[{token:t.NgZone},{token:$},{token:gt,optional:!0}],target:t.ɵɵFactoryTarget.Injectable}),ft.ɵprov=t.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:ft,providedIn:"root"}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:ft,decorators:[{type:o,args:[{providedIn:"root"}]}],ctorParameters:function(){return[{type:t.NgZone},{type:void 0,decorators:[{type:a,args:[$]}]},{type:void 0,decorators:[{type:i},{type:a,args:[gt]}]}]}});class yt{constructor(e,t,n,r){this.ngZone=e,this.host=t,this.renderer=n,this.clipboardSrv=r,this.cbOnSuccess=new l,this.cbOnError=new l,this.onClick=e=>{this.clipboardSrv.isSupported?this.targetElm&&this.clipboardSrv.isTargetValid(this.targetElm)?this.handleResult(this.clipboardSrv.copyFromInputElement(this.targetElm),this.targetElm.value,e):this.cbContent&&this.handleResult(this.clipboardSrv.copyFromContent(this.cbContent,this.container),this.cbContent,e):this.handleResult(!1,void 0,e)}}ngOnInit(){this.ngZone.runOutsideAngular((()=>{this.clickListener=this.renderer.listen(this.host.nativeElement,"click",this.onClick)}))}ngOnDestroy(){this.clickListener&&this.clickListener(),this.clipboardSrv.destroy(this.container)}handleResult(e,t,n){let r={isSuccess:e,content:t,successMessage:this.cbSuccessMsg,event:n};e?this.cbOnSuccess.observed&&this.ngZone.run((()=>{this.cbOnSuccess.emit(r)})):this.cbOnError.observed&&this.ngZone.run((()=>{this.cbOnError.emit(r)})),this.clipboardSrv.pushCopyResponse(r)}}yt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:yt,deps:[{token:t.NgZone},{token:t.ElementRef},{token:t.Renderer2},{token:ft}],target:t.ɵɵFactoryTarget.Directive}),yt.ɵdir=t.ɵɵngDeclareDirective({minVersion:"12.0.0",version:"13.0.1",type:yt,selector:"[ngxClipboard]",inputs:{targetElm:["ngxClipboard","targetElm"],container:"container",cbContent:"cbContent",cbSuccessMsg:"cbSuccessMsg"},outputs:{cbOnSuccess:"cbOnSuccess",cbOnError:"cbOnError"},ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:yt,decorators:[{type:s,args:[{selector:"[ngxClipboard]"}]}],ctorParameters:function(){return[{type:t.NgZone},{type:t.ElementRef},{type:t.Renderer2},{type:ft}]},propDecorators:{targetElm:[{type:m,args:["ngxClipboard"]}],container:[{type:m}],cbContent:[{type:m}],cbSuccessMsg:[{type:m}],cbOnSuccess:[{type:p}],cbOnError:[{type:p}]}});class bt{constructor(e,t,n){this._clipboardService=e,this._viewContainerRef=t,this._templateRef=n}ngOnInit(){this._clipboardService.isSupported&&this._viewContainerRef.createEmbeddedView(this._templateRef)}}bt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:bt,deps:[{token:ft},{token:t.ViewContainerRef},{token:t.TemplateRef}],target:t.ɵɵFactoryTarget.Directive}),bt.ɵdir=t.ɵɵngDeclareDirective({minVersion:"12.0.0",version:"13.0.1",type:bt,selector:"[ngxClipboardIfSupported]",ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:bt,decorators:[{type:s,args:[{selector:"[ngxClipboardIfSupported]"}]}],ctorParameters:function(){return[{type:ft},{type:t.ViewContainerRef},{type:t.TemplateRef}]}});class xt{}xt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:xt,deps:[],target:t.ɵɵFactoryTarget.NgModule}),xt.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:xt,declarations:[yt,bt],imports:[J],exports:[yt,bt]}),xt.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:xt,imports:[[J]]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:xt,decorators:[{type:d,args:[{imports:[J],declarations:[yt,bt],exports:[yt,bt]}]}]});class ht{constructor(){this.textAlign="left"}}e("ExampleHintComponent",ht),ht.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ht,deps:[],target:t.ɵɵFactoryTarget.Component}),ht.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ht,selector:"tb-example-hint",inputs:{hintText:"hintText",popupHelpLink:"popupHelpLink",textAlign:"textAlign"},ngImport:t,template:'<div [hidden]="!hintText" class="tb-form-hint tb-primary-fill space-between">\n <div [innerHTML]=" hintText | translate | safe: \'html\'"\n [style.text-align]="textAlign"\n class="hint-text"></div>\n <div *ngIf="popupHelpLink" class="see-example" tb-help-popup="{{ popupHelpLink }}"\n hintMode\n tb-help-popup-placement="right"\n trigger-style="letter-spacing:0.25px; font-size:12px"\n [tb-help-popup-style]="{maxWidth: \'820px\'}"\n trigger-text="{{ \'tb.key-val.see-examples\' | translate }}">\n </div>\n</div>\n',styles:[":host .space-between{display:flex;justify-content:space-between;gap:20px}:host .space-between .see-example{display:flex;flex-shrink:0}:host .hint-text{width:100%}\n"],dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ue.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"pipe",type:ce.SafePipe,name:"safe"},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ht,decorators:[{type:n,args:[{selector:"tb-example-hint",template:'<div [hidden]="!hintText" class="tb-form-hint tb-primary-fill space-between">\n <div [innerHTML]=" hintText | translate | safe: \'html\'"\n [style.text-align]="textAlign"\n class="hint-text"></div>\n <div *ngIf="popupHelpLink" class="see-example" tb-help-popup="{{ popupHelpLink }}"\n hintMode\n tb-help-popup-placement="right"\n trigger-style="letter-spacing:0.25px; font-size:12px"\n [tb-help-popup-style]="{maxWidth: \'820px\'}"\n trigger-text="{{ \'tb.key-val.see-examples\' | translate }}">\n </div>\n</div>\n',styles:[":host .space-between{display:flex;justify-content:space-between;gap:20px}:host .space-between .see-example{display:flex;flex-shrink:0}:host .hint-text{width:100%}\n"]}]}],propDecorators:{hintText:[{type:m}],popupHelpLink:[{type:m}],textAlign:[{type:m}]}});class vt extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopeMap=f,this.attributeScopes=Object.keys(f),this.telemetryTypeTranslationsMap=y}configForm(){return this.attributesConfigForm}onConfigurationSet(e){this.attributesConfigForm=this.fb.group({scope:[e?e.scope:null,[_.required]],notifyDevice:[!e||e.notifyDevice,[]],sendAttributesUpdatedNotification:[!!e&&e.sendAttributesUpdatedNotification,[]],updateAttributesOnlyOnValueChange:[!!e&&e.updateAttributesOnlyOnValueChange,[]]}),this.attributesConfigForm.get("scope").valueChanges.subscribe((e=>{e!==f.SHARED_SCOPE&&this.attributesConfigForm.get("notifyDevice").patchValue(!1,{emitEvent:!1}),e===f.CLIENT_SCOPE&&this.attributesConfigForm.get("sendAttributesUpdatedNotification").patchValue(!1,{emitEvent:!1}),this.attributesConfigForm.get("updateAttributesOnlyOnValueChange").patchValue(!1,{emitEvent:!1})}))}}e("AttributesConfigComponent",vt),vt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vt,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),vt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:vt,selector:"tb-action-node-attributes-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="attributesConfigForm" class="tb-form-panel no-border no-padding">\n <div class="tb-form-panel stroked">\n <tb-example-hint [hintText]="\'tb.rulenode.attributes-scope-hint\'">\n </tb-example-hint>\n <div class="tb-form-row no-border no-padding tb-standard-fields">\n <mat-form-field class="flex">\n <mat-label>{{ \'tb.rulenode.attributes-scope\' | translate }}</mat-label>\n <mat-select required\n class="tb-entity-type-select" matInput formControlName="scope">\n <mat-option *ngFor="let scope of attributeScopes" [value]="scope">\n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label>{{ \'tb.rulenode.attributes-scope-value\' | translate }}</mat-label>\n <input type="text" matInput readonly disabled [ngModel]="attributesConfigForm.get(\'scope\').value" [ngModelOptions]="{standalone: true}">\n <button type="button"\n matSuffix\n mat-icon-button\n aria-label="Copy"\n ngxClipboard\n [cbContent]="attributesConfigForm.get(\'scope\').value"\n matTooltip="{{ \'tb.rulenode.attributes-scope-value-copy\' | translate }}">\n <mat-icon aria-hidden="false"\n aria-label="help-icon">content_copy\n </mat-icon>\n </button>\n </mat-form-field>\n </div>\n </div>\n\n <section class="tb-form-panel stroked">\n <mat-expansion-panel class="tb-settings">\n <mat-expansion-panel-header>\n <mat-panel-title translate>tb.rulenode.advanced-settings</mat-panel-title>\n </mat-expansion-panel-header>\n <div tb-hint-tooltip-icon="{{ (attributesConfigForm.get(\'updateAttributesOnlyOnValueChange\').value\n ? \'tb.rulenode.update-attributes-only-on-value-change-hint-enabled\'\n : \'tb.rulenode.update-attributes-only-on-value-change-hint\') | translate }}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="updateAttributesOnlyOnValueChange">\n {{ \'tb.rulenode.update-attributes-only-on-value-change\' | translate }}\n </mat-slide-toggle>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.send-attributes-updated-notification-hint\' | translate }}"\n *ngIf="attributesConfigForm.get(\'scope\').value !== attributeScopeMap.CLIENT_SCOPE"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="sendAttributesUpdatedNotification">\n {{ \'tb.rulenode.send-attributes-updated-notification\' | translate }}\n </mat-slide-toggle>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.notify-device-on-update-hint\' | translate }}"\n *ngIf="attributesConfigForm.get(\'scope\').value === attributeScopeMap.SHARED_SCOPE"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="notifyDevice">\n {{ \'tb.rulenode.notify-device\' | translate }}\n </mat-slide-toggle>\n </div>\n </mat-expansion-panel>\n </section>\n</section>\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ee.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"component",type:ae.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:ae.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:ae.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:yt,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:ht,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vt,decorators:[{type:n,args:[{selector:"tb-action-node-attributes-config",template:'<section [formGroup]="attributesConfigForm" class="tb-form-panel no-border no-padding">\n <div class="tb-form-panel stroked">\n <tb-example-hint [hintText]="\'tb.rulenode.attributes-scope-hint\'">\n </tb-example-hint>\n <div class="tb-form-row no-border no-padding tb-standard-fields">\n <mat-form-field class="flex">\n <mat-label>{{ \'tb.rulenode.attributes-scope\' | translate }}</mat-label>\n <mat-select required\n class="tb-entity-type-select" matInput formControlName="scope">\n <mat-option *ngFor="let scope of attributeScopes" [value]="scope">\n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label>{{ \'tb.rulenode.attributes-scope-value\' | translate }}</mat-label>\n <input type="text" matInput readonly disabled [ngModel]="attributesConfigForm.get(\'scope\').value" [ngModelOptions]="{standalone: true}">\n <button type="button"\n matSuffix\n mat-icon-button\n aria-label="Copy"\n ngxClipboard\n [cbContent]="attributesConfigForm.get(\'scope\').value"\n matTooltip="{{ \'tb.rulenode.attributes-scope-value-copy\' | translate }}">\n <mat-icon aria-hidden="false"\n aria-label="help-icon">content_copy\n </mat-icon>\n </button>\n </mat-form-field>\n </div>\n </div>\n\n <section class="tb-form-panel stroked">\n <mat-expansion-panel class="tb-settings">\n <mat-expansion-panel-header>\n <mat-panel-title translate>tb.rulenode.advanced-settings</mat-panel-title>\n </mat-expansion-panel-header>\n <div tb-hint-tooltip-icon="{{ (attributesConfigForm.get(\'updateAttributesOnlyOnValueChange\').value\n ? \'tb.rulenode.update-attributes-only-on-value-change-hint-enabled\'\n : \'tb.rulenode.update-attributes-only-on-value-change-hint\') | translate }}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="updateAttributesOnlyOnValueChange">\n {{ \'tb.rulenode.update-attributes-only-on-value-change\' | translate }}\n </mat-slide-toggle>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.send-attributes-updated-notification-hint\' | translate }}"\n *ngIf="attributesConfigForm.get(\'scope\').value !== attributeScopeMap.CLIENT_SCOPE"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="sendAttributesUpdatedNotification">\n {{ \'tb.rulenode.send-attributes-updated-notification\' | translate }}\n </mat-slide-toggle>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.notify-device-on-update-hint\' | translate }}"\n *ngIf="attributesConfigForm.get(\'scope\').value === attributeScopeMap.SHARED_SCOPE"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="notifyDevice">\n {{ \'tb.rulenode.notify-device\' | translate }}\n </mat-slide-toggle>\n </div>\n </mat-expansion-panel>\n </section>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class Ct extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ge(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-details-function"}configForm(){return this.clearAlarmConfigForm}onConfigurationSet(e){this.clearAlarmConfigForm=this.fb.group({scriptLang:[e?e.scriptLang:b.JS,[_.required]],alarmDetailsBuildJs:[e?e.alarmDetailsBuildJs:null,[]],alarmDetailsBuildTbel:[e?e.alarmDetailsBuildTbel:null,[]],alarmType:[e?e.alarmType:null,[_.required]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.clearAlarmConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.clearAlarmConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.clearAlarmConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.clearAlarmConfigForm.get("alarmDetailsBuildJs").setValidators(t===b.JS?[_.required]:[]),this.clearAlarmConfigForm.get("alarmDetailsBuildJs").updateValueAndValidity({emitEvent:e}),this.clearAlarmConfigForm.get("alarmDetailsBuildTbel").setValidators(t===b.TBEL?[_.required]:[]),this.clearAlarmConfigForm.get("alarmDetailsBuildTbel").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),e}testScript(e){const t=this.clearAlarmConfigForm.get("scriptLang").value,n=t===b.JS?"alarmDetailsBuildJs":"alarmDetailsBuildTbel",r=t===b.JS?"rulenode/clear_alarm_node_script_fn":"rulenode/tbel/clear_alarm_node_script_fn",o=this.clearAlarmConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"json",this.translate.instant("tb.rulenode.details"),"Details",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.clearAlarmConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.clearAlarmConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}e("ClearAlarmConfigComponent",Ct),Ct.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ct,deps:[{token:R.Store},{token:O.UntypedFormBuilder},{token:fe.NodeScriptTestService},{token:X.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Ct.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ct,selector:"tb-action-node-clear-alarm-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'<section [formGroup]="clearAlarmConfigForm" fxLayout="column">\n <tb-script-lang formControlName="scriptLang" *ngIf="tbelEnabled"></tb-script-lang>\n <tb-js-func *ngIf="clearAlarmConfigForm.get(\'scriptLang\').value === scriptLanguage.JS"\n #jsFuncComponent\n formControlName="alarmDetailsBuildJs"\n functionName="Details"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n helpId="rulenode/clear_alarm_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <tb-js-func *ngIf="clearAlarmConfigForm.get(\'scriptLang\').value === scriptLanguage.TBEL"\n #tbelFuncComponent\n formControlName="alarmDetailsBuildTbel"\n functionName="Details"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n [disableUndefinedCheck]="true"\n [scriptLanguage]="scriptLanguage.TBEL"\n helpId="rulenode/tbel/clear_alarm_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <div fxLayout="row" style="padding-bottom: 16px;">\n <button mat-button mat-raised-button color="primary" (click)="testScript()">\n {{ testScriptLabel | translate }}\n </button>\n </div>\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.alarm-type</mat-label>\n <input required matInput formControlName="alarmType">\n <mat-error *ngIf="clearAlarmConfigForm.get(\'alarmType\').hasError(\'required\')">\n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n</section>\n',dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ce.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","propertyHighlightRules","objectHighlightRules","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:ee.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ct,decorators:[{type:n,args:[{selector:"tb-action-node-clear-alarm-config",template:'<section [formGroup]="clearAlarmConfigForm" fxLayout="column">\n <tb-script-lang formControlName="scriptLang" *ngIf="tbelEnabled"></tb-script-lang>\n <tb-js-func *ngIf="clearAlarmConfigForm.get(\'scriptLang\').value === scriptLanguage.JS"\n #jsFuncComponent\n formControlName="alarmDetailsBuildJs"\n functionName="Details"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n helpId="rulenode/clear_alarm_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <tb-js-func *ngIf="clearAlarmConfigForm.get(\'scriptLang\').value === scriptLanguage.TBEL"\n #tbelFuncComponent\n formControlName="alarmDetailsBuildTbel"\n functionName="Details"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n [disableUndefinedCheck]="true"\n [scriptLanguage]="scriptLanguage.TBEL"\n helpId="rulenode/tbel/clear_alarm_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <div fxLayout="row" style="padding-bottom: 16px;">\n <button mat-button mat-raised-button color="primary" (click)="testScript()">\n {{ testScriptLabel | translate }}\n </button>\n </div>\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.alarm-type</mat-label>\n <input required matInput formControlName="alarmType">\n <mat-error *ngIf="clearAlarmConfigForm.get(\'alarmType\').hasError(\'required\')">\n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder},{type:fe.NodeScriptTestService},{type:X.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}});class Ft extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.alarmSeverities=Object.keys(x),this.alarmSeverityTranslationMap=h,this.separatorKeysCodes=[ke,Te,Le],this.tbelEnabled=ge(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-details-function"}configForm(){return this.createAlarmConfigForm}onConfigurationSet(e){this.createAlarmConfigForm=this.fb.group({scriptLang:[e?e.scriptLang:b.JS,[_.required]],alarmDetailsBuildJs:[e?e.alarmDetailsBuildJs:null,[]],alarmDetailsBuildTbel:[e?e.alarmDetailsBuildTbel:null,[]],useMessageAlarmData:[!!e&&e.useMessageAlarmData,[]],overwriteAlarmDetails:[!!e&&e.overwriteAlarmDetails,[]],alarmType:[e?e.alarmType:null,[]],severity:[e?e.severity:null,[]],propagate:[!!e&&e.propagate,[]],relationTypes:[e?e.relationTypes:null,[]],propagateToOwner:[!!e&&e.propagateToOwner,[]],propagateToTenant:[!!e&&e.propagateToTenant,[]],dynamicSeverity:!1}),this.createAlarmConfigForm.get("dynamicSeverity").valueChanges.subscribe((e=>{e?this.createAlarmConfigForm.get("severity").patchValue("",{emitEvent:!1}):this.createAlarmConfigForm.get("severity").patchValue(this.alarmSeverities[0],{emitEvent:!1})}))}validatorTriggers(){return["useMessageAlarmData","overwriteAlarmDetails","scriptLang"]}updateValidators(e){const t=this.createAlarmConfigForm.get("useMessageAlarmData").value,n=this.createAlarmConfigForm.get("overwriteAlarmDetails").value;t?(this.createAlarmConfigForm.get("alarmType").setValidators([]),this.createAlarmConfigForm.get("severity").setValidators([])):(this.createAlarmConfigForm.get("alarmType").setValidators([_.required]),this.createAlarmConfigForm.get("severity").setValidators([_.required])),this.createAlarmConfigForm.get("alarmType").updateValueAndValidity({emitEvent:e}),this.createAlarmConfigForm.get("severity").updateValueAndValidity({emitEvent:e});let r=this.createAlarmConfigForm.get("scriptLang").value;r!==b.TBEL||this.tbelEnabled||(r=b.JS,this.createAlarmConfigForm.get("scriptLang").patchValue(r,{emitEvent:!1}),setTimeout((()=>{this.createAlarmConfigForm.updateValueAndValidity({emitEvent:!0})})));const o=!1===t||!0===n;this.createAlarmConfigForm.get("alarmDetailsBuildJs").setValidators(o&&r===b.JS?[_.required]:[]),this.createAlarmConfigForm.get("alarmDetailsBuildTbel").setValidators(o&&r===b.TBEL?[_.required]:[]),this.createAlarmConfigForm.get("alarmDetailsBuildJs").updateValueAndValidity({emitEvent:e}),this.createAlarmConfigForm.get("alarmDetailsBuildTbel").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),e}testScript(e){const t=this.createAlarmConfigForm.get("scriptLang").value,n=t===b.JS?"alarmDetailsBuildJs":"alarmDetailsBuildTbel",r=t===b.JS?"rulenode/create_alarm_node_script_fn":"rulenode/tbel/create_alarm_node_script_fn",o=this.createAlarmConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"json",this.translate.instant("tb.rulenode.details"),"Details",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.createAlarmConfigForm.get(n).setValue(e),this.changeScript.emit())}))}removeKey(e,t){const n=this.createAlarmConfigForm.get(t).value,r=n.indexOf(e);r>=0&&(n.splice(r,1),this.createAlarmConfigForm.get(t).setValue(n,{emitEvent:!0}))}addKey(e,t){const n=e.input;let r=e.value;if((r||"").trim()){r=r.trim();let e=this.createAlarmConfigForm.get(t).value;e&&-1!==e.indexOf(r)||(e||(e=[]),e.push(r),this.createAlarmConfigForm.get(t).setValue(e,{emitEvent:!0}))}n&&(n.value="")}onValidate(){const e=this.createAlarmConfigForm.get("useMessageAlarmData").value,t=this.createAlarmConfigForm.get("overwriteAlarmDetails").value;if(!e||t){this.createAlarmConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}}e("CreateAlarmConfigComponent",Ft),Ft.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ft,deps:[{token:R.Store},{token:O.UntypedFormBuilder},{token:fe.NodeScriptTestService},{token:X.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Ft.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ft,selector:"tb-action-node-create-alarm-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'<section [formGroup]="createAlarmConfigForm" fxLayout="column">\n <mat-checkbox formControlName="useMessageAlarmData">\n {{ \'tb.rulenode.use-message-alarm-data\' | translate }}\n </mat-checkbox>\n <mat-checkbox formControlName="overwriteAlarmDetails" *ngIf="createAlarmConfigForm.get(\'useMessageAlarmData\').value === true">\n {{ \'tb.rulenode.overwrite-alarm-details\' | translate }}\n </mat-checkbox>\n <section fxLayout="column" *ngIf="createAlarmConfigForm.get(\'useMessageAlarmData\').value === false ||\n createAlarmConfigForm.get(\'overwriteAlarmDetails\').value === true">\n <tb-script-lang formControlName="scriptLang" *ngIf="tbelEnabled"></tb-script-lang>\n <tb-js-func *ngIf="createAlarmConfigForm.get(\'scriptLang\').value === scriptLanguage.JS"\n #jsFuncComponent\n formControlName="alarmDetailsBuildJs"\n functionName="Details"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n helpId="rulenode/create_alarm_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <tb-js-func *ngIf="createAlarmConfigForm.get(\'scriptLang\').value === scriptLanguage.TBEL"\n #tbelFuncComponent\n formControlName="alarmDetailsBuildTbel"\n functionName="Details"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n [disableUndefinedCheck]="true"\n [scriptLanguage]="scriptLanguage.TBEL"\n helpId="rulenode/tbel/create_alarm_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <div fxLayout="row" style="padding-bottom: 16px;">\n <button mat-button mat-raised-button color="primary" (click)="testScript()">\n {{ testScriptLabel | translate }}\n </button>\n </div>\n </section>\n <section fxLayout="column" *ngIf="createAlarmConfigForm.get(\'useMessageAlarmData\').value === false">\n <mat-form-field fxFlex subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.alarm-type</mat-label>\n <input required matInput formControlName="alarmType">\n <mat-error *ngIf="createAlarmConfigForm.get(\'alarmType\').hasError(\'required\')">\n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <mat-checkbox formControlName="dynamicSeverity">\n {{ \'tb.rulenode.use-alarm-severity-pattern\' | translate }}\n </mat-checkbox>\n <mat-form-field fxFlex *ngIf="!createAlarmConfigForm.get(\'dynamicSeverity\').value">\n <mat-label translate>tb.rulenode.alarm-severity</mat-label>\n <mat-select formControlName="severity" required>\n <mat-option *ngFor="let severity of alarmSeverities" [value]="severity">\n {{ alarmSeverityTranslationMap.get(severity) | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf="createAlarmConfigForm.get(\'severity\').hasError(\'required\')">\n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex *ngIf="createAlarmConfigForm.get(\'dynamicSeverity\').value" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.alarm-severity-pattern</mat-label>\n <input matInput formControlName="severity" required>\n <mat-error *ngIf="createAlarmConfigForm.get(\'severity\').hasError(\'required\')">\n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n </mat-error>\n <mat-hint [innerHTML]="\'tb.rulenode.alarm-severity-pattern-hint\' | translate | safe: \'html\'"></mat-hint>\n </mat-form-field>\n <mat-checkbox formControlName="propagate">\n {{ \'tb.rulenode.propagate\' | translate }}\n </mat-checkbox>\n <section *ngIf="createAlarmConfigForm.get(\'propagate\').value === true">\n <mat-form-field floatLabel="always" class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.relation-types-list</mat-label>\n <mat-chip-grid #relationTypesChipList>\n <mat-chip-row\n *ngFor="let key of createAlarmConfigForm.get(\'relationTypes\').value;"\n (removed)="removeKey(key, \'relationTypes\')">\n {{key}}\n <mat-icon matChipRemove>close</mat-icon>\n </mat-chip-row>\n <input matInput type="text" placeholder="{{\'tb.rulenode.relation-types-list\' | translate}}"\n [matChipInputFor]="relationTypesChipList"\n [matChipInputSeparatorKeyCodes]="separatorKeysCodes"\n (matChipInputTokenEnd)="addKey($event, \'relationTypes\')"\n [matChipInputAddOnBlur]="true">\n </mat-chip-grid>\n <mat-hint translate>tb.rulenode.relation-types-list-hint</mat-hint>\n </mat-form-field>\n </section>\n <mat-checkbox formControlName="propagateToOwner">\n {{ \'tb.rulenode.propagate-to-owner\' | translate }}\n </mat-checkbox>\n <mat-checkbox formControlName="propagateToTenant">\n {{ \'tb.rulenode.propagate-to-tenant\' | translate }}\n </mat-checkbox>\n </section>\n</section>\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ce.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","propertyHighlightRules","objectHighlightRules","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:ee.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:Ie.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Se.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:Se.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:Se.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:Se.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:ce.SafePipe,name:"safe"},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ft,decorators:[{type:n,args:[{selector:"tb-action-node-create-alarm-config",template:'<section [formGroup]="createAlarmConfigForm" fxLayout="column">\n <mat-checkbox formControlName="useMessageAlarmData">\n {{ \'tb.rulenode.use-message-alarm-data\' | translate }}\n </mat-checkbox>\n <mat-checkbox formControlName="overwriteAlarmDetails" *ngIf="createAlarmConfigForm.get(\'useMessageAlarmData\').value === true">\n {{ \'tb.rulenode.overwrite-alarm-details\' | translate }}\n </mat-checkbox>\n <section fxLayout="column" *ngIf="createAlarmConfigForm.get(\'useMessageAlarmData\').value === false ||\n createAlarmConfigForm.get(\'overwriteAlarmDetails\').value === true">\n <tb-script-lang formControlName="scriptLang" *ngIf="tbelEnabled"></tb-script-lang>\n <tb-js-func *ngIf="createAlarmConfigForm.get(\'scriptLang\').value === scriptLanguage.JS"\n #jsFuncComponent\n formControlName="alarmDetailsBuildJs"\n functionName="Details"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n helpId="rulenode/create_alarm_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <tb-js-func *ngIf="createAlarmConfigForm.get(\'scriptLang\').value === scriptLanguage.TBEL"\n #tbelFuncComponent\n formControlName="alarmDetailsBuildTbel"\n functionName="Details"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n [disableUndefinedCheck]="true"\n [scriptLanguage]="scriptLanguage.TBEL"\n helpId="rulenode/tbel/create_alarm_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <div fxLayout="row" style="padding-bottom: 16px;">\n <button mat-button mat-raised-button color="primary" (click)="testScript()">\n {{ testScriptLabel | translate }}\n </button>\n </div>\n </section>\n <section fxLayout="column" *ngIf="createAlarmConfigForm.get(\'useMessageAlarmData\').value === false">\n <mat-form-field fxFlex subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.alarm-type</mat-label>\n <input required matInput formControlName="alarmType">\n <mat-error *ngIf="createAlarmConfigForm.get(\'alarmType\').hasError(\'required\')">\n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <mat-checkbox formControlName="dynamicSeverity">\n {{ \'tb.rulenode.use-alarm-severity-pattern\' | translate }}\n </mat-checkbox>\n <mat-form-field fxFlex *ngIf="!createAlarmConfigForm.get(\'dynamicSeverity\').value">\n <mat-label translate>tb.rulenode.alarm-severity</mat-label>\n <mat-select formControlName="severity" required>\n <mat-option *ngFor="let severity of alarmSeverities" [value]="severity">\n {{ alarmSeverityTranslationMap.get(severity) | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf="createAlarmConfigForm.get(\'severity\').hasError(\'required\')">\n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex *ngIf="createAlarmConfigForm.get(\'dynamicSeverity\').value" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.alarm-severity-pattern</mat-label>\n <input matInput formControlName="severity" required>\n <mat-error *ngIf="createAlarmConfigForm.get(\'severity\').hasError(\'required\')">\n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n </mat-error>\n <mat-hint [innerHTML]="\'tb.rulenode.alarm-severity-pattern-hint\' | translate | safe: \'html\'"></mat-hint>\n </mat-form-field>\n <mat-checkbox formControlName="propagate">\n {{ \'tb.rulenode.propagate\' | translate }}\n </mat-checkbox>\n <section *ngIf="createAlarmConfigForm.get(\'propagate\').value === true">\n <mat-form-field floatLabel="always" class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.relation-types-list</mat-label>\n <mat-chip-grid #relationTypesChipList>\n <mat-chip-row\n *ngFor="let key of createAlarmConfigForm.get(\'relationTypes\').value;"\n (removed)="removeKey(key, \'relationTypes\')">\n {{key}}\n <mat-icon matChipRemove>close</mat-icon>\n </mat-chip-row>\n <input matInput type="text" placeholder="{{\'tb.rulenode.relation-types-list\' | translate}}"\n [matChipInputFor]="relationTypesChipList"\n [matChipInputSeparatorKeyCodes]="separatorKeysCodes"\n (matChipInputTokenEnd)="addKey($event, \'relationTypes\')"\n [matChipInputAddOnBlur]="true">\n </mat-chip-grid>\n <mat-hint translate>tb.rulenode.relation-types-list-hint</mat-hint>\n </mat-form-field>\n </section>\n <mat-checkbox formControlName="propagateToOwner">\n {{ \'tb.rulenode.propagate-to-owner\' | translate }}\n </mat-checkbox>\n <mat-checkbox formControlName="propagateToTenant">\n {{ \'tb.rulenode.propagate-to-tenant\' | translate }}\n </mat-checkbox>\n </section>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder},{type:fe.NodeScriptTestService},{type:X.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}});class kt extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=new Map([[v.FROM,"tb.rulenode.search-direction-from"],[v.TO,"tb.rulenode.search-direction-to"]]),this.entityType=C,this.entityTypeNamePatternTranslation=new Map([[C.DEVICE,"tb.rulenode.device-name-pattern"],[C.ASSET,"tb.rulenode.asset-name-pattern"],[C.ENTITY_VIEW,"tb.rulenode.entity-view-name-pattern"],[C.CUSTOMER,"tb.rulenode.customer-title-pattern"],[C.USER,"tb.rulenode.user-name-pattern"],[C.DASHBOARD,"tb.rulenode.dashboard-name-pattern"],[C.EDGE,"tb.rulenode.edge-name-pattern"]]),this.allowedEntityTypes=[C.DEVICE,C.ASSET,C.ENTITY_VIEW,C.TENANT,C.CUSTOMER,C.USER,C.DASHBOARD,C.EDGE]}configForm(){return this.createRelationConfigForm}onConfigurationSet(e){this.createRelationConfigForm=this.fb.group({direction:[e?e.direction:null,[_.required]],entityType:[e?e.entityType:null,[_.required]],entityNamePattern:[e?e.entityNamePattern:null,[]],entityTypePattern:[e?e.entityTypePattern:null,[]],relationType:[e?e.relationType:null,[_.required]],createEntityIfNotExists:[!!e&&e.createEntityIfNotExists,[]],removeCurrentRelations:[!!e&&e.removeCurrentRelations,[]],changeOriginatorToRelatedEntity:[!!e&&e.changeOriginatorToRelatedEntity,[]]})}validatorTriggers(){return["entityType","createEntityIfNotExists"]}updateValidators(e){const t=this.createRelationConfigForm.get("entityType").value;if(t?this.createRelationConfigForm.get("entityNamePattern").setValidators([_.required,_.pattern(/.*\S.*/)]):this.createRelationConfigForm.get("entityNamePattern").setValidators([]),!t||t!==C.DEVICE&&t!==C.ASSET)this.createRelationConfigForm.get("entityTypePattern").setValidators([]);else{const e=[_.pattern(/.*\S.*/)];this.createRelationConfigForm.get("createEntityIfNotExists").value&&e.push(_.required),this.createRelationConfigForm.get("entityTypePattern").setValidators(e)}this.createRelationConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e}),this.createRelationConfigForm.get("entityTypePattern").updateValueAndValidity({emitEvent:e})}prepareOutputConfig(e){return e.entityNamePattern=e.entityNamePattern?e.entityNamePattern.trim():null,e.entityTypePattern=e.entityTypePattern?e.entityTypePattern.trim():null,e}}e("CreateRelationConfigComponent",kt),kt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kt,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),kt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:kt,selector:"tb-action-node-create-relation-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="createRelationConfigForm" class="tb-form-panel no-padding no-border">\n <div class="tb-form-panel stroked no-padding-bottom">\n <div class="tb-form-panel-title" translate>tb.rulenode.relation-parameters</div>\n <div fxLayout="column">\n <mat-form-field class="mat-block" hideRequiredMarker>\n <mat-label translate>relation.direction</mat-label>\n <mat-select required matInput formControlName="direction">\n <mat-option *ngFor="let type of directionTypes" [value]="type">\n {{ directionTypeTranslations.get(type) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <tb-relation-type-autocomplete\n required\n formControlName="relationType">\n </tb-relation-type-autocomplete>\n </div>\n </div>\n\n <div class="tb-form-panel stroked no-padding-bottom">\n <div class="tb-form-panel-title" translate>tb.rulenode.target-entity</div>\n <div fxLayout="row" fxLayoutGap="16px">\n <tb-entity-type-select\n fxFlex\n showLabel\n required\n [allowedEntityTypes]="allowedEntityTypes"\n formControlName="entityType">\n </tb-entity-type-select>\n\n <mat-form-field *ngIf="createRelationConfigForm.get(\'entityType\').value &&\n createRelationConfigForm.get(\'entityType\').value !== entityType.TENANT"\n fxFlex class="mat-block">\n <mat-label>{{ entityTypeNamePatternTranslation.get(createRelationConfigForm.get(\'entityType\').value) | translate }}</mat-label>\n <input required matInput formControlName="entityNamePattern">\n </mat-form-field>\n\n <mat-form-field *ngIf="createRelationConfigForm.get(\'entityType\').value === entityType.DEVICE ||\n createRelationConfigForm.get(\'entityType\').value === entityType.ASSET"\n fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.profile-name</mat-label>\n <input matInput formControlName="entityTypePattern">\n </mat-form-field>\n </div>\n\n <tb-example-hint [hintText]="\'tb.rulenode.kv-map-pattern-hint\'"\n *ngIf="createRelationConfigForm.get(\'entityType\').value === entityType.CUSTOMER ||\n createRelationConfigForm.get(\'entityType\').value === entityType.DEVICE ||\n createRelationConfigForm.get(\'entityType\').value === entityType.ASSET"></tb-example-hint>\n\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.create-entity-if-not-exists-hint\' | translate }}"\n *ngIf="createRelationConfigForm.get(\'entityType\').value === entityType.CUSTOMER ||\n createRelationConfigForm.get(\'entityType\').value === entityType.DEVICE ||\n createRelationConfigForm.get(\'entityType\').value === entityType.ASSET"\n style="margin-bottom: 18px"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="createEntityIfNotExists">\n {{ \'tb.rulenode.create-entity-if-not-exists\' | translate }}\n </mat-slide-toggle>\n </div>\n </div>\n <section class="tb-form-panel stroked no-padding">\n <mat-expansion-panel class="tb-settings">\n <mat-expansion-panel-header style="padding: 16px">\n <mat-panel-title translate>tb.rulenode.advanced-settings</mat-panel-title>\n </mat-expansion-panel-header>\n <div class="tb-form-panel no-border no-padding-top">\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.remove-current-relations-hint\' | translate }}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="removeCurrentRelations">\n {{ \'tb.rulenode.remove-current-relations\' | translate }}\n </mat-slide-toggle>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.change-originator-to-related-entity-hint\' | translate }}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="changeOriginatorToRelatedEntity">\n {{ \'tb.rulenode.change-originator-to-related-entity\' | translate }}\n </mat-slide-toggle>\n </div>\n </div>\n </mat-expansion-panel>\n </section>\n</section>\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ne.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled","additionEntityTypes"]},{kind:"component",type:qe.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"component",type:ae.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:ae.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:ae.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:ht,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kt,decorators:[{type:n,args:[{selector:"tb-action-node-create-relation-config",template:'<section [formGroup]="createRelationConfigForm" class="tb-form-panel no-padding no-border">\n <div class="tb-form-panel stroked no-padding-bottom">\n <div class="tb-form-panel-title" translate>tb.rulenode.relation-parameters</div>\n <div fxLayout="column">\n <mat-form-field class="mat-block" hideRequiredMarker>\n <mat-label translate>relation.direction</mat-label>\n <mat-select required matInput formControlName="direction">\n <mat-option *ngFor="let type of directionTypes" [value]="type">\n {{ directionTypeTranslations.get(type) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <tb-relation-type-autocomplete\n required\n formControlName="relationType">\n </tb-relation-type-autocomplete>\n </div>\n </div>\n\n <div class="tb-form-panel stroked no-padding-bottom">\n <div class="tb-form-panel-title" translate>tb.rulenode.target-entity</div>\n <div fxLayout="row" fxLayoutGap="16px">\n <tb-entity-type-select\n fxFlex\n showLabel\n required\n [allowedEntityTypes]="allowedEntityTypes"\n formControlName="entityType">\n </tb-entity-type-select>\n\n <mat-form-field *ngIf="createRelationConfigForm.get(\'entityType\').value &&\n createRelationConfigForm.get(\'entityType\').value !== entityType.TENANT"\n fxFlex class="mat-block">\n <mat-label>{{ entityTypeNamePatternTranslation.get(createRelationConfigForm.get(\'entityType\').value) | translate }}</mat-label>\n <input required matInput formControlName="entityNamePattern">\n </mat-form-field>\n\n <mat-form-field *ngIf="createRelationConfigForm.get(\'entityType\').value === entityType.DEVICE ||\n createRelationConfigForm.get(\'entityType\').value === entityType.ASSET"\n fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.profile-name</mat-label>\n <input matInput formControlName="entityTypePattern">\n </mat-form-field>\n </div>\n\n <tb-example-hint [hintText]="\'tb.rulenode.kv-map-pattern-hint\'"\n *ngIf="createRelationConfigForm.get(\'entityType\').value === entityType.CUSTOMER ||\n createRelationConfigForm.get(\'entityType\').value === entityType.DEVICE ||\n createRelationConfigForm.get(\'entityType\').value === entityType.ASSET"></tb-example-hint>\n\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.create-entity-if-not-exists-hint\' | translate }}"\n *ngIf="createRelationConfigForm.get(\'entityType\').value === entityType.CUSTOMER ||\n createRelationConfigForm.get(\'entityType\').value === entityType.DEVICE ||\n createRelationConfigForm.get(\'entityType\').value === entityType.ASSET"\n style="margin-bottom: 18px"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="createEntityIfNotExists">\n {{ \'tb.rulenode.create-entity-if-not-exists\' | translate }}\n </mat-slide-toggle>\n </div>\n </div>\n <section class="tb-form-panel stroked no-padding">\n <mat-expansion-panel class="tb-settings">\n <mat-expansion-panel-header style="padding: 16px">\n <mat-panel-title translate>tb.rulenode.advanced-settings</mat-panel-title>\n </mat-expansion-panel-header>\n <div class="tb-form-panel no-border no-padding-top">\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.remove-current-relations-hint\' | translate }}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="removeCurrentRelations">\n {{ \'tb.rulenode.remove-current-relations\' | translate }}\n </mat-slide-toggle>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.change-originator-to-related-entity-hint\' | translate }}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="changeOriginatorToRelatedEntity">\n {{ \'tb.rulenode.change-originator-to-related-entity\' | translate }}\n </mat-slide-toggle>\n </div>\n </div>\n </mat-expansion-panel>\n </section>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class Tt extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=new Map([[v.FROM,"tb.rulenode.del-relation-direction-from"],[v.TO,"tb.rulenode.del-relation-direction-to"]]),this.entityTypeNamePatternTranslation=new Map([[C.DEVICE,"tb.rulenode.device-name-pattern"],[C.ASSET,"tb.rulenode.asset-name-pattern"],[C.ENTITY_VIEW,"tb.rulenode.entity-view-name-pattern"],[C.CUSTOMER,"tb.rulenode.customer-title-pattern"],[C.USER,"tb.rulenode.user-name-pattern"],[C.DASHBOARD,"tb.rulenode.dashboard-name-pattern"],[C.EDGE,"tb.rulenode.edge-name-pattern"]]),this.entityType=C,this.allowedEntityTypes=[C.DEVICE,C.ASSET,C.ENTITY_VIEW,C.TENANT,C.CUSTOMER,C.USER,C.DASHBOARD,C.EDGE]}configForm(){return this.deleteRelationConfigForm}onConfigurationSet(e){this.deleteRelationConfigForm=this.fb.group({deleteForSingleEntity:[!!e&&e.deleteForSingleEntity,[]],direction:[e?e.direction:null,[_.required]],entityType:[e?e.entityType:null,[]],entityNamePattern:[e?e.entityNamePattern:null,[]],relationType:[e?e.relationType:null,[_.required]]})}validatorTriggers(){return["deleteForSingleEntity","entityType"]}updateValidators(e){const t=this.deleteRelationConfigForm.get("deleteForSingleEntity").value,n=this.deleteRelationConfigForm.get("entityType").value;t?this.deleteRelationConfigForm.get("entityType").setValidators([_.required]):this.deleteRelationConfigForm.get("entityType").setValidators([]),t&&n&&n!==C.TENANT?this.deleteRelationConfigForm.get("entityNamePattern").setValidators([_.required,_.pattern(/.*\S.*/)]):this.deleteRelationConfigForm.get("entityNamePattern").setValidators([]),this.deleteRelationConfigForm.get("entityType").updateValueAndValidity({emitEvent:!1}),this.deleteRelationConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e})}prepareOutputConfig(e){return e.entityNamePattern=e.entityNamePattern?e.entityNamePattern.trim():null,e}}e("DeleteRelationConfigComponent",Tt),Tt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tt,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Tt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Tt,selector:"tb-action-node-delete-relation-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="deleteRelationConfigForm" class="tb-form-panel no-padding no-border">\n <div class="tb-form-panel stroked no-padding-bottom">\n <div class="tb-form-panel-title" translate>tb.rulenode.relation-parameters</div>\n <div fxLayout="column">\n <mat-form-field class="mat-block" hideRequiredMarker>\n <mat-label translate>relation.direction</mat-label>\n <mat-select required matInput formControlName="direction">\n <mat-option *ngFor="let type of directionTypes" [value]="type">\n {{ directionTypeTranslations.get(type) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <tb-relation-type-autocomplete\n required\n formControlName="relationType">\n </tb-relation-type-autocomplete>\n </div>\n </div>\n <div class="tb-form-panel stroked">\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.delete-relation-with-specific-entity-hint\' | translate }}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="deleteForSingleEntity">\n {{ \'tb.rulenode.delete-relation-with-specific-entity\' | translate }}\n </mat-slide-toggle>\n </div>\n <div *ngIf="deleteRelationConfigForm.get(\'deleteForSingleEntity\').value">\n <div fxLayout="row" fxLayoutGap="10px">\n <tb-entity-type-select\n fxFlex\n showLabel\n required\n [allowedEntityTypes]="allowedEntityTypes"\n formControlName="entityType">\n </tb-entity-type-select>\n <mat-form-field *ngIf="deleteRelationConfigForm.get(\'entityType\').value && deleteRelationConfigForm.get(\'entityType\').value !== entityType.TENANT"\n fxFlex class="mat-block">\n <mat-label>{{ entityTypeNamePatternTranslation.get(deleteRelationConfigForm.get(\'entityType\').value) | translate }}</mat-label>\n <input required matInput formControlName="entityNamePattern">\n </mat-form-field>\n </div>\n <tb-example-hint *ngIf="deleteRelationConfigForm.get(\'entityType\').value && deleteRelationConfigForm.get(\'entityType\').value !== entityType.TENANT"\n [hintText]="\'tb.rulenode.kv-map-single-pattern-hint\'"></tb-example-hint>\n </div>\n </div>\n</section>\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ne.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled","additionEntityTypes"]},{kind:"component",type:qe.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:ht,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tt,decorators:[{type:n,args:[{selector:"tb-action-node-delete-relation-config",template:'<section [formGroup]="deleteRelationConfigForm" class="tb-form-panel no-padding no-border">\n <div class="tb-form-panel stroked no-padding-bottom">\n <div class="tb-form-panel-title" translate>tb.rulenode.relation-parameters</div>\n <div fxLayout="column">\n <mat-form-field class="mat-block" hideRequiredMarker>\n <mat-label translate>relation.direction</mat-label>\n <mat-select required matInput formControlName="direction">\n <mat-option *ngFor="let type of directionTypes" [value]="type">\n {{ directionTypeTranslations.get(type) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <tb-relation-type-autocomplete\n required\n formControlName="relationType">\n </tb-relation-type-autocomplete>\n </div>\n </div>\n <div class="tb-form-panel stroked">\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.delete-relation-with-specific-entity-hint\' | translate }}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="deleteForSingleEntity">\n {{ \'tb.rulenode.delete-relation-with-specific-entity\' | translate }}\n </mat-slide-toggle>\n </div>\n <div *ngIf="deleteRelationConfigForm.get(\'deleteForSingleEntity\').value">\n <div fxLayout="row" fxLayoutGap="10px">\n <tb-entity-type-select\n fxFlex\n showLabel\n required\n [allowedEntityTypes]="allowedEntityTypes"\n formControlName="entityType">\n </tb-entity-type-select>\n <mat-form-field *ngIf="deleteRelationConfigForm.get(\'entityType\').value && deleteRelationConfigForm.get(\'entityType\').value !== entityType.TENANT"\n fxFlex class="mat-block">\n <mat-label>{{ entityTypeNamePatternTranslation.get(deleteRelationConfigForm.get(\'entityType\').value) | translate }}</mat-label>\n <input required matInput formControlName="entityNamePattern">\n </mat-form-field>\n </div>\n <tb-example-hint *ngIf="deleteRelationConfigForm.get(\'entityType\').value && deleteRelationConfigForm.get(\'entityType\').value !== entityType.TENANT"\n [hintText]="\'tb.rulenode.kv-map-single-pattern-hint\'"></tb-example-hint>\n </div>\n </div>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class Lt extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.deviceProfile}onConfigurationSet(e){this.deviceProfile=this.fb.group({persistAlarmRulesState:[!!e&&e.persistAlarmRulesState],fetchAlarmRulesStateOnStart:[!!e&&e.fetchAlarmRulesStateOnStart]})}validatorTriggers(){return["persistAlarmRulesState"]}updateValidators(e){this.deviceProfile.get("persistAlarmRulesState").value?this.deviceProfile.get("fetchAlarmRulesStateOnStart").enable({emitEvent:!1}):(this.deviceProfile.get("fetchAlarmRulesStateOnStart").setValue(!1,{emitEvent:!1}),this.deviceProfile.get("fetchAlarmRulesStateOnStart").disable({emitEvent:!1})),this.deviceProfile.get("fetchAlarmRulesStateOnStart").updateValueAndValidity({emitEvent:e})}}e("DeviceProfileConfigComponent",Lt),Lt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lt,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Lt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Lt,selector:"tb-device-profile-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="deviceProfile" class="tb-form-panel stroked">\n <div class="tb-form-hint tb-primary-fill" translate>tb.rulenode.device-profile-node-hint</div>\n <div tb-hint-tooltip-icon="{{\'tb.rulenode.persist-alarm-rules-hint\' | translate }}"\n class="tb-form-row no-border no-padding slide-toggle">\n <mat-slide-toggle class="mat-slide" formControlName="persistAlarmRulesState">\n {{ \'tb.rulenode.persist-alarm-rules\' | translate }}\n </mat-slide-toggle>\n </div>\n <div tb-hint-tooltip-icon="{{\'tb.rulenode.fetch-alarm-rules-hint\' | translate }}"\n class="tb-form-row no-border no-padding slide-toggle">\n <mat-slide-toggle class="mat-slide" formControlName="fetchAlarmRulesStateOnStart">\n {{ \'tb.rulenode.fetch-alarm-rules\' | translate }}\n </mat-slide-toggle>\n </div>\n</section>\n',dependencies:[{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lt,decorators:[{type:n,args:[{selector:"tb-device-profile-config",template:'<section [formGroup]="deviceProfile" class="tb-form-panel stroked">\n <div class="tb-form-hint tb-primary-fill" translate>tb.rulenode.device-profile-node-hint</div>\n <div tb-hint-tooltip-icon="{{\'tb.rulenode.persist-alarm-rules-hint\' | translate }}"\n class="tb-form-row no-border no-padding slide-toggle">\n <mat-slide-toggle class="mat-slide" formControlName="persistAlarmRulesState">\n {{ \'tb.rulenode.persist-alarm-rules\' | translate }}\n </mat-slide-toggle>\n </div>\n <div tb-hint-tooltip-icon="{{\'tb.rulenode.fetch-alarm-rules-hint\' | translate }}"\n class="tb-form-row no-border no-padding slide-toggle">\n <mat-slide-toggle class="mat-slide" formControlName="fetchAlarmRulesStateOnStart">\n {{ \'tb.rulenode.fetch-alarm-rules\' | translate }}\n </mat-slide-toggle>\n </div>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class It extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ge(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.allowedEntityTypes=[C.DEVICE,C.ASSET,C.ENTITY_VIEW,C.CUSTOMER,C.USER,C.DASHBOARD,F.CURRENT_TENANT],this.additionEntityTypes={CURRENT_RULE_NODE:this.translate.instant("tb.rulenode.current-rule-node")},this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-generator-function"}configForm(){return this.generatorConfigForm}onConfigurationSet(e){this.generatorConfigForm=this.fb.group({msgCount:[e?e.msgCount:null,[_.required,_.min(0)]],periodInSeconds:[e?e.periodInSeconds:null,[_.required,_.min(1)]],originator:[e?e.originator:null,[]],scriptLang:[e?e.scriptLang:b.JS,[_.required]],jsScript:[e?e.jsScript:null,[]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.generatorConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.generatorConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.generatorConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.generatorConfigForm.get("jsScript").setValidators(t===b.JS?[_.required]:[]),this.generatorConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.generatorConfigForm.get("tbelScript").setValidators(t===b.TBEL?[_.required]:[]),this.generatorConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS),e.originatorId&&e.originatorType?e.originator={id:e.originatorId,entityType:e.originatorType}:e.originator=null,delete e.originatorId,delete e.originatorType),e}prepareOutputConfig(e){return e.originator?(e.originatorId=e.originator.id,e.originatorType=e.originator.entityType):(e.originatorId=null,e.originatorType=null),delete e.originator,e}testScript(e){const t=this.generatorConfigForm.get("scriptLang").value,n=t===b.JS?"jsScript":"tbelScript",r=t===b.JS?"rulenode/generator_node_script_fn":"rulenode/tbel/generator_node_script_fn",o=this.generatorConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"generate",this.translate.instant("tb.rulenode.generator"),"Generate",["prevMsg","prevMetadata","prevMsgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.generatorConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.generatorConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}var St;e("GeneratorConfigComponent",It),It.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:It,deps:[{token:R.Store},{token:O.UntypedFormBuilder},{token:fe.NodeScriptTestService},{token:X.TranslateService}],target:t.ɵɵFactoryTarget.Component}),It.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:It,selector:"tb-action-node-generator-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'<section [formGroup]="generatorConfigForm" class="tb-form-panel no-border no-padding">\n <div class="tb-form-panel no-padding-bottom stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.generation-parameters</div>\n <div class="tb-form-row no-border no-padding tb-standard-fields column-xs">\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.message-count</mat-label>\n <input required type="number" min="0" step="1" matInput formControlName="msgCount">\n <mat-error *ngIf="generatorConfigForm.get(\'msgCount\').hasError(\'required\')">\n {{ \'tb.rulenode.message-count-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="generatorConfigForm.get(\'msgCount\').hasError(\'min\')">\n {{ \'tb.rulenode.min-message-count-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.period-seconds</mat-label>\n <input required type="number" min="1" step="1" matInput formControlName="periodInSeconds">\n <mat-error *ngIf="generatorConfigForm.get(\'periodInSeconds\').hasError(\'required\')">\n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="generatorConfigForm.get(\'periodInSeconds\').hasError(\'min\')">\n {{ \'tb.rulenode.min-period-seconds-message\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n </div>\n\n <div class="tb-form-panel no-padding-bottom stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.originator</div>\n <tb-entity-select fxFlex\n required="true"\n useAliasEntityTypes="true"\n [allowedEntityTypes]="allowedEntityTypes"\n [additionEntityTypes]="additionEntityTypes"\n formControlName="originator">\n </tb-entity-select>\n </div>\n <div class="tb-form-panel no-padding-bottom stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.generator-function</div>\n <tb-js-func *ngIf="generatorConfigForm.get(\'scriptLang\').value === scriptLanguage.JS"\n #jsFuncComponent\n formControlName="jsScript"\n functionName="Generate"\n [functionArgs]="[\'prevMsg\', \'prevMetadata\', \'prevMsgType\']"\n helpId="rulenode/generator_node_script_fn"\n noValidate="true">\n <tb-toggle-select toolbarPrefixButton formControlName="scriptLang" appearance="fill" *ngIf="tbelEnabled">\n <tb-toggle-option [value]="scriptLanguage.TBEL">\n {{ \'tb.rulenode.script-lang-tbel\' | translate }}\n </tb-toggle-option>\n <tb-toggle-option [value]="scriptLanguage.JS">\n {{ \'tb.rulenode.script-lang-js\' | translate }}\n </tb-toggle-option>\n </tb-toggle-select>\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <tb-js-func *ngIf="generatorConfigForm.get(\'scriptLang\').value === scriptLanguage.TBEL"\n #tbelFuncComponent\n formControlName="tbelScript"\n functionName="Generate"\n [functionArgs]="[\'prevMsg\', \'prevMetadata\', \'prevMsgType\']"\n [disableUndefinedCheck]="true"\n [scriptLanguage]="scriptLanguage.TBEL"\n helpId="rulenode/tbel/generator_node_script_fn"\n noValidate="true">\n <tb-toggle-select toolbarPrefixButton formControlName="scriptLang" appearance="fill">\n <tb-toggle-option [value]="scriptLanguage.TBEL">\n {{ \'tb.rulenode.script-lang-tbel\' | translate }}\n </tb-toggle-option>\n <tb-toggle-option [value]="scriptLanguage.JS">\n {{ \'tb.rulenode.script-lang-js\' | translate }}\n </tb-toggle-option>\n </tb-toggle-select>\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <div fxLayout="row" style="padding-bottom: 16px;">\n <button mat-button mat-raised-button color="primary" (click)="testScript()">\n {{ testScriptLabel | translate }}\n </button>\n </div>\n </div>\n</section>\n',styles:[":host ::ng-deep .mat-button-toggle-group{min-width:120px;height:24px!important}:host ::ng-deep .mat-button-toggle-group .mat-button-toggle{font-size:0}:host ::ng-deep .mat-button-toggle-group .mat-button-toggle .mat-button-toggle-button{height:20px!important;line-height:20px!important;border:none!important}:host ::ng-deep .mat-button-toggle-group .mat-button-toggle .mat-button-toggle-button .mat-button-toggle-label-content{font-size:14px!important;line-height:20px!important}@media screen and (min-width: 599px){:host ::ng-deep .tb-entity-select{display:flex;flex-direction:row;gap:16px}}:host ::ng-deep .tb-entity-select tb-entity-type-select{flex:1}:host ::ng-deep .tb-entity-select tb-entity-autocomplete{flex:1}:host ::ng-deep .tb-entity-select tb-entity-autocomplete mat-form-field{width:100%!important}\n"],dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ae.EntitySelectComponent,selector:"tb-entity-select",inputs:["allowedEntityTypes","useAliasEntityTypes","required","disabled","additionEntityTypes"]},{kind:"component",type:Ce.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","propertyHighlightRules","objectHighlightRules","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:ee.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Me.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Ee.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination","fillHeight","extraPadding","primaryBackground"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:It,decorators:[{type:n,args:[{selector:"tb-action-node-generator-config",template:'<section [formGroup]="generatorConfigForm" class="tb-form-panel no-border no-padding">\n <div class="tb-form-panel no-padding-bottom stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.generation-parameters</div>\n <div class="tb-form-row no-border no-padding tb-standard-fields column-xs">\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.message-count</mat-label>\n <input required type="number" min="0" step="1" matInput formControlName="msgCount">\n <mat-error *ngIf="generatorConfigForm.get(\'msgCount\').hasError(\'required\')">\n {{ \'tb.rulenode.message-count-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="generatorConfigForm.get(\'msgCount\').hasError(\'min\')">\n {{ \'tb.rulenode.min-message-count-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.period-seconds</mat-label>\n <input required type="number" min="1" step="1" matInput formControlName="periodInSeconds">\n <mat-error *ngIf="generatorConfigForm.get(\'periodInSeconds\').hasError(\'required\')">\n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="generatorConfigForm.get(\'periodInSeconds\').hasError(\'min\')">\n {{ \'tb.rulenode.min-period-seconds-message\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n </div>\n\n <div class="tb-form-panel no-padding-bottom stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.originator</div>\n <tb-entity-select fxFlex\n required="true"\n useAliasEntityTypes="true"\n [allowedEntityTypes]="allowedEntityTypes"\n [additionEntityTypes]="additionEntityTypes"\n formControlName="originator">\n </tb-entity-select>\n </div>\n <div class="tb-form-panel no-padding-bottom stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.generator-function</div>\n <tb-js-func *ngIf="generatorConfigForm.get(\'scriptLang\').value === scriptLanguage.JS"\n #jsFuncComponent\n formControlName="jsScript"\n functionName="Generate"\n [functionArgs]="[\'prevMsg\', \'prevMetadata\', \'prevMsgType\']"\n helpId="rulenode/generator_node_script_fn"\n noValidate="true">\n <tb-toggle-select toolbarPrefixButton formControlName="scriptLang" appearance="fill" *ngIf="tbelEnabled">\n <tb-toggle-option [value]="scriptLanguage.TBEL">\n {{ \'tb.rulenode.script-lang-tbel\' | translate }}\n </tb-toggle-option>\n <tb-toggle-option [value]="scriptLanguage.JS">\n {{ \'tb.rulenode.script-lang-js\' | translate }}\n </tb-toggle-option>\n </tb-toggle-select>\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <tb-js-func *ngIf="generatorConfigForm.get(\'scriptLang\').value === scriptLanguage.TBEL"\n #tbelFuncComponent\n formControlName="tbelScript"\n functionName="Generate"\n [functionArgs]="[\'prevMsg\', \'prevMetadata\', \'prevMsgType\']"\n [disableUndefinedCheck]="true"\n [scriptLanguage]="scriptLanguage.TBEL"\n helpId="rulenode/tbel/generator_node_script_fn"\n noValidate="true">\n <tb-toggle-select toolbarPrefixButton formControlName="scriptLang" appearance="fill">\n <tb-toggle-option [value]="scriptLanguage.TBEL">\n {{ \'tb.rulenode.script-lang-tbel\' | translate }}\n </tb-toggle-option>\n <tb-toggle-option [value]="scriptLanguage.JS">\n {{ \'tb.rulenode.script-lang-js\' | translate }}\n </tb-toggle-option>\n </tb-toggle-select>\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <div fxLayout="row" style="padding-bottom: 16px;">\n <button mat-button mat-raised-button color="primary" (click)="testScript()">\n {{ testScriptLabel | translate }}\n </button>\n </div>\n </div>\n</section>\n',styles:[":host ::ng-deep .mat-button-toggle-group{min-width:120px;height:24px!important}:host ::ng-deep .mat-button-toggle-group .mat-button-toggle{font-size:0}:host ::ng-deep .mat-button-toggle-group .mat-button-toggle .mat-button-toggle-button{height:20px!important;line-height:20px!important;border:none!important}:host ::ng-deep .mat-button-toggle-group .mat-button-toggle .mat-button-toggle-button .mat-button-toggle-label-content{font-size:14px!important;line-height:20px!important}@media screen and (min-width: 599px){:host ::ng-deep .tb-entity-select{display:flex;flex-direction:row;gap:16px}}:host ::ng-deep .tb-entity-select tb-entity-type-select{flex:1}:host ::ng-deep .tb-entity-select tb-entity-autocomplete{flex:1}:host ::ng-deep .tb-entity-select tb-entity-autocomplete mat-form-field{width:100%!important}\n"]}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder},{type:fe.NodeScriptTestService},{type:X.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}}),function(e){e.CUSTOMER="CUSTOMER",e.TENANT="TENANT",e.RELATED="RELATED",e.ALARM_ORIGINATOR="ALARM_ORIGINATOR",e.ENTITY="ENTITY"}(St||(St={}));const Nt=new Map([[St.CUSTOMER,"tb.rulenode.originator-customer"],[St.TENANT,"tb.rulenode.originator-tenant"],[St.RELATED,"tb.rulenode.originator-related"],[St.ALARM_ORIGINATOR,"tb.rulenode.originator-alarm-originator"],[St.ENTITY,"tb.rulenode.originator-entity"]]),qt=new Map([[St.CUSTOMER,"tb.rulenode.originator-customer-desc"],[St.TENANT,"tb.rulenode.originator-tenant-desc"],[St.RELATED,"tb.rulenode.originator-related-entity-desc"],[St.ALARM_ORIGINATOR,"tb.rulenode.originator-alarm-originator-desc"],[St.ENTITY,"tb.rulenode.originator-entity-by-name-pattern-desc"]]),At=[k.createdTime,k.name,{value:"type",name:"tb.rulenode.profile-name",keyName:"originatorProfileName"},k.firstName,k.lastName,k.email,k.title,k.country,k.state,k.city,k.address,k.address2,k.zip,k.phone,k.label,{value:"id",name:"tb.rulenode.id",keyName:"id"},{value:"additionalInfo",name:"tb.rulenode.additional-info",keyName:"additionalInfo"}],Mt=new Map([["type","profileName"],["createdTime","createdTime"],["name","name"],["firstName","firstName"],["lastName","lastName"],["email","email"],["title","title"],["country","country"],["state","state"],["city","city"],["address","address"],["address2","address2"],["zip","zip"],["phone","phone"],["label","label"],["id","id"],["additionalInfo","additionalInfo"]]);var Et;!function(e){e.CIRCLE="CIRCLE",e.POLYGON="POLYGON"}(Et||(Et={}));const wt=new Map([[Et.CIRCLE,"tb.rulenode.perimeter-circle"],[Et.POLYGON,"tb.rulenode.perimeter-polygon"]]);var Gt;!function(e){e.MILLISECONDS="MILLISECONDS",e.SECONDS="SECONDS",e.MINUTES="MINUTES",e.HOURS="HOURS",e.DAYS="DAYS"}(Gt||(Gt={}));const Dt=new Map([[Gt.MILLISECONDS,"tb.rulenode.time-unit-milliseconds"],[Gt.SECONDS,"tb.rulenode.time-unit-seconds"],[Gt.MINUTES,"tb.rulenode.time-unit-minutes"],[Gt.HOURS,"tb.rulenode.time-unit-hours"],[Gt.DAYS,"tb.rulenode.time-unit-days"]]);var Vt;!function(e){e.METER="METER",e.KILOMETER="KILOMETER",e.FOOT="FOOT",e.MILE="MILE",e.NAUTICAL_MILE="NAUTICAL_MILE"}(Vt||(Vt={}));const Pt=new Map([[Vt.METER,"tb.rulenode.range-unit-meter"],[Vt.KILOMETER,"tb.rulenode.range-unit-kilometer"],[Vt.FOOT,"tb.rulenode.range-unit-foot"],[Vt.MILE,"tb.rulenode.range-unit-mile"],[Vt.NAUTICAL_MILE,"tb.rulenode.range-unit-nautical-mile"]]);var Rt;!function(e){e.ID="ID",e.TITLE="TITLE",e.COUNTRY="COUNTRY",e.STATE="STATE",e.CITY="CITY",e.ZIP="ZIP",e.ADDRESS="ADDRESS",e.ADDRESS2="ADDRESS2",e.PHONE="PHONE",e.EMAIL="EMAIL",e.ADDITIONAL_INFO="ADDITIONAL_INFO"}(Rt||(Rt={}));const Ot=new Map([[Rt.ID,"tb.rulenode.entity-details-id"],[Rt.TITLE,"tb.rulenode.entity-details-title"],[Rt.COUNTRY,"tb.rulenode.entity-details-country"],[Rt.STATE,"tb.rulenode.entity-details-state"],[Rt.CITY,"tb.rulenode.entity-details-city"],[Rt.ZIP,"tb.rulenode.entity-details-zip"],[Rt.ADDRESS,"tb.rulenode.entity-details-address"],[Rt.ADDRESS2,"tb.rulenode.entity-details-address2"],[Rt.PHONE,"tb.rulenode.entity-details-phone"],[Rt.EMAIL,"tb.rulenode.entity-details-email"],[Rt.ADDITIONAL_INFO,"tb.rulenode.entity-details-additional_info"]]);var _t;!function(e){e.FIRST="FIRST",e.LAST="LAST",e.ALL="ALL"}(_t||(_t={}));const Bt=new Map([[_t.FIRST,"tb.rulenode.first"],[_t.LAST,"tb.rulenode.last"],[_t.ALL,"tb.rulenode.all"]]),Kt=new Map([[_t.FIRST,"tb.rulenode.first-mode-hint"],[_t.LAST,"tb.rulenode.last-mode-hint"],[_t.ALL,"tb.rulenode.all-mode-hint"]]);var Ht,zt;!function(e){e.ASC="ASC",e.DESC="DESC"}(Ht||(Ht={})),function(e){e.ATTRIBUTES="ATTRIBUTES",e.LATEST_TELEMETRY="LATEST_TELEMETRY",e.FIELDS="FIELDS"}(zt||(zt={}));const Ut=new Map([[zt.ATTRIBUTES,"tb.rulenode.attributes"],[zt.LATEST_TELEMETRY,"tb.rulenode.latest-telemetry"],[zt.FIELDS,"tb.rulenode.fields"]]),jt=new Map([[zt.ATTRIBUTES,"tb.rulenode.add-mapped-attribute-to"],[zt.LATEST_TELEMETRY,"tb.rulenode.add-mapped-latest-telemetry-to"],[zt.FIELDS,"tb.rulenode.add-mapped-fields-to"]]),$t=new Map([[Ht.ASC,"tb.rulenode.ascending"],[Ht.DESC,"tb.rulenode.descending"]]);var Jt;!function(e){e.STANDARD="STANDARD",e.FIFO="FIFO"}(Jt||(Jt={}));const Qt=new Map([[Jt.STANDARD,"tb.rulenode.sqs-queue-standard"],[Jt.FIFO,"tb.rulenode.sqs-queue-fifo"]]),Yt=["anonymous","basic","cert.PEM"],Wt=new Map([["anonymous","tb.rulenode.credentials-anonymous"],["basic","tb.rulenode.credentials-basic"],["cert.PEM","tb.rulenode.credentials-pem"]]),Zt=["sas","cert.PEM"],Xt=new Map([["sas","tb.rulenode.credentials-sas"],["cert.PEM","tb.rulenode.credentials-pem"]]);var en;!function(e){e.GET="GET",e.POST="POST",e.PUT="PUT",e.DELETE="DELETE"}(en||(en={}));const tn=["US-ASCII","ISO-8859-1","UTF-8","UTF-16BE","UTF-16LE","UTF-16"],nn=new Map([["US-ASCII","tb.rulenode.charset-us-ascii"],["ISO-8859-1","tb.rulenode.charset-iso-8859-1"],["UTF-8","tb.rulenode.charset-utf-8"],["UTF-16BE","tb.rulenode.charset-utf-16be"],["UTF-16LE","tb.rulenode.charset-utf-16le"],["UTF-16","tb.rulenode.charset-utf-16"]]);var rn;!function(e){e.CUSTOM="CUSTOM",e.ADD="ADD",e.SUB="SUB",e.MULT="MULT",e.DIV="DIV",e.SIN="SIN",e.SINH="SINH",e.COS="COS",e.COSH="COSH",e.TAN="TAN",e.TANH="TANH",e.ACOS="ACOS",e.ASIN="ASIN",e.ATAN="ATAN",e.ATAN2="ATAN2",e.EXP="EXP",e.EXPM1="EXPM1",e.SQRT="SQRT",e.CBRT="CBRT",e.GET_EXP="GET_EXP",e.HYPOT="HYPOT",e.LOG="LOG",e.LOG10="LOG10",e.LOG1P="LOG1P",e.CEIL="CEIL",e.FLOOR="FLOOR",e.FLOOR_DIV="FLOOR_DIV",e.FLOOR_MOD="FLOOR_MOD",e.ABS="ABS",e.MIN="MIN",e.MAX="MAX",e.POW="POW",e.SIGNUM="SIGNUM",e.RAD="RAD",e.DEG="DEG"}(rn||(rn={}));const on=new Map([[rn.CUSTOM,{value:rn.CUSTOM,name:"Custom Function",description:"Use this function to specify complex mathematical expression.",minArgs:1,maxArgs:16}],[rn.ADD,{value:rn.ADD,name:"Addition",description:"x + y",minArgs:2,maxArgs:2}],[rn.SUB,{value:rn.SUB,name:"Subtraction",description:"x - y",minArgs:2,maxArgs:2}],[rn.MULT,{value:rn.MULT,name:"Multiplication",description:"x * y",minArgs:2,maxArgs:2}],[rn.DIV,{value:rn.DIV,name:"Division",description:"x / y",minArgs:2,maxArgs:2}],[rn.SIN,{value:rn.SIN,name:"Sine",description:"Returns the trigonometric sine of an angle in radians.",minArgs:1,maxArgs:1}],[rn.SINH,{value:rn.SINH,name:"Hyperbolic sine",description:"Returns the hyperbolic sine of an argument.",minArgs:1,maxArgs:1}],[rn.COS,{value:rn.COS,name:"Cosine",description:"Returns the trigonometric cosine of an angle in radians.",minArgs:1,maxArgs:1}],[rn.COSH,{value:rn.COSH,name:"Hyperbolic cosine",description:"Returns the hyperbolic cosine of an argument.",minArgs:1,maxArgs:1}],[rn.TAN,{value:rn.TAN,name:"Tangent",description:"Returns the trigonometric tangent of an angle in radians",minArgs:1,maxArgs:1}],[rn.TANH,{value:rn.TANH,name:"Hyperbolic tangent",description:"Returns the hyperbolic tangent of an argument",minArgs:1,maxArgs:1}],[rn.ACOS,{value:rn.ACOS,name:"Arc cosine",description:"Returns the arc cosine of an argument",minArgs:1,maxArgs:1}],[rn.ASIN,{value:rn.ASIN,name:"Arc sine",description:"Returns the arc sine of an argument",minArgs:1,maxArgs:1}],[rn.ATAN,{value:rn.ATAN,name:"Arc tangent",description:"Returns the arc tangent of an argument",minArgs:1,maxArgs:1}],[rn.ATAN2,{value:rn.ATAN2,name:"2-argument arc tangent",description:"Returns the angle theta from the conversion of rectangular coordinates (x, y) to polar coordinates (r, theta)",minArgs:2,maxArgs:2}],[rn.EXP,{value:rn.EXP,name:"Exponential",description:"Returns Euler's number e raised to the power of an argument",minArgs:1,maxArgs:1}],[rn.EXPM1,{value:rn.EXPM1,name:"Exponential minus one",description:"Returns Euler's number e raised to the power of an argument minus one",minArgs:1,maxArgs:1}],[rn.SQRT,{value:rn.SQRT,name:"Square",description:"Returns the correctly rounded positive square root of an argument",minArgs:1,maxArgs:1}],[rn.CBRT,{value:rn.CBRT,name:"Cube root",description:"Returns the cube root of an argument",minArgs:1,maxArgs:1}],[rn.GET_EXP,{value:rn.GET_EXP,name:"Get exponent",description:"Returns the unbiased exponent used in the representation of an argument",minArgs:1,maxArgs:1}],[rn.HYPOT,{value:rn.HYPOT,name:"Square root",description:"Returns the square root of the squares of the arguments",minArgs:2,maxArgs:2}],[rn.LOG,{value:rn.LOG,name:"Logarithm",description:"Returns the natural logarithm of an argument",minArgs:1,maxArgs:1}],[rn.LOG10,{value:rn.LOG10,name:"Base 10 logarithm",description:"Returns the base 10 logarithm of an argument",minArgs:1,maxArgs:1}],[rn.LOG1P,{value:rn.LOG1P,name:"Logarithm of the sum",description:"Returns the natural logarithm of the sum of an argument",minArgs:1,maxArgs:1}],[rn.CEIL,{value:rn.CEIL,name:"Ceiling",description:"Returns the smallest (closest to negative infinity) of an argument",minArgs:1,maxArgs:1}],[rn.FLOOR,{value:rn.FLOOR,name:"Floor",description:"Returns the largest (closest to positive infinity) of an argument",minArgs:1,maxArgs:1}],[rn.FLOOR_DIV,{value:rn.FLOOR_DIV,name:"Floor division",description:"Returns the largest (closest to positive infinity) of the arguments",minArgs:2,maxArgs:2}],[rn.FLOOR_MOD,{value:rn.FLOOR_MOD,name:"Floor modulus",description:"Returns the floor modulus of the arguments",minArgs:2,maxArgs:2}],[rn.ABS,{value:rn.ABS,name:"Absolute",description:"Returns the absolute value of an argument",minArgs:1,maxArgs:1}],[rn.MIN,{value:rn.MIN,name:"Min",description:"Returns the smaller of the arguments",minArgs:2,maxArgs:2}],[rn.MAX,{value:rn.MAX,name:"Max",description:"Returns the greater of the arguments",minArgs:2,maxArgs:2}],[rn.POW,{value:rn.POW,name:"Raise to a power",description:"Returns the value of the first argument raised to the power of the second argument",minArgs:2,maxArgs:2}],[rn.SIGNUM,{value:rn.SIGNUM,name:"Sign of a real number",description:"Returns the signum function of the argument",minArgs:1,maxArgs:1}],[rn.RAD,{value:rn.RAD,name:"Radian",description:"Converts an angle measured in degrees to an approximately equivalent angle measured in radians",minArgs:1,maxArgs:1}],[rn.DEG,{value:rn.DEG,name:"Degrees",description:"Converts an angle measured in radians to an approximately equivalent angle measured in degrees.",minArgs:1,maxArgs:1}]]);var an,ln,sn;!function(e){e.MESSAGE_BODY="MESSAGE_BODY",e.MESSAGE_METADATA="MESSAGE_METADATA",e.ATTRIBUTE="ATTRIBUTE",e.TIME_SERIES="TIME_SERIES",e.CONSTANT="CONSTANT"}(an||(an={})),function(e){e.MESSAGE_BODY="MESSAGE_BODY",e.MESSAGE_METADATA="MESSAGE_METADATA",e.ATTRIBUTE="ATTRIBUTE",e.TIME_SERIES="TIME_SERIES"}(ln||(ln={})),function(e){e.DATA="DATA",e.METADATA="METADATA"}(sn||(sn={}));const mn=new Map([[sn.DATA,"tb.rulenode.message-to-metadata"],[sn.METADATA,"tb.rulenode.metadata-to-message"]]),pn=(new Map([[sn.DATA,"tb.rulenode.from-message"],[sn.METADATA,"tb.rulenode.from-metadata"]]),new Map([[sn.DATA,"tb.rulenode.message"],[sn.METADATA,"tb.rulenode.metadata"]])),dn=new Map([[sn.DATA,"tb.rulenode.message"],[sn.METADATA,"tb.rulenode.message-metadata"]]),un=new Map([[an.MESSAGE_BODY,{name:"tb.rulenode.message-body-type",description:"Fetch argument value from incoming message"}],[an.MESSAGE_METADATA,{name:"tb.rulenode.message-metadata-type",description:"Fetch argument value from incoming message metadata"}],[an.ATTRIBUTE,{name:"tb.rulenode.attribute-type",description:"Fetch attribute value from database"}],[an.TIME_SERIES,{name:"tb.rulenode.time-series-type",description:"Fetch latest time-series value from database"}],[an.CONSTANT,{name:"tb.rulenode.constant-type",description:"Define constant value"}]]),cn=new Map([[ln.MESSAGE_BODY,{name:"tb.rulenode.message-body-type",description:"Add result to the outgoing message"}],[ln.MESSAGE_METADATA,{name:"tb.rulenode.message-metadata-type",description:"Add result to the outgoing message metadata"}],[ln.ATTRIBUTE,{name:"tb.rulenode.attribute-type",description:"Store result as an entity attribute in the database"}],[ln.TIME_SERIES,{name:"tb.rulenode.time-series-type",description:"Store result as an entity time-series in the database"}]]),gn=["x","y","z","a","b","c","d","k","l","m","n","o","p","r","s","t"];var fn,yn;!function(e){e.SHARED_SCOPE="SHARED_SCOPE",e.SERVER_SCOPE="SERVER_SCOPE",e.CLIENT_SCOPE="CLIENT_SCOPE"}(fn||(fn={})),function(e){e.SHARED_SCOPE="SHARED_SCOPE",e.SERVER_SCOPE="SERVER_SCOPE"}(yn||(yn={}));const bn=new Map([[fn.SHARED_SCOPE,"tb.rulenode.shared-scope"],[fn.SERVER_SCOPE,"tb.rulenode.server-scope"],[fn.CLIENT_SCOPE,"tb.rulenode.client-scope"]]);var xn;!function(e){e.ON_FIRST_MESSAGE="ON_FIRST_MESSAGE",e.ON_EACH_MESSAGE="ON_EACH_MESSAGE"}(xn||(xn={}));const hn=new Map([[xn.ON_EACH_MESSAGE,{value:!0,name:"tb.rulenode.presence-monitoring-strategy-on-each-message"}],[xn.ON_FIRST_MESSAGE,{value:!1,name:"tb.rulenode.presence-monitoring-strategy-on-first-message"}]]);class vn extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.perimeterType=Et,this.perimeterTypes=Object.keys(Et),this.perimeterTypeTranslationMap=wt,this.rangeUnits=Object.keys(Vt),this.rangeUnitTranslationMap=Pt,this.presenceMonitoringStrategies=hn,this.presenceMonitoringStrategyKeys=Array.from(this.presenceMonitoringStrategies.keys()),this.timeUnits=Object.keys(Gt),this.timeUnitsTranslationMap=Dt,this.defaultPaddingEnable=!0}configForm(){return this.geoActionConfigForm}onConfigurationSet(e){this.geoActionConfigForm=this.fb.group({reportPresenceStatusOnEachMessage:[!e||e.reportPresenceStatusOnEachMessage,[_.required]],latitudeKeyName:[e?e.latitudeKeyName:null,[_.required]],longitudeKeyName:[e?e.longitudeKeyName:null,[_.required]],perimeterType:[e?e.perimeterType:null,[_.required]],fetchPerimeterInfoFromMessageMetadata:[!!e&&e.fetchPerimeterInfoFromMessageMetadata,[]],perimeterKeyName:[e?e.perimeterKeyName:null,[]],centerLatitude:[e?e.centerLatitude:null,[]],centerLongitude:[e?e.centerLatitude:null,[]],range:[e?e.range:null,[]],rangeUnit:[e?e.rangeUnit:null,[]],polygonsDefinition:[e?e.polygonsDefinition:null,[]],minInsideDuration:[e?e.minInsideDuration:null,[_.required,_.min(1),_.max(2147483647)]],minInsideDurationTimeUnit:[e?e.minInsideDurationTimeUnit:null,[_.required]],minOutsideDuration:[e?e.minOutsideDuration:null,[_.required,_.min(1),_.max(2147483647)]],minOutsideDurationTimeUnit:[e?e.minOutsideDurationTimeUnit:null,[_.required]]})}validatorTriggers(){return["fetchPerimeterInfoFromMessageMetadata","perimeterType"]}updateValidators(e){const t=this.geoActionConfigForm.get("fetchPerimeterInfoFromMessageMetadata").value,n=this.geoActionConfigForm.get("perimeterType").value;t?this.geoActionConfigForm.get("perimeterKeyName").setValidators([_.required]):this.geoActionConfigForm.get("perimeterKeyName").setValidators([]),t||n!==Et.CIRCLE?(this.geoActionConfigForm.get("centerLatitude").setValidators([]),this.geoActionConfigForm.get("centerLongitude").setValidators([]),this.geoActionConfigForm.get("range").setValidators([]),this.geoActionConfigForm.get("rangeUnit").setValidators([]),this.defaultPaddingEnable=!0):(this.geoActionConfigForm.get("centerLatitude").setValidators([_.required,_.min(-90),_.max(90)]),this.geoActionConfigForm.get("centerLongitude").setValidators([_.required,_.min(-180),_.max(180)]),this.geoActionConfigForm.get("range").setValidators([_.required,_.min(0)]),this.geoActionConfigForm.get("rangeUnit").setValidators([_.required]),this.defaultPaddingEnable=!1),t||n!==Et.POLYGON?this.geoActionConfigForm.get("polygonsDefinition").setValidators([]):this.geoActionConfigForm.get("polygonsDefinition").setValidators([_.required]),this.geoActionConfigForm.get("perimeterKeyName").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("centerLatitude").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("centerLongitude").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("range").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("rangeUnit").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("polygonsDefinition").updateValueAndValidity({emitEvent:e})}}e("GpsGeoActionConfigComponent",vn),vn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vn,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),vn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:vn,selector:"tb-action-node-gps-geofencing-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="geoActionConfigForm" class="tb-form-panel no-border no-padding">\n <section class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.coordinate-field-names</div>\n <section>\n <div fxLayout="row" fxLayoutGap="16px">\n <mat-form-field fxFlex="50" class="mat-block">\n <mat-label>{{ \'tb.rulenode.latitude-field-name\' | translate }}</mat-label>\n <input matInput formControlName="latitudeKeyName" required>\n <mat-error *ngIf="geoActionConfigForm.get(\'latitudeKeyName\').hasError(\'required\')">\n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex="50" class="mat-block">\n <mat-label>{{ \'tb.rulenode.longitude-field-name\' | translate }}</mat-label>\n <input matInput formControlName="longitudeKeyName" required>\n <mat-error *ngIf="geoActionConfigForm.get(\'longitudeKeyName\').hasError(\'required\')">\n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <div class="tb-form-hint tb-primary-fill" translate>tb.rulenode.coordinate-field-hint</div>\n </section>\n </section>\n <section class="tb-form-panel stroked" [class.no-padding-bottom]="!defaultPaddingEnable">\n <div class="tb-form-panel-title" translate>tb.rulenode.geofence-configuration</div>\n <section fxLayout="column">\n <mat-form-field fxFlex class="mat-block" hideRequiredMarker>\n <mat-label>{{ \'tb.rulenode.perimeter-type\' | translate }}</mat-label>\n <mat-select formControlName="perimeterType">\n <mat-option *ngFor="let type of perimeterTypes" [value]="type">\n {{ perimeterTypeTranslationMap.get(type) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <div tb-hint-tooltip-icon="{{ geoActionConfigForm.get(\'perimeterType\').value === perimeterType.CIRCLE\n ? (\'tb.rulenode.fetch-circle-parameter-info-from-metadata-hint\'\n | translate : { perimeterKeyName: geoActionConfigForm.get(\'perimeterKeyName\').valid\n ? geoActionConfigForm.get(\'perimeterKeyName\').value\n : \'ss_perimeter\'})\n : (\'tb.rulenode.fetch-poligon-parameter-info-from-metadata-hint\'\n | translate : { perimeterKeyName: geoActionConfigForm.get(\'perimeterKeyName\').valid\n ? geoActionConfigForm.get(\'perimeterKeyName\').value\n : \'ss_perimeter\'}) }}"\n class="tb-form-row no-border no-padding slide-toggle">\n <mat-slide-toggle class="mat-slide" formControlName="fetchPerimeterInfoFromMessageMetadata">\n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n </mat-slide-toggle>\n </div>\n <mat-form-field *ngIf="geoActionConfigForm.get(\'fetchPerimeterInfoFromMessageMetadata\').value" class="mat-block">\n <mat-label>{{ \'tb.rulenode.perimeter-key-name\' | translate }}</mat-label>\n <input matInput formControlName="perimeterKeyName" required>\n <mat-error *ngIf="geoActionConfigForm.get(\'perimeterKeyName\').hasError(\'required\')">\n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n </mat-error>\n <mat-hint>{{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}</mat-hint>\n </mat-form-field>\n <div fxLayout="column"\n *ngIf="geoActionConfigForm.get(\'perimeterType\').value === perimeterType.CIRCLE &&\n !geoActionConfigForm.get(\'fetchPerimeterInfoFromMessageMetadata\').value">\n <div fxLayout="row" fxLayoutGap="16px">\n <mat-form-field fxFlex>\n <mat-label>{{ \'tb.rulenode.circle-center-latitude\' | translate }}</mat-label>\n <input type="number" min="-90" max="90" step="0.1" matInput formControlName="centerLatitude" required>\n <mat-error *ngIf="geoActionConfigForm.get(\'centerLatitude\').hasError(\'required\')">\n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex>\n <mat-label>{{ \'tb.rulenode.circle-center-longitude\' | translate }}</mat-label>\n <input type="number" min="-180" max="180" step="0.1" matInput formControlName="centerLongitude" required>\n <mat-error *ngIf="geoActionConfigForm.get(\'centerLongitude\').hasError(\'required\')">\n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <div fxLayout="row" fxLayoutGap="16px">\n <mat-form-field fxFlex>\n <mat-label>{{ \'tb.rulenode.range\' | translate }}</mat-label>\n <input type="number" min="0" step="0.1" matInput formControlName="range" required>\n <mat-error *ngIf="geoActionConfigForm.get(\'range\').hasError(\'required\')">\n {{ \'tb.rulenode.range-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex>\n <mat-label>{{ \'tb.rulenode.range-units\' | translate }}</mat-label>\n <mat-select formControlName="rangeUnit" required>\n <mat-option *ngFor="let type of rangeUnits" [value]="type">\n {{ rangeUnitTranslationMap.get(type) | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf="geoActionConfigForm.get(\'rangeUnit\').hasError(\'required\')">\n {{ \'tb.rulenode.range-units-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n </div>\n <div fxLayout="column" *ngIf="geoActionConfigForm.get(\'perimeterType\').value === perimeterType.POLYGON &&\n !geoActionConfigForm.get(\'fetchPerimeterInfoFromMessageMetadata\').value">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.polygon-definition</mat-label>\n <input matInput formControlName="polygonsDefinition" required>\n <mat-icon matSuffix class="margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.polygon-definition-hint\' | translate }}">\n help\n </mat-icon>\n <mat-error *ngIf="geoActionConfigForm.get(\'polygonsDefinition\').hasError(\'required\')">\n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n </section>\n </section>\n <section class="tb-form-panel stroked no-padding-bottom">\n <div fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap.lt-md="16px" fxLayoutAlign="space-between">\n <div class="tb-form-panel-title">{{ \'tb.rulenode.presence-monitoring-strategy\' | translate }}</div>\n <tb-toggle-select class="fetch-to-data-toggle" formControlName="reportPresenceStatusOnEachMessage" appearance="fill" >\n <tb-toggle-option *ngFor="let strategy of presenceMonitoringStrategyKeys" [value]="presenceMonitoringStrategies.get(strategy).value">\n {{ presenceMonitoringStrategies.get(strategy).name | translate }}\n </tb-toggle-option>\n </tb-toggle-select>\n </div>\n <div class="tb-form-hint tb-primary-fill"> {{ geoActionConfigForm.get(\'reportPresenceStatusOnEachMessage\').value === false ?\n (\'tb.rulenode.presence-monitoring-strategy-on-first-message-hint\' | translate) :\n (\'tb.rulenode.presence-monitoring-strategy-on-each-message-hint\' | translate) }}\n </div>\n <section fxLayout="column">\n <div *ngIf="geoActionConfigForm.get(\'reportPresenceStatusOnEachMessage\').value === false">\n <div fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap.gt-sm="8px">\n <mat-form-field fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.min-inside-duration</mat-label>\n <input type="number" step="1" min="1" max="2147483647" matInput formControlName="minInsideDuration" required>\n <mat-error *ngIf="geoActionConfigForm.get(\'minInsideDuration\').hasError(\'required\')">\n {{ \'tb.rulenode.min-inside-duration-value-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="geoActionConfigForm.get(\'minInsideDuration\').hasError(\'min\')">\n {{ \'tb.rulenode.time-value-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="geoActionConfigForm.get(\'minInsideDuration\').hasError(\'max\')">\n {{ \'tb.rulenode.time-value-range\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.min-inside-duration-time-unit</mat-label>\n <mat-select formControlName="minInsideDurationTimeUnit" required>\n <mat-option *ngFor="let timeUnit of timeUnits" [value]="timeUnit">\n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap.gt-sm="8px">\n <mat-form-field fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.min-outside-duration</mat-label>\n <input type="number" step="1" min="1" max="2147483647" matInput formControlName="minOutsideDuration" required>\n <mat-error *ngIf="geoActionConfigForm.get(\'minOutsideDuration\').hasError(\'required\')">\n {{ \'tb.rulenode.min-outside-duration-value-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="geoActionConfigForm.get(\'minOutsideDuration\').hasError(\'min\')">\n {{ \'tb.rulenode.time-value-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="geoActionConfigForm.get(\'minOutsideDuration\').hasError(\'max\')">\n {{ \'tb.rulenode.time-value-range\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.min-outside-duration-time-unit</mat-label>\n <mat-select formControlName="minOutsideDurationTimeUnit" required>\n <mat-option *ngFor="let timeUnit of timeUnits" [value]="timeUnit">\n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n </div>\n </section>\n </section>\n</section>\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Me.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Ee.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination","fillHeight","extraPadding","primaryBackground"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vn,decorators:[{type:n,args:[{selector:"tb-action-node-gps-geofencing-config",template:'<section [formGroup]="geoActionConfigForm" class="tb-form-panel no-border no-padding">\n <section class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.coordinate-field-names</div>\n <section>\n <div fxLayout="row" fxLayoutGap="16px">\n <mat-form-field fxFlex="50" class="mat-block">\n <mat-label>{{ \'tb.rulenode.latitude-field-name\' | translate }}</mat-label>\n <input matInput formControlName="latitudeKeyName" required>\n <mat-error *ngIf="geoActionConfigForm.get(\'latitudeKeyName\').hasError(\'required\')">\n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex="50" class="mat-block">\n <mat-label>{{ \'tb.rulenode.longitude-field-name\' | translate }}</mat-label>\n <input matInput formControlName="longitudeKeyName" required>\n <mat-error *ngIf="geoActionConfigForm.get(\'longitudeKeyName\').hasError(\'required\')">\n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <div class="tb-form-hint tb-primary-fill" translate>tb.rulenode.coordinate-field-hint</div>\n </section>\n </section>\n <section class="tb-form-panel stroked" [class.no-padding-bottom]="!defaultPaddingEnable">\n <div class="tb-form-panel-title" translate>tb.rulenode.geofence-configuration</div>\n <section fxLayout="column">\n <mat-form-field fxFlex class="mat-block" hideRequiredMarker>\n <mat-label>{{ \'tb.rulenode.perimeter-type\' | translate }}</mat-label>\n <mat-select formControlName="perimeterType">\n <mat-option *ngFor="let type of perimeterTypes" [value]="type">\n {{ perimeterTypeTranslationMap.get(type) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <div tb-hint-tooltip-icon="{{ geoActionConfigForm.get(\'perimeterType\').value === perimeterType.CIRCLE\n ? (\'tb.rulenode.fetch-circle-parameter-info-from-metadata-hint\'\n | translate : { perimeterKeyName: geoActionConfigForm.get(\'perimeterKeyName\').valid\n ? geoActionConfigForm.get(\'perimeterKeyName\').value\n : \'ss_perimeter\'})\n : (\'tb.rulenode.fetch-poligon-parameter-info-from-metadata-hint\'\n | translate : { perimeterKeyName: geoActionConfigForm.get(\'perimeterKeyName\').valid\n ? geoActionConfigForm.get(\'perimeterKeyName\').value\n : \'ss_perimeter\'}) }}"\n class="tb-form-row no-border no-padding slide-toggle">\n <mat-slide-toggle class="mat-slide" formControlName="fetchPerimeterInfoFromMessageMetadata">\n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n </mat-slide-toggle>\n </div>\n <mat-form-field *ngIf="geoActionConfigForm.get(\'fetchPerimeterInfoFromMessageMetadata\').value" class="mat-block">\n <mat-label>{{ \'tb.rulenode.perimeter-key-name\' | translate }}</mat-label>\n <input matInput formControlName="perimeterKeyName" required>\n <mat-error *ngIf="geoActionConfigForm.get(\'perimeterKeyName\').hasError(\'required\')">\n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n </mat-error>\n <mat-hint>{{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}</mat-hint>\n </mat-form-field>\n <div fxLayout="column"\n *ngIf="geoActionConfigForm.get(\'perimeterType\').value === perimeterType.CIRCLE &&\n !geoActionConfigForm.get(\'fetchPerimeterInfoFromMessageMetadata\').value">\n <div fxLayout="row" fxLayoutGap="16px">\n <mat-form-field fxFlex>\n <mat-label>{{ \'tb.rulenode.circle-center-latitude\' | translate }}</mat-label>\n <input type="number" min="-90" max="90" step="0.1" matInput formControlName="centerLatitude" required>\n <mat-error *ngIf="geoActionConfigForm.get(\'centerLatitude\').hasError(\'required\')">\n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex>\n <mat-label>{{ \'tb.rulenode.circle-center-longitude\' | translate }}</mat-label>\n <input type="number" min="-180" max="180" step="0.1" matInput formControlName="centerLongitude" required>\n <mat-error *ngIf="geoActionConfigForm.get(\'centerLongitude\').hasError(\'required\')">\n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <div fxLayout="row" fxLayoutGap="16px">\n <mat-form-field fxFlex>\n <mat-label>{{ \'tb.rulenode.range\' | translate }}</mat-label>\n <input type="number" min="0" step="0.1" matInput formControlName="range" required>\n <mat-error *ngIf="geoActionConfigForm.get(\'range\').hasError(\'required\')">\n {{ \'tb.rulenode.range-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex>\n <mat-label>{{ \'tb.rulenode.range-units\' | translate }}</mat-label>\n <mat-select formControlName="rangeUnit" required>\n <mat-option *ngFor="let type of rangeUnits" [value]="type">\n {{ rangeUnitTranslationMap.get(type) | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf="geoActionConfigForm.get(\'rangeUnit\').hasError(\'required\')">\n {{ \'tb.rulenode.range-units-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n </div>\n <div fxLayout="column" *ngIf="geoActionConfigForm.get(\'perimeterType\').value === perimeterType.POLYGON &&\n !geoActionConfigForm.get(\'fetchPerimeterInfoFromMessageMetadata\').value">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.polygon-definition</mat-label>\n <input matInput formControlName="polygonsDefinition" required>\n <mat-icon matSuffix class="margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.polygon-definition-hint\' | translate }}">\n help\n </mat-icon>\n <mat-error *ngIf="geoActionConfigForm.get(\'polygonsDefinition\').hasError(\'required\')">\n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n </section>\n </section>\n <section class="tb-form-panel stroked no-padding-bottom">\n <div fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap.lt-md="16px" fxLayoutAlign="space-between">\n <div class="tb-form-panel-title">{{ \'tb.rulenode.presence-monitoring-strategy\' | translate }}</div>\n <tb-toggle-select class="fetch-to-data-toggle" formControlName="reportPresenceStatusOnEachMessage" appearance="fill" >\n <tb-toggle-option *ngFor="let strategy of presenceMonitoringStrategyKeys" [value]="presenceMonitoringStrategies.get(strategy).value">\n {{ presenceMonitoringStrategies.get(strategy).name | translate }}\n </tb-toggle-option>\n </tb-toggle-select>\n </div>\n <div class="tb-form-hint tb-primary-fill"> {{ geoActionConfigForm.get(\'reportPresenceStatusOnEachMessage\').value === false ?\n (\'tb.rulenode.presence-monitoring-strategy-on-first-message-hint\' | translate) :\n (\'tb.rulenode.presence-monitoring-strategy-on-each-message-hint\' | translate) }}\n </div>\n <section fxLayout="column">\n <div *ngIf="geoActionConfigForm.get(\'reportPresenceStatusOnEachMessage\').value === false">\n <div fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap.gt-sm="8px">\n <mat-form-field fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.min-inside-duration</mat-label>\n <input type="number" step="1" min="1" max="2147483647" matInput formControlName="minInsideDuration" required>\n <mat-error *ngIf="geoActionConfigForm.get(\'minInsideDuration\').hasError(\'required\')">\n {{ \'tb.rulenode.min-inside-duration-value-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="geoActionConfigForm.get(\'minInsideDuration\').hasError(\'min\')">\n {{ \'tb.rulenode.time-value-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="geoActionConfigForm.get(\'minInsideDuration\').hasError(\'max\')">\n {{ \'tb.rulenode.time-value-range\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.min-inside-duration-time-unit</mat-label>\n <mat-select formControlName="minInsideDurationTimeUnit" required>\n <mat-option *ngFor="let timeUnit of timeUnits" [value]="timeUnit">\n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap.gt-sm="8px">\n <mat-form-field fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.min-outside-duration</mat-label>\n <input type="number" step="1" min="1" max="2147483647" matInput formControlName="minOutsideDuration" required>\n <mat-error *ngIf="geoActionConfigForm.get(\'minOutsideDuration\').hasError(\'required\')">\n {{ \'tb.rulenode.min-outside-duration-value-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="geoActionConfigForm.get(\'minOutsideDuration\').hasError(\'min\')">\n {{ \'tb.rulenode.time-value-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="geoActionConfigForm.get(\'minOutsideDuration\').hasError(\'max\')">\n {{ \'tb.rulenode.time-value-range\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.min-outside-duration-time-unit</mat-label>\n <mat-select formControlName="minOutsideDurationTimeUnit" required>\n <mat-option *ngFor="let timeUnit of timeUnits" [value]="timeUnit">\n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n </div>\n </section>\n </section>\n</section>\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class Cn extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ge(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-to-string-function"}configForm(){return this.logConfigForm}onConfigurationSet(e){this.logConfigForm=this.fb.group({scriptLang:[e?e.scriptLang:b.JS,[_.required]],jsScript:[e?e.jsScript:null,[]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.logConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.logConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.logConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.logConfigForm.get("jsScript").setValidators(t===b.JS?[_.required]:[]),this.logConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.logConfigForm.get("tbelScript").setValidators(t===b.TBEL?[_.required]:[]),this.logConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),e}testScript(e){const t=this.logConfigForm.get("scriptLang").value,n=t===b.JS?"jsScript":"tbelScript",r=t===b.JS?"rulenode/log_node_script_fn":"rulenode/tbel/log_node_script_fn",o=this.logConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"string",this.translate.instant("tb.rulenode.to-string"),"ToString",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.logConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.logConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}e("LogConfigComponent",Cn),Cn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cn,deps:[{token:R.Store},{token:O.UntypedFormBuilder},{token:fe.NodeScriptTestService},{token:X.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Cn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Cn,selector:"tb-action-node-log-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'<section [formGroup]="logConfigForm" fxLayout="column">\n <tb-script-lang formControlName="scriptLang" *ngIf="tbelEnabled"></tb-script-lang>\n <tb-js-func *ngIf="logConfigForm.get(\'scriptLang\').value === scriptLanguage.JS"\n #jsFuncComponent\n formControlName="jsScript"\n functionName="ToString"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n helpId="rulenode/log_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <tb-js-func *ngIf="logConfigForm.get(\'scriptLang\').value === scriptLanguage.TBEL"\n #tbelFuncComponent\n formControlName="tbelScript"\n functionName="ToString"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n [disableUndefinedCheck]="true"\n [scriptLanguage]="scriptLanguage.TBEL"\n helpId="rulenode/tbel/log_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <div fxLayout="row">\n <button mat-button mat-raised-button color="primary" (click)="testScript()">\n {{ testScriptLabel | translate }}\n </button>\n </div>\n</section>\n',dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ce.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","propertyHighlightRules","objectHighlightRules","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:ee.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cn,decorators:[{type:n,args:[{selector:"tb-action-node-log-config",template:'<section [formGroup]="logConfigForm" fxLayout="column">\n <tb-script-lang formControlName="scriptLang" *ngIf="tbelEnabled"></tb-script-lang>\n <tb-js-func *ngIf="logConfigForm.get(\'scriptLang\').value === scriptLanguage.JS"\n #jsFuncComponent\n formControlName="jsScript"\n functionName="ToString"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n helpId="rulenode/log_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <tb-js-func *ngIf="logConfigForm.get(\'scriptLang\').value === scriptLanguage.TBEL"\n #tbelFuncComponent\n formControlName="tbelScript"\n functionName="ToString"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n [disableUndefinedCheck]="true"\n [scriptLanguage]="scriptLanguage.TBEL"\n helpId="rulenode/tbel/log_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <div fxLayout="row">\n <button mat-button mat-raised-button color="primary" (click)="testScript()">\n {{ testScriptLabel | translate }}\n </button>\n </div>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder},{type:fe.NodeScriptTestService},{type:X.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}});class Fn extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.msgCountConfigForm}onConfigurationSet(e){this.msgCountConfigForm=this.fb.group({interval:[e?e.interval:null,[_.required,_.min(1)]],telemetryPrefix:[e?e.telemetryPrefix:null,[_.required]]})}}e("MsgCountConfigComponent",Fn),Fn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fn,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Fn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Fn,selector:"tb-action-node-msg-count-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="msgCountConfigForm" fxLayout="column">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.interval-seconds</mat-label>\n <input required type="number" min="1" step="1" matInput formControlName="interval">\n <mat-error *ngIf="msgCountConfigForm.get(\'interval\').hasError(\'required\')">\n {{ \'tb.rulenode.interval-seconds-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="msgCountConfigForm.get(\'interval\').hasError(\'min\')">\n {{ \'tb.rulenode.min-interval-seconds-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.output-timeseries-key-prefix</mat-label>\n <input required matInput formControlName="telemetryPrefix">\n <mat-error *ngIf="msgCountConfigForm.get(\'telemetryPrefix\').hasError(\'required\')">\n {{ \'tb.rulenode.output-timeseries-key-prefix-required\' | translate }}\n </mat-error>\n </mat-form-field>\n</section>\n',dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fn,decorators:[{type:n,args:[{selector:"tb-action-node-msg-count-config",template:'<section [formGroup]="msgCountConfigForm" fxLayout="column">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.interval-seconds</mat-label>\n <input required type="number" min="1" step="1" matInput formControlName="interval">\n <mat-error *ngIf="msgCountConfigForm.get(\'interval\').hasError(\'required\')">\n {{ \'tb.rulenode.interval-seconds-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="msgCountConfigForm.get(\'interval\').hasError(\'min\')">\n {{ \'tb.rulenode.min-interval-seconds-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.output-timeseries-key-prefix</mat-label>\n <input required matInput formControlName="telemetryPrefix">\n <mat-error *ngIf="msgCountConfigForm.get(\'telemetryPrefix\').hasError(\'required\')">\n {{ \'tb.rulenode.output-timeseries-key-prefix-required\' | translate }}\n </mat-error>\n </mat-form-field>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class kn extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.msgDelayConfigForm}onConfigurationSet(e){this.msgDelayConfigForm=this.fb.group({useMetadataPeriodInSecondsPatterns:[!!e&&e.useMetadataPeriodInSecondsPatterns,[]],periodInSeconds:[e?e.periodInSeconds:null,[]],periodInSecondsPattern:[e?e.periodInSecondsPattern:null,[]],maxPendingMsgs:[e?e.maxPendingMsgs:null,[_.required,_.min(1),_.max(1e5)]]})}validatorTriggers(){return["useMetadataPeriodInSecondsPatterns"]}updateValidators(e){this.msgDelayConfigForm.get("useMetadataPeriodInSecondsPatterns").value?(this.msgDelayConfigForm.get("periodInSecondsPattern").setValidators([_.required]),this.msgDelayConfigForm.get("periodInSeconds").setValidators([])):(this.msgDelayConfigForm.get("periodInSecondsPattern").setValidators([]),this.msgDelayConfigForm.get("periodInSeconds").setValidators([_.required,_.min(0)])),this.msgDelayConfigForm.get("periodInSecondsPattern").updateValueAndValidity({emitEvent:e}),this.msgDelayConfigForm.get("periodInSeconds").updateValueAndValidity({emitEvent:e})}}e("MsgDelayConfigComponent",kn),kn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kn,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),kn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:kn,selector:"tb-action-node-msg-delay-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="msgDelayConfigForm" fxLayout="column">\n <mat-checkbox formControlName="useMetadataPeriodInSecondsPatterns">\n {{ \'tb.rulenode.use-metadata-period-in-seconds-patterns\' | translate }}\n </mat-checkbox>\n <div class="tb-hint" translate>tb.rulenode.use-metadata-period-in-seconds-patterns-hint</div>\n <mat-form-field *ngIf="msgDelayConfigForm.get(\'useMetadataPeriodInSecondsPatterns\').value !== true; else periodInSecondsPattern"\n class="mat-block">\n <mat-label translate>tb.rulenode.period-seconds</mat-label>\n <input required type="number" min="0" step="1" matInput formControlName="periodInSeconds">\n <mat-error *ngIf="msgDelayConfigForm.get(\'periodInSeconds\').hasError(\'required\')">\n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="msgDelayConfigForm.get(\'periodInSeconds\').hasError(\'min\')">\n {{ \'tb.rulenode.min-period-0-seconds-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <ng-template #periodInSecondsPattern>\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.period-in-seconds-pattern</mat-label>\n <input required matInput formControlName="periodInSecondsPattern">\n <mat-error *ngIf="msgDelayConfigForm.get(\'periodInSecondsPattern\').hasError(\'required\')">\n {{ \'tb.rulenode.period-in-seconds-pattern-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n </ng-template>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.max-pending-messages</mat-label>\n <input required type="number" min="1" max="100000" step="1" matInput formControlName="maxPendingMsgs">\n <mat-error *ngIf="msgDelayConfigForm.get(\'maxPendingMsgs\').hasError(\'required\')">\n {{ \'tb.rulenode.max-pending-messages-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="msgDelayConfigForm.get(\'maxPendingMsgs\').hasError(\'min\')">\n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="msgDelayConfigForm.get(\'maxPendingMsgs\').hasError(\'max\')">\n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n </mat-error>\n </mat-form-field>\n</section>\n',dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ie.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kn,decorators:[{type:n,args:[{selector:"tb-action-node-msg-delay-config",template:'<section [formGroup]="msgDelayConfigForm" fxLayout="column">\n <mat-checkbox formControlName="useMetadataPeriodInSecondsPatterns">\n {{ \'tb.rulenode.use-metadata-period-in-seconds-patterns\' | translate }}\n </mat-checkbox>\n <div class="tb-hint" translate>tb.rulenode.use-metadata-period-in-seconds-patterns-hint</div>\n <mat-form-field *ngIf="msgDelayConfigForm.get(\'useMetadataPeriodInSecondsPatterns\').value !== true; else periodInSecondsPattern"\n class="mat-block">\n <mat-label translate>tb.rulenode.period-seconds</mat-label>\n <input required type="number" min="0" step="1" matInput formControlName="periodInSeconds">\n <mat-error *ngIf="msgDelayConfigForm.get(\'periodInSeconds\').hasError(\'required\')">\n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="msgDelayConfigForm.get(\'periodInSeconds\').hasError(\'min\')">\n {{ \'tb.rulenode.min-period-0-seconds-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <ng-template #periodInSecondsPattern>\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.period-in-seconds-pattern</mat-label>\n <input required matInput formControlName="periodInSecondsPattern">\n <mat-error *ngIf="msgDelayConfigForm.get(\'periodInSecondsPattern\').hasError(\'required\')">\n {{ \'tb.rulenode.period-in-seconds-pattern-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n </ng-template>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.max-pending-messages</mat-label>\n <input required type="number" min="1" max="100000" step="1" matInput formControlName="maxPendingMsgs">\n <mat-error *ngIf="msgDelayConfigForm.get(\'maxPendingMsgs\').hasError(\'required\')">\n {{ \'tb.rulenode.max-pending-messages-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="msgDelayConfigForm.get(\'maxPendingMsgs\').hasError(\'min\')">\n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="msgDelayConfigForm.get(\'maxPendingMsgs\').hasError(\'max\')">\n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n </mat-error>\n </mat-form-field>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class Tn extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopes=Object.keys(f),this.telemetryTypeTranslationsMap=y}configForm(){return this.pushToCloudConfigForm}onConfigurationSet(e){this.pushToCloudConfigForm=this.fb.group({scope:[e?e.scope:null,[_.required]]})}}e("PushToCloudConfigComponent",Tn),Tn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tn,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Tn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Tn,selector:"tb-action-node-push-to-cloud-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="pushToCloudConfigForm" class="tb-form-panel no-border no-padding">\n <div class="tb-form-panel stroked">\n <tb-example-hint [hintText]="\'tb.rulenode.attributes-scope-hint\'">\n </tb-example-hint>\n <div class="tb-form-row no-border no-padding tb-standard-fields">\n <mat-form-field class="flex">\n <mat-label>{{ \'tb.rulenode.attributes-scope\' | translate }}</mat-label>\n <mat-select required\n class="tb-entity-type-select" matInput formControlName="scope">\n <mat-option *ngFor="let scope of attributeScopes" [value]="scope">\n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label>{{ \'tb.rulenode.attributes-scope-value\' | translate }}</mat-label>\n <input type="text" matInput readonly disabled [ngModel]="pushToCloudConfigForm.get(\'scope\').value" [ngModelOptions]="{standalone: true}">\n <button type="button"\n matSuffix\n mat-icon-button\n aria-label="Copy"\n ngxClipboard\n [cbContent]="pushToCloudConfigForm.get(\'scope\').value"\n matTooltip="{{ \'tb.rulenode.attributes-scope-value-copy\' | translate }}">\n <mat-icon aria-hidden="false"\n aria-label="help-icon">content_copy\n </mat-icon>\n </button>\n </mat-form-field>\n </div>\n </div>\n</section>\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:ee.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:yt,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:ht,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tn,decorators:[{type:n,args:[{selector:"tb-action-node-push-to-cloud-config",template:'<section [formGroup]="pushToCloudConfigForm" class="tb-form-panel no-border no-padding">\n <div class="tb-form-panel stroked">\n <tb-example-hint [hintText]="\'tb.rulenode.attributes-scope-hint\'">\n </tb-example-hint>\n <div class="tb-form-row no-border no-padding tb-standard-fields">\n <mat-form-field class="flex">\n <mat-label>{{ \'tb.rulenode.attributes-scope\' | translate }}</mat-label>\n <mat-select required\n class="tb-entity-type-select" matInput formControlName="scope">\n <mat-option *ngFor="let scope of attributeScopes" [value]="scope">\n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label>{{ \'tb.rulenode.attributes-scope-value\' | translate }}</mat-label>\n <input type="text" matInput readonly disabled [ngModel]="pushToCloudConfigForm.get(\'scope\').value" [ngModelOptions]="{standalone: true}">\n <button type="button"\n matSuffix\n mat-icon-button\n aria-label="Copy"\n ngxClipboard\n [cbContent]="pushToCloudConfigForm.get(\'scope\').value"\n matTooltip="{{ \'tb.rulenode.attributes-scope-value-copy\' | translate }}">\n <mat-icon aria-hidden="false"\n aria-label="help-icon">content_copy\n </mat-icon>\n </button>\n </mat-form-field>\n </div>\n </div>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class Ln extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopes=Object.keys(f),this.telemetryTypeTranslationsMap=y}configForm(){return this.pushToEdgeConfigForm}onConfigurationSet(e){this.pushToEdgeConfigForm=this.fb.group({scope:[e?e.scope:null,[_.required]]})}}e("PushToEdgeConfigComponent",Ln),Ln.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ln,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Ln.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ln,selector:"tb-action-node-push-to-edge-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="pushToEdgeConfigForm" class="tb-form-panel no-border no-padding">\n <div class="tb-form-panel stroked">\n <tb-example-hint [hintText]="\'tb.rulenode.attributes-scope-hint\'">\n </tb-example-hint>\n <div class="tb-form-row no-border no-padding tb-standard-fields">\n <mat-form-field class="flex">\n <mat-label>{{ \'tb.rulenode.attributes-scope\' | translate }}</mat-label>\n <mat-select required\n class="tb-entity-type-select" matInput formControlName="scope">\n <mat-option *ngFor="let scope of attributeScopes" [value]="scope">\n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label>{{ \'tb.rulenode.attributes-scope-value\' | translate }}</mat-label>\n <input type="text" matInput readonly disabled [ngModel]="pushToEdgeConfigForm.get(\'scope\').value" [ngModelOptions]="{standalone: true}">\n <button type="button"\n matSuffix\n mat-icon-button\n aria-label="Copy"\n ngxClipboard\n [cbContent]="pushToEdgeConfigForm.get(\'scope\').value"\n matTooltip="{{ \'tb.rulenode.attributes-scope-value-copy\' | translate }}">\n <mat-icon aria-hidden="false"\n aria-label="help-icon">content_copy\n </mat-icon>\n </button>\n </mat-form-field>\n </div>\n </div>\n</section>\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:ee.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:yt,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:ht,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ln,decorators:[{type:n,args:[{selector:"tb-action-node-push-to-edge-config",template:'<section [formGroup]="pushToEdgeConfigForm" class="tb-form-panel no-border no-padding">\n <div class="tb-form-panel stroked">\n <tb-example-hint [hintText]="\'tb.rulenode.attributes-scope-hint\'">\n </tb-example-hint>\n <div class="tb-form-row no-border no-padding tb-standard-fields">\n <mat-form-field class="flex">\n <mat-label>{{ \'tb.rulenode.attributes-scope\' | translate }}</mat-label>\n <mat-select required\n class="tb-entity-type-select" matInput formControlName="scope">\n <mat-option *ngFor="let scope of attributeScopes" [value]="scope">\n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label>{{ \'tb.rulenode.attributes-scope-value\' | translate }}</mat-label>\n <input type="text" matInput readonly disabled [ngModel]="pushToEdgeConfigForm.get(\'scope\').value" [ngModelOptions]="{standalone: true}">\n <button type="button"\n matSuffix\n mat-icon-button\n aria-label="Copy"\n ngxClipboard\n [cbContent]="pushToEdgeConfigForm.get(\'scope\').value"\n matTooltip="{{ \'tb.rulenode.attributes-scope-value-copy\' | translate }}">\n <mat-icon aria-hidden="false"\n aria-label="help-icon">content_copy\n </mat-icon>\n </button>\n </mat-form-field>\n </div>\n </div>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class In extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.rpcReplyConfigForm}onConfigurationSet(e){this.rpcReplyConfigForm=this.fb.group({serviceIdMetaDataAttribute:[e?e.serviceIdMetaDataAttribute:null,[]],sessionIdMetaDataAttribute:[e?e.sessionIdMetaDataAttribute:null,[]],requestIdMetaDataAttribute:[e?e.requestIdMetaDataAttribute:null,[]]})}}e("RpcReplyConfigComponent",In),In.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:In,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),In.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:In,selector:"tb-action-node-rpc-reply-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="rpcReplyConfigForm" class="tb-form-panel stroked no-padding-bottom">\n <div class="tb-form-panel-title" translate>tb.rulenode.reply-routing-configuration</div>\n <tb-example-hint [hintText]="\'tb.rulenode.rpc-reply-routing-configuration-hint\'">\n </tb-example-hint>\n <div class="tb-form-row no-border no-padding tb-standard-fields column-xs">\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.service-id-metadata-attribute</mat-label>\n <input matInput formControlName="serviceIdMetaDataAttribute">\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.session-id-metadata-attribute</mat-label>\n <input matInput formControlName="sessionIdMetaDataAttribute">\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.request-id-metadata-attribute</mat-label>\n <input matInput formControlName="requestIdMetaDataAttribute">\n </mat-form-field>\n </div>\n</section>\n',dependencies:[{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ht,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:In,decorators:[{type:n,args:[{selector:"tb-action-node-rpc-reply-config",template:'<section [formGroup]="rpcReplyConfigForm" class="tb-form-panel stroked no-padding-bottom">\n <div class="tb-form-panel-title" translate>tb.rulenode.reply-routing-configuration</div>\n <tb-example-hint [hintText]="\'tb.rulenode.rpc-reply-routing-configuration-hint\'">\n </tb-example-hint>\n <div class="tb-form-row no-border no-padding tb-standard-fields column-xs">\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.service-id-metadata-attribute</mat-label>\n <input matInput formControlName="serviceIdMetaDataAttribute">\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.session-id-metadata-attribute</mat-label>\n <input matInput formControlName="sessionIdMetaDataAttribute">\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.request-id-metadata-attribute</mat-label>\n <input matInput formControlName="requestIdMetaDataAttribute">\n </mat-form-field>\n </div>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class Sn extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.rpcRequestConfigForm}onConfigurationSet(e){this.rpcRequestConfigForm=this.fb.group({timeoutInSeconds:[e?e.timeoutInSeconds:null,[_.required,_.min(0)]]})}}e("RpcRequestConfigComponent",Sn),Sn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sn,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Sn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Sn,selector:"tb-action-node-rpc-request-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="rpcRequestConfigForm" fxLayout="column">\n <mat-form-field fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.timeout-sec</mat-label>\n <input type="number" min="0" step="1" matInput formControlName="timeoutInSeconds" required>\n <mat-error *ngIf="rpcRequestConfigForm.get(\'timeoutInSeconds\').hasError(\'required\')">\n {{ \'tb.rulenode.timeout-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="rpcRequestConfigForm.get(\'timeoutInSeconds\').hasError(\'min\')">\n {{ \'tb.rulenode.min-timeout-message\' | translate }}\n </mat-error>\n </mat-form-field>\n</section>\n',dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sn,decorators:[{type:n,args:[{selector:"tb-action-node-rpc-request-config",template:'<section [formGroup]="rpcRequestConfigForm" fxLayout="column">\n <mat-form-field fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.timeout-sec</mat-label>\n <input type="number" min="0" step="1" matInput formControlName="timeoutInSeconds" required>\n <mat-error *ngIf="rpcRequestConfigForm.get(\'timeoutInSeconds\').hasError(\'required\')">\n {{ \'tb.rulenode.timeout-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="rpcRequestConfigForm.get(\'timeoutInSeconds\').hasError(\'min\')">\n {{ \'tb.rulenode.min-timeout-message\' | translate }}\n </mat-error>\n </mat-form-field>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class Nn extends T{get required(){return this.requiredValue}set required(e){this.requiredValue=we(e)}constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.injector=n,this.fb=r,this.propagateChange=null,this.valueChangeSubscription=null}ngOnInit(){this.ngControl=this.injector.get(B),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.kvListFormGroup=this.fb.group({}),this.kvListFormGroup.addControl("keyVals",this.fb.array([]))}keyValsFormArray(){return this.kvListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.kvListFormGroup.disable({emitEvent:!1}):this.kvListFormGroup.enable({emitEvent:!1})}writeValue(e){this.valueChangeSubscription&&this.valueChangeSubscription.unsubscribe();const t=[];if(e)for(const n of Object.keys(e))Object.prototype.hasOwnProperty.call(e,n)&&t.push(this.fb.group({key:[n,[_.required]],value:[e[n],[_.required]]}));this.kvListFormGroup.setControl("keyVals",this.fb.array(t)),this.valueChangeSubscription=this.kvListFormGroup.valueChanges.subscribe((()=>{this.updateModel()}))}removeKeyVal(e){this.kvListFormGroup.get("keyVals").removeAt(e)}addKeyVal(){this.kvListFormGroup.get("keyVals").push(this.fb.group({key:["",[_.required]],value:["",[_.required]]}))}validate(e){const t=this.kvListFormGroup.get("keyVals").value;if(!t.length&&this.required)return{kvMapRequired:!0};if(!this.kvListFormGroup.valid)return{kvFieldsRequired:!0};if(this.uniqueKeyValuePairValidator)for(const e of t)if(e.key===e.value)return{uniqueKeyValuePair:!0};return null}updateModel(){const e=this.kvListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.kvListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("KvMapConfigOldComponent",Nn),Nn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nn,deps:[{token:R.Store},{token:X.TranslateService},{token:t.Injector},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Nn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Nn,selector:"tb-kv-map-config-old",inputs:{disabled:"disabled",uniqueKeyValuePairValidator:"uniqueKeyValuePairValidator",requiredText:"requiredText",keyText:"keyText",keyRequiredText:"keyRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",required:"required"},providers:[{provide:K,useExisting:c((()=>Nn)),multi:!0},{provide:H,useExisting:c((()=>Nn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'<section fxLayout="column" class="tb-kv-map-config" [formGroup]="kvListFormGroup">\n <div class="header" fxFlex fxLayout="row" fxLayoutGap="8px">\n <span class="cell tb-required" fxFlex>{{ keyText | translate }}</span>\n <span class="cell tb-required" fxFlex>{{ valText | translate }}</span>\n <span [fxShow]="!disabled" style="width: 52px;" innerHTML="&nbsp"></span>\n </div>\n <div class="body">\n <div class="row" fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px"\n formArrayName="keyVals"\n *ngFor="let keyValControl of keyValsFormArray().controls; let $index = index">\n <mat-form-field fxFlex class="cell mat-block">\n <input [formControl]="keyValControl.get(\'key\')" matInput required\n placeholder="{{ keyText | translate }}"/>\n <mat-error *ngIf="keyValControl.get(\'key\').hasError(\'required\')">\n {{ keyRequiredText | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex class="cell mat-block">\n <input [formControl]="keyValControl.get(\'value\')" matInput required\n placeholder="{{ valText | translate }}"/>\n <mat-error *ngIf="keyValControl.get(\'value\').hasError(\'required\')">\n {{ valRequiredText | translate }}\n </mat-error>\n </mat-form-field>\n <button mat-icon-button color="primary"\n [fxShow]="!disabled"\n type="button"\n (click)="removeKeyVal($index)"\n [disabled]="isLoading$ | async"\n matTooltip="{{ \'tb.key-val.remove-entry\' | translate }}"\n matTooltipPosition="above">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n <div *ngIf="hintText" class="tb-hint" [innerHTML]="hintText | translate | safe: \'html\'"></div>\n </div>\n <tb-error [error]="ngControl.hasError(\'kvMapRequired\') || ngControl.hasError(\'uniqueKeyValuePair\') ?\n (ngControl.hasError(\'kvMapRequired\') ? translate.instant(requiredText) :\n translate.instant(\'tb.key-val.unique-key-value-pair-error\', {keyText: translate.instant(keyText),\n valText: translate.instant(valText)})) : \'\'"></tb-error>\n <div style="margin-top: 16px;">\n <button mat-button mat-raised-button color="primary"\n [fxShow]="!disabled"\n [disabled]="isLoading$ | async"\n (click)="addKeyVal()"\n type="button"\n matTooltip="{{ \'tb.key-val.add-entry\' | translate }}"\n matTooltipPosition="above">\n <mat-icon>add</mat-icon>\n {{ \'action.add\' | translate }}\n </button>\n </div>\n</section>\n',styles:[":host .tb-kv-map-config{margin-bottom:16px}:host .tb-kv-map-config .header{padding-left:5px;padding-right:5px;padding-bottom:5px}:host .tb-kv-map-config .header .cell{padding-left:5px;padding-right:5px;color:#757575;font-size:12px;font-weight:700;white-space:nowrap}:host .tb-kv-map-config .header .tb-required:after{color:#757575;font-size:12px;font-weight:700}:host .tb-kv-map-config .body{padding-left:5px;padding-right:5px;padding-bottom:0;max-height:300px;overflow:auto}:host .tb-kv-map-config .body .cell{padding-left:5px;padding-right:5px}:host .tb-kv-map-config tb-error{display:block;margin-top:-12px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ve.TbErrorComponent,selector:"tb-error",inputs:["noMargin","error"]},{kind:"component",type:ee.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:Pe.DefaultShowHideDirective,selector:" [fxShow], [fxShow.print], [fxShow.xs], [fxShow.sm], [fxShow.md], [fxShow.lg], [fxShow.xl], [fxShow.lt-sm], [fxShow.lt-md], [fxShow.lt-lg], [fxShow.lt-xl], [fxShow.gt-xs], [fxShow.gt-sm], [fxShow.gt-md], [fxShow.gt-lg], [fxHide], [fxHide.print], [fxHide.xs], [fxHide.sm], [fxHide.md], [fxHide.lg], [fxHide.xl], [fxHide.lt-sm], [fxHide.lt-md], [fxHide.lt-lg], [fxHide.lt-xl], [fxHide.gt-xs], [fxHide.gt-sm], [fxHide.gt-md], [fxHide.gt-lg]",inputs:["fxShow","fxShow.print","fxShow.xs","fxShow.sm","fxShow.md","fxShow.lg","fxShow.xl","fxShow.lt-sm","fxShow.lt-md","fxShow.lt-lg","fxShow.lt-xl","fxShow.gt-xs","fxShow.gt-sm","fxShow.gt-md","fxShow.gt-lg","fxHide","fxHide.print","fxHide.xs","fxHide.sm","fxHide.md","fxHide.lg","fxHide.xl","fxHide.lt-sm","fxHide.lt-md","fxHide.lt-lg","fxHide.lt-xl","fxHide.gt-xs","fxHide.gt-sm","fxHide.gt-md","fxHide.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormArrayName,selector:"[formArrayName]",inputs:["formArrayName"]},{kind:"pipe",type:j.AsyncPipe,name:"async"},{kind:"pipe",type:ce.SafePipe,name:"safe"},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nn,decorators:[{type:n,args:[{selector:"tb-kv-map-config-old",providers:[{provide:K,useExisting:c((()=>Nn)),multi:!0},{provide:H,useExisting:c((()=>Nn)),multi:!0}],template:'<section fxLayout="column" class="tb-kv-map-config" [formGroup]="kvListFormGroup">\n <div class="header" fxFlex fxLayout="row" fxLayoutGap="8px">\n <span class="cell tb-required" fxFlex>{{ keyText | translate }}</span>\n <span class="cell tb-required" fxFlex>{{ valText | translate }}</span>\n <span [fxShow]="!disabled" style="width: 52px;" innerHTML="&nbsp"></span>\n </div>\n <div class="body">\n <div class="row" fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px"\n formArrayName="keyVals"\n *ngFor="let keyValControl of keyValsFormArray().controls; let $index = index">\n <mat-form-field fxFlex class="cell mat-block">\n <input [formControl]="keyValControl.get(\'key\')" matInput required\n placeholder="{{ keyText | translate }}"/>\n <mat-error *ngIf="keyValControl.get(\'key\').hasError(\'required\')">\n {{ keyRequiredText | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex class="cell mat-block">\n <input [formControl]="keyValControl.get(\'value\')" matInput required\n placeholder="{{ valText | translate }}"/>\n <mat-error *ngIf="keyValControl.get(\'value\').hasError(\'required\')">\n {{ valRequiredText | translate }}\n </mat-error>\n </mat-form-field>\n <button mat-icon-button color="primary"\n [fxShow]="!disabled"\n type="button"\n (click)="removeKeyVal($index)"\n [disabled]="isLoading$ | async"\n matTooltip="{{ \'tb.key-val.remove-entry\' | translate }}"\n matTooltipPosition="above">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n <div *ngIf="hintText" class="tb-hint" [innerHTML]="hintText | translate | safe: \'html\'"></div>\n </div>\n <tb-error [error]="ngControl.hasError(\'kvMapRequired\') || ngControl.hasError(\'uniqueKeyValuePair\') ?\n (ngControl.hasError(\'kvMapRequired\') ? translate.instant(requiredText) :\n translate.instant(\'tb.key-val.unique-key-value-pair-error\', {keyText: translate.instant(keyText),\n valText: translate.instant(valText)})) : \'\'"></tb-error>\n <div style="margin-top: 16px;">\n <button mat-button mat-raised-button color="primary"\n [fxShow]="!disabled"\n [disabled]="isLoading$ | async"\n (click)="addKeyVal()"\n type="button"\n matTooltip="{{ \'tb.key-val.add-entry\' | translate }}"\n matTooltipPosition="above">\n <mat-icon>add</mat-icon>\n {{ \'action.add\' | translate }}\n </button>\n </div>\n</section>\n',styles:[":host .tb-kv-map-config{margin-bottom:16px}:host .tb-kv-map-config .header{padding-left:5px;padding-right:5px;padding-bottom:5px}:host .tb-kv-map-config .header .cell{padding-left:5px;padding-right:5px;color:#757575;font-size:12px;font-weight:700;white-space:nowrap}:host .tb-kv-map-config .header .tb-required:after{color:#757575;font-size:12px;font-weight:700}:host .tb-kv-map-config .body{padding-left:5px;padding-right:5px;padding-bottom:0;max-height:300px;overflow:auto}:host .tb-kv-map-config .body .cell{padding-left:5px;padding-right:5px}:host .tb-kv-map-config tb-error{display:block;margin-top:-12px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:X.TranslateService},{type:t.Injector},{type:O.FormBuilder}]},propDecorators:{disabled:[{type:m}],uniqueKeyValuePairValidator:[{type:m}],requiredText:[{type:m}],keyText:[{type:m}],keyRequiredText:[{type:m}],valText:[{type:m}],valRequiredText:[{type:m}],hintText:[{type:m}],required:[{type:m}]}});class qn extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.saveToCustomTableConfigForm}onConfigurationSet(e){this.saveToCustomTableConfigForm=this.fb.group({tableName:[e?e.tableName:null,[_.required,_.pattern(/.*\S.*/)]],fieldsMapping:[e?e.fieldsMapping:null,[_.required]]})}prepareOutputConfig(e){return e.tableName=e.tableName.trim(),e}}e("SaveToCustomTableConfigComponent",qn),qn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qn,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),qn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:qn,selector:"tb-action-node-custom-table-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="saveToCustomTableConfigForm" fxLayout="column">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.custom-table-name</mat-label>\n <input required matInput formControlName="tableName">\n <mat-error *ngIf="saveToCustomTableConfigForm.get(\'tableName\').hasError(\'required\') ||\n saveToCustomTableConfigForm.get(\'tableName\').hasError(\'pattern\')">\n {{ \'tb.rulenode.custom-table-name-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.custom-table-hint</mat-hint>\n </mat-form-field>\n <label translate class="tb-title tb-required">tb.rulenode.fields-mapping</label>\n <tb-kv-map-config-old\n required\n formControlName="fieldsMapping"\n requiredText="tb.rulenode.fields-mapping-required"\n keyText="tb.rulenode.message-field"\n keyRequiredText="tb.rulenode.message-field-required"\n valText="tb.rulenode.table-col"\n valRequiredText="tb.rulenode.table-col-required">\n </tb-kv-map-config-old>\n</section>\n',dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qn,decorators:[{type:n,args:[{selector:"tb-action-node-custom-table-config",template:'<section [formGroup]="saveToCustomTableConfigForm" fxLayout="column">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.custom-table-name</mat-label>\n <input required matInput formControlName="tableName">\n <mat-error *ngIf="saveToCustomTableConfigForm.get(\'tableName\').hasError(\'required\') ||\n saveToCustomTableConfigForm.get(\'tableName\').hasError(\'pattern\')">\n {{ \'tb.rulenode.custom-table-name-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.custom-table-hint</mat-hint>\n </mat-form-field>\n <label translate class="tb-title tb-required">tb.rulenode.fields-mapping</label>\n <tb-kv-map-config-old\n required\n formControlName="fieldsMapping"\n requiredText="tb.rulenode.fields-mapping-required"\n keyText="tb.rulenode.message-field"\n keyRequiredText="tb.rulenode.message-field-required"\n valText="tb.rulenode.table-col"\n valRequiredText="tb.rulenode.table-col-required">\n </tb-kv-map-config-old>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class An extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.timeseriesConfigForm}onConfigurationSet(e){this.timeseriesConfigForm=this.fb.group({defaultTTL:[e?e.defaultTTL:null,[_.required,_.min(0)]],skipLatestPersistence:[!!e&&e.skipLatestPersistence,[]],useServerTs:[!!e&&e.useServerTs,[]]})}}e("TimeseriesConfigComponent",An),An.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:An,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),An.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:An,selector:"tb-action-node-timeseries-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="timeseriesConfigForm" class="tb-form-panel no-border no-padding">\n <mat-form-field fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.default-ttl</mat-label>\n <input type="number" min="0" step="1" matInput formControlName="defaultTTL" required>\n <mat-icon class="help-icon margin-8 cursor-pointer"\n aria-hidden="false"\n aria-label="help-icon"\n matSuffix\n matTooltip="{{ \'tb.rulenode.default-ttl-hint\' | translate }}">\n help\n </mat-icon>\n <mat-error *ngIf="timeseriesConfigForm.get(\'defaultTTL\').hasError(\'required\')">\n {{ \'tb.rulenode.default-ttl-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="timeseriesConfigForm.get(\'defaultTTL\').hasError(\'min\')">\n {{ \'tb.rulenode.min-default-ttl-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <div class="tb-form-panel stroked">\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.use-server-ts-hint\' | translate}}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="useServerTs">\n {{ \'tb.rulenode.use-server-ts\' | translate }}\n </mat-slide-toggle>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.skip-latest-persistence-hint\' | translate}}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="skipLatestPersistence">\n {{ \'tb.rulenode.skip-latest-persistence\' | translate }}\n </mat-slide-toggle>\n </div>\n </div>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:An,decorators:[{type:n,args:[{selector:"tb-action-node-timeseries-config",template:'<section [formGroup]="timeseriesConfigForm" class="tb-form-panel no-border no-padding">\n <mat-form-field fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.default-ttl</mat-label>\n <input type="number" min="0" step="1" matInput formControlName="defaultTTL" required>\n <mat-icon class="help-icon margin-8 cursor-pointer"\n aria-hidden="false"\n aria-label="help-icon"\n matSuffix\n matTooltip="{{ \'tb.rulenode.default-ttl-hint\' | translate }}">\n help\n </mat-icon>\n <mat-error *ngIf="timeseriesConfigForm.get(\'defaultTTL\').hasError(\'required\')">\n {{ \'tb.rulenode.default-ttl-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="timeseriesConfigForm.get(\'defaultTTL\').hasError(\'min\')">\n {{ \'tb.rulenode.min-default-ttl-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <div class="tb-form-panel stroked">\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.use-server-ts-hint\' | translate}}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="useServerTs">\n {{ \'tb.rulenode.use-server-ts\' | translate }}\n </mat-slide-toggle>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.skip-latest-persistence-hint\' | translate}}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="skipLatestPersistence">\n {{ \'tb.rulenode.skip-latest-persistence\' | translate }}\n </mat-slide-toggle>\n </div>\n </div>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class Mn extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.unassignCustomerConfigForm}prepareInputConfig(e){return{customerNamePattern:ye(e?.customerNamePattern)?e.customerNamePattern:null,unassignFromCustomer:ye(e?.customerNamePattern)}}onConfigurationSet(e){this.unassignCustomerConfigForm=this.fb.group({customerNamePattern:[e.customerNamePattern,[]],unassignFromCustomer:[e.unassignFromCustomer,[]]})}validatorTriggers(){return["unassignFromCustomer"]}updateValidators(e){this.unassignCustomerConfigForm.get("unassignFromCustomer").value?this.unassignCustomerConfigForm.get("customerNamePattern").setValidators([_.required,_.pattern(/.*\S.*/)]):this.unassignCustomerConfigForm.get("customerNamePattern").setValidators([]),this.unassignCustomerConfigForm.get("customerNamePattern").updateValueAndValidity({emitEvent:e})}prepareOutputConfig(e){return{customerNamePattern:e.unassignFromCustomer?e.customerNamePattern.trim():null}}}e("UnassignCustomerConfigComponent",Mn),Mn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mn,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Mn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Mn,selector:"tb-action-node-un-assign-to-customer-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="unassignCustomerConfigForm" fxLayout="column">\n <div class="tb-form-panel no-padding no-border">\n\n <div class="tb-form-panel stroked" [class.no-padding-bottom]="unassignCustomerConfigForm.get(\'unassignFromCustomer\').value">\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.unassign-from-customer-tooltip\' | translate }}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="unassignFromCustomer">\n {{ \'tb.rulenode.unassign-from-customer\' | translate }}\n </mat-slide-toggle>\n </div>\n <mat-form-field class="mat-block" subscriptSizing="dynamic" *ngIf="unassignCustomerConfigForm.get(\'unassignFromCustomer\').value">\n <mat-label translate>tb.rulenode.customer-name-pattern</mat-label>\n <input required matInput formControlName="customerNamePattern">\n <mat-error *ngIf="unassignCustomerConfigForm.get(\'customerNamePattern\').hasError(\'required\') ||\n unassignCustomerConfigForm.get(\'customerNamePattern\').hasError(\'pattern\')">\n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.customer-name-pattern-hint</mat-hint>\n </mat-form-field>\n </div>\n </div>\n</section>\n',dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mn,decorators:[{type:n,args:[{selector:"tb-action-node-un-assign-to-customer-config",template:'<section [formGroup]="unassignCustomerConfigForm" fxLayout="column">\n <div class="tb-form-panel no-padding no-border">\n\n <div class="tb-form-panel stroked" [class.no-padding-bottom]="unassignCustomerConfigForm.get(\'unassignFromCustomer\').value">\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.unassign-from-customer-tooltip\' | translate }}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="unassignFromCustomer">\n {{ \'tb.rulenode.unassign-from-customer\' | translate }}\n </mat-slide-toggle>\n </div>\n <mat-form-field class="mat-block" subscriptSizing="dynamic" *ngIf="unassignCustomerConfigForm.get(\'unassignFromCustomer\').value">\n <mat-label translate>tb.rulenode.customer-name-pattern</mat-label>\n <input required matInput formControlName="customerNamePattern">\n <mat-error *ngIf="unassignCustomerConfigForm.get(\'customerNamePattern\').hasError(\'required\') ||\n unassignCustomerConfigForm.get(\'customerNamePattern\').hasError(\'pattern\')">\n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.customer-name-pattern-hint</mat-hint>\n </mat-form-field>\n </div>\n </div>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class En extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.sendRestApiCallReplyConfigForm}onConfigurationSet(e){this.sendRestApiCallReplyConfigForm=this.fb.group({requestIdMetaDataAttribute:[e?e.requestIdMetaDataAttribute:null,[]],serviceIdMetaDataAttribute:[e?e.serviceIdMetaDataAttribute:null,[]]})}}e("SendRestApiCallReplyConfigComponent",En),En.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:En,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),En.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:En,selector:"tb-action-node-send-rest-api-call-reply-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="sendRestApiCallReplyConfigForm" class="tb-form-panel stroked no-padding-bottom">\n <div class="tb-form-panel-title" translate>tb.rulenode.reply-routing-configuration</div>\n <tb-example-hint [hintText]="\'tb.rulenode.reply-routing-configuration-hint\'">\n </tb-example-hint>\n <div class="tb-form-row no-border no-padding tb-standard-fields column-xs">\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.service-id-metadata-attribute</mat-label>\n <input matInput formControlName="serviceIdMetaDataAttribute">\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.request-id-metadata-attribute</mat-label>\n <input matInput formControlName="requestIdMetaDataAttribute">\n </mat-form-field>\n </div>\n</section>\n',dependencies:[{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ht,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:En,decorators:[{type:n,args:[{selector:"tb-action-node-send-rest-api-call-reply-config",template:'<section [formGroup]="sendRestApiCallReplyConfigForm" class="tb-form-panel stroked no-padding-bottom">\n <div class="tb-form-panel-title" translate>tb.rulenode.reply-routing-configuration</div>\n <tb-example-hint [hintText]="\'tb.rulenode.reply-routing-configuration-hint\'">\n </tb-example-hint>\n <div class="tb-form-row no-border no-padding tb-standard-fields column-xs">\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.service-id-metadata-attribute</mat-label>\n <input matInput formControlName="serviceIdMetaDataAttribute">\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.request-id-metadata-attribute</mat-label>\n <input matInput formControlName="requestIdMetaDataAttribute">\n </mat-form-field>\n </div>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class wn extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopeMap=f,this.attributeScopes=Object.keys(f),this.telemetryTypeTranslationsMap=y,this.separatorKeysCodes=[ke,Te,Le]}configForm(){return this.deleteAttributesConfigForm}onConfigurationSet(e){this.deleteAttributesConfigForm=this.fb.group({scope:[e?e.scope:null,[_.required]],keys:[e?e.keys:null,[_.required]],sendAttributesDeletedNotification:[!!e&&e.sendAttributesDeletedNotification,[]],notifyDevice:[!!e&&e.notifyDevice,[]]}),this.deleteAttributesConfigForm.get("scope").valueChanges.subscribe((e=>{e!==f.SHARED_SCOPE&&this.deleteAttributesConfigForm.get("notifyDevice").patchValue(!1,{emitEvent:!1})}))}removeKey(e){const t=this.deleteAttributesConfigForm.get("keys").value,n=t.indexOf(e);n>=0&&(t.splice(n,1),this.deleteAttributesConfigForm.get("keys").patchValue(t,{emitEvent:!0}))}addKey(e){const t=e.input;let n=e.value;if((n||"").trim()){n=n.trim();let e=this.deleteAttributesConfigForm.get("keys").value;e&&-1!==e.indexOf(n)||(e||(e=[]),e.push(n),this.deleteAttributesConfigForm.get("keys").patchValue(e,{emitEvent:!0}))}t&&(t.value="")}}e("DeleteAttributesConfigComponent",wn),wn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:wn,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),wn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:wn,selector:"tb-action-node-delete-attributes-config",viewQueries:[{propertyName:"attributeChipList",first:!0,predicate:["attributeChipList"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'<section [formGroup]="deleteAttributesConfigForm" class="tb-form-panel no-border no-padding">\n <div class="tb-form-panel stroked">\n <tb-example-hint [hintText]="\'tb.rulenode.attributes-scope-hint\'">\n </tb-example-hint>\n <div class="tb-form-row no-border no-padding tb-standard-fields">\n <mat-form-field class="flex">\n <mat-label>{{ \'tb.rulenode.attributes-scope\' | translate }}</mat-label>\n <mat-select required\n class="tb-entity-type-select" matInput formControlName="scope">\n <mat-option *ngFor="let scope of attributeScopes" [value]="scope">\n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label>{{ \'tb.rulenode.attributes-scope-value\' | translate }}</mat-label>\n <input type="text" matInput readonly disabled [ngModel]="deleteAttributesConfigForm.get(\'scope\').value" [ngModelOptions]="{standalone: true}">\n <button type="button"\n matSuffix\n mat-icon-button\n aria-label="Copy"\n ngxClipboard\n [cbContent]="deleteAttributesConfigForm.get(\'scope\').value"\n matTooltip="{{ \'tb.rulenode.attributes-scope-value-copy\' | translate }}">\n <mat-icon aria-hidden="false"\n aria-label="help-icon">content_copy\n </mat-icon>\n </button>\n </mat-form-field>\n </div>\n </div>\n\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label>{{ \'tb.rulenode.attributes-keys\' | translate }}</mat-label>\n <mat-chip-grid formControlName="keys" #attributeChipList>\n <mat-chip-row\n *ngFor="let key of deleteAttributesConfigForm.get(\'keys\').value;"\n (removed)="removeKey(key)">\n {{key}}\n <mat-icon matChipRemove>close</mat-icon>\n </mat-chip-row>\n <input matInput type="text"\n [matChipInputFor]="attributeChipList"\n [matChipInputSeparatorKeyCodes]="separatorKeysCodes"\n (matChipInputTokenEnd)="addKey($event)"\n [matChipInputAddOnBlur]="true">\n </mat-chip-grid>\n <mat-error *ngIf="deleteAttributesConfigForm.get(\'keys\').hasError(\'required\')">{{ \'tb.rulenode.attributes-keys-required\' | translate }}</mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n\n <section class="tb-form-panel stroked">\n <mat-expansion-panel class="tb-settings">\n <mat-expansion-panel-header>\n <mat-panel-title translate>tb.rulenode.advanced-settings</mat-panel-title>\n </mat-expansion-panel-header>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.send-attributes-deleted-notification-hint\' | translate }}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="sendAttributesDeletedNotification">\n {{ \'tb.rulenode.send-attributes-deleted-notification\' | translate }}\n </mat-slide-toggle>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.notify-device-on-delete-hint\' | translate }}"\n *ngIf="deleteAttributesConfigForm.get(\'scope\').value === attributeScopeMap.SHARED_SCOPE"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="notifyDevice">\n {{ \'tb.rulenode.notify-device\' | translate }}\n </mat-slide-toggle>\n </div>\n </mat-expansion-panel>\n </section>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ee.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"component",type:ae.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:ae.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:ae.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"component",type:Se.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:Se.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:Se.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:Se.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:yt,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:ht,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:wn,decorators:[{type:n,args:[{selector:"tb-action-node-delete-attributes-config",template:'<section [formGroup]="deleteAttributesConfigForm" class="tb-form-panel no-border no-padding">\n <div class="tb-form-panel stroked">\n <tb-example-hint [hintText]="\'tb.rulenode.attributes-scope-hint\'">\n </tb-example-hint>\n <div class="tb-form-row no-border no-padding tb-standard-fields">\n <mat-form-field class="flex">\n <mat-label>{{ \'tb.rulenode.attributes-scope\' | translate }}</mat-label>\n <mat-select required\n class="tb-entity-type-select" matInput formControlName="scope">\n <mat-option *ngFor="let scope of attributeScopes" [value]="scope">\n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label>{{ \'tb.rulenode.attributes-scope-value\' | translate }}</mat-label>\n <input type="text" matInput readonly disabled [ngModel]="deleteAttributesConfigForm.get(\'scope\').value" [ngModelOptions]="{standalone: true}">\n <button type="button"\n matSuffix\n mat-icon-button\n aria-label="Copy"\n ngxClipboard\n [cbContent]="deleteAttributesConfigForm.get(\'scope\').value"\n matTooltip="{{ \'tb.rulenode.attributes-scope-value-copy\' | translate }}">\n <mat-icon aria-hidden="false"\n aria-label="help-icon">content_copy\n </mat-icon>\n </button>\n </mat-form-field>\n </div>\n </div>\n\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label>{{ \'tb.rulenode.attributes-keys\' | translate }}</mat-label>\n <mat-chip-grid formControlName="keys" #attributeChipList>\n <mat-chip-row\n *ngFor="let key of deleteAttributesConfigForm.get(\'keys\').value;"\n (removed)="removeKey(key)">\n {{key}}\n <mat-icon matChipRemove>close</mat-icon>\n </mat-chip-row>\n <input matInput type="text"\n [matChipInputFor]="attributeChipList"\n [matChipInputSeparatorKeyCodes]="separatorKeysCodes"\n (matChipInputTokenEnd)="addKey($event)"\n [matChipInputAddOnBlur]="true">\n </mat-chip-grid>\n <mat-error *ngIf="deleteAttributesConfigForm.get(\'keys\').hasError(\'required\')">{{ \'tb.rulenode.attributes-keys-required\' | translate }}</mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n\n <section class="tb-form-panel stroked">\n <mat-expansion-panel class="tb-settings">\n <mat-expansion-panel-header>\n <mat-panel-title translate>tb.rulenode.advanced-settings</mat-panel-title>\n </mat-expansion-panel-header>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.send-attributes-deleted-notification-hint\' | translate }}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="sendAttributesDeletedNotification">\n {{ \'tb.rulenode.send-attributes-deleted-notification\' | translate }}\n </mat-slide-toggle>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.notify-device-on-delete-hint\' | translate }}"\n *ngIf="deleteAttributesConfigForm.get(\'scope\').value === attributeScopeMap.SHARED_SCOPE"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="notifyDevice">\n {{ \'tb.rulenode.notify-device\' | translate }}\n </mat-slide-toggle>\n </div>\n </mat-expansion-panel>\n </section>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]},propDecorators:{attributeChipList:[{type:u,args:["attributeChipList"]}]}});class Gn extends T{get function(){return this.functionValue}set function(e){e&&this.functionValue!==e&&(this.functionValue=e,this.setupArgumentsFormGroup(!0))}constructor(e,t){super(e),this.store=e,this.fb=t,this.maxArgs=16,this.minArgs=1,this.displayArgumentName=!1,this.mathFunctionMap=on,this.ArgumentType=an,this.attributeScopeMap=bn,this.argumentTypeMap=un,this.arguments=Object.values(an),this.attributeScope=Object.values(fn),this.propagateChange=null,this.valueChangeSubscription=[]}ngOnInit(){this.argumentsFormGroup=this.fb.group({arguments:this.fb.array([])}),this.valueChangeSubscription.push(this.argumentsFormGroup.valueChanges.subscribe((()=>{this.updateModel()}))),this.setupArgumentsFormGroup()}onDrop(e){const t=this.argumentsFormArray,n=t.at(e.previousIndex);t.removeAt(e.previousIndex),t.insert(e.currentIndex,n),this.updateArgumentNames()}get argumentsFormArray(){return this.argumentsFormGroup.get("arguments")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.argumentsFormGroup.disable({emitEvent:!1}):(this.argumentsFormGroup.enable({emitEvent:!1}),this.argumentsFormArray.controls.forEach((e=>this.updateArgumentControlValidators(e))))}ngOnDestroy(){this.valueChangeSubscription.length&&this.valueChangeSubscription.forEach((e=>e.unsubscribe()))}writeValue(e){const t=[];e&&e.forEach(((e,n)=>{t.push(this.createArgumentControl(e,n))})),this.argumentsFormGroup.setControl("arguments",this.fb.array(t),{emitEvent:!1}),this.setupArgumentsFormGroup()}removeArgument(e){this.argumentsFormArray.removeAt(e),this.updateArgumentNames()}addArgument(e=!0){const t=this.argumentsFormArray,n=this.createArgumentControl(null,t.length);t.push(n,{emitEvent:e})}validate(e){return this.argumentsFormGroup.valid?null:{argumentsRequired:!0}}setupArgumentsFormGroup(e=!1){if(this.function&&(this.maxArgs=this.mathFunctionMap.get(this.function).maxArgs,this.minArgs=this.mathFunctionMap.get(this.function).minArgs,this.displayArgumentName=this.function===rn.CUSTOM),this.argumentsFormGroup){for(this.argumentsFormGroup.get("arguments").setValidators([_.minLength(this.minArgs),_.maxLength(this.maxArgs)]);this.argumentsFormArray.length>this.maxArgs;)this.removeArgument(this.maxArgs-1);for(;this.argumentsFormArray.length<this.minArgs;)this.addArgument(e);this.argumentsFormGroup.get("arguments").updateValueAndValidity({emitEvent:!1})}}createArgumentControl(e,t){const n=this.fb.group({type:[e?.type,[_.required]],key:[e?.key,[_.required]],name:[gn[t],[_.required]],attributeScope:[e?.attributeScope??fn.SERVER_SCOPE,[_.required]],defaultValue:[e?.defaultValue?e?.defaultValue:null]});return this.updateArgumentControlValidators(n),this.valueChangeSubscription.push(n.get("type").valueChanges.subscribe((()=>{this.updateArgumentControlValidators(n),n.get("attributeScope").updateValueAndValidity({emitEvent:!1}),n.get("defaultValue").updateValueAndValidity({emitEvent:!1})}))),n}updateArgumentControlValidators(e){const t=e.get("type").value;t===an.ATTRIBUTE?e.get("attributeScope").enable({emitEvent:!1}):e.get("attributeScope").disable({emitEvent:!1}),t&&t!==an.CONSTANT?e.get("defaultValue").enable({emitEvent:!1}):e.get("defaultValue").disable({emitEvent:!1})}updateArgumentNames(){this.argumentsFormArray.controls.forEach(((e,t)=>{e.get("name").setValue(gn[t])}))}updateModel(){const e=this.argumentsFormArray.value;e.length&&this.argumentsFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}}e("ArgumentsMapConfigComponent",Gn),Gn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Gn,deps:[{token:R.Store},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Gn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Gn,selector:"tb-arguments-map-config",inputs:{disabled:"disabled",function:"function"},providers:[{provide:K,useExisting:c((()=>Gn)),multi:!0},{provide:H,useExisting:c((()=>Gn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'<section fxLayout="column">\n\n <div [ngClass]="{\'tb-readonly\': disabled}"\n style="max-height: 500px; overflow: auto;">\n <mat-list class="tb-drop-list arguments-list" cdkDropList cdkDropListOrientation="vertical"\n [formGroup]="argumentsFormGroup"\n (cdkDropListDropped)="onDrop($event)"\n [cdkDropListDisabled]="disabled">\n <mat-list-item *ngFor="let argumentControl of argumentsFormArray.controls; let $index = index"\n formArrayName="arguments"\n cdkDrag class="tb-argument tb-draggable"\n [cdkDragDisabled]="disabled"\n style="height: 100%">\n <div fxFlex fxLayout="row" fxLayoutAlign="start center">\n <button *ngIf="!disabled" mat-icon-button color="primary"\n cdkDragHandle\n class="tb-drag-handle handle"\n style="min-width: 40px; margin: 0"\n matTooltip="{{ \'action.drag\' | translate }}"\n matTooltipPosition="above">\n <mat-icon>drag_handle</mat-icon>\n </button>\n <div fxFlex fxLAyout="row" fxLayoutAlign="start center" fxLayoutGap="16px">\n <span *ngIf="displayArgumentName"\n style="padding: 0 10px; min-width: 20px;">{{argumentControl.get(\'name\').value}}.</span>\n <div fxFlex fxLayout="column">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.argument-source-field-input</mat-label>\n <mat-select [formControl]="argumentControl.get(\'type\')" required>\n <mat-select-trigger>\n {{ argumentTypeMap.get(argumentControl.get(\'type\').value)?.name | translate }}\n </mat-select-trigger>\n <mat-option *ngFor="let argument of arguments" [value]="argument"\n style="border-bottom: 1px solid #eee;">\n {{ argumentTypeMap.get(argument).name | translate }}\n <small style="display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">\n {{ argumentTypeMap.get(argument).description }}\n </small>\n </mat-option>\n </mat-select>\n <mat-error *ngIf="argumentControl.get(\'type\').hasError(\'required\')" translate>\n tb.rulenode.argument-source-field-input-required\n </mat-error>\n </mat-form-field>\n <div fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="16px">\n <mat-form-field fxFlex="50" floatLabel="always" class="mat-block"\n *ngIf="argumentControl.get(\'type\').value && argumentControl.get(\'type\').value !== ArgumentType.CONSTANT">\n <mat-label translate>tb.rulenode.argument-key-field-input</mat-label>\n <input [formControl]="argumentControl.get(\'key\')" matInput required/>\n <mat-icon class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon" matSuffix\n color="primary"\n matTooltip="{{ \'tb.rulenode.math-templatization-tooltip\' | translate }}">\n help\n </mat-icon>\n <mat-error *ngIf="argumentControl.get(\'key\').hasError(\'required\')" translate>\n tb.rulenode.argument-key-field-input-required\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex floatLabel="always" class="mat-block"\n *ngIf="argumentControl.get(\'type\').value === ArgumentType.CONSTANT">\n <mat-label translate>tb.rulenode.constant-value-field-input</mat-label>\n <input [formControl]="argumentControl.get(\'key\')"\n matInput\n required\n step="1" min="0"\n type="number"/>\n <mat-error *ngIf="argumentControl.get(\'key\').hasError(\'required\')" translate>\n tb.rulenode.constant-value-field-input-required\n </mat-error>\n </mat-form-field>\n <mat-form-field *ngIf="argumentControl.get(\'type\').value && argumentControl.get(\'type\').value !== ArgumentType.CONSTANT"\n fxFlex="50" floatLabel="always" class="mat-block">\n <mat-label translate>tb.rulenode.default-value-field-input</mat-label>\n <input [formControl]="argumentControl.get(\'defaultValue\')" matInput step="1" type="number"/>\n </mat-form-field>\n </div>\n <mat-form-field *ngIf="argumentControl.get(\'type\').value === ArgumentType.ATTRIBUTE" class="mat-block">\n <mat-label translate>tb.rulenode.attribute-scope-field-input</mat-label>\n <mat-select required [formControl]="argumentControl.get(\'attributeScope\')">\n <mat-option *ngFor="let scope of attributeScope" [value]="scope">\n {{ attributeScopeMap.get(scope) | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf="argumentControl.get(\'attributeScope\').hasError(\'required\')" translate>\n tb.rulenode.attribute-scope-field-input-required\n </mat-error>\n </mat-form-field>\n </div>\n <button *ngIf="!disabled" mat-icon-button color="primary" style="min-width: 40px;"\n (click)="removeArgument($index)"\n matTooltip="{{ \'action.remove\' | translate }}"\n matTooltipPosition="above">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n </div>\n </mat-list-item>\n </mat-list>\n </div>\n <div *ngIf="!argumentsFormArray.length">\n <span translate fxLayoutAlign="center center"\n class="tb-prompt">tb.rulenode.no-arguments-prompt</span>\n </div>\n <button mat-button mat-raised-button color="primary"\n [disabled]="argumentsFormArray.length >= maxArgs"\n (click)="addArgument()"\n type="button"\n matTooltipPosition="above">\n <mat-icon>add</mat-icon>\n {{ \'action.add\' | translate }}\n </button>\n</section>\n',styles:[":host .mat-mdc-list-item.tb-argument{border:solid rgba(0,0,0,.25) 1px;border-radius:4px;padding:10px 0;margin-bottom:16px}:host .arguments-list{padding:0}\n"],dependencies:[{kind:"directive",type:j.NgClass,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ee.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:ne.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Re.MatList,selector:"mat-list",exportAs:["matList"]},{kind:"component",type:Re.MatListItem,selector:"mat-list-item, a[mat-list-item], button[mat-list-item]",inputs:["activated"],exportAs:["matListItem"]},{kind:"directive",type:Oe.CdkDropList,selector:"[cdkDropList], cdk-drop-list",inputs:["cdkDropListConnectedTo","cdkDropListData","cdkDropListOrientation","id","cdkDropListLockAxis","cdkDropListDisabled","cdkDropListSortingDisabled","cdkDropListEnterPredicate","cdkDropListSortPredicate","cdkDropListAutoScrollDisabled","cdkDropListAutoScrollStep"],outputs:["cdkDropListDropped","cdkDropListEntered","cdkDropListExited","cdkDropListSorted"],exportAs:["cdkDropList"]},{kind:"directive",type:Oe.CdkDrag,selector:"[cdkDrag]",inputs:["cdkDragData","cdkDragLockAxis","cdkDragRootElement","cdkDragBoundary","cdkDragStartDelay","cdkDragFreeDragPosition","cdkDragDisabled","cdkDragConstrainPosition","cdkDragPreviewClass","cdkDragPreviewContainer"],outputs:["cdkDragStarted","cdkDragReleased","cdkDragEnded","cdkDragEntered","cdkDragExited","cdkDragDropped","cdkDragMoved"],exportAs:["cdkDrag"]},{kind:"directive",type:Oe.CdkDragHandle,selector:"[cdkDragHandle]",inputs:["cdkDragHandleDisabled"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:Pe.DefaultClassDirective,selector:" [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl], [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl], [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]",inputs:["ngClass","ngClass.xs","ngClass.sm","ngClass.md","ngClass.lg","ngClass.xl","ngClass.lt-sm","ngClass.lt-md","ngClass.lt-lg","ngClass.lt-xl","ngClass.gt-xs","ngClass.gt-sm","ngClass.gt-md","ngClass.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormArrayName,selector:"[formArrayName]",inputs:["formArrayName"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Gn,decorators:[{type:n,args:[{selector:"tb-arguments-map-config",providers:[{provide:K,useExisting:c((()=>Gn)),multi:!0},{provide:H,useExisting:c((()=>Gn)),multi:!0}],template:'<section fxLayout="column">\n\n <div [ngClass]="{\'tb-readonly\': disabled}"\n style="max-height: 500px; overflow: auto;">\n <mat-list class="tb-drop-list arguments-list" cdkDropList cdkDropListOrientation="vertical"\n [formGroup]="argumentsFormGroup"\n (cdkDropListDropped)="onDrop($event)"\n [cdkDropListDisabled]="disabled">\n <mat-list-item *ngFor="let argumentControl of argumentsFormArray.controls; let $index = index"\n formArrayName="arguments"\n cdkDrag class="tb-argument tb-draggable"\n [cdkDragDisabled]="disabled"\n style="height: 100%">\n <div fxFlex fxLayout="row" fxLayoutAlign="start center">\n <button *ngIf="!disabled" mat-icon-button color="primary"\n cdkDragHandle\n class="tb-drag-handle handle"\n style="min-width: 40px; margin: 0"\n matTooltip="{{ \'action.drag\' | translate }}"\n matTooltipPosition="above">\n <mat-icon>drag_handle</mat-icon>\n </button>\n <div fxFlex fxLAyout="row" fxLayoutAlign="start center" fxLayoutGap="16px">\n <span *ngIf="displayArgumentName"\n style="padding: 0 10px; min-width: 20px;">{{argumentControl.get(\'name\').value}}.</span>\n <div fxFlex fxLayout="column">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.argument-source-field-input</mat-label>\n <mat-select [formControl]="argumentControl.get(\'type\')" required>\n <mat-select-trigger>\n {{ argumentTypeMap.get(argumentControl.get(\'type\').value)?.name | translate }}\n </mat-select-trigger>\n <mat-option *ngFor="let argument of arguments" [value]="argument"\n style="border-bottom: 1px solid #eee;">\n {{ argumentTypeMap.get(argument).name | translate }}\n <small style="display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">\n {{ argumentTypeMap.get(argument).description }}\n </small>\n </mat-option>\n </mat-select>\n <mat-error *ngIf="argumentControl.get(\'type\').hasError(\'required\')" translate>\n tb.rulenode.argument-source-field-input-required\n </mat-error>\n </mat-form-field>\n <div fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="16px">\n <mat-form-field fxFlex="50" floatLabel="always" class="mat-block"\n *ngIf="argumentControl.get(\'type\').value && argumentControl.get(\'type\').value !== ArgumentType.CONSTANT">\n <mat-label translate>tb.rulenode.argument-key-field-input</mat-label>\n <input [formControl]="argumentControl.get(\'key\')" matInput required/>\n <mat-icon class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon" matSuffix\n color="primary"\n matTooltip="{{ \'tb.rulenode.math-templatization-tooltip\' | translate }}">\n help\n </mat-icon>\n <mat-error *ngIf="argumentControl.get(\'key\').hasError(\'required\')" translate>\n tb.rulenode.argument-key-field-input-required\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex floatLabel="always" class="mat-block"\n *ngIf="argumentControl.get(\'type\').value === ArgumentType.CONSTANT">\n <mat-label translate>tb.rulenode.constant-value-field-input</mat-label>\n <input [formControl]="argumentControl.get(\'key\')"\n matInput\n required\n step="1" min="0"\n type="number"/>\n <mat-error *ngIf="argumentControl.get(\'key\').hasError(\'required\')" translate>\n tb.rulenode.constant-value-field-input-required\n </mat-error>\n </mat-form-field>\n <mat-form-field *ngIf="argumentControl.get(\'type\').value && argumentControl.get(\'type\').value !== ArgumentType.CONSTANT"\n fxFlex="50" floatLabel="always" class="mat-block">\n <mat-label translate>tb.rulenode.default-value-field-input</mat-label>\n <input [formControl]="argumentControl.get(\'defaultValue\')" matInput step="1" type="number"/>\n </mat-form-field>\n </div>\n <mat-form-field *ngIf="argumentControl.get(\'type\').value === ArgumentType.ATTRIBUTE" class="mat-block">\n <mat-label translate>tb.rulenode.attribute-scope-field-input</mat-label>\n <mat-select required [formControl]="argumentControl.get(\'attributeScope\')">\n <mat-option *ngFor="let scope of attributeScope" [value]="scope">\n {{ attributeScopeMap.get(scope) | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf="argumentControl.get(\'attributeScope\').hasError(\'required\')" translate>\n tb.rulenode.attribute-scope-field-input-required\n </mat-error>\n </mat-form-field>\n </div>\n <button *ngIf="!disabled" mat-icon-button color="primary" style="min-width: 40px;"\n (click)="removeArgument($index)"\n matTooltip="{{ \'action.remove\' | translate }}"\n matTooltipPosition="above">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n </div>\n </mat-list-item>\n </mat-list>\n </div>\n <div *ngIf="!argumentsFormArray.length">\n <span translate fxLayoutAlign="center center"\n class="tb-prompt">tb.rulenode.no-arguments-prompt</span>\n </div>\n <button mat-button mat-raised-button color="primary"\n [disabled]="argumentsFormArray.length >= maxArgs"\n (click)="addArgument()"\n type="button"\n matTooltipPosition="above">\n <mat-icon>add</mat-icon>\n {{ \'action.add\' | translate }}\n </button>\n</section>\n',styles:[":host .mat-mdc-list-item.tb-argument{border:solid rgba(0,0,0,.25) 1px;border-radius:4px;padding:10px 0;margin-bottom:16px}:host .arguments-list{padding:0}\n"]}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder}]},propDecorators:{disabled:[{type:m}],function:[{type:m}]}});class Dn extends T{get required(){return this.requiredValue}set required(e){this.requiredValue=we(e)}constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.injector=n,this.fb=r,this.searchText="",this.dirty=!1,this.mathOperation=[...on.values()],this.propagateChange=null}ngOnInit(){this.mathFunctionForm=this.fb.group({operation:[""]}),this.filteredOptions=this.mathFunctionForm.get("operation").valueChanges.pipe(_e((e=>{let t;t="string"==typeof e&&rn[e]?rn[e]:null,this.updateView(t)})),Be((e=>(this.searchText=e||"",e?this._filter(e):this.mathOperation.slice()))))}_filter(e){const t=e.toLowerCase();return this.mathOperation.filter((e=>e.name.toLowerCase().includes(t)||e.value.toLowerCase().includes(t)))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.mathFunctionForm.disable({emitEvent:!1}):this.mathFunctionForm.enable({emitEvent:!1})}mathFunctionDisplayFn(e){if(e){const t=on.get(e);return t.value+" | "+t.name}return""}writeValue(e){this.modelValue=e,this.mathFunctionForm.get("operation").setValue(e,{emitEvent:!1}),this.dirty=!0}updateView(e){this.modelValue!==e&&(this.modelValue=e,this.propagateChange(this.modelValue))}onFocus(){this.dirty&&(this.mathFunctionForm.get("operation").updateValueAndValidity({onlySelf:!0}),this.dirty=!1)}clear(){this.mathFunctionForm.get("operation").patchValue(""),setTimeout((()=>{this.operationInput.nativeElement.blur(),this.operationInput.nativeElement.focus()}),0)}}e("MathFunctionAutocompleteComponent",Dn),Dn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Dn,deps:[{token:R.Store},{token:X.TranslateService},{token:t.Injector},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Dn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Dn,selector:"tb-math-function-autocomplete",inputs:{required:"required",disabled:"disabled"},providers:[{provide:K,useExisting:c((()=>Dn)),multi:!0}],viewQueries:[{propertyName:"operationInput",first:!0,predicate:["operationInput"],descendants:!0,static:!0}],usesInheritance:!0,ngImport:t,template:'<mat-form-field [formGroup]="mathFunctionForm" class="mat-block">\n <mat-label translate>tb.rulenode.functions-field-input</mat-label>\n <input [required]="required"\n (focusin)="onFocus()"\n type="text"\n #operationInput matInput\n formControlName="operation"\n [matAutocomplete]="auto">\n <button *ngIf="mathFunctionForm.get(\'operation\').value"\n type="button"\n matSuffix mat-icon-button aria-label="Clear"\n (click)="clear()">\n <mat-icon class="material-icons">close</mat-icon>\n </button>\n <mat-autocomplete #auto="matAutocomplete" class="tb-autocomplete" [displayWith]="mathFunctionDisplayFn">\n <mat-option *ngFor="let option of filteredOptions | async" [value]="option.value">\n <span [innerHTML]="option.value + \' | \' + option.name | highlight:searchText"></span>\n <small style="display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">\n {{ option.description }}\n </small>\n </mat-option>\n <mat-option *ngIf="!(filteredOptions | async)?.length" [value]="null">\n <span translate>tb.rulenode.no-option-found</span>\n </mat-option>\n </mat-autocomplete>\n</mat-form-field>\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ee.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:$e.MatAutocomplete,selector:"mat-autocomplete",inputs:["disableRipple","hideSingleSelectionIndicator"],exportAs:["matAutocomplete"]},{kind:"directive",type:$e.MatAutocompleteTrigger,selector:"input[matAutocomplete], textarea[matAutocomplete]",exportAs:["matAutocompleteTrigger"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:j.AsyncPipe,name:"async"},{kind:"pipe",type:Je.HighlightPipe,name:"highlight"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Dn,decorators:[{type:n,args:[{selector:"tb-math-function-autocomplete",providers:[{provide:K,useExisting:c((()=>Dn)),multi:!0}],template:'<mat-form-field [formGroup]="mathFunctionForm" class="mat-block">\n <mat-label translate>tb.rulenode.functions-field-input</mat-label>\n <input [required]="required"\n (focusin)="onFocus()"\n type="text"\n #operationInput matInput\n formControlName="operation"\n [matAutocomplete]="auto">\n <button *ngIf="mathFunctionForm.get(\'operation\').value"\n type="button"\n matSuffix mat-icon-button aria-label="Clear"\n (click)="clear()">\n <mat-icon class="material-icons">close</mat-icon>\n </button>\n <mat-autocomplete #auto="matAutocomplete" class="tb-autocomplete" [displayWith]="mathFunctionDisplayFn">\n <mat-option *ngFor="let option of filteredOptions | async" [value]="option.value">\n <span [innerHTML]="option.value + \' | \' + option.name | highlight:searchText"></span>\n <small style="display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">\n {{ option.description }}\n </small>\n </mat-option>\n <mat-option *ngIf="!(filteredOptions | async)?.length" [value]="null">\n <span translate>tb.rulenode.no-option-found</span>\n </mat-option>\n </mat-autocomplete>\n</mat-form-field>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:X.TranslateService},{type:t.Injector},{type:O.UntypedFormBuilder}]},propDecorators:{required:[{type:m}],disabled:[{type:m}],operationInput:[{type:u,args:["operationInput",{static:!0}]}]}});class Vn extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.MathFunction=rn,this.ArgumentTypeResult=ln,this.argumentTypeResultMap=cn,this.attributeScopeMap=bn,this.argumentsResult=Object.values(ln),this.attributeScopeResult=Object.values(yn)}configForm(){return this.mathFunctionConfigForm}onConfigurationSet(e){this.mathFunctionConfigForm=this.fb.group({operation:[e?e.operation:null,[_.required]],arguments:[e?e.arguments:null,[_.required]],customFunction:[e?e.customFunction:"",[_.required]],result:this.fb.group({type:[e?e.result.type:null,[_.required]],attributeScope:[e?e.result.attributeScope:null,[_.required]],key:[e?e.result.key:"",[_.required]],resultValuePrecision:[e?e.result.resultValuePrecision:0],addToBody:[!!e&&e.result.addToBody],addToMetadata:[!!e&&e.result.addToMetadata]})})}updateValidators(e){const t=this.mathFunctionConfigForm.get("operation").value,n=this.mathFunctionConfigForm.get("result.type").value;t===rn.CUSTOM?(this.mathFunctionConfigForm.get("customFunction").enable({emitEvent:!1}),null===this.mathFunctionConfigForm.get("customFunction").value&&this.mathFunctionConfigForm.get("customFunction").patchValue("(x - 32) / 1.8",{emitEvent:!1})):this.mathFunctionConfigForm.get("customFunction").disable({emitEvent:!1}),n===ln.ATTRIBUTE?this.mathFunctionConfigForm.get("result.attributeScope").enable({emitEvent:!1}):this.mathFunctionConfigForm.get("result.attributeScope").disable({emitEvent:!1}),this.mathFunctionConfigForm.get("customFunction").updateValueAndValidity({emitEvent:e}),this.mathFunctionConfigForm.get("result.attributeScope").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["operation","result.type"]}}e("MathFunctionConfigComponent",Vn),Vn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Vn,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Vn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Vn,selector:"tb-action-node-math-function-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="mathFunctionConfigForm" fxLayout="column">\n <tb-math-function-autocomplete\n fxFlex="30" fxFlex.md fxFlex.xs\n required\n formControlName="operation">\n </tb-math-function-autocomplete>\n <fieldset class="fields-group" fxLayout="column" fxLayoutGap="8px">\n <legend class="group-title" translate>tb.rulenode.argument-tile</legend>\n <tb-arguments-map-config formControlName="arguments"\n [function]="mathFunctionConfigForm.get(\'operation\').value">\n </tb-arguments-map-config>\n </fieldset>\n <fieldset *ngIf="mathFunctionConfigForm.get(\'operation\').value === MathFunction.CUSTOM"\n class="fields-group" fxLayout="column" fxLayoutGap="8px">\n <legend class="group-title">{{\'tb.rulenode.custom-expression-field-input\' | translate }} *</legend>\n <mat-form-field fxFlex class="mat-block no-margin-top" subscriptSizing="dynamic">\n <input matInput formControlName="customFunction" required/>\n <mat-error *ngIf="mathFunctionConfigForm.get(\'customFunction\').hasError(\'required\')" translate>\n tb.rulenode.custom-expression-field-input-required\n </mat-error>\n <mat-hint translate>tb.rulenode.custom-expression-field-input-hint</mat-hint>\n </mat-form-field>\n </fieldset>\n <fieldset class="fields-group" fxLayout="column" fxLayoutGap="8px">\n <legend class="group-title" translate>tb.rulenode.result-title</legend>\n <div formGroupName="result">\n <mat-form-field fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.type-field-input</mat-label>\n <mat-select formControlName="type" required>\n <mat-select-trigger>\n {{ argumentTypeResultMap.get(mathFunctionConfigForm.get(\'result.type\').value)?.name | translate }}\n </mat-select-trigger>\n <mat-option *ngFor="let argument of argumentsResult" [value]="argument"\n style="border-bottom: 1px solid #eee;">\n {{ argumentTypeResultMap.get(argument).name | translate }}\n <small style="display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">\n {{ argumentTypeResultMap.get(argument).description }}\n </small>\n </mat-option>\n </mat-select>\n <mat-error *ngIf="mathFunctionConfigForm.get(\'result.type\').hasError(\'required\')" translate>\n tb.rulenode.type-field-input-required\n </mat-error>\n </mat-form-field>\n <div fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="16px">\n <mat-form-field fxFlex class="mat-block" *ngIf="mathFunctionConfigForm.get(\'result\').get(\'type\').value === ArgumentTypeResult.ATTRIBUTE">\n <mat-label translate>tb.rulenode.attribute-scope-field-input</mat-label>\n <mat-select required formControlName="attributeScope">\n <mat-option *ngFor="let scope of attributeScopeResult" [value]="scope">\n {{ attributeScopeMap.get(scope) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field fxFlex floatLabel="always" class="mat-block">\n <mat-label translate>tb.rulenode.key-field-input</mat-label>\n <input matInput formControlName="key" required/>\n <mat-icon class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon" matSuffix\n color="primary"\n matTooltip="{{ \'tb.rulenode.math-templatization-tooltip\' | translate }}">help</mat-icon>\n <mat-error *ngIf="mathFunctionConfigForm.get(\'result.key\').hasError(\'required\')" translate>\n tb.rulenode.key-field-input-required\n </mat-error>\n </mat-form-field>\n </div>\n <div fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="16px">\n <mat-form-field fxFlex floatLabel="always" class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.number-floating-point-field-input</mat-label>\n <input formControlName="resultValuePrecision"\n matInput\n step="1" min="0"\n type="number"/>\n <mat-hint [innerHTML]="\'tb.rulenode.number-floating-point-field-input-hint\' | translate | safe: \'html\'"></mat-hint>\n </mat-form-field>\n </div>\n <div *ngIf="[ArgumentTypeResult.ATTRIBUTE, ArgumentTypeResult.TIME_SERIES].includes(mathFunctionConfigForm.get(\'result\').get(\'type\').value)"\n fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutAlign="start" fxLayoutGap.gt-xs="16px" style="padding-top: 16px;">\n <mat-checkbox formControlName="addToBody">\n {{\'tb.rulenode.add-to-message-field-input\' | translate }}\n </mat-checkbox>\n <mat-checkbox formControlName="addToMetadata">\n {{\'tb.rulenode.add-to-metadata-field-input\' | translate}}\n </mat-checkbox>\n </div>\n </div>\n </fieldset>\n</section>\n',styles:[":host ::ng-deep .fields-group{padding:0 16px 8px;margin:10px 0;border:1px groove rgba(0,0,0,.25);border-radius:4px}:host ::ng-deep .fields-group .mat-mdc-form-field .mat-mdc-form-field-infix{width:100%}:host ::ng-deep .fields-group legend{color:#000000b3;width:-moz-fit-content;width:fit-content}:host ::ng-deep .fields-group legend+*{display:block}:host ::ng-deep .fields-group legend+*.no-margin-top{margin-top:0}\n"],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ie.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:ne.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:O.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Gn,selector:"tb-arguments-map-config",inputs:["disabled","function"]},{kind:"component",type:Dn,selector:"tb-math-function-autocomplete",inputs:["required","disabled"]},{kind:"pipe",type:ce.SafePipe,name:"safe"},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Vn,decorators:[{type:n,args:[{selector:"tb-action-node-math-function-config",template:'<section [formGroup]="mathFunctionConfigForm" fxLayout="column">\n <tb-math-function-autocomplete\n fxFlex="30" fxFlex.md fxFlex.xs\n required\n formControlName="operation">\n </tb-math-function-autocomplete>\n <fieldset class="fields-group" fxLayout="column" fxLayoutGap="8px">\n <legend class="group-title" translate>tb.rulenode.argument-tile</legend>\n <tb-arguments-map-config formControlName="arguments"\n [function]="mathFunctionConfigForm.get(\'operation\').value">\n </tb-arguments-map-config>\n </fieldset>\n <fieldset *ngIf="mathFunctionConfigForm.get(\'operation\').value === MathFunction.CUSTOM"\n class="fields-group" fxLayout="column" fxLayoutGap="8px">\n <legend class="group-title">{{\'tb.rulenode.custom-expression-field-input\' | translate }} *</legend>\n <mat-form-field fxFlex class="mat-block no-margin-top" subscriptSizing="dynamic">\n <input matInput formControlName="customFunction" required/>\n <mat-error *ngIf="mathFunctionConfigForm.get(\'customFunction\').hasError(\'required\')" translate>\n tb.rulenode.custom-expression-field-input-required\n </mat-error>\n <mat-hint translate>tb.rulenode.custom-expression-field-input-hint</mat-hint>\n </mat-form-field>\n </fieldset>\n <fieldset class="fields-group" fxLayout="column" fxLayoutGap="8px">\n <legend class="group-title" translate>tb.rulenode.result-title</legend>\n <div formGroupName="result">\n <mat-form-field fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.type-field-input</mat-label>\n <mat-select formControlName="type" required>\n <mat-select-trigger>\n {{ argumentTypeResultMap.get(mathFunctionConfigForm.get(\'result.type\').value)?.name | translate }}\n </mat-select-trigger>\n <mat-option *ngFor="let argument of argumentsResult" [value]="argument"\n style="border-bottom: 1px solid #eee;">\n {{ argumentTypeResultMap.get(argument).name | translate }}\n <small style="display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">\n {{ argumentTypeResultMap.get(argument).description }}\n </small>\n </mat-option>\n </mat-select>\n <mat-error *ngIf="mathFunctionConfigForm.get(\'result.type\').hasError(\'required\')" translate>\n tb.rulenode.type-field-input-required\n </mat-error>\n </mat-form-field>\n <div fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="16px">\n <mat-form-field fxFlex class="mat-block" *ngIf="mathFunctionConfigForm.get(\'result\').get(\'type\').value === ArgumentTypeResult.ATTRIBUTE">\n <mat-label translate>tb.rulenode.attribute-scope-field-input</mat-label>\n <mat-select required formControlName="attributeScope">\n <mat-option *ngFor="let scope of attributeScopeResult" [value]="scope">\n {{ attributeScopeMap.get(scope) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field fxFlex floatLabel="always" class="mat-block">\n <mat-label translate>tb.rulenode.key-field-input</mat-label>\n <input matInput formControlName="key" required/>\n <mat-icon class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon" matSuffix\n color="primary"\n matTooltip="{{ \'tb.rulenode.math-templatization-tooltip\' | translate }}">help</mat-icon>\n <mat-error *ngIf="mathFunctionConfigForm.get(\'result.key\').hasError(\'required\')" translate>\n tb.rulenode.key-field-input-required\n </mat-error>\n </mat-form-field>\n </div>\n <div fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="16px">\n <mat-form-field fxFlex floatLabel="always" class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.number-floating-point-field-input</mat-label>\n <input formControlName="resultValuePrecision"\n matInput\n step="1" min="0"\n type="number"/>\n <mat-hint [innerHTML]="\'tb.rulenode.number-floating-point-field-input-hint\' | translate | safe: \'html\'"></mat-hint>\n </mat-form-field>\n </div>\n <div *ngIf="[ArgumentTypeResult.ATTRIBUTE, ArgumentTypeResult.TIME_SERIES].includes(mathFunctionConfigForm.get(\'result\').get(\'type\').value)"\n fxFlex fxLayout="row" fxLayout.xs="column" fxLayoutAlign="start" fxLayoutGap.gt-xs="16px" style="padding-top: 16px;">\n <mat-checkbox formControlName="addToBody">\n {{\'tb.rulenode.add-to-message-field-input\' | translate }}\n </mat-checkbox>\n <mat-checkbox formControlName="addToMetadata">\n {{\'tb.rulenode.add-to-metadata-field-input\' | translate}}\n </mat-checkbox>\n </div>\n </div>\n </fieldset>\n</section>\n',styles:[":host ::ng-deep .fields-group{padding:0 16px 8px;margin:10px 0;border:1px groove rgba(0,0,0,.25);border-radius:4px}:host ::ng-deep .fields-group .mat-mdc-form-field .mat-mdc-form-field-infix{width:100%}:host ::ng-deep .fields-group legend{color:#000000b3;width:-moz-fit-content;width:fit-content}:host ::ng-deep .fields-group legend+*{display:block}:host ::ng-deep .fields-group legend+*.no-margin-top{margin-top:0}\n"]}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class Pn extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.messageTypeNames=L,this.eventOptions=[I.CONNECT_EVENT,I.ACTIVITY_EVENT,I.DISCONNECT_EVENT,I.INACTIVITY_EVENT]}configForm(){return this.deviceState}prepareInputConfig(e){return{event:ye(e?.event)?e.event:I.ACTIVITY_EVENT}}onConfigurationSet(e){this.deviceState=this.fb.group({event:[e.event,[_.required]]})}}e("DeviceStateConfigComponent",Pn),Pn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Pn,deps:[{token:R.Store},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Pn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Pn,selector:"tb-action-node-device-state-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="deviceState">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label>{{ \'tb.rulenode.select-device-connectivity-event\' | translate }}</mat-label>\n <mat-select formControlName="event">\n <mat-option *ngFor="let eventOption of eventOptions" [value]="eventOption">\n {{ messageTypeNames.get(eventOption) }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n</section>\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Pn,decorators:[{type:n,args:[{selector:"tb-action-node-device-state-config",template:'<section [formGroup]="deviceState">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label>{{ \'tb.rulenode.select-device-connectivity-event\' | translate }}</mat-label>\n <mat-select formControlName="event">\n <mat-option *ngFor="let eventOption of eventOptions" [value]="eventOption">\n {{ messageTypeNames.get(eventOption) }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder}]}});class Rn{constructor(e,t){this.injector=e,this.fb=t,this.propagateChange=()=>{},this.destroy$=new ie,this.disabled=!1,this.uniqueKeyValuePairValidator=!1,this.required=!1,this.duplicateValuesValidator=e=>e.controls.key.value===e.controls.value.value&&e.controls.key.value&&e.controls.value.value?{uniqueKeyValuePair:!0}:null,this.oneMapRequiredValidator=e=>e.get("keyVals").value.length,this.propagateNestedErrors=e=>{if(this.kvListFormGroup&&this.kvListFormGroup.get("keyVals")&&"VALID"===this.kvListFormGroup.get("keyVals")?.status)return null;const t={};if(this.kvListFormGroup&&this.kvListFormGroup.setErrors(null),e instanceof z||e instanceof U){if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;for(const n of Object.keys(e.controls)){const r=this.propagateNestedErrors(e.controls[n]);if(r&&Object.keys(r).length)for(const e of Object.keys(r))t[e]=!0}return t}if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;return be(t,{})?null:t}}ngOnInit(){this.ngControl=this.injector.get(B),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.kvListFormGroup=this.fb.group({keyVals:this.fb.array([])},{validators:[this.propagateNestedErrors,this.oneMapRequiredValidator]}),this.kvListFormGroup.valueChanges.pipe(le(this.destroy$)).subscribe((()=>{this.updateModel()}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}keyValsFormArray(){return this.kvListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.kvListFormGroup.disable({emitEvent:!1}):this.kvListFormGroup.enable({emitEvent:!1})}writeValue(e){const t=Object.keys(e).map((t=>({key:t,value:e[t]})));if(this.keyValsFormArray().length===t.length)this.keyValsFormArray().patchValue(t,{emitEvent:!1});else{const e=[];t.forEach((t=>{e.push(this.fb.group({key:[t.key,[_.required,_.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],value:[t.value,[_.required,_.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]},{validators:this.uniqueKeyValuePairValidator?[this.duplicateValuesValidator]:[]}))})),this.kvListFormGroup.setControl("keyVals",this.fb.array(e,this.propagateNestedErrors),{emitEvent:!1})}}removeKeyVal(e){this.keyValsFormArray().removeAt(e)}addKeyVal(){this.keyValsFormArray().push(this.fb.group({key:["",[_.required,_.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],value:["",[_.required,_.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]},{validators:this.uniqueKeyValuePairValidator?[this.duplicateValuesValidator]:[]}))}validate(){const e=this.kvListFormGroup.get("keyVals").value;if(!e.length&&this.required)return{kvMapRequired:!0};if(!this.kvListFormGroup.valid)return{kvFieldsRequired:!0};if(this.uniqueKeyValuePairValidator)for(const t of e)if(t.key===t.value)return{uniqueKeyValuePair:!0};return null}updateModel(){const e=this.kvListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.kvListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("KvMapConfigComponent",Rn),Rn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rn,deps:[{token:t.Injector},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Rn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Rn,selector:"tb-kv-map-config",inputs:{disabled:"disabled",uniqueKeyValuePairValidator:"uniqueKeyValuePairValidator",labelText:"labelText",requiredText:"requiredText",keyText:"keyText",keyRequiredText:"keyRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",popupHelpLink:"popupHelpLink",required:"required"},providers:[{provide:K,useExisting:c((()=>Rn)),multi:!0},{provide:H,useExisting:c((()=>Rn)),multi:!0}],ngImport:t,template:'<section [formGroup]="kvListFormGroup" class="tb-form-panel stroked">\n <div class="tb-form-row no-padding no-border space-between">\n <div class="tb-form-panel-title">{{ labelText }}</div>\n <div class="tb-form-panel-hint tb-error" translate *ngIf="kvListFormGroup.hasError(\'kvMapRequired\')">\n {{ requiredText }}\n </div>\n <div class="tb-form-panel-hint tb-error" translate *ngIf="kvListFormGroup.hasError(\'required\')">\n tb.rulenode.map-fields-required\n </div>\n <div class="tb-form-panel-hint tb-error" translate *ngIf="kvListFormGroup.hasError(\'uniqueKeyValuePair\')">\n {{ \'tb.key-val.unique-key-value-pair-error\' | translate:\n {\n valText: valText,\n keyText: keyText\n } }}\n </div>\n </div>\n <div class="tb-form-panel no-border no-padding">\n <div class="tb-form-table">\n <div class="tb-form-table-header">\n <div class="tb-form-table-header-cell field-space">{{ keyText }}</div>\n <div class="tb-form-table-header-cell field-space">{{ valText }}</div>\n <div class="tb-form-table-header-cell actions-header"></div>\n </div>\n <div class="tb-form-table-body">\n <div class="tb-form-table-row"\n *ngFor="let keyValControl of keyValsFormArray().controls; let $index = index;">\n <mat-form-field class="tb-inline-field field-space" appearance="outline" subscriptSizing="dynamic">\n <input [placeholder]="keyText+\'*\'" [formControl]="keyValControl.get(\'key\')" matInput/>\n </mat-form-field>\n <mat-form-field class="tb-inline-field field-space" appearance="outline" subscriptSizing="dynamic">\n <input [placeholder]="valText+\'*\'" [formControl]="keyValControl.get(\'value\')" matInput/>\n </mat-form-field>\n <div class="tb-form-table-row-cell-buttons">\n <button [class.tb-hidden]="keyValsFormArray().controls.length === 1"\n type="button"\n mat-icon-button\n (click)="removeKeyVal($index)"\n [disabled]="disabled"\n matTooltip="{{ \'tb.key-val.remove-mapping-entry\' | translate }}"\n matTooltipPosition="above">\n <mat-icon>delete</mat-icon>\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n <div>\n <button type="button" mat-stroked-button color="primary" (click)="addKeyVal()">\n {{ \'tb.key-val.add-mapping-entry\' | translate }}\n </button>\n </div>\n <tb-example-hint [hintText]="hintText" [popupHelpLink]="popupHelpLink" *ngIf="popupHelpLink || hintText"></tb-example-hint>\n</section>\n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ee.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ht,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),Ye([S()],Rn.prototype,"disabled",void 0),Ye([S()],Rn.prototype,"uniqueKeyValuePairValidator",void 0),Ye([S()],Rn.prototype,"required",void 0),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rn,decorators:[{type:n,args:[{selector:"tb-kv-map-config",providers:[{provide:K,useExisting:c((()=>Rn)),multi:!0},{provide:H,useExisting:c((()=>Rn)),multi:!0}],template:'<section [formGroup]="kvListFormGroup" class="tb-form-panel stroked">\n <div class="tb-form-row no-padding no-border space-between">\n <div class="tb-form-panel-title">{{ labelText }}</div>\n <div class="tb-form-panel-hint tb-error" translate *ngIf="kvListFormGroup.hasError(\'kvMapRequired\')">\n {{ requiredText }}\n </div>\n <div class="tb-form-panel-hint tb-error" translate *ngIf="kvListFormGroup.hasError(\'required\')">\n tb.rulenode.map-fields-required\n </div>\n <div class="tb-form-panel-hint tb-error" translate *ngIf="kvListFormGroup.hasError(\'uniqueKeyValuePair\')">\n {{ \'tb.key-val.unique-key-value-pair-error\' | translate:\n {\n valText: valText,\n keyText: keyText\n } }}\n </div>\n </div>\n <div class="tb-form-panel no-border no-padding">\n <div class="tb-form-table">\n <div class="tb-form-table-header">\n <div class="tb-form-table-header-cell field-space">{{ keyText }}</div>\n <div class="tb-form-table-header-cell field-space">{{ valText }}</div>\n <div class="tb-form-table-header-cell actions-header"></div>\n </div>\n <div class="tb-form-table-body">\n <div class="tb-form-table-row"\n *ngFor="let keyValControl of keyValsFormArray().controls; let $index = index;">\n <mat-form-field class="tb-inline-field field-space" appearance="outline" subscriptSizing="dynamic">\n <input [placeholder]="keyText+\'*\'" [formControl]="keyValControl.get(\'key\')" matInput/>\n </mat-form-field>\n <mat-form-field class="tb-inline-field field-space" appearance="outline" subscriptSizing="dynamic">\n <input [placeholder]="valText+\'*\'" [formControl]="keyValControl.get(\'value\')" matInput/>\n </mat-form-field>\n <div class="tb-form-table-row-cell-buttons">\n <button [class.tb-hidden]="keyValsFormArray().controls.length === 1"\n type="button"\n mat-icon-button\n (click)="removeKeyVal($index)"\n [disabled]="disabled"\n matTooltip="{{ \'tb.key-val.remove-mapping-entry\' | translate }}"\n matTooltipPosition="above">\n <mat-icon>delete</mat-icon>\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n <div>\n <button type="button" mat-stroked-button color="primary" (click)="addKeyVal()">\n {{ \'tb.key-val.add-mapping-entry\' | translate }}\n </button>\n </div>\n <tb-example-hint [hintText]="hintText" [popupHelpLink]="popupHelpLink" *ngIf="popupHelpLink || hintText"></tb-example-hint>\n</section>\n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:t.Injector},{type:O.FormBuilder}]},propDecorators:{disabled:[{type:m}],uniqueKeyValuePairValidator:[{type:m}],labelText:[{type:m}],requiredText:[{type:m}],keyText:[{type:m}],keyRequiredText:[{type:m}],valText:[{type:m}],valRequiredText:[{type:m}],hintText:[{type:m}],popupHelpLink:[{type:m}],required:[{type:m}]}});class On extends T{get required(){return this.requiredValue}set required(e){this.requiredValue=we(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.values(v),this.directionTypeTranslations=N,this.entityType=C,this.propagateChange=null}ngOnInit(){this.deviceRelationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[_.required]],maxLevel:[null,[_.min(1)]],relationType:[null],deviceTypes:[null,[_.required]]}),this.deviceRelationsQueryFormGroup.valueChanges.subscribe((e=>{this.deviceRelationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.deviceRelationsQueryFormGroup.disable({emitEvent:!1}):this.deviceRelationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.deviceRelationsQueryFormGroup.reset(e,{emitEvent:!1})}}e("DeviceRelationsQueryConfigComponent",On),On.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:On,deps:[{token:R.Store},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),On.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:On,selector:"tb-device-relations-query-config",inputs:{disabled:"disabled",required:"required"},providers:[{provide:K,useExisting:c((()=>On)),multi:!0}],usesInheritance:!0,ngImport:t,template:'<section fxLayout="column" [formGroup]="deviceRelationsQueryFormGroup">\n <div fxLayoutGap="22px" fxLayout="row">\n <mat-form-field class="mat-block" subscriptSizing="dynamic" fxFlex="50" style="min-width: 100px;" hideRequiredMarker>\n <mat-label translate>relation.direction</mat-label>\n <mat-select required formControlName="direction">\n <mat-option *ngFor="let type of directionTypes" [value]="type">\n {{ directionTypeTranslations.get(type) | translate }} <span translate>tb.rulenode.relations-query-config-direction-suffix</span>\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field fxFlex="50" floatLabel="always" class="mat-block">\n <mat-label translate>tb.rulenode.max-relation-level</mat-label>\n <input matInput\n type="number"\n min="1"\n step="1"\n placeholder="{{ \'tb.rulenode.unlimited-level\' | translate }}"\n formControlName="maxLevel">\n <mat-error *ngIf="deviceRelationsQueryFormGroup.get(\'maxLevel\').hasError(\'min\')">\n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.last-level-device-relation-tooltip\' | translate }}"\n *ngIf="deviceRelationsQueryFormGroup.get(\'maxLevel\').value > 1"\n class="tb-form-row no-border no-padding last-level-slide-toggle">\n <mat-slide-toggle class="mat-slide" formControlName="fetchLastLevelOnly">\n {{ \'alias.last-level-relation\' | translate }}\n </mat-slide-toggle>\n </div>\n <tb-relation-type-autocomplete\n fxFlex\n formControlName="relationType">\n </tb-relation-type-autocomplete>\n <tb-entity-subtype-list\n required\n [label]="\'tb.rulenode.device-profiles\' | translate"\n [entityType]="entityType.DEVICE"\n [emptyInputPlaceholder]="\'tb.rulenode.add-device-profile\' | translate"\n [filledInputPlaceholder]="\'tb.rulenode.add-device-profile\' | translate"\n formControlName="deviceTypes">\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon" color="primary"\n matTooltip="{{ \'tb.rulenode.chip-help\' | translate: { inputName: \'tb.rulenode.device-profile\' | translate } }}">help</mat-icon>\n </tb-entity-subtype-list>\n</section>\n',styles:[":host .last-level-slide-toggle{margin:8px 0 24px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:We.EntitySubTypeListComponent,selector:"tb-entity-subtype-list",inputs:["required","floatLabel","label","disabled","entityType","emptyInputPlaceholder","filledInputPlaceholder","appearance","subscriptSizing","additionalClasses"]},{kind:"component",type:qe.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:On,decorators:[{type:n,args:[{selector:"tb-device-relations-query-config",providers:[{provide:K,useExisting:c((()=>On)),multi:!0}],template:'<section fxLayout="column" [formGroup]="deviceRelationsQueryFormGroup">\n <div fxLayoutGap="22px" fxLayout="row">\n <mat-form-field class="mat-block" subscriptSizing="dynamic" fxFlex="50" style="min-width: 100px;" hideRequiredMarker>\n <mat-label translate>relation.direction</mat-label>\n <mat-select required formControlName="direction">\n <mat-option *ngFor="let type of directionTypes" [value]="type">\n {{ directionTypeTranslations.get(type) | translate }} <span translate>tb.rulenode.relations-query-config-direction-suffix</span>\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field fxFlex="50" floatLabel="always" class="mat-block">\n <mat-label translate>tb.rulenode.max-relation-level</mat-label>\n <input matInput\n type="number"\n min="1"\n step="1"\n placeholder="{{ \'tb.rulenode.unlimited-level\' | translate }}"\n formControlName="maxLevel">\n <mat-error *ngIf="deviceRelationsQueryFormGroup.get(\'maxLevel\').hasError(\'min\')">\n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.last-level-device-relation-tooltip\' | translate }}"\n *ngIf="deviceRelationsQueryFormGroup.get(\'maxLevel\').value > 1"\n class="tb-form-row no-border no-padding last-level-slide-toggle">\n <mat-slide-toggle class="mat-slide" formControlName="fetchLastLevelOnly">\n {{ \'alias.last-level-relation\' | translate }}\n </mat-slide-toggle>\n </div>\n <tb-relation-type-autocomplete\n fxFlex\n formControlName="relationType">\n </tb-relation-type-autocomplete>\n <tb-entity-subtype-list\n required\n [label]="\'tb.rulenode.device-profiles\' | translate"\n [entityType]="entityType.DEVICE"\n [emptyInputPlaceholder]="\'tb.rulenode.add-device-profile\' | translate"\n [filledInputPlaceholder]="\'tb.rulenode.add-device-profile\' | translate"\n formControlName="deviceTypes">\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon" color="primary"\n matTooltip="{{ \'tb.rulenode.chip-help\' | translate: { inputName: \'tb.rulenode.device-profile\' | translate } }}">help</mat-icon>\n </tb-entity-subtype-list>\n</section>\n',styles:[":host .last-level-slide-toggle{margin:8px 0 24px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder}]},propDecorators:{disabled:[{type:m}],required:[{type:m}]}});class _n extends T{get required(){return this.requiredValue}set required(e){this.requiredValue=we(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.values(v),this.directionTypeTranslations=N,this.propagateChange=null}ngOnInit(){this.relationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[_.required]],maxLevel:[null,[_.min(1)]],filters:[null]}),this.relationsQueryFormGroup.valueChanges.subscribe((e=>{this.relationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.relationsQueryFormGroup.disable({emitEvent:!1}):this.relationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.relationsQueryFormGroup.reset(e||{},{emitEvent:!1})}}e("RelationsQueryConfigComponent",_n),_n.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_n,deps:[{token:R.Store},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),_n.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:_n,selector:"tb-relations-query-config",inputs:{disabled:"disabled",required:"required"},providers:[{provide:K,useExisting:c((()=>_n)),multi:!0}],usesInheritance:!0,ngImport:t,template:'<section [formGroup]="relationsQueryFormGroup" class="tb-form-panel stroked">\n <div class="tb-form-panel-title tb-required" translate>tb.rulenode.relations-query</div>\n <section>\n <div fxLayoutGap="16px" fxLayout="row">\n <mat-form-field fxFlex="50" class="mat-block" style="min-width: 100px;" hideRequiredMarker>\n <mat-label translate>relation.direction</mat-label>\n <mat-select required formControlName="direction">\n <mat-option *ngFor="let type of directionTypes" [value]="type">\n {{ directionTypeTranslations.get(type) | translate }} <span translate>tb.rulenode.relations-query-config-direction-suffix</span>\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field fxFlex="50" floatLabel="always" class="mat-block">\n <mat-label translate>tb.rulenode.max-relation-level</mat-label>\n <input matInput\n type="number"\n min="1"\n step="1"\n placeholder="{{ \'tb.rulenode.unlimited-level\' | translate }}"\n formControlName="maxLevel">\n <mat-error *ngIf="relationsQueryFormGroup.get(\'maxLevel\').hasError(\'min\')">\n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.last-level-relation-tooltip\' | translate }}"\n *ngIf="relationsQueryFormGroup.get(\'maxLevel\').value > 1"\n class="tb-form-row no-border no-padding last-level-slide-toggle">\n <mat-slide-toggle class="mat-slide" formControlName="fetchLastLevelOnly">\n {{ \'alias.last-level-relation\' | translate }}\n </mat-slide-toggle>\n </div>\n </section>\n <section [formGroup]="relationsQueryFormGroup" class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>relation.relation-filters</div>\n <tb-relation-filters\n formControlName="filters">\n </tb-relation-filters>\n </section>\n</section>\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:Ze.RelationFiltersComponent,selector:"tb-relation-filters",inputs:["disabled","allowedEntityTypes","enableNotOption"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_n,decorators:[{type:n,args:[{selector:"tb-relations-query-config",providers:[{provide:K,useExisting:c((()=>_n)),multi:!0}],template:'<section [formGroup]="relationsQueryFormGroup" class="tb-form-panel stroked">\n <div class="tb-form-panel-title tb-required" translate>tb.rulenode.relations-query</div>\n <section>\n <div fxLayoutGap="16px" fxLayout="row">\n <mat-form-field fxFlex="50" class="mat-block" style="min-width: 100px;" hideRequiredMarker>\n <mat-label translate>relation.direction</mat-label>\n <mat-select required formControlName="direction">\n <mat-option *ngFor="let type of directionTypes" [value]="type">\n {{ directionTypeTranslations.get(type) | translate }} <span translate>tb.rulenode.relations-query-config-direction-suffix</span>\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field fxFlex="50" floatLabel="always" class="mat-block">\n <mat-label translate>tb.rulenode.max-relation-level</mat-label>\n <input matInput\n type="number"\n min="1"\n step="1"\n placeholder="{{ \'tb.rulenode.unlimited-level\' | translate }}"\n formControlName="maxLevel">\n <mat-error *ngIf="relationsQueryFormGroup.get(\'maxLevel\').hasError(\'min\')">\n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.last-level-relation-tooltip\' | translate }}"\n *ngIf="relationsQueryFormGroup.get(\'maxLevel\').value > 1"\n class="tb-form-row no-border no-padding last-level-slide-toggle">\n <mat-slide-toggle class="mat-slide" formControlName="fetchLastLevelOnly">\n {{ \'alias.last-level-relation\' | translate }}\n </mat-slide-toggle>\n </div>\n </section>\n <section [formGroup]="relationsQueryFormGroup" class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>relation.relation-filters</div>\n <tb-relation-filters\n formControlName="filters">\n </tb-relation-filters>\n </section>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder}]},propDecorators:{disabled:[{type:m}],required:[{type:m}]}});class Bn extends T{get required(){return this.requiredValue}set required(e){this.requiredValue=we(e)}constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.truncate=n,this.fb=r,this.placeholder="tb.rulenode.add-message-type",this.separatorKeysCodes=[ke,Te,Le],this.messageTypes=[],this.messageTypesList=[],this.searchText="",this.propagateChange=e=>{},this.messageTypeConfigForm=this.fb.group({messageType:[null]});for(const e of Object.keys(I))this.messageTypesList.push({name:L.get(I[e]),value:e})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}ngOnInit(){this.filteredMessageTypes=this.messageTypeConfigForm.get("messageType").valueChanges.pipe(Ke(""),Be((e=>e||"")),He((e=>this.fetchMessageTypes(e))),ze())}setDisabledState(e){this.disabled=e,this.disabled?this.messageTypeConfigForm.disable({emitEvent:!1}):this.messageTypeConfigForm.enable({emitEvent:!1})}writeValue(e){this.searchText="",this.messageTypes.length=0,e&&e.forEach((e=>{const t=this.messageTypesList.find((t=>t.value===e));t?this.messageTypes.push({name:t.name,value:t.value}):this.messageTypes.push({name:e,value:e})}))}displayMessageTypeFn(e){return e?e.name:void 0}textIsNotEmpty(e){return e&&e.length>0}createMessageType(e,t){e.preventDefault(),this.transformMessageType(t)}add(e){this.transformMessageType(e.value)}fetchMessageTypes(e){if(this.searchText=e,this.searchText&&this.searchText.length){const e=this.searchText.toUpperCase();return se(this.messageTypesList.filter((t=>t.name.toUpperCase().includes(e))))}return se(this.messageTypesList)}transformMessageType(e){if((e||"").trim()){let t;const n=e.trim(),r=this.messageTypesList.find((e=>e.name===n));t=r?{name:r.name,value:r.value}:{name:n,value:n},t&&this.addMessageType(t)}this.clear("")}remove(e){const t=this.messageTypes.indexOf(e);t>=0&&(this.messageTypes.splice(t,1),this.updateModel())}selected(e){this.addMessageType(e.option.value),this.clear("")}addMessageType(e){-1===this.messageTypes.findIndex((t=>t.value===e.value))&&(this.messageTypes.push(e),this.updateModel())}onFocus(){this.messageTypeConfigForm.get("messageType").updateValueAndValidity({onlySelf:!0,emitEvent:!0})}clear(e=""){this.messageTypeInput.nativeElement.value=e,this.messageTypeConfigForm.get("messageType").patchValue(null,{emitEvent:!0}),setTimeout((()=>{this.messageTypeInput.nativeElement.blur(),this.messageTypeInput.nativeElement.focus()}),0)}updateModel(){const e=this.messageTypes.map((e=>e.value));this.required?(this.chipList.errorState=!e.length,this.propagateChange(e.length>0?e:null)):(this.chipList.errorState=!1,this.propagateChange(e))}}e("MessageTypesConfigComponent",Bn),Bn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Bn,deps:[{token:R.Store},{token:X.TranslateService},{token:q.TruncatePipe},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Bn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Bn,selector:"tb-message-types-config",inputs:{required:"required",label:"label",placeholder:"placeholder",disabled:"disabled"},providers:[{provide:K,useExisting:c((()=>Bn)),multi:!0}],viewQueries:[{propertyName:"chipList",first:!0,predicate:["chipList"],descendants:!0},{propertyName:"matAutocomplete",first:!0,predicate:["messageTypeAutocomplete"],descendants:!0},{propertyName:"messageTypeInput",first:!0,predicate:["messageTypeInput"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'<mat-form-field [formGroup]="messageTypeConfigForm" style="width: 100%;">\n <mat-label *ngIf="label">{{ label }}</mat-label>\n <mat-chip-grid #chipList [required]="required">\n <mat-chip-row\n *ngFor="let messageType of messageTypes"\n [removable]="true"\n (removed)="remove(messageType)">\n {{messageType.name}}\n <mat-icon matChipRemove>close</mat-icon>\n </mat-chip-row>\n <input matInput type="text" placeholder="{{ placeholder | translate }}"\n #messageTypeInput\n (focusin)="onFocus()"\n formControlName="messageType"\n matAutocompleteOrigin\n #origin="matAutocompleteOrigin"\n [matAutocompleteConnectedTo]="origin"\n [matAutocomplete]="messageTypeAutocomplete"\n [matChipInputFor]="chipList"\n [matChipInputSeparatorKeyCodes]="separatorKeysCodes"\n (matChipInputTokenEnd)="add($event)">\n </mat-chip-grid>\n <mat-autocomplete #messageTypeAutocomplete="matAutocomplete"\n class="tb-autocomplete"\n (optionSelected)="selected($event)"\n [displayWith]="displayMessageTypeFn">\n <mat-option *ngFor="let messageType of filteredMessageTypes | async" [value]="messageType">\n <span [innerHTML]="messageType.name | highlight:searchText"></span>\n </mat-option>\n <mat-option *ngIf="(filteredMessageTypes | async)?.length === 0" [value]="null" class="tb-not-found">\n <div class="tb-not-found-content" (click)="$event.stopPropagation()">\n <div *ngIf="!textIsNotEmpty(searchText); else searchNotEmpty">\n <span translate>tb.rulenode.no-message-types-found</span>\n </div>\n <ng-template #searchNotEmpty>\n <span>\n {{ \'tb.rulenode.no-message-type-matching\' | translate :\n {messageType: truncate.transform(searchText, true, 6, &apos;...&apos;)}\n }}\n </span>\n </ng-template>\n <span>\n <a translate (click)="createMessageType($event, searchText)">tb.rulenode.create-new-message-type</a>\n </span>\n </div>\n </mat-option>\n </mat-autocomplete>\n <mat-icon class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon" matSuffix\n color="primary"\n matTooltip="{{ \'tb.rulenode.chip-help\' | translate: { inputName: \'tb.rulenode.message-type\' | translate } }}">help</mat-icon>\n <mat-error *ngIf="chipList.errorState">\n {{ \'tb.rulenode.select-message-types-required\' | translate }}\n </mat-error>\n</mat-form-field>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:$e.MatAutocomplete,selector:"mat-autocomplete",inputs:["disableRipple","hideSingleSelectionIndicator"],exportAs:["matAutocomplete"]},{kind:"directive",type:$e.MatAutocompleteTrigger,selector:"input[matAutocomplete], textarea[matAutocomplete]",exportAs:["matAutocompleteTrigger"]},{kind:"directive",type:$e.MatAutocompleteOrigin,selector:"[matAutocompleteOrigin]",exportAs:["matAutocompleteOrigin"]},{kind:"component",type:Se.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:Se.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:Se.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:Se.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:j.AsyncPipe,name:"async"},{kind:"pipe",type:Je.HighlightPipe,name:"highlight"},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Bn,decorators:[{type:n,args:[{selector:"tb-message-types-config",providers:[{provide:K,useExisting:c((()=>Bn)),multi:!0}],template:'<mat-form-field [formGroup]="messageTypeConfigForm" style="width: 100%;">\n <mat-label *ngIf="label">{{ label }}</mat-label>\n <mat-chip-grid #chipList [required]="required">\n <mat-chip-row\n *ngFor="let messageType of messageTypes"\n [removable]="true"\n (removed)="remove(messageType)">\n {{messageType.name}}\n <mat-icon matChipRemove>close</mat-icon>\n </mat-chip-row>\n <input matInput type="text" placeholder="{{ placeholder | translate }}"\n #messageTypeInput\n (focusin)="onFocus()"\n formControlName="messageType"\n matAutocompleteOrigin\n #origin="matAutocompleteOrigin"\n [matAutocompleteConnectedTo]="origin"\n [matAutocomplete]="messageTypeAutocomplete"\n [matChipInputFor]="chipList"\n [matChipInputSeparatorKeyCodes]="separatorKeysCodes"\n (matChipInputTokenEnd)="add($event)">\n </mat-chip-grid>\n <mat-autocomplete #messageTypeAutocomplete="matAutocomplete"\n class="tb-autocomplete"\n (optionSelected)="selected($event)"\n [displayWith]="displayMessageTypeFn">\n <mat-option *ngFor="let messageType of filteredMessageTypes | async" [value]="messageType">\n <span [innerHTML]="messageType.name | highlight:searchText"></span>\n </mat-option>\n <mat-option *ngIf="(filteredMessageTypes | async)?.length === 0" [value]="null" class="tb-not-found">\n <div class="tb-not-found-content" (click)="$event.stopPropagation()">\n <div *ngIf="!textIsNotEmpty(searchText); else searchNotEmpty">\n <span translate>tb.rulenode.no-message-types-found</span>\n </div>\n <ng-template #searchNotEmpty>\n <span>\n {{ \'tb.rulenode.no-message-type-matching\' | translate :\n {messageType: truncate.transform(searchText, true, 6, &apos;...&apos;)}\n }}\n </span>\n </ng-template>\n <span>\n <a translate (click)="createMessageType($event, searchText)">tb.rulenode.create-new-message-type</a>\n </span>\n </div>\n </mat-option>\n </mat-autocomplete>\n <mat-icon class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon" matSuffix\n color="primary"\n matTooltip="{{ \'tb.rulenode.chip-help\' | translate: { inputName: \'tb.rulenode.message-type\' | translate } }}">help</mat-icon>\n <mat-error *ngIf="chipList.errorState">\n {{ \'tb.rulenode.select-message-types-required\' | translate }}\n </mat-error>\n</mat-form-field>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:X.TranslateService},{type:q.TruncatePipe},{type:O.FormBuilder}]},propDecorators:{required:[{type:m}],label:[{type:m}],placeholder:[{type:m}],disabled:[{type:m}],chipList:[{type:u,args:["chipList",{static:!1}]}],matAutocomplete:[{type:u,args:["messageTypeAutocomplete",{static:!1}]}],messageTypeInput:[{type:u,args:["messageTypeInput",{static:!1}]}]}});class Kn extends T{get required(){return this.requiredValue}set required(e){this.requiredValue=we(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.subscriptions=[],this.disableCertPemCredentials=!1,this.passwordFieldRequired=!0,this.allCredentialsTypes=Yt,this.credentialsTypeTranslationsMap=Wt,this.propagateChange=e=>{}}ngOnInit(){this.credentialsConfigFormGroup=this.fb.group({type:[null,[_.required]],username:[null,[]],password:[null,[]],caCert:[null,[]],caCertFileName:[null,[]],privateKey:[null,[]],privateKeyFileName:[null,[]],cert:[null,[]],certFileName:[null,[]]}),this.subscriptions.push(this.credentialsConfigFormGroup.valueChanges.subscribe((()=>{this.updateView()}))),this.subscriptions.push(this.credentialsConfigFormGroup.get("type").valueChanges.subscribe((()=>{this.credentialsTypeChanged()})))}ngOnChanges(e){for(const t of Object.keys(e)){const n=e[t];if(!n.firstChange&&n.currentValue!==n.previousValue&&n.currentValue&&"disableCertPemCredentials"===t){"cert.PEM"===this.credentialsConfigFormGroup.get("type").value&&setTimeout((()=>{this.credentialsConfigFormGroup.get("type").patchValue("anonymous",{emitEvent:!0})}))}}}ngOnDestroy(){this.subscriptions.forEach((e=>e.unsubscribe()))}writeValue(e){ye(e)&&(this.credentialsConfigFormGroup.reset(e,{emitEvent:!1}),this.updateValidators())}setDisabledState(e){e?this.credentialsConfigFormGroup.disable({emitEvent:!1}):(this.credentialsConfigFormGroup.enable({emitEvent:!1}),this.updateValidators())}updateView(){let e=this.credentialsConfigFormGroup.value;const t=e.type;switch(t){case"anonymous":e={type:t};break;case"basic":e={type:t,username:e.username,password:e.password};break;case"cert.PEM":delete e.username}this.propagateChange(e)}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}validate(e){return this.credentialsConfigFormGroup.valid?null:{credentialsConfig:{valid:!1}}}credentialsTypeChanged(){this.credentialsConfigFormGroup.patchValue({username:null,password:null,caCert:null,caCertFileName:null,privateKey:null,privateKeyFileName:null,cert:null,certFileName:null}),this.updateValidators()}updateValidators(e=!1){const t=this.credentialsConfigFormGroup.get("type").value;switch(e&&this.credentialsConfigFormGroup.reset({type:t},{emitEvent:!1}),this.credentialsConfigFormGroup.setValidators([]),this.credentialsConfigFormGroup.get("username").setValidators([]),this.credentialsConfigFormGroup.get("password").setValidators([]),t){case"anonymous":break;case"basic":this.credentialsConfigFormGroup.get("username").setValidators([_.required]),this.credentialsConfigFormGroup.get("password").setValidators(this.passwordFieldRequired?[_.required]:[]);break;case"cert.PEM":this.credentialsConfigFormGroup.setValidators([this.requiredFilesSelected(_.required,[["caCert","caCertFileName"],["privateKey","privateKeyFileName","cert","certFileName"]])])}this.credentialsConfigFormGroup.get("username").updateValueAndValidity({emitEvent:e}),this.credentialsConfigFormGroup.get("password").updateValueAndValidity({emitEvent:e}),this.credentialsConfigFormGroup.updateValueAndValidity({emitEvent:e})}requiredFilesSelected(e,t=null){return n=>{t||(t=[Object.keys(n.controls)]);return n?.controls&&t.some((t=>t.every((t=>!e(n.controls[t])))))?null:{notAllRequiredFilesSelected:!0}}}}e("CredentialsConfigComponent",Kn),Kn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kn,deps:[{token:R.Store},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Kn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Kn,selector:"tb-credentials-config",inputs:{required:"required",disableCertPemCredentials:"disableCertPemCredentials",passwordFieldRequired:"passwordFieldRequired"},providers:[{provide:K,useExisting:c((()=>Kn)),multi:!0},{provide:H,useExisting:c((()=>Kn)),multi:!0}],usesInheritance:!0,usesOnChanges:!0,ngImport:t,template:'<section [formGroup]="credentialsConfigFormGroup" fxLayout="column">\n <mat-expansion-panel class="tb-credentials-config-panel-group">\n <mat-expansion-panel-header>\n <mat-panel-title translate>tb.rulenode.credentials</mat-panel-title>\n <mat-panel-description>\n {{ credentialsTypeTranslationsMap.get(credentialsConfigFormGroup.get(\'type\').value) | translate }}\n </mat-panel-description>\n </mat-expansion-panel-header>\n <ng-template matExpansionPanelContent>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.credentials-type</mat-label>\n <mat-select formControlName="type" required>\n <mat-option *ngFor="let credentialsType of allCredentialsTypes" [value]="credentialsType"\n [disabled]="credentialsType === \'cert.PEM\' && disableCertPemCredentials">\n {{ credentialsTypeTranslationsMap.get(credentialsType) | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf="credentialsConfigFormGroup.get(\'type\').hasError(\'required\')">\n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <section fxLayout="column" [ngSwitch]="credentialsConfigFormGroup.get(\'type\').value">\n <ng-template ngSwitchCase="anonymous">\n </ng-template>\n <ng-template ngSwitchCase="basic">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.username</mat-label>\n <input required matInput formControlName="username">\n <mat-error *ngIf="credentialsConfigFormGroup.get(\'username\').hasError(\'required\')">\n {{ \'tb.rulenode.username-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.password</mat-label>\n <input type="password" [required]="passwordFieldRequired" matInput formControlName="password">\n <tb-toggle-password matSuffix></tb-toggle-password>\n <mat-error *ngIf="credentialsConfigFormGroup.get(\'password\').hasError(\'required\')">\n {{ \'tb.rulenode.password-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </ng-template>\n <ng-template ngSwitchCase="cert.PEM">\n <div class="tb-hint">{{ \'tb.rulenode.credentials-pem-hint\' | translate }}</div>\n <tb-file-input formControlName="caCert"\n inputId="caCertSelect"\n [existingFileName]="credentialsConfigFormGroup.get(\'caCertFileName\').value"\n (fileNameChanged)="credentialsConfigFormGroup.get(\'caCertFileName\').setValue($event)"\n label="{{\'tb.rulenode.ca-cert\' | translate}}"\n noFileText="tb.rulenode.no-file"\n dropLabel="{{\'tb.rulenode.drop-file\' | translate}}">\n </tb-file-input>\n <tb-file-input formControlName="cert"\n inputId="CertSelect"\n [existingFileName]="credentialsConfigFormGroup.get(\'certFileName\').value"\n (fileNameChanged)="credentialsConfigFormGroup.get(\'certFileName\').setValue($event)"\n label="{{\'tb.rulenode.cert\' | translate}}"\n noFileText="tb.rulenode.no-file"\n dropLabel="{{\'tb.rulenode.drop-file\' | translate}}">\n </tb-file-input>\n <tb-file-input style="padding-bottom: 8px;"\n formControlName="privateKey"\n inputId="privateKeySelect"\n [existingFileName]="credentialsConfigFormGroup.get(\'privateKeyFileName\').value"\n (fileNameChanged)="credentialsConfigFormGroup.get(\'privateKeyFileName\').setValue($event)"\n label="{{\'tb.rulenode.private-key\' | translate}}"\n noFileText="tb.rulenode.no-file"\n dropLabel="{{\'tb.rulenode.drop-file\' | translate}}">\n </tb-file-input>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.private-key-password</mat-label>\n <input type="password" matInput formControlName="password">\n <tb-toggle-password matSuffix></tb-toggle-password>\n </mat-form-field>\n </ng-template>\n </section>\n </ng-template>\n </mat-expansion-panel>\n</section>\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:j.NgSwitch,selector:"[ngSwitch]",inputs:["ngSwitch"]},{kind:"directive",type:j.NgSwitchCase,selector:"[ngSwitchCase]",inputs:["ngSwitchCase"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:ae.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:ae.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:ae.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:ae.MatExpansionPanelDescription,selector:"mat-panel-description"},{kind:"directive",type:ae.MatExpansionPanelContent,selector:"ng-template[matExpansionPanelContent]"},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Xe.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:et.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kn,decorators:[{type:n,args:[{selector:"tb-credentials-config",providers:[{provide:K,useExisting:c((()=>Kn)),multi:!0},{provide:H,useExisting:c((()=>Kn)),multi:!0}],template:'<section [formGroup]="credentialsConfigFormGroup" fxLayout="column">\n <mat-expansion-panel class="tb-credentials-config-panel-group">\n <mat-expansion-panel-header>\n <mat-panel-title translate>tb.rulenode.credentials</mat-panel-title>\n <mat-panel-description>\n {{ credentialsTypeTranslationsMap.get(credentialsConfigFormGroup.get(\'type\').value) | translate }}\n </mat-panel-description>\n </mat-expansion-panel-header>\n <ng-template matExpansionPanelContent>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.credentials-type</mat-label>\n <mat-select formControlName="type" required>\n <mat-option *ngFor="let credentialsType of allCredentialsTypes" [value]="credentialsType"\n [disabled]="credentialsType === \'cert.PEM\' && disableCertPemCredentials">\n {{ credentialsTypeTranslationsMap.get(credentialsType) | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf="credentialsConfigFormGroup.get(\'type\').hasError(\'required\')">\n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <section fxLayout="column" [ngSwitch]="credentialsConfigFormGroup.get(\'type\').value">\n <ng-template ngSwitchCase="anonymous">\n </ng-template>\n <ng-template ngSwitchCase="basic">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.username</mat-label>\n <input required matInput formControlName="username">\n <mat-error *ngIf="credentialsConfigFormGroup.get(\'username\').hasError(\'required\')">\n {{ \'tb.rulenode.username-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.password</mat-label>\n <input type="password" [required]="passwordFieldRequired" matInput formControlName="password">\n <tb-toggle-password matSuffix></tb-toggle-password>\n <mat-error *ngIf="credentialsConfigFormGroup.get(\'password\').hasError(\'required\')">\n {{ \'tb.rulenode.password-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </ng-template>\n <ng-template ngSwitchCase="cert.PEM">\n <div class="tb-hint">{{ \'tb.rulenode.credentials-pem-hint\' | translate }}</div>\n <tb-file-input formControlName="caCert"\n inputId="caCertSelect"\n [existingFileName]="credentialsConfigFormGroup.get(\'caCertFileName\').value"\n (fileNameChanged)="credentialsConfigFormGroup.get(\'caCertFileName\').setValue($event)"\n label="{{\'tb.rulenode.ca-cert\' | translate}}"\n noFileText="tb.rulenode.no-file"\n dropLabel="{{\'tb.rulenode.drop-file\' | translate}}">\n </tb-file-input>\n <tb-file-input formControlName="cert"\n inputId="CertSelect"\n [existingFileName]="credentialsConfigFormGroup.get(\'certFileName\').value"\n (fileNameChanged)="credentialsConfigFormGroup.get(\'certFileName\').setValue($event)"\n label="{{\'tb.rulenode.cert\' | translate}}"\n noFileText="tb.rulenode.no-file"\n dropLabel="{{\'tb.rulenode.drop-file\' | translate}}">\n </tb-file-input>\n <tb-file-input style="padding-bottom: 8px;"\n formControlName="privateKey"\n inputId="privateKeySelect"\n [existingFileName]="credentialsConfigFormGroup.get(\'privateKeyFileName\').value"\n (fileNameChanged)="credentialsConfigFormGroup.get(\'privateKeyFileName\').setValue($event)"\n label="{{\'tb.rulenode.private-key\' | translate}}"\n noFileText="tb.rulenode.no-file"\n dropLabel="{{\'tb.rulenode.drop-file\' | translate}}">\n </tb-file-input>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.private-key-password</mat-label>\n <input type="password" matInput formControlName="password">\n <tb-toggle-password matSuffix></tb-toggle-password>\n </mat-form-field>\n </ng-template>\n </section>\n </ng-template>\n </mat-expansion-panel>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder}]},propDecorators:{required:[{type:m}],disableCertPemCredentials:[{type:m}],passwordFieldRequired:[{type:m}]}});class Hn{set required(e){this.requiredValue!==e&&(this.requiredValue=e,this.updateValidators())}get required(){return this.requiredValue}constructor(e){this.fb=e,this.subscriptSizing="fixed",this.messageTypes=[{name:"Post attributes",value:"POST_ATTRIBUTES_REQUEST"},{name:"Post telemetry",value:"POST_TELEMETRY_REQUEST"},{name:"Custom",value:""}],this.propagateChange=()=>{},this.destroy$=new ie,this.messageTypeFormGroup=this.fb.group({messageTypeAlias:[null,[_.required]],messageType:[{value:null,disabled:!0},[_.maxLength(255)]]}),this.messageTypeFormGroup.get("messageTypeAlias").valueChanges.pipe(le(this.destroy$)).subscribe((e=>this.updateMessageTypeValue(e))),this.messageTypeFormGroup.valueChanges.pipe(le(this.destroy$)).subscribe((()=>this.updateView()))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}registerOnTouched(e){}registerOnChange(e){this.propagateChange=e}writeValue(e){this.modelValue=e;let t=this.messageTypes.find((t=>t.value===e));t||(t=this.messageTypes.find((e=>""===e.value))),this.messageTypeFormGroup.get("messageTypeAlias").patchValue(t,{emitEvent:!1}),this.messageTypeFormGroup.get("messageType").patchValue(e,{emitEvent:!1})}validate(){return this.messageTypeFormGroup.valid?null:{messageTypeInvalid:!0}}setDisabledState(e){this.disabled=e,e?this.messageTypeFormGroup.disable({emitEvent:!1}):(this.messageTypeFormGroup.enable({emitEvent:!1}),"Custom"!==this.messageTypeFormGroup.get("messageTypeAlias").value?.name&&this.messageTypeFormGroup.get("messageType").disable({emitEvent:!1}))}updateView(){const e=this.messageTypeFormGroup.getRawValue().messageType;this.modelValue!==e&&(this.modelValue=e,this.propagateChange(this.modelValue))}updateValidators(){this.messageTypeFormGroup.get("messageType").setValidators(this.required?[_.required,_.maxLength(255)]:[_.maxLength(255)]),this.messageTypeFormGroup.get("messageType").updateValueAndValidity({emitEvent:!1})}updateMessageTypeValue(e){"Custom"!==e?.name?this.messageTypeFormGroup.get("messageType").disable({emitEvent:!1}):this.messageTypeFormGroup.get("messageType").enable({emitEvent:!1}),this.messageTypeFormGroup.get("messageType").patchValue(e.value??null)}}e("OutputMessageTypeAutocompleteComponent",Hn),Hn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hn,deps:[{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Hn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Hn,selector:"tb-output-message-type-autocomplete",inputs:{subscriptSizing:"subscriptSizing",disabled:"disabled",required:"required"},providers:[{provide:K,useExisting:c((()=>Hn)),multi:!0},{provide:H,useExisting:c((()=>Hn)),multi:!0}],ngImport:t,template:'<section class="tb-form-row no-border no-padding tb-standard-fields column-xs" [formGroup]="messageTypeFormGroup">\n <mat-form-field class="flex" subscriptSizing="{{ subscriptSizing }}" hideRequiredMarker>\n <mat-label>{{\'tb.rulenode.output-message-type\' | translate}}</mat-label>\n <mat-select formControlName="messageTypeAlias">\n <mat-option *ngFor="let msgType of messageTypes" [value]="msgType">\n {{msgType.name}}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="flex" subscriptSizing="{{ subscriptSizing }}" [hideRequiredMarker]="messageTypeFormGroup.get(\'messageType\').disabled">\n <mat-label>{{\'tb.rulenode.message-type-value\' | translate}}</mat-label>\n <input matInput type="text" formControlName="messageType">\n <button type="button"\n matSuffix\n mat-icon-button\n aria-label="Copy"\n *ngIf="messageTypeFormGroup.get(\'messageType\').value"\n ngxClipboard\n [cbContent]="messageTypeFormGroup.get(\'messageType\').value"\n matTooltip="{{ \'tb.rulenode.copy-message-type\' | translate }}">\n <mat-icon aria-hidden="false"\n aria-label="help-icon">content_copy\n </mat-icon>\n </button>\n <mat-error *ngIf="messageTypeFormGroup.get(\'messageType\').hasError(\'required\')">\n {{ \'tb.rulenode.message-type-value-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="messageTypeFormGroup.get(\'messageType\').hasError(\'maxlength\')">\n {{ \'tb.rulenode.message-type-value-max-length\' | translate }}\n </mat-error>\n </mat-form-field>\n</section>\n\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ee.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:yt,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),Ye([S()],Hn.prototype,"disabled",void 0),Ye([S()],Hn.prototype,"required",null),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hn,decorators:[{type:n,args:[{selector:"tb-output-message-type-autocomplete",providers:[{provide:K,useExisting:c((()=>Hn)),multi:!0},{provide:H,useExisting:c((()=>Hn)),multi:!0}],template:'<section class="tb-form-row no-border no-padding tb-standard-fields column-xs" [formGroup]="messageTypeFormGroup">\n <mat-form-field class="flex" subscriptSizing="{{ subscriptSizing }}" hideRequiredMarker>\n <mat-label>{{\'tb.rulenode.output-message-type\' | translate}}</mat-label>\n <mat-select formControlName="messageTypeAlias">\n <mat-option *ngFor="let msgType of messageTypes" [value]="msgType">\n {{msgType.name}}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="flex" subscriptSizing="{{ subscriptSizing }}" [hideRequiredMarker]="messageTypeFormGroup.get(\'messageType\').disabled">\n <mat-label>{{\'tb.rulenode.message-type-value\' | translate}}</mat-label>\n <input matInput type="text" formControlName="messageType">\n <button type="button"\n matSuffix\n mat-icon-button\n aria-label="Copy"\n *ngIf="messageTypeFormGroup.get(\'messageType\').value"\n ngxClipboard\n [cbContent]="messageTypeFormGroup.get(\'messageType\').value"\n matTooltip="{{ \'tb.rulenode.copy-message-type\' | translate }}">\n <mat-icon aria-hidden="false"\n aria-label="help-icon">content_copy\n </mat-icon>\n </button>\n <mat-error *ngIf="messageTypeFormGroup.get(\'messageType\').hasError(\'required\')">\n {{ \'tb.rulenode.message-type-value-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="messageTypeFormGroup.get(\'messageType\').hasError(\'maxlength\')">\n {{ \'tb.rulenode.message-type-value-max-length\' | translate }}\n </mat-error>\n </mat-form-field>\n</section>\n\n'}]}],ctorParameters:function(){return[{type:O.FormBuilder}]},propDecorators:{subscriptSizing:[{type:m}],disabled:[{type:m}],required:[{type:m}]}});class zn{constructor(e,t){this.fb=e,this.translate=t,this.translation=pn,this.propagateChange=()=>{},this.destroy$=new ie,this.selectOptions=[]}ngOnInit(){this.initOptions(),this.chipControlGroup=this.fb.group({chipControl:[null,[]]}),this.chipControlGroup.get("chipControl").valueChanges.pipe(Ue(this.destroy$)).subscribe((e=>{e&&this.propagateChange(e)}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}initOptions(){for(const e of this.translation.keys())this.selectOptions.push({value:e,name:this.translate.instant(this.translation.get(e))})}writeValue(e){this.chipControlGroup.get("chipControl").patchValue(e,{emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){e?this.chipControlGroup.disable({emitEvent:!1}):this.chipControlGroup.enable({emitEvent:!1})}}e("MsgMetadataChipComponent",zn),zn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zn,deps:[{token:O.FormBuilder},{token:X.TranslateService}],target:t.ɵɵFactoryTarget.Component}),zn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:zn,selector:"tb-msg-metadata-chip",inputs:{labelText:"labelText",translation:"translation"},providers:[{provide:K,useExisting:c((()=>zn)),multi:!0}],ngImport:t,template:'<div [formGroup]="chipControlGroup" class="tb-form-row space-between">\n <div class="fixed-title-width">{{ labelText }}</div>\n <mat-chip-listbox formControlName="chipControl">\n <mat-chip-option *ngFor="let option of selectOptions"\n selectable="{{ chipControlGroup.get(\'chipControl\').value !== option.value }}"\n color="primary"\n [value]="option.value">{{ option.name }}</mat-chip-option>\n </mat-chip-listbox>\n</div>\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Se.MatChipListbox,selector:"mat-chip-listbox",inputs:["tabIndex","multiple","aria-orientation","selectable","compareWith","required","hideSingleSelectionIndicator","value"],outputs:["change"]},{kind:"component",type:Se.MatChipOption,selector:"mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]",inputs:["color","disabled","disableRipple","tabIndex","selectable","selected"],outputs:["selectionChange"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zn,decorators:[{type:n,args:[{selector:"tb-msg-metadata-chip",providers:[{provide:K,useExisting:c((()=>zn)),multi:!0}],template:'<div [formGroup]="chipControlGroup" class="tb-form-row space-between">\n <div class="fixed-title-width">{{ labelText }}</div>\n <mat-chip-listbox formControlName="chipControl">\n <mat-chip-option *ngFor="let option of selectOptions"\n selectable="{{ chipControlGroup.get(\'chipControl\').value !== option.value }}"\n color="primary"\n [value]="option.value">{{ option.name }}</mat-chip-option>\n </mat-chip-listbox>\n</div>\n'}]}],ctorParameters:function(){return[{type:O.FormBuilder},{type:X.TranslateService}]},propDecorators:{labelText:[{type:m}],translation:[{type:m}]}});class Un extends T{constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.injector=n,this.fb=r,this.destroy$=new ie,this.sourceFieldSubcritption=[],this.propagateChange=null,this.disabled=!1,this.required=!1,this.oneMapRequiredValidator=e=>e.get("keyVals").value.length,this.propagateNestedErrors=e=>{if(this.svListFormGroup&&this.svListFormGroup.get("keyVals")&&"VALID"===this.svListFormGroup.get("keyVals")?.status)return null;const t={};if(this.svListFormGroup&&this.svListFormGroup.setErrors(null),e instanceof z||e instanceof U){if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;for(const n of Object.keys(e.controls)){const r=this.propagateNestedErrors(e.controls[n]);if(r&&Object.keys(r).length)for(const e of Object.keys(r))t[e]=!0}return t}if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;return be(t,{})?null:t}}ngOnInit(){this.ngControl=this.injector.get(B),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.svListFormGroup=this.fb.group({keyVals:this.fb.array([])},{validators:[this.propagateNestedErrors,this.oneMapRequiredValidator]}),this.svListFormGroup.valueChanges.pipe(Ue(this.destroy$)).subscribe((()=>{this.updateModel()}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}keyValsFormArray(){return this.svListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.svListFormGroup.disable({emitEvent:!1}):this.svListFormGroup.enable({emitEvent:!1})}writeValue(e){const t=Object.keys(e).map((t=>({key:t,value:e[t]})));if(this.keyValsFormArray().length===t.length)this.keyValsFormArray().patchValue(t,{emitEvent:!1});else{const e=[];t.forEach((t=>{e.push(this.fb.group({key:[t.key,[_.required]],value:[t.value,[_.required,_.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]}))})),this.svListFormGroup.setControl("keyVals",this.fb.array(e,this.propagateNestedErrors),{emitEvent:!1});for(const e of this.keyValsFormArray().controls)this.keyChangeSubscribe(e)}}filterSelectOptions(e){const t=[];for(const e of this.svListFormGroup.get("keyVals").value){const n=this.selectOptions.find((t=>t.value===e.key));n&&t.push(n)}const n=[];for(const r of this.selectOptions)ye(t.find((e=>e.value===r.value)))&&r.value!==e?.get("key").value||n.push(r);return n}removeKeyVal(e){this.keyValsFormArray().removeAt(e),this.sourceFieldSubcritption[e].unsubscribe(),this.sourceFieldSubcritption.splice(e,1)}addKeyVal(){this.keyValsFormArray().push(this.fb.group({key:["",[_.required]],value:["",[_.required,_.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]})),this.keyChangeSubscribe(this.keyValsFormArray().at(this.keyValsFormArray().length-1))}keyChangeSubscribe(e){this.sourceFieldSubcritption.push(e.get("key").valueChanges.pipe(Ue(this.destroy$)).subscribe((t=>{const n=Mt.get(t);e.get("value").patchValue(this.targetKeyPrefix+n[0].toUpperCase()+n.slice(1))})))}validate(e){return!this.svListFormGroup.get("keyVals").value.length&&this.required?{svMapRequired:!0}:this.svListFormGroup.valid?null:{svFieldsRequired:!0}}updateModel(){const e=this.svListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.svListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("SvMapConfigComponent",Un),Un.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Un,deps:[{token:R.Store},{token:X.TranslateService},{token:t.Injector},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Un.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Un,selector:"tb-sv-map-config",inputs:{selectOptions:"selectOptions",disabled:"disabled",labelText:"labelText",requiredText:"requiredText",targetKeyPrefix:"targetKeyPrefix",selectText:"selectText",selectRequiredText:"selectRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",popupHelpLink:"popupHelpLink",required:"required"},providers:[{provide:K,useExisting:c((()=>Un)),multi:!0},{provide:H,useExisting:c((()=>Un)),multi:!0}],usesInheritance:!0,ngImport:t,template:'<section [formGroup]="svListFormGroup" class="tb-form-panel stroked">\n <div class="tb-form-row no-padding no-border space-between">\n <div class="tb-form-panel-title">{{ labelText }}</div>\n <div class="tb-form-panel-hint tb-error" translate *ngIf="svListFormGroup.hasError(\'required\')">\n tb.rulenode.map-fields-required\n </div>\n <div class="tb-form-panel-hint tb-error" translate *ngIf="svListFormGroup.hasError(\'svMapRequired\')">\n {{ requiredText }}\n </div>\n </div>\n <div class="tb-form-panel no-border no-padding">\n <div class="tb-form-table">\n <div class="tb-form-table-header">\n <div class="tb-form-table-header-cell field-space">{{ selectText }}</div>\n <div class="tb-form-table-header-cell field-space">{{ valText }}</div>\n <div class="tb-form-table-header-cell actions-header"></div>\n </div>\n <div class="tb-form-table-body">\n <div class="tb-form-table-row"\n *ngFor="let keyValControl of keyValsFormArray().controls; let $index = index;">\n <mat-form-field class="tb-inline-field field-space" appearance="outline" subscriptSizing="dynamic">\n <mat-select [placeholder]="selectText" [formControl]="keyValControl.get(\'key\')" required>\n <mat-option *ngFor="let option of filterSelectOptions(keyValControl)" [value]="option.value">\n {{option.name}}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="tb-inline-field field-space" appearance="outline" subscriptSizing="dynamic">\n <input [placeholder]="valText" [formControl]="keyValControl.get(\'value\')" matInput/>\n </mat-form-field>\n <div class="tb-form-table-row-cell-buttons">\n <button [ngClass]="{\'tb-hidden\': keyValsFormArray().controls.length === 1}"\n type="button"\n mat-icon-button\n (click)="removeKeyVal($index)"\n [disabled]="isLoading$ | async"\n matTooltip="{{ \'tb.key-val.remove-mapping-entry\' | translate }}"\n matTooltipPosition="above">\n <mat-icon>delete</mat-icon>\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n <div>\n <button [disabled]="(isLoading$ | async) || keyValsFormArray().length >= selectOptions.length"\n type="button" mat-stroked-button color="primary" (click)="addKeyVal()">\n {{ \'tb.key-val.add-mapping-entry\' | translate }}\n </button>\n </div>\n <tb-example-hint [hintText]="hintText" [popupHelpLink]="popupHelpLink"></tb-example-hint>\n</section>\n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:j.NgClass,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ee.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:Pe.DefaultClassDirective,selector:" [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl], [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl], [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]",inputs:["ngClass","ngClass.xs","ngClass.sm","ngClass.md","ngClass.lg","ngClass.xl","ngClass.lt-sm","ngClass.lt-md","ngClass.lt-lg","ngClass.lt-xl","ngClass.gt-xs","ngClass.gt-sm","ngClass.gt-md","ngClass.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ht,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:j.AsyncPipe,name:"async"},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),Ye([S()],Un.prototype,"disabled",void 0),Ye([S()],Un.prototype,"required",void 0),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Un,decorators:[{type:n,args:[{selector:"tb-sv-map-config",providers:[{provide:K,useExisting:c((()=>Un)),multi:!0},{provide:H,useExisting:c((()=>Un)),multi:!0}],template:'<section [formGroup]="svListFormGroup" class="tb-form-panel stroked">\n <div class="tb-form-row no-padding no-border space-between">\n <div class="tb-form-panel-title">{{ labelText }}</div>\n <div class="tb-form-panel-hint tb-error" translate *ngIf="svListFormGroup.hasError(\'required\')">\n tb.rulenode.map-fields-required\n </div>\n <div class="tb-form-panel-hint tb-error" translate *ngIf="svListFormGroup.hasError(\'svMapRequired\')">\n {{ requiredText }}\n </div>\n </div>\n <div class="tb-form-panel no-border no-padding">\n <div class="tb-form-table">\n <div class="tb-form-table-header">\n <div class="tb-form-table-header-cell field-space">{{ selectText }}</div>\n <div class="tb-form-table-header-cell field-space">{{ valText }}</div>\n <div class="tb-form-table-header-cell actions-header"></div>\n </div>\n <div class="tb-form-table-body">\n <div class="tb-form-table-row"\n *ngFor="let keyValControl of keyValsFormArray().controls; let $index = index;">\n <mat-form-field class="tb-inline-field field-space" appearance="outline" subscriptSizing="dynamic">\n <mat-select [placeholder]="selectText" [formControl]="keyValControl.get(\'key\')" required>\n <mat-option *ngFor="let option of filterSelectOptions(keyValControl)" [value]="option.value">\n {{option.name}}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="tb-inline-field field-space" appearance="outline" subscriptSizing="dynamic">\n <input [placeholder]="valText" [formControl]="keyValControl.get(\'value\')" matInput/>\n </mat-form-field>\n <div class="tb-form-table-row-cell-buttons">\n <button [ngClass]="{\'tb-hidden\': keyValsFormArray().controls.length === 1}"\n type="button"\n mat-icon-button\n (click)="removeKeyVal($index)"\n [disabled]="isLoading$ | async"\n matTooltip="{{ \'tb.key-val.remove-mapping-entry\' | translate }}"\n matTooltipPosition="above">\n <mat-icon>delete</mat-icon>\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n <div>\n <button [disabled]="(isLoading$ | async) || keyValsFormArray().length >= selectOptions.length"\n type="button" mat-stroked-button color="primary" (click)="addKeyVal()">\n {{ \'tb.key-val.add-mapping-entry\' | translate }}\n </button>\n </div>\n <tb-example-hint [hintText]="hintText" [popupHelpLink]="popupHelpLink"></tb-example-hint>\n</section>\n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:X.TranslateService},{type:t.Injector},{type:O.FormBuilder}]},propDecorators:{selectOptions:[{type:m}],disabled:[{type:m}],labelText:[{type:m}],requiredText:[{type:m}],targetKeyPrefix:[{type:m}],selectText:[{type:m}],selectRequiredText:[{type:m}],valText:[{type:m}],valRequiredText:[{type:m}],hintText:[{type:m}],popupHelpLink:[{type:m}],required:[{type:m}]}});class jn extends T{get required(){return this.requiredValue}set required(e){this.requiredValue=we(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=N,this.propagateChange=null}ngOnInit(){this.relationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[_.required]],maxLevel:[null,[]],filters:[null]}),this.relationsQueryFormGroup.valueChanges.subscribe((e=>{this.relationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.relationsQueryFormGroup.disable({emitEvent:!1}):this.relationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.relationsQueryFormGroup.reset(e||{},{emitEvent:!1})}}e("RelationsQueryConfigOldComponent",jn),jn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jn,deps:[{token:R.Store},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),jn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:jn,selector:"tb-relations-query-config-old",inputs:{disabled:"disabled",required:"required"},providers:[{provide:K,useExisting:c((()=>jn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'<section fxLayout="column" [formGroup]="relationsQueryFormGroup">\n <mat-checkbox formControlName="fetchLastLevelOnly">\n {{ \'alias.last-level-relation\' | translate }}\n </mat-checkbox>\n <div fxLayoutGap="8px" fxLayout="row">\n <mat-form-field class="mat-block" style="min-width: 100px;">\n <mat-label translate>relation.direction</mat-label>\n <mat-select required matInput formControlName="direction">\n <mat-option *ngFor="let type of directionTypes" [value]="type">\n {{ directionTypeTranslations.get(type) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field fxFlex floatLabel="always" class="mat-block">\n <mat-label translate>tb.rulenode.max-relation-level</mat-label>\n <input matInput\n type="number"\n min="1"\n step="1"\n placeholder="{{ \'tb.rulenode.unlimited-level\' | translate }}"\n formControlName="maxLevel">\n </mat-form-field>\n </div>\n <div class="mat-caption" style="color: #6e6e6e;" translate>relation.relation-filters</div>\n <tb-relation-filters\n formControlName="filters"\n ></tb-relation-filters>\n</section>\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Ie.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Ze.RelationFiltersComponent,selector:"tb-relation-filters",inputs:["disabled","allowedEntityTypes","enableNotOption"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jn,decorators:[{type:n,args:[{selector:"tb-relations-query-config-old",providers:[{provide:K,useExisting:c((()=>jn)),multi:!0}],template:'<section fxLayout="column" [formGroup]="relationsQueryFormGroup">\n <mat-checkbox formControlName="fetchLastLevelOnly">\n {{ \'alias.last-level-relation\' | translate }}\n </mat-checkbox>\n <div fxLayoutGap="8px" fxLayout="row">\n <mat-form-field class="mat-block" style="min-width: 100px;">\n <mat-label translate>relation.direction</mat-label>\n <mat-select required matInput formControlName="direction">\n <mat-option *ngFor="let type of directionTypes" [value]="type">\n {{ directionTypeTranslations.get(type) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field fxFlex floatLabel="always" class="mat-block">\n <mat-label translate>tb.rulenode.max-relation-level</mat-label>\n <input matInput\n type="number"\n min="1"\n step="1"\n placeholder="{{ \'tb.rulenode.unlimited-level\' | translate }}"\n formControlName="maxLevel">\n </mat-form-field>\n </div>\n <div class="mat-caption" style="color: #6e6e6e;" translate>relation.relation-filters</div>\n <tb-relation-filters\n formControlName="filters"\n ></tb-relation-filters>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder}]},propDecorators:{disabled:[{type:m}],required:[{type:m}]}});class $n{constructor(e,t){this.translate=e,this.fb=t,this.propagateChange=e=>{},this.destroy$=new ie,this.separatorKeysCodes=[ke,Te,Le],this.onTouched=()=>{}}ngOnInit(){this.attributeControlGroup=this.fb.group({clientAttributeNames:[[],[]],sharedAttributeNames:[[],[]],serverAttributeNames:[[],[]],latestTsKeyNames:[[],[]],getLatestValueWithTs:[!1,[]]},{validators:this.atLeastOne(_.required,["clientAttributeNames","sharedAttributeNames","serverAttributeNames","latestTsKeyNames"])}),this.attributeControlGroup.valueChanges.pipe(Ue(this.destroy$)).subscribe((e=>{this.propagateChange(this.preparePropagateValue(e))}))}preparePropagateValue(e){const t={};for(const n in e)t[n]="getLatestValueWithTs"===n||ye(e[n])?e[n]:[];return t}validate(){return this.attributeControlGroup.valid?null:{atLeastOneRequired:!0}}atLeastOne(e,t=null){return n=>{t||(t=Object.keys(n.controls));return n?.controls&&t.some((t=>!e(n.controls[t])))?null:{atLeastOne:!0}}}writeValue(e){this.attributeControlGroup.setValue(e,{emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){this.onTouched=e}setDisabledState(e){e?this.attributeControlGroup.disable({emitEvent:!1}):this.attributeControlGroup.enable({emitEvent:!1})}ngOnDestroy(){this.destroy$.next(null),this.destroy$.complete()}}e("SelectAttributesComponent",$n),$n.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$n,deps:[{token:X.TranslateService},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),$n.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:$n,selector:"tb-select-attributes",inputs:{popupHelpLink:"popupHelpLink"},providers:[{provide:K,useExisting:c((()=>$n)),multi:!0},{provide:H,useExisting:$n,multi:!0}],ngImport:t,template:'<div class="tb-form-panel no-padding no-border" [formGroup]="attributeControlGroup">\n <tb-example-hint [hintText]="\'tb.rulenode.kv-map-pattern-hint\' | translate"\n [popupHelpLink]="popupHelpLink"></tb-example-hint>\n <tb-string-items-list subscriptSizing="dynamic" class="mat-block" editable\n (focusout)="onTouched()"\n [placeholder]="\'tb.rulenode.add-attribute-key\' | translate"\n [label]="\'tb.rulenode.client-attributes\' | translate" formControlName="clientAttributeNames">\n <ng-container matSuffix *ngTemplateOutlet="helpIcon"></ng-container>\n </tb-string-items-list>\n <tb-string-items-list subscriptSizing="dynamic" class="mat-block" editable\n (focusout)="onTouched()"\n [placeholder]="\'tb.rulenode.add-attribute-key\' | translate"\n [label]="\'tb.rulenode.shared-attributes\' | translate" formControlName="sharedAttributeNames">\n <ng-container matSuffix *ngTemplateOutlet="helpIcon"></ng-container>\n </tb-string-items-list>\n <tb-string-items-list subscriptSizing="dynamic" class="mat-block" editable\n (focusout)="onTouched()"\n [placeholder]="\'tb.rulenode.add-attribute-key\' | translate"\n [label]="\'tb.rulenode.server-attributes\' | translate" formControlName="serverAttributeNames">\n <ng-container matSuffix *ngTemplateOutlet="helpIcon"></ng-container>\n </tb-string-items-list>\n <tb-string-items-list subscriptSizing="dynamic" editable class="mat-block"\n (focusout)="onTouched()"\n [placeholder]="\'tb.rulenode.add-telemetry-key\' | translate"\n [label]="\'tb.rulenode.latest-telemetry\' | translate" formControlName="latestTsKeyNames">\n <ng-container matSuffix *ngTemplateOutlet="helpIcon"></ng-container>\n </tb-string-items-list>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.fetch-latest-telemetry-with-timestamp-tooltip\' | translate:\n { latestTsKeyName: attributeControlGroup.get(\'latestTsKeyNames\').value[0]} }}"\n *ngIf="attributeControlGroup.get(\'latestTsKeyNames\').value?.length > 0"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="getLatestValueWithTs">\n {{ \'tb.rulenode.fetch-latest-telemetry-with-timestamp\' | translate }}\n </mat-slide-toggle>\n </div>\n</div>\n\n<ng-template #helpIcon>\n <mat-icon class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.chip-help\' | translate: { inputName: \'tb.rulenode.field-name\' | translate } }}">help</mat-icon>\n</ng-template>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:j.NgTemplateOutlet,selector:"[ngTemplateOutlet]",inputs:["ngTemplateOutletContext","ngTemplateOutlet","ngTemplateOutletInjector"]},{kind:"component",type:tt.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:ht,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$n,decorators:[{type:n,args:[{selector:"tb-select-attributes",providers:[{provide:K,useExisting:c((()=>$n)),multi:!0},{provide:H,useExisting:$n,multi:!0}],template:'<div class="tb-form-panel no-padding no-border" [formGroup]="attributeControlGroup">\n <tb-example-hint [hintText]="\'tb.rulenode.kv-map-pattern-hint\' | translate"\n [popupHelpLink]="popupHelpLink"></tb-example-hint>\n <tb-string-items-list subscriptSizing="dynamic" class="mat-block" editable\n (focusout)="onTouched()"\n [placeholder]="\'tb.rulenode.add-attribute-key\' | translate"\n [label]="\'tb.rulenode.client-attributes\' | translate" formControlName="clientAttributeNames">\n <ng-container matSuffix *ngTemplateOutlet="helpIcon"></ng-container>\n </tb-string-items-list>\n <tb-string-items-list subscriptSizing="dynamic" class="mat-block" editable\n (focusout)="onTouched()"\n [placeholder]="\'tb.rulenode.add-attribute-key\' | translate"\n [label]="\'tb.rulenode.shared-attributes\' | translate" formControlName="sharedAttributeNames">\n <ng-container matSuffix *ngTemplateOutlet="helpIcon"></ng-container>\n </tb-string-items-list>\n <tb-string-items-list subscriptSizing="dynamic" class="mat-block" editable\n (focusout)="onTouched()"\n [placeholder]="\'tb.rulenode.add-attribute-key\' | translate"\n [label]="\'tb.rulenode.server-attributes\' | translate" formControlName="serverAttributeNames">\n <ng-container matSuffix *ngTemplateOutlet="helpIcon"></ng-container>\n </tb-string-items-list>\n <tb-string-items-list subscriptSizing="dynamic" editable class="mat-block"\n (focusout)="onTouched()"\n [placeholder]="\'tb.rulenode.add-telemetry-key\' | translate"\n [label]="\'tb.rulenode.latest-telemetry\' | translate" formControlName="latestTsKeyNames">\n <ng-container matSuffix *ngTemplateOutlet="helpIcon"></ng-container>\n </tb-string-items-list>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.fetch-latest-telemetry-with-timestamp-tooltip\' | translate:\n { latestTsKeyName: attributeControlGroup.get(\'latestTsKeyNames\').value[0]} }}"\n *ngIf="attributeControlGroup.get(\'latestTsKeyNames\').value?.length > 0"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="getLatestValueWithTs">\n {{ \'tb.rulenode.fetch-latest-telemetry-with-timestamp\' | translate }}\n </mat-slide-toggle>\n </div>\n</div>\n\n<ng-template #helpIcon>\n <mat-icon class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.chip-help\' | translate: { inputName: \'tb.rulenode.field-name\' | translate } }}">help</mat-icon>\n</ng-template>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:X.TranslateService},{type:O.FormBuilder}]},propDecorators:{popupHelpLink:[{type:m}]}});class Jn extends T{constructor(e,t){super(e),this.store=e,this.fb=t,this.propagateChange=null,this.destroy$=new ie,this.alarmStatus=A,this.alarmStatusTranslations=M}ngOnInit(){this.alarmStatusGroup=this.fb.group({alarmStatus:[null,[]]}),this.alarmStatusGroup.get("alarmStatus").valueChanges.pipe(Ue(this.destroy$)).subscribe((e=>{this.propagateChange(e)}))}setDisabledState(e){e?this.alarmStatusGroup.disable({emitEvent:!1}):this.alarmStatusGroup.enable({emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}writeValue(e){this.alarmStatusGroup.get("alarmStatus").patchValue(e,{emitEvent:!1})}}e("AlarmStatusSelectComponent",Jn),Jn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jn,deps:[{token:R.Store},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Jn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Jn,selector:"tb-alarm-status-select",providers:[{provide:K,useExisting:c((()=>Jn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'<section [formGroup]="alarmStatusGroup" fxLayout="column" fxLayoutAlign="center center">\n <mat-chip-listbox multiple formControlName="alarmStatus" class="chip-listbox" fxLayout="column">\n <div class="toggle-column">\n <mat-chip-option fxFlex class="option" [value]="alarmStatus.ACTIVE_UNACK">\n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_UNACK) | translate }}\n </mat-chip-option>\n <mat-chip-option fxFlex class="option" [value]="alarmStatus.ACTIVE_ACK">\n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_ACK) | translate }}\n </mat-chip-option>\n </div>\n <div class="toggle-column">\n <mat-chip-option fxFlex class="option" [value]="alarmStatus.CLEARED_UNACK">\n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_UNACK) | translate }}\n </mat-chip-option>\n <mat-chip-option fxFlex class="option" [value]="alarmStatus.CLEARED_ACK">\n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_ACK) | translate }}\n </mat-chip-option>\n </div>\n </mat-chip-listbox>\n</section>\n',styles:[":host .chip-listbox{max-width:460px;width:100%}:host .chip-listbox .toggle-column{display:flex;flex:1 1 100%;gap:8px}:host .chip-listbox .option{margin:0}@media screen and (max-width: 959px){:host .chip-listbox{max-width:360px}:host .chip-listbox .toggle-column{flex-direction:column}}:host ::ng-deep .chip-listbox .mdc-evolution-chip-set__chips{gap:8px}:host ::ng-deep .chip-listbox .option button{flex-basis:100%;justify-content:start}:host ::ng-deep .chip-listbox .option .mdc-evolution-chip__graphic{flex-grow:0}\n"],dependencies:[{kind:"component",type:Se.MatChipListbox,selector:"mat-chip-listbox",inputs:["tabIndex","multiple","aria-orientation","selectable","compareWith","required","hideSingleSelectionIndicator","value"],outputs:["change"]},{kind:"component",type:Se.MatChipOption,selector:"mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]",inputs:["color","disabled","disableRipple","tabIndex","selectable","selected"],outputs:["selectionChange"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jn,decorators:[{type:n,args:[{selector:"tb-alarm-status-select",providers:[{provide:K,useExisting:c((()=>Jn)),multi:!0}],template:'<section [formGroup]="alarmStatusGroup" fxLayout="column" fxLayoutAlign="center center">\n <mat-chip-listbox multiple formControlName="alarmStatus" class="chip-listbox" fxLayout="column">\n <div class="toggle-column">\n <mat-chip-option fxFlex class="option" [value]="alarmStatus.ACTIVE_UNACK">\n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_UNACK) | translate }}\n </mat-chip-option>\n <mat-chip-option fxFlex class="option" [value]="alarmStatus.ACTIVE_ACK">\n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_ACK) | translate }}\n </mat-chip-option>\n </div>\n <div class="toggle-column">\n <mat-chip-option fxFlex class="option" [value]="alarmStatus.CLEARED_UNACK">\n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_UNACK) | translate }}\n </mat-chip-option>\n <mat-chip-option fxFlex class="option" [value]="alarmStatus.CLEARED_ACK">\n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_ACK) | translate }}\n </mat-chip-option>\n </div>\n </mat-chip-listbox>\n</section>\n',styles:[":host .chip-listbox{max-width:460px;width:100%}:host .chip-listbox .toggle-column{display:flex;flex:1 1 100%;gap:8px}:host .chip-listbox .option{margin:0}@media screen and (max-width: 959px){:host .chip-listbox{max-width:360px}:host .chip-listbox .toggle-column{flex-direction:column}}:host ::ng-deep .chip-listbox .mdc-evolution-chip-set__chips{gap:8px}:host ::ng-deep .chip-listbox .option button{flex-basis:100%;justify-content:start}:host ::ng-deep .chip-listbox .option .mdc-evolution-chip__graphic{flex-grow:0}\n"]}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder}]}});class Qn{}e("RulenodeCoreConfigCommonModule",Qn),Qn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Qn.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Qn,declarations:[Rn,On,_n,Bn,Kn,Gn,Dn,Hn,Nn,zn,Un,jn,$n,Jn,ht],imports:[J,E,Qe],exports:[Rn,On,_n,Bn,Kn,Gn,Dn,Hn,Nn,zn,Un,jn,$n,Jn,ht]}),Qn.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,imports:[J,E,Qe]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,decorators:[{type:d,args:[{declarations:[Rn,On,_n,Bn,Kn,Gn,Dn,Hn,Nn,zn,Un,jn,$n,Jn,ht],imports:[J,E,Qe],exports:[Rn,On,_n,Bn,Kn,Gn,Dn,Hn,Nn,zn,Un,jn,$n,Jn,ht]}]}]});class Yn{}e("RuleNodeCoreConfigActionModule",Yn),Yn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Yn,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Yn.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Yn,declarations:[wn,vt,An,Sn,Cn,ct,Ct,Ft,kt,kn,Tt,It,vn,Fn,In,qn,Mn,En,Lt,Ln,Tn,Vn,Pn],imports:[J,E,Qe,Qn],exports:[wn,vt,An,Sn,Cn,ct,Ct,Ft,kt,kn,Tt,It,vn,Fn,In,qn,Mn,En,Lt,Ln,Tn,Vn,Pn]}),Yn.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Yn,imports:[J,E,Qe,Qn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Yn,decorators:[{type:d,args:[{declarations:[wn,vt,An,Sn,Cn,ct,Ct,Ft,kt,kn,Tt,It,vn,Fn,In,qn,Mn,En,Lt,Ln,Tn,Vn,Pn],imports:[J,E,Qe,Qn],exports:[wn,vt,An,Sn,Cn,ct,Ct,Ft,kt,kn,Tt,It,vn,Fn,In,qn,Mn,En,Lt,Ln,Tn,Vn,Pn]}]}]});class Wn extends g{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.separatorKeysCodes=[ke,Te,Le]}configForm(){return this.calculateDeltaConfigForm}onConfigurationSet(e){this.calculateDeltaConfigForm=this.fb.group({inputValueKey:[e.inputValueKey,[_.required,_.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],outputValueKey:[e.outputValueKey,[_.required,_.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],useCache:[e.useCache,[]],addPeriodBetweenMsgs:[e.addPeriodBetweenMsgs,[]],periodValueKey:[e.periodValueKey,[]],round:[e.round,[_.min(0),_.max(15)]],tellFailureIfDeltaIsNegative:[e.tellFailureIfDeltaIsNegative,[]],excludeZeroDeltas:[e.excludeZeroDeltas,[]]})}prepareInputConfig(e){return{inputValueKey:ye(e?.inputValueKey)?e.inputValueKey:null,outputValueKey:ye(e?.outputValueKey)?e.outputValueKey:null,useCache:!ye(e?.useCache)||e.useCache,addPeriodBetweenMsgs:!!ye(e?.addPeriodBetweenMsgs)&&e.addPeriodBetweenMsgs,periodValueKey:ye(e?.periodValueKey)?e.periodValueKey:null,round:ye(e?.round)?e.round:null,tellFailureIfDeltaIsNegative:!ye(e?.tellFailureIfDeltaIsNegative)||e.tellFailureIfDeltaIsNegative,excludeZeroDeltas:!!ye(e?.excludeZeroDeltas)&&e.excludeZeroDeltas}}prepareOutputConfig(e){return xe(e)}updateValidators(e){this.calculateDeltaConfigForm.get("addPeriodBetweenMsgs").value?this.calculateDeltaConfigForm.get("periodValueKey").setValidators([_.required]):this.calculateDeltaConfigForm.get("periodValueKey").setValidators([]),this.calculateDeltaConfigForm.get("periodValueKey").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["addPeriodBetweenMsgs"]}}e("CalculateDeltaConfigComponent",Wn),Wn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Wn,deps:[{token:R.Store},{token:X.TranslateService},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Wn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Wn,selector:"tb-enrichment-node-calculate-delta-config",usesInheritance:!0,ngImport:t,template:"<section [formGroup]=\"calculateDeltaConfigForm\">\n <div fxLayout.gt-sm=\"row\" fxLayoutGap.gt-sm=\"22px\">\n <mat-form-field class=\"mat-block\" fxFlex>\n <mat-label>{{ 'tb.rulenode.input-value-key' | translate }}</mat-label>\n <input matInput formControlName=\"inputValueKey\">\n <mat-error *ngIf=\"calculateDeltaConfigForm.get('inputValueKey').hasError('required') ||\n calculateDeltaConfigForm.get('inputValueKey').hasError('pattern')\">\n {{ 'tb.rulenode.input-value-key-required' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class=\"mat-block\" fxFlex>\n <mat-label>{{ 'tb.rulenode.output-value-key' | translate }}</mat-label>\n <input matInput formControlName=\"outputValueKey\">\n <mat-error *ngIf=\"calculateDeltaConfigForm.get('outputValueKey').hasError('required') ||\n calculateDeltaConfigForm.get('outputValueKey').hasError('pattern')\">\n {{ 'tb.rulenode.output-value-key-required' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <mat-form-field class=\"mat-block\" fxFlex>\n <mat-label>{{ 'tb.rulenode.number-of-digits-after-floating-point' | translate }}</mat-label>\n <input type=\"number\" min=\"0\" max=\"15\" step=\"1\" matInput formControlName=\"round\">\n <mat-error *ngIf=\"calculateDeltaConfigForm.get('round').hasError('min')\">\n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n </mat-error>\n <mat-error *ngIf=\"calculateDeltaConfigForm.get('round').hasError('max')\">\n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n </mat-error>\n </mat-form-field>\n <div class=\"tb-form-panel no-padding no-border\">\n <div tb-hint-tooltip-icon=\"{{ 'tb.rulenode.failure-if-delta-negative-tooltip' | translate }}\"\n class=\"tb-form-row same-padding\">\n <mat-slide-toggle class=\"mat-slide margin\" formControlName=\"tellFailureIfDeltaIsNegative\">\n {{ 'tb.rulenode.failure-if-delta-negative' | translate }}\n </mat-slide-toggle>\n </div>\n <div tb-hint-tooltip-icon=\"{{ 'tb.rulenode.use-caching-tooltip' | translate :\n { inputValueKey: calculateDeltaConfigForm.get('inputValueKey').valid ?\n calculateDeltaConfigForm.get('inputValueKey').value : 'tb.rulenode.input-value-key' | translate } }}\"\n class=\"tb-form-row same-padding\">\n <mat-slide-toggle class=\"mat-slide margin\" formControlName=\"useCache\">\n {{ 'tb.rulenode.use-caching' | translate }}\n </mat-slide-toggle>\n </div>\n <div class=\"tb-form-panel stroked\" [class.no-padding-bottom]=\"calculateDeltaConfigForm.get('addPeriodBetweenMsgs').value\">\n <div tb-hint-tooltip-icon=\"{{ 'tb.rulenode.add-time-difference-between-readings-tooltip' | translate:\n { periodValueKey: (calculateDeltaConfigForm.get('periodValueKey').valid &&\n calculateDeltaConfigForm.get('addPeriodBetweenMsgs').value) ? calculateDeltaConfigForm.get('periodValueKey').value :\n 'periodInMs' } }}\"\n class=\"tb-form-row no-border no-padding\">\n <mat-slide-toggle class=\"mat-slide\" formControlName=\"addPeriodBetweenMsgs\">\n {{ 'tb.rulenode.add-time-difference-between-readings' | translate:\n { inputValueKey: calculateDeltaConfigForm.get('inputValueKey').valid ?\n calculateDeltaConfigForm.get('inputValueKey').value : 'tb.rulenode.input-value-key' | translate } }}\n </mat-slide-toggle>\n </div>\n <mat-form-field class=\"mat-block\" *ngIf=\"calculateDeltaConfigForm.get('addPeriodBetweenMsgs').value\">\n <mat-label>{{ 'tb.rulenode.period-value-key' | translate }}</mat-label>\n <input required matInput formControlName=\"periodValueKey\">\n <mat-error *ngIf=\"calculateDeltaConfigForm.get('periodValueKey').hasError('required')\">\n {{ 'tb.rulenode.period-value-key-required' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <div tb-hint-tooltip-icon=\"{{ calculateDeltaConfigForm.get('addPeriodBetweenMsgs').value ? ('tb.rulenode.exclude-zero-deltas-time-difference-hint' | translate :{\n outputValueKey: calculateDeltaConfigForm.get('outputValueKey').valid ? calculateDeltaConfigForm.get('outputValueKey').value : 'tb.rulenode.output-value-key' | translate,\n periodValueKey: calculateDeltaConfigForm.get('periodValueKey').valid ? calculateDeltaConfigForm.get('periodValueKey').value : 'tb.rulenode.period-value-key' | translate\n }) : ('tb.rulenode.exclude-zero-deltas-hint' | translate :{ outputValueKey: calculateDeltaConfigForm.get('outputValueKey').valid ? calculateDeltaConfigForm.get('outputValueKey').value : 'tb.rulenode.output-value-key' | translate }) }}\"\n class=\"tb-form-row same-padding\">\n <mat-slide-toggle class=\"mat-slide margin\" formControlName=\"excludeZeroDeltas\">\n {{ 'tb.rulenode.exclude-zero-deltas' | translate }}\n </mat-slide-toggle>\n </div>\n </div>\n</section>\n",dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Wn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-calculate-delta-config",template:"<section [formGroup]=\"calculateDeltaConfigForm\">\n <div fxLayout.gt-sm=\"row\" fxLayoutGap.gt-sm=\"22px\">\n <mat-form-field class=\"mat-block\" fxFlex>\n <mat-label>{{ 'tb.rulenode.input-value-key' | translate }}</mat-label>\n <input matInput formControlName=\"inputValueKey\">\n <mat-error *ngIf=\"calculateDeltaConfigForm.get('inputValueKey').hasError('required') ||\n calculateDeltaConfigForm.get('inputValueKey').hasError('pattern')\">\n {{ 'tb.rulenode.input-value-key-required' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class=\"mat-block\" fxFlex>\n <mat-label>{{ 'tb.rulenode.output-value-key' | translate }}</mat-label>\n <input matInput formControlName=\"outputValueKey\">\n <mat-error *ngIf=\"calculateDeltaConfigForm.get('outputValueKey').hasError('required') ||\n calculateDeltaConfigForm.get('outputValueKey').hasError('pattern')\">\n {{ 'tb.rulenode.output-value-key-required' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <mat-form-field class=\"mat-block\" fxFlex>\n <mat-label>{{ 'tb.rulenode.number-of-digits-after-floating-point' | translate }}</mat-label>\n <input type=\"number\" min=\"0\" max=\"15\" step=\"1\" matInput formControlName=\"round\">\n <mat-error *ngIf=\"calculateDeltaConfigForm.get('round').hasError('min')\">\n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n </mat-error>\n <mat-error *ngIf=\"calculateDeltaConfigForm.get('round').hasError('max')\">\n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n </mat-error>\n </mat-form-field>\n <div class=\"tb-form-panel no-padding no-border\">\n <div tb-hint-tooltip-icon=\"{{ 'tb.rulenode.failure-if-delta-negative-tooltip' | translate }}\"\n class=\"tb-form-row same-padding\">\n <mat-slide-toggle class=\"mat-slide margin\" formControlName=\"tellFailureIfDeltaIsNegative\">\n {{ 'tb.rulenode.failure-if-delta-negative' | translate }}\n </mat-slide-toggle>\n </div>\n <div tb-hint-tooltip-icon=\"{{ 'tb.rulenode.use-caching-tooltip' | translate :\n { inputValueKey: calculateDeltaConfigForm.get('inputValueKey').valid ?\n calculateDeltaConfigForm.get('inputValueKey').value : 'tb.rulenode.input-value-key' | translate } }}\"\n class=\"tb-form-row same-padding\">\n <mat-slide-toggle class=\"mat-slide margin\" formControlName=\"useCache\">\n {{ 'tb.rulenode.use-caching' | translate }}\n </mat-slide-toggle>\n </div>\n <div class=\"tb-form-panel stroked\" [class.no-padding-bottom]=\"calculateDeltaConfigForm.get('addPeriodBetweenMsgs').value\">\n <div tb-hint-tooltip-icon=\"{{ 'tb.rulenode.add-time-difference-between-readings-tooltip' | translate:\n { periodValueKey: (calculateDeltaConfigForm.get('periodValueKey').valid &&\n calculateDeltaConfigForm.get('addPeriodBetweenMsgs').value) ? calculateDeltaConfigForm.get('periodValueKey').value :\n 'periodInMs' } }}\"\n class=\"tb-form-row no-border no-padding\">\n <mat-slide-toggle class=\"mat-slide\" formControlName=\"addPeriodBetweenMsgs\">\n {{ 'tb.rulenode.add-time-difference-between-readings' | translate:\n { inputValueKey: calculateDeltaConfigForm.get('inputValueKey').valid ?\n calculateDeltaConfigForm.get('inputValueKey').value : 'tb.rulenode.input-value-key' | translate } }}\n </mat-slide-toggle>\n </div>\n <mat-form-field class=\"mat-block\" *ngIf=\"calculateDeltaConfigForm.get('addPeriodBetweenMsgs').value\">\n <mat-label>{{ 'tb.rulenode.period-value-key' | translate }}</mat-label>\n <input required matInput formControlName=\"periodValueKey\">\n <mat-error *ngIf=\"calculateDeltaConfigForm.get('periodValueKey').hasError('required')\">\n {{ 'tb.rulenode.period-value-key-required' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <div tb-hint-tooltip-icon=\"{{ calculateDeltaConfigForm.get('addPeriodBetweenMsgs').value ? ('tb.rulenode.exclude-zero-deltas-time-difference-hint' | translate :{\n outputValueKey: calculateDeltaConfigForm.get('outputValueKey').valid ? calculateDeltaConfigForm.get('outputValueKey').value : 'tb.rulenode.output-value-key' | translate,\n periodValueKey: calculateDeltaConfigForm.get('periodValueKey').valid ? calculateDeltaConfigForm.get('periodValueKey').value : 'tb.rulenode.period-value-key' | translate\n }) : ('tb.rulenode.exclude-zero-deltas-hint' | translate :{ outputValueKey: calculateDeltaConfigForm.get('outputValueKey').valid ? calculateDeltaConfigForm.get('outputValueKey').value : 'tb.rulenode.output-value-key' | translate }) }}\"\n class=\"tb-form-row same-padding\">\n <mat-slide-toggle class=\"mat-slide margin\" formControlName=\"excludeZeroDeltas\">\n {{ 'tb.rulenode.exclude-zero-deltas' | translate }}\n </mat-slide-toggle>\n </div>\n </div>\n</section>\n"}]}],ctorParameters:function(){return[{type:R.Store},{type:X.TranslateService},{type:O.FormBuilder}]}});class Zn extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.fetchToData=[],this.DataToFetch=zt;for(const e of Ut.keys())e!==zt.FIELDS&&this.fetchToData.push({value:e,name:this.translate.instant(Ut.get(e))})}configForm(){return this.customerAttributesConfigForm}prepareOutputConfig(e){const t={};for(const n of Object.keys(e.dataMapping))t[n.trim()]=e.dataMapping[n];return e.dataMapping=t,xe(e)}prepareInputConfig(e){let t,n;return t=ye(e?.telemetry)?e.telemetry?zt.LATEST_TELEMETRY:zt.ATTRIBUTES:ye(e?.dataToFetch)?e.dataToFetch:zt.ATTRIBUTES,n=ye(e?.attrMapping)?e.attrMapping:ye(e?.dataMapping)?e.dataMapping:null,{dataToFetch:t,dataMapping:n,fetchTo:ye(e?.fetchTo)?e.fetchTo:sn.METADATA}}selectTranslation(e,t){return this.customerAttributesConfigForm.get("dataToFetch").value===zt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.customerAttributesConfigForm=this.fb.group({dataToFetch:[e.dataToFetch,[]],dataMapping:[e.dataMapping,[_.required]],fetchTo:[e.fetchTo]})}}e("CustomerAttributesConfigComponent",Zn),Zn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Zn,deps:[{token:R.Store},{token:O.FormBuilder},{token:X.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Zn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Zn,selector:"tb-enrichment-node-customer-attributes-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="customerAttributesConfigForm" class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.mapping-of-customers</div>\n <div fxFlex fxLayoutAlign="center center">\n <div class="fetch-to-data-toggle">\n <tb-toggle-select class="fetch-to-data-toggle" formControlName="dataToFetch" appearance="fill">\n <tb-toggle-option *ngFor="let data of fetchToData" [value]="data.value">\n {{ data.name }}\n </tb-toggle-option>\n </tb-toggle-select>\n </div>\n </div>\n <tb-kv-map-config\n required\n formControlName="dataMapping"\n [requiredText]="\'tb.rulenode.attr-mapping-required\' | translate"\n [labelText]="selectTranslation(\'tb.rulenode.latest-telemetry-mapping\',\'tb.rulenode.attributes-mapping\') | translate"\n [keyText]="selectTranslation(\'tb.rulenode.source-telemetry\',\'tb.rulenode.source-attribute\') | translate"\n [keyRequiredText]="selectTranslation(\'tb.rulenode.source-telemetry-required\',\'tb.rulenode.source-attribute-required\') | translate"\n [valText]="\'tb.rulenode.target-key\' | translate"\n [valRequiredText]="\'tb.rulenode.target-key-required\' | translate"\n [hintText]="\'tb.rulenode.kv-map-pattern-hint\'"\n popupHelpLink="rulenode/customer_attributes_node_fields_templatization">\n </tb-kv-map-config>\n <tb-msg-metadata-chip\n [labelText]="customerAttributesConfigForm.get(\'dataToFetch\').value === DataToFetch.LATEST_TELEMETRY ?\n (\'tb.rulenode.add-mapped-latest-telemetry-to\' | translate) : (\'tb.rulenode.add-mapped-attribute-to\' | translate)"\n formControlName="fetchTo">\n </tb-msg-metadata-chip>\n</section>\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:Z.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Me.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Ee.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination","fillHeight","extraPadding","primaryBackground"]},{kind:"component",type:Rn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Zn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-customer-attributes-config",template:'<section [formGroup]="customerAttributesConfigForm" class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.mapping-of-customers</div>\n <div fxFlex fxLayoutAlign="center center">\n <div class="fetch-to-data-toggle">\n <tb-toggle-select class="fetch-to-data-toggle" formControlName="dataToFetch" appearance="fill">\n <tb-toggle-option *ngFor="let data of fetchToData" [value]="data.value">\n {{ data.name }}\n </tb-toggle-option>\n </tb-toggle-select>\n </div>\n </div>\n <tb-kv-map-config\n required\n formControlName="dataMapping"\n [requiredText]="\'tb.rulenode.attr-mapping-required\' | translate"\n [labelText]="selectTranslation(\'tb.rulenode.latest-telemetry-mapping\',\'tb.rulenode.attributes-mapping\') | translate"\n [keyText]="selectTranslation(\'tb.rulenode.source-telemetry\',\'tb.rulenode.source-attribute\') | translate"\n [keyRequiredText]="selectTranslation(\'tb.rulenode.source-telemetry-required\',\'tb.rulenode.source-attribute-required\') | translate"\n [valText]="\'tb.rulenode.target-key\' | translate"\n [valRequiredText]="\'tb.rulenode.target-key-required\' | translate"\n [hintText]="\'tb.rulenode.kv-map-pattern-hint\'"\n popupHelpLink="rulenode/customer_attributes_node_fields_templatization">\n </tb-kv-map-config>\n <tb-msg-metadata-chip\n [labelText]="customerAttributesConfigForm.get(\'dataToFetch\').value === DataToFetch.LATEST_TELEMETRY ?\n (\'tb.rulenode.add-mapped-latest-telemetry-to\' | translate) : (\'tb.rulenode.add-mapped-attribute-to\' | translate)"\n formControlName="fetchTo">\n </tb-msg-metadata-chip>\n</section>\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"]}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder},{type:X.TranslateService}]}});class Xn extends g{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n}configForm(){return this.deviceAttributesConfigForm}onConfigurationSet(e){this.deviceAttributesConfigForm=this.fb.group({deviceRelationsQuery:[e.deviceRelationsQuery,[_.required]],tellFailureIfAbsent:[e.tellFailureIfAbsent,[]],fetchTo:[e.fetchTo,[]],attributesControl:[e.attributesControl,[]]})}prepareInputConfig(e){return he(e)&&(e.attributesControl={clientAttributeNames:ye(e?.clientAttributeNames)?e.clientAttributeNames:[],latestTsKeyNames:ye(e?.latestTsKeyNames)?e.latestTsKeyNames:[],serverAttributeNames:ye(e?.serverAttributeNames)?e.serverAttributeNames:[],sharedAttributeNames:ye(e?.sharedAttributeNames)?e.sharedAttributeNames:[],getLatestValueWithTs:!!ye(e?.getLatestValueWithTs)&&e.getLatestValueWithTs}),{deviceRelationsQuery:ye(e?.deviceRelationsQuery)?e.deviceRelationsQuery:null,tellFailureIfAbsent:!ye(e?.tellFailureIfAbsent)||e.tellFailureIfAbsent,fetchTo:ye(e?.fetchTo)?e.fetchTo:sn.METADATA,attributesControl:e?e.attributesControl:null}}prepareOutputConfig(e){for(const t of Object.keys(e.attributesControl))e[t]=e.attributesControl[t];return delete e.attributesControl,e}}e("DeviceAttributesConfigComponent",Xn),Xn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Xn,deps:[{token:R.Store},{token:X.TranslateService},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Xn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Xn,selector:"tb-enrichment-node-device-attributes-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="deviceAttributesConfigForm" class="tb-form-panel no-padding no-border">\n <div class="tb-form-panel stroked no-padding-bottom">\n <div class="tb-form-panel-title" translate>tb.rulenode.device-relations-query</div>\n <tb-device-relations-query-config\n required\n formControlName="deviceRelationsQuery">\n </tb-device-relations-query-config>\n </div>\n <div class="tb-form-panel stroked">\n <div class="tb-form-row no-padding no-border space-between">\n <div class="tb-form-panel-title tb-required" translate>tb.rulenode.related-device-attributes</div>\n <div class="tb-form-panel-hint tb-error" translate\n [hidden]="!(deviceAttributesConfigForm.get(\'attributesControl\').touched &&\n deviceAttributesConfigForm.get(\'attributesControl\').hasError(\'atLeastOneRequired\'))">\n tb.rulenode.at-least-one-field-required\n </div>\n </div>\n <tb-select-attributes formControlName="attributesControl"\n popupHelpLink="rulenode/related_device_attributes_node_fields_templatization"></tb-select-attributes>\n <tb-msg-metadata-chip formControlName="fetchTo"\n [labelText]="\'tb.rulenode.add-selected-attributes-to\' | translate"></tb-msg-metadata-chip>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.tell-failure-tooltip\' | translate }}"\n class="tb-form-row same-padding">\n <mat-slide-toggle class="mat-slide margin" formControlName="tellFailureIfAbsent">\n {{ \'tb.rulenode.tell-failure\' | translate }}\n </mat-slide-toggle>\n </div>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:On,selector:"tb-device-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:$n,selector:"tb-select-attributes",inputs:["popupHelpLink"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Xn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-device-attributes-config",template:'<section [formGroup]="deviceAttributesConfigForm" class="tb-form-panel no-padding no-border">\n <div class="tb-form-panel stroked no-padding-bottom">\n <div class="tb-form-panel-title" translate>tb.rulenode.device-relations-query</div>\n <tb-device-relations-query-config\n required\n formControlName="deviceRelationsQuery">\n </tb-device-relations-query-config>\n </div>\n <div class="tb-form-panel stroked">\n <div class="tb-form-row no-padding no-border space-between">\n <div class="tb-form-panel-title tb-required" translate>tb.rulenode.related-device-attributes</div>\n <div class="tb-form-panel-hint tb-error" translate\n [hidden]="!(deviceAttributesConfigForm.get(\'attributesControl\').touched &&\n deviceAttributesConfigForm.get(\'attributesControl\').hasError(\'atLeastOneRequired\'))">\n tb.rulenode.at-least-one-field-required\n </div>\n </div>\n <tb-select-attributes formControlName="attributesControl"\n popupHelpLink="rulenode/related_device_attributes_node_fields_templatization"></tb-select-attributes>\n <tb-msg-metadata-chip formControlName="fetchTo"\n [labelText]="\'tb.rulenode.add-selected-attributes-to\' | translate"></tb-msg-metadata-chip>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.tell-failure-tooltip\' | translate }}"\n class="tb-form-row same-padding">\n <mat-slide-toggle class="mat-slide margin" formControlName="tellFailureIfAbsent">\n {{ \'tb.rulenode.tell-failure\' | translate }}\n </mat-slide-toggle>\n </div>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:X.TranslateService},{type:O.FormBuilder}]}});class er extends g{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.predefinedValues=[];for(const e of Object.keys(Rt))this.predefinedValues.push({value:Rt[e],name:this.translate.instant(Ot.get(Rt[e]))})}ngOnInit(){super.ngOnInit()}configForm(){return this.entityDetailsConfigForm}prepareInputConfig(e){let t;return t=ye(e?.addToMetadata)?e.addToMetadata?sn.METADATA:sn.DATA:e?.fetchTo?e.fetchTo:sn.DATA,{detailsList:ye(e?.detailsList)?e.detailsList:null,fetchTo:t}}onConfigurationSet(e){this.entityDetailsConfigForm=this.fb.group({detailsList:[e.detailsList,[_.required]],fetchTo:[e.fetchTo,[]]})}}e("EntityDetailsConfigComponent",er),er.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:er,deps:[{token:R.Store},{token:X.TranslateService},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),er.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:er,selector:"tb-enrichment-node-entity-details-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="entityDetailsConfigForm">\n <tb-string-items-list [predefinedValues]="predefinedValues"\n class="mat-block" required\n [label]="\'tb.rulenode.select-details\' | translate"\n [placeholder]="\'tb.rulenode.add-detail\' | translate"\n [requiredText]="\'tb.rulenode.entity-details-list-empty\' | translate"\n formControlName="detailsList">\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.chip-help\' | translate: { inputName: \'tb.rulenode.detail\' | translate } }}">\n help\n </mat-icon>\n </tb-string-items-list>\n <tb-msg-metadata-chip\n [labelText]="\'tb.rulenode.add-selected-details-to\' | translate"\n formControlName="fetchTo">\n </tb-msg-metadata-chip>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:tt.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:er,decorators:[{type:n,args:[{selector:"tb-enrichment-node-entity-details-config",template:'<section [formGroup]="entityDetailsConfigForm">\n <tb-string-items-list [predefinedValues]="predefinedValues"\n class="mat-block" required\n [label]="\'tb.rulenode.select-details\' | translate"\n [placeholder]="\'tb.rulenode.add-detail\' | translate"\n [requiredText]="\'tb.rulenode.entity-details-list-empty\' | translate"\n formControlName="detailsList">\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.chip-help\' | translate: { inputName: \'tb.rulenode.detail\' | translate } }}">\n help\n </mat-icon>\n </tb-string-items-list>\n <tb-msg-metadata-chip\n [labelText]="\'tb.rulenode.add-selected-details-to\' | translate"\n formControlName="fetchTo">\n </tb-msg-metadata-chip>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:X.TranslateService},{type:O.FormBuilder}]}});class tr extends g{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.separatorKeysCodes=[ke,Te,Le],this.aggregationTypes=w,this.aggregations=Object.values(w),this.aggregationTypesTranslations=G,this.fetchMode=_t,this.samplingOrders=Object.values(Ht),this.samplingOrdersTranslate=$t,this.timeUnits=Object.values(Gt),this.timeUnitsTranslationMap=Dt,this.deduplicationStrategiesHintTranslations=Kt,this.headerOptions=[],this.timeUnitMap={[Gt.MILLISECONDS]:1,[Gt.SECONDS]:1e3,[Gt.MINUTES]:6e4,[Gt.HOURS]:36e5,[Gt.DAYS]:864e5},this.intervalValidator=()=>e=>e.get("startInterval").value*this.timeUnitMap[e.get("startIntervalTimeUnit").value]<=e.get("endInterval").value*this.timeUnitMap[e.get("endIntervalTimeUnit").value]?{intervalError:!0}:null;for(const e of Bt.keys())this.headerOptions.push({value:e,name:this.translate.instant(Bt.get(e))})}configForm(){return this.getTelemetryFromDatabaseConfigForm}onConfigurationSet(e){this.getTelemetryFromDatabaseConfigForm=this.fb.group({latestTsKeyNames:[e.latestTsKeyNames,[_.required]],aggregation:[e.aggregation,[_.required]],fetchMode:[e.fetchMode,[_.required]],orderBy:[e.orderBy,[]],limit:[e.limit,[]],useMetadataIntervalPatterns:[e.useMetadataIntervalPatterns,[]],interval:this.fb.group({startInterval:[e.interval.startInterval,[]],startIntervalTimeUnit:[e.interval.startIntervalTimeUnit,[]],endInterval:[e.interval.endInterval,[]],endIntervalTimeUnit:[e.interval.endIntervalTimeUnit,[]]}),startIntervalPattern:[e.startIntervalPattern,[]],endIntervalPattern:[e.endIntervalPattern,[]]})}validatorTriggers(){return["fetchMode","useMetadataIntervalPatterns"]}toggleChange(e){this.getTelemetryFromDatabaseConfigForm.get("fetchMode").patchValue(e,{emitEvent:!0})}prepareOutputConfig(e){return e.startInterval=e.interval.startInterval,e.startIntervalTimeUnit=e.interval.startIntervalTimeUnit,e.endInterval=e.interval.endInterval,e.endIntervalTimeUnit=e.interval.endIntervalTimeUnit,delete e.interval,xe(e)}prepareInputConfig(e){return he(e)&&(e.interval={startInterval:e.startInterval,startIntervalTimeUnit:e.startIntervalTimeUnit,endInterval:e.endInterval,endIntervalTimeUnit:e.endIntervalTimeUnit}),{latestTsKeyNames:ye(e?.latestTsKeyNames)?e.latestTsKeyNames:null,aggregation:ye(e?.aggregation)?e.aggregation:w.NONE,fetchMode:ye(e?.fetchMode)?e.fetchMode:_t.FIRST,orderBy:ye(e?.orderBy)?e.orderBy:Ht.ASC,limit:ye(e?.limit)?e.limit:1e3,useMetadataIntervalPatterns:!!ye(e?.useMetadataIntervalPatterns)&&e.useMetadataIntervalPatterns,interval:{startInterval:ye(e?.interval?.startInterval)?e.interval.startInterval:2,startIntervalTimeUnit:ye(e?.interval?.startIntervalTimeUnit)?e.interval.startIntervalTimeUnit:Gt.MINUTES,endInterval:ye(e?.interval?.endInterval)?e.interval.endInterval:1,endIntervalTimeUnit:ye(e?.interval?.endIntervalTimeUnit)?e.interval.endIntervalTimeUnit:Gt.MINUTES},startIntervalPattern:ye(e?.startIntervalPattern)?e.startIntervalPattern:null,endIntervalPattern:ye(e?.endIntervalPattern)?e.endIntervalPattern:null}}updateValidators(e){const t=this.getTelemetryFromDatabaseConfigForm.get("fetchMode").value,n=this.getTelemetryFromDatabaseConfigForm.get("useMetadataIntervalPatterns").value;t&&t===_t.ALL?(this.getTelemetryFromDatabaseConfigForm.get("aggregation").setValidators([_.required]),this.getTelemetryFromDatabaseConfigForm.get("orderBy").setValidators([_.required]),this.getTelemetryFromDatabaseConfigForm.get("limit").setValidators([_.required,_.min(2),_.max(1e3)])):(this.getTelemetryFromDatabaseConfigForm.get("aggregation").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("orderBy").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("limit").setValidators([])),n?(this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").setValidators([_.required,_.pattern(/(?:.|\s)*\S(&:.|\s)*/)]),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").setValidators([_.required,_.pattern(/(?:.|\s)*\S(&:.|\s)*/)])):(this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").setValidators([_.required,_.min(1),_.max(2147483647)]),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").setValidators([_.required]),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").setValidators([_.required,_.min(1),_.max(2147483647)]),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").setValidators([_.required]),this.getTelemetryFromDatabaseConfigForm.get("interval").setValidators([this.intervalValidator()]),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").setValidators([])),this.getTelemetryFromDatabaseConfigForm.get("aggregation").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("orderBy").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("limit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").updateValueAndValidity({emitEvent:e})}removeKey(e,t){const n=this.getTelemetryFromDatabaseConfigForm.get(t).value,r=n.indexOf(e);r>=0&&(n.splice(r,1),this.getTelemetryFromDatabaseConfigForm.get(t).setValue(n,{emitEvent:!0}))}clearChipGrid(){this.getTelemetryFromDatabaseConfigForm.get("latestTsKeyNames").patchValue([],{emitEvent:!0})}addKey(e,t){const n=e.input;let r=e.value;if((r||"").trim()){r=r.trim();let e=this.getTelemetryFromDatabaseConfigForm.get(t).value;e&&-1!==e.indexOf(r)||(e||(e=[]),e.push(r),this.getTelemetryFromDatabaseConfigForm.get(t).setValue(e,{emitEvent:!0}))}n&&(n.value="")}defaultPaddingEnable(){return this.getTelemetryFromDatabaseConfigForm.get("fetchMode").value===_t.ALL&&this.getTelemetryFromDatabaseConfigForm.get("aggregation").value===w.NONE}}e("GetTelemetryFromDatabaseConfigComponent",tr),tr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:tr,deps:[{token:R.Store},{token:X.TranslateService},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),tr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:tr,selector:"tb-enrichment-node-get-telemetry-from-database",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="getTelemetryFromDatabaseConfigForm" class="tb-form-panel no-padding no-border">\n <tb-string-items-list class="mat-block" editable [placeholder]="\'tb.rulenode.add-timeseries-key\' | translate"\n subscriptSizing="dynamic" required\n [requiredText]="\'tb.rulenode.timeseries-keys-required\' | translate"\n [label]="\'tb.rulenode.timeseries-keys\' | translate" formControlName="latestTsKeyNames"\n [hint]="\'tb.rulenode.general-pattern-hint\' | translate">\n <div matHintEnd class="see-example" tb-help-popup="{{\'rulenode/originator_telemetry_node_fields_templatization\'}}"\n hintMode\n tb-help-popup-placement="right"\n trigger-style="letter-spacing:0.25px; font-size:12px"\n [tb-help-popup-style]="{maxWidth: \'820px\'}"\n trigger-text="{{ \'tb.key-val.see-examples\' | translate }}"></div>\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon" color="primary"\n matTooltip="{{ \'tb.rulenode.chip-help\' | translate: { inputName: \'tb.rulenode.timeseries-key\' | translate } }}">help\n </mat-icon>\n </tb-string-items-list>\n <div class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.fetch-interval</div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.use-metadata-dynamic-interval-tooltip\' | translate }}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="useMetadataIntervalPatterns">\n {{ \'tb.rulenode.use-metadata-dynamic-interval\' | translate }}\n </mat-slide-toggle>\n </div>\n <div formGroupName="interval" fxLayout="column"\n *ngIf="getTelemetryFromDatabaseConfigForm.get(\'useMetadataIntervalPatterns\').value === false; else intervalPattern">\n <div fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="0" fxLayoutGap.gt-sm="16px">\n <mat-form-field fxFlex="50" class="mat-block">\n <mat-label>{{ \'tb.rulenode.interval-start\' | translate }}</mat-label>\n <input type="number" step="1" min="1" max="2147483647" matInput formControlName="startInterval" required>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').hasError(\'required\')">\n {{ \'tb.rulenode.start-interval-value-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').hasError(\'min\')">\n {{ \'tb.rulenode.time-value-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').hasError(\'max\')">\n {{ \'tb.rulenode.time-value-range\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex="50" class="mat-block" hideRequiredMarker>\n <mat-label>{{ \'tb.rulenode.time-unit\' | translate }}</mat-label>\n <mat-select formControlName="startIntervalTimeUnit" required>\n <mat-option *ngFor="let timeUnit of timeUnits" [value]="timeUnit">\n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="0" fxLayoutGap.gt-sm="16px">\n <mat-form-field fxFlex="50" class="mat-block">\n <mat-label>{{ \'tb.rulenode.interval-end\' | translate }}</mat-label>\n <input type="number" step="1" min="1" max="2147483647" matInput formControlName="endInterval" required>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').hasError(\'required\')">\n {{ \'tb.rulenode.end-interval-value-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').hasError(\'min\')">\n {{ \'tb.rulenode.time-value-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').hasError(\'max\')">\n {{ \'tb.rulenode.time-value-range\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex="50" class="mat-block" hideRequiredMarker>\n <mat-label>{{ \'tb.rulenode.time-unit\' | translate }}</mat-label>\n <mat-select formControlName="endIntervalTimeUnit" required>\n <mat-option *ngFor="let timeUnit of timeUnits" [value]="timeUnit">\n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div class="description-block tb-primary-fill" [class.error]="getTelemetryFromDatabaseConfigForm.get(\'interval\').invalid">\n <mat-icon class="description-icon">error_outline</mat-icon>\n <div class="description-text">\n <ng-container *ngIf="getTelemetryFromDatabaseConfigForm.get(\'interval\').valid; else invalidText">\n {{ \'tb.rulenode.fetch-timeseries-from-to\' | translate:\n {\n startInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').value,\n endInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').value,\n startIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.startIntervalTimeUnit\').value.toLowerCase(),\n endIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.endIntervalTimeUnit\').value.toLowerCase()\n } }}\n </ng-container>\n <ng-template #invalidText>\n {{ "tb.rulenode.fetch-timeseries-from-to-invalid" | translate }}\n </ng-template>\n </div>\n </div>\n </div>\n <ng-template #intervalPattern>\n <div fxLayout="column" class="input-block">\n <mat-form-field fxFlex class="mat-block">\n <mat-label>{{ \'tb.rulenode.start-interval\' | translate }}</mat-label>\n <input matInput formControlName="startIntervalPattern" required>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'startIntervalPattern\').hasError(\'required\') ||\n getTelemetryFromDatabaseConfigForm.get(\'startIntervalPattern\').hasError(\'pattern\')">\n {{ \'tb.rulenode.start-interval-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex class="mat-block">\n <mat-label>{{ \'tb.rulenode.end-interval\' | translate }}</mat-label>\n <input matInput formControlName="endIntervalPattern" required>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'endIntervalPattern\').hasError(\'required\') ||\n getTelemetryFromDatabaseConfigForm.get(\'endIntervalPattern\').hasError(\'pattern\')">\n {{ \'tb.rulenode.end-interval-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <tb-example-hint [hintText]="\'tb.rulenode.metadata-dynamic-interval-hint\' | translate"\n popupHelpLink="rulenode/originator_telemetry_node_fields_templatization">\n </tb-example-hint>\n </div>\n </ng-template>\n </div>\n <div class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.fetch-strategy</div>\n <div class="tb-form-panel no-border no-padding item-center">\n <div class="fetch-mod-toggle">\n <tb-toggle-select formControlName="fetchMode" appearance="fill">\n <tb-toggle-option *ngFor="let data of headerOptions" [value]="data.value">\n {{ data.name }}\n </tb-toggle-option>\n </tb-toggle-select>\n </div>\n <div class="tb-form-hint tb-primary-fill hint-container">\n {{ deduplicationStrategiesHintTranslations.get(getTelemetryFromDatabaseConfigForm.get(\'fetchMode\').value) | translate }}\n </div>\n </div>\n <div *ngIf="getTelemetryFromDatabaseConfigForm.get(\'fetchMode\').value === fetchMode.ALL">\n <mat-form-field class="mat-block" hideRequiredMarker\n [subscriptSizing]="defaultPaddingEnable() ? \'fixed\' : \'dynamic\'">\n <mat-label>{{ \'aggregation.function\' | translate }}</mat-label>\n <mat-select formControlName="aggregation" required>\n <mat-option *ngFor="let aggregation of aggregations" [value]="aggregation">\n {{ aggregationTypesTranslations.get(aggregationTypes[aggregation]) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <div *ngIf="getTelemetryFromDatabaseConfigForm.get(\'aggregation\').value === aggregationTypes.NONE">\n <mat-form-field class="mat-block" hideRequiredMarker>\n <mat-label> {{ "tb.rulenode.order-by-timestamp" | translate }} </mat-label>\n <mat-select formControlName="orderBy" required>\n <mat-option *ngFor="let order of samplingOrders" [value]="order">\n {{ samplingOrdersTranslate.get(order) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label>{{ "tb.rulenode.limit" | translate }}</mat-label>\n <input type="number" min="2" max="1000" step="1" matInput formControlName="limit" required>\n <mat-hint>{{ "tb.rulenode.limit-hint" | translate }}</mat-hint>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'limit\').hasError(\'required\')">\n {{ \'tb.rulenode.limit-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'limit\').hasError(\'min\')">\n {{ \'tb.rulenode.limit-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'limit\').hasError(\'max\')">\n {{ \'tb.rulenode.limit-range\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n </div>\n </div>\n</section>\n',styles:[":host .see-example{display:inline-block}:host .description-block{display:flex;align-items:center;border-radius:6px;border:1px solid #EAEAEA}:host .description-block .description-icon{font-size:24px;height:24px;min-height:24px;width:24px;min-width:24px;line-height:24px;color:#d9d9d9;margin:4px}:host .description-block .description-text{font-size:12px;line-height:16px;letter-spacing:.25px;margin:6px}:host .description-block.error{color:var(--mdc-theme-error, #f44336)}:host .description-block.error .description-icon{color:var(--mdc-theme-error, #f44336)}:host .item-center{align-items:center}:host .item-center .fetch-mod-toggle{width:100%}:host .hint-container{width:100%}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ue.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"component",type:tt.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:O.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Me.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Ee.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination","fillHeight","extraPadding","primaryBackground"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:ht,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:tr,decorators:[{type:n,args:[{selector:"tb-enrichment-node-get-telemetry-from-database",template:'<section [formGroup]="getTelemetryFromDatabaseConfigForm" class="tb-form-panel no-padding no-border">\n <tb-string-items-list class="mat-block" editable [placeholder]="\'tb.rulenode.add-timeseries-key\' | translate"\n subscriptSizing="dynamic" required\n [requiredText]="\'tb.rulenode.timeseries-keys-required\' | translate"\n [label]="\'tb.rulenode.timeseries-keys\' | translate" formControlName="latestTsKeyNames"\n [hint]="\'tb.rulenode.general-pattern-hint\' | translate">\n <div matHintEnd class="see-example" tb-help-popup="{{\'rulenode/originator_telemetry_node_fields_templatization\'}}"\n hintMode\n tb-help-popup-placement="right"\n trigger-style="letter-spacing:0.25px; font-size:12px"\n [tb-help-popup-style]="{maxWidth: \'820px\'}"\n trigger-text="{{ \'tb.key-val.see-examples\' | translate }}"></div>\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon" color="primary"\n matTooltip="{{ \'tb.rulenode.chip-help\' | translate: { inputName: \'tb.rulenode.timeseries-key\' | translate } }}">help\n </mat-icon>\n </tb-string-items-list>\n <div class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.fetch-interval</div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.use-metadata-dynamic-interval-tooltip\' | translate }}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="useMetadataIntervalPatterns">\n {{ \'tb.rulenode.use-metadata-dynamic-interval\' | translate }}\n </mat-slide-toggle>\n </div>\n <div formGroupName="interval" fxLayout="column"\n *ngIf="getTelemetryFromDatabaseConfigForm.get(\'useMetadataIntervalPatterns\').value === false; else intervalPattern">\n <div fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="0" fxLayoutGap.gt-sm="16px">\n <mat-form-field fxFlex="50" class="mat-block">\n <mat-label>{{ \'tb.rulenode.interval-start\' | translate }}</mat-label>\n <input type="number" step="1" min="1" max="2147483647" matInput formControlName="startInterval" required>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').hasError(\'required\')">\n {{ \'tb.rulenode.start-interval-value-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').hasError(\'min\')">\n {{ \'tb.rulenode.time-value-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').hasError(\'max\')">\n {{ \'tb.rulenode.time-value-range\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex="50" class="mat-block" hideRequiredMarker>\n <mat-label>{{ \'tb.rulenode.time-unit\' | translate }}</mat-label>\n <mat-select formControlName="startIntervalTimeUnit" required>\n <mat-option *ngFor="let timeUnit of timeUnits" [value]="timeUnit">\n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="0" fxLayoutGap.gt-sm="16px">\n <mat-form-field fxFlex="50" class="mat-block">\n <mat-label>{{ \'tb.rulenode.interval-end\' | translate }}</mat-label>\n <input type="number" step="1" min="1" max="2147483647" matInput formControlName="endInterval" required>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').hasError(\'required\')">\n {{ \'tb.rulenode.end-interval-value-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').hasError(\'min\')">\n {{ \'tb.rulenode.time-value-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').hasError(\'max\')">\n {{ \'tb.rulenode.time-value-range\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex="50" class="mat-block" hideRequiredMarker>\n <mat-label>{{ \'tb.rulenode.time-unit\' | translate }}</mat-label>\n <mat-select formControlName="endIntervalTimeUnit" required>\n <mat-option *ngFor="let timeUnit of timeUnits" [value]="timeUnit">\n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div class="description-block tb-primary-fill" [class.error]="getTelemetryFromDatabaseConfigForm.get(\'interval\').invalid">\n <mat-icon class="description-icon">error_outline</mat-icon>\n <div class="description-text">\n <ng-container *ngIf="getTelemetryFromDatabaseConfigForm.get(\'interval\').valid; else invalidText">\n {{ \'tb.rulenode.fetch-timeseries-from-to\' | translate:\n {\n startInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').value,\n endInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').value,\n startIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.startIntervalTimeUnit\').value.toLowerCase(),\n endIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.endIntervalTimeUnit\').value.toLowerCase()\n } }}\n </ng-container>\n <ng-template #invalidText>\n {{ "tb.rulenode.fetch-timeseries-from-to-invalid" | translate }}\n </ng-template>\n </div>\n </div>\n </div>\n <ng-template #intervalPattern>\n <div fxLayout="column" class="input-block">\n <mat-form-field fxFlex class="mat-block">\n <mat-label>{{ \'tb.rulenode.start-interval\' | translate }}</mat-label>\n <input matInput formControlName="startIntervalPattern" required>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'startIntervalPattern\').hasError(\'required\') ||\n getTelemetryFromDatabaseConfigForm.get(\'startIntervalPattern\').hasError(\'pattern\')">\n {{ \'tb.rulenode.start-interval-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex class="mat-block">\n <mat-label>{{ \'tb.rulenode.end-interval\' | translate }}</mat-label>\n <input matInput formControlName="endIntervalPattern" required>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'endIntervalPattern\').hasError(\'required\') ||\n getTelemetryFromDatabaseConfigForm.get(\'endIntervalPattern\').hasError(\'pattern\')">\n {{ \'tb.rulenode.end-interval-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <tb-example-hint [hintText]="\'tb.rulenode.metadata-dynamic-interval-hint\' | translate"\n popupHelpLink="rulenode/originator_telemetry_node_fields_templatization">\n </tb-example-hint>\n </div>\n </ng-template>\n </div>\n <div class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.fetch-strategy</div>\n <div class="tb-form-panel no-border no-padding item-center">\n <div class="fetch-mod-toggle">\n <tb-toggle-select formControlName="fetchMode" appearance="fill">\n <tb-toggle-option *ngFor="let data of headerOptions" [value]="data.value">\n {{ data.name }}\n </tb-toggle-option>\n </tb-toggle-select>\n </div>\n <div class="tb-form-hint tb-primary-fill hint-container">\n {{ deduplicationStrategiesHintTranslations.get(getTelemetryFromDatabaseConfigForm.get(\'fetchMode\').value) | translate }}\n </div>\n </div>\n <div *ngIf="getTelemetryFromDatabaseConfigForm.get(\'fetchMode\').value === fetchMode.ALL">\n <mat-form-field class="mat-block" hideRequiredMarker\n [subscriptSizing]="defaultPaddingEnable() ? \'fixed\' : \'dynamic\'">\n <mat-label>{{ \'aggregation.function\' | translate }}</mat-label>\n <mat-select formControlName="aggregation" required>\n <mat-option *ngFor="let aggregation of aggregations" [value]="aggregation">\n {{ aggregationTypesTranslations.get(aggregationTypes[aggregation]) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <div *ngIf="getTelemetryFromDatabaseConfigForm.get(\'aggregation\').value === aggregationTypes.NONE">\n <mat-form-field class="mat-block" hideRequiredMarker>\n <mat-label> {{ "tb.rulenode.order-by-timestamp" | translate }} </mat-label>\n <mat-select formControlName="orderBy" required>\n <mat-option *ngFor="let order of samplingOrders" [value]="order">\n {{ samplingOrdersTranslate.get(order) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label>{{ "tb.rulenode.limit" | translate }}</mat-label>\n <input type="number" min="2" max="1000" step="1" matInput formControlName="limit" required>\n <mat-hint>{{ "tb.rulenode.limit-hint" | translate }}</mat-hint>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'limit\').hasError(\'required\')">\n {{ \'tb.rulenode.limit-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'limit\').hasError(\'min\')">\n {{ \'tb.rulenode.limit-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="getTelemetryFromDatabaseConfigForm.get(\'limit\').hasError(\'max\')">\n {{ \'tb.rulenode.limit-range\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n </div>\n </div>\n</section>\n',styles:[":host .see-example{display:inline-block}:host .description-block{display:flex;align-items:center;border-radius:6px;border:1px solid #EAEAEA}:host .description-block .description-icon{font-size:24px;height:24px;min-height:24px;width:24px;min-width:24px;line-height:24px;color:#d9d9d9;margin:4px}:host .description-block .description-text{font-size:12px;line-height:16px;letter-spacing:.25px;margin:6px}:host .description-block.error{color:var(--mdc-theme-error, #f44336)}:host .description-block.error .description-icon{color:var(--mdc-theme-error, #f44336)}:host .item-center{align-items:center}:host .item-center .fetch-mod-toggle{width:100%}:host .hint-container{width:100%}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:X.TranslateService},{type:O.FormBuilder}]}});class nr extends g{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n}configForm(){return this.originatorAttributesConfigForm}onConfigurationSet(e){this.originatorAttributesConfigForm=this.fb.group({tellFailureIfAbsent:[e.tellFailureIfAbsent,[]],fetchTo:[e.fetchTo,[]],attributesControl:[e.attributesControl,[]]})}prepareInputConfig(e){return he(e)&&(e.attributesControl={clientAttributeNames:ye(e?.clientAttributeNames)?e.clientAttributeNames:[],latestTsKeyNames:ye(e?.latestTsKeyNames)?e.latestTsKeyNames:[],serverAttributeNames:ye(e?.serverAttributeNames)?e.serverAttributeNames:[],sharedAttributeNames:ye(e?.sharedAttributeNames)?e.sharedAttributeNames:[],getLatestValueWithTs:!!ye(e?.getLatestValueWithTs)&&e.getLatestValueWithTs}),{fetchTo:ye(e?.fetchTo)?e.fetchTo:sn.METADATA,tellFailureIfAbsent:!!ye(e?.tellFailureIfAbsent)&&e.tellFailureIfAbsent,attributesControl:ye(e?.attributesControl)?e.attributesControl:null}}prepareOutputConfig(e){for(const t of Object.keys(e.attributesControl))e[t]=e.attributesControl[t];return delete e.attributesControl,e}}e("OriginatorAttributesConfigComponent",nr),nr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:nr,deps:[{token:R.Store},{token:X.TranslateService},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),nr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:nr,selector:"tb-enrichment-node-originator-attributes-config",usesInheritance:!0,ngImport:t,template:'<section class="tb-form-panel no-padding no-border" [formGroup]="originatorAttributesConfigForm">\n <div class="tb-form-panel stroked">\n <div class="tb-form-row no-padding no-border space-between">\n <div class="tb-form-panel-title tb-required" translate>tb.rulenode.originator-attributes</div>\n <div class="tb-form-panel-hint tb-error" translate\n [hidden]="!(originatorAttributesConfigForm.get(\'attributesControl\').touched &&\n originatorAttributesConfigForm.get(\'attributesControl\').hasError(\'atLeastOneRequired\'))">\n tb.rulenode.at-least-one-field-required\n </div>\n </div>\n <tb-select-attributes formControlName="attributesControl"\n popupHelpLink="rulenode/originator_attributes_node_fields_templatization">\n </tb-select-attributes>\n <tb-msg-metadata-chip [labelText]="\'tb.rulenode.add-originator-attributes-to\' | translate"\n formControlName="fetchTo">\n </tb-msg-metadata-chip>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.tell-failure-tooltip\' | translate }}" class="tb-form-row same-padding">\n <mat-slide-toggle class="mat-slide margin" formControlName="tellFailureIfAbsent">\n {{ \'tb.rulenode.tell-failure\' | translate }}\n </mat-slide-toggle>\n </div>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:$n,selector:"tb-select-attributes",inputs:["popupHelpLink"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:nr,decorators:[{type:n,args:[{selector:"tb-enrichment-node-originator-attributes-config",template:'<section class="tb-form-panel no-padding no-border" [formGroup]="originatorAttributesConfigForm">\n <div class="tb-form-panel stroked">\n <div class="tb-form-row no-padding no-border space-between">\n <div class="tb-form-panel-title tb-required" translate>tb.rulenode.originator-attributes</div>\n <div class="tb-form-panel-hint tb-error" translate\n [hidden]="!(originatorAttributesConfigForm.get(\'attributesControl\').touched &&\n originatorAttributesConfigForm.get(\'attributesControl\').hasError(\'atLeastOneRequired\'))">\n tb.rulenode.at-least-one-field-required\n </div>\n </div>\n <tb-select-attributes formControlName="attributesControl"\n popupHelpLink="rulenode/originator_attributes_node_fields_templatization">\n </tb-select-attributes>\n <tb-msg-metadata-chip [labelText]="\'tb.rulenode.add-originator-attributes-to\' | translate"\n formControlName="fetchTo">\n </tb-msg-metadata-chip>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.tell-failure-tooltip\' | translate }}" class="tb-form-row same-padding">\n <mat-slide-toggle class="mat-slide margin" formControlName="tellFailureIfAbsent">\n {{ \'tb.rulenode.tell-failure\' | translate }}\n </mat-slide-toggle>\n </div>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:X.TranslateService},{type:O.FormBuilder}]}});class rr extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.originatorFields=[];for(const e of At)this.originatorFields.push({value:e.value,name:this.translate.instant(e.name)})}configForm(){return this.originatorFieldsConfigForm}prepareOutputConfig(e){return xe(e)}prepareInputConfig(e){return{dataMapping:ye(e?.dataMapping)?e.dataMapping:null,ignoreNullStrings:ye(e?.ignoreNullStrings)?e.ignoreNullStrings:null,fetchTo:ye(e?.fetchTo)?e.fetchTo:sn.METADATA}}onConfigurationSet(e){this.originatorFieldsConfigForm=this.fb.group({dataMapping:[e.dataMapping,[_.required]],ignoreNullStrings:[e.ignoreNullStrings,[]],fetchTo:[e.fetchTo,[]]})}}e("OriginatorFieldsConfigComponent",rr),rr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:rr,deps:[{token:R.Store},{token:O.FormBuilder},{token:X.TranslateService}],target:t.ɵɵFactoryTarget.Component}),rr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:rr,selector:"tb-enrichment-node-originator-fields-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="originatorFieldsConfigForm" class="tb-form-panel no-padding no-border">\n <tb-sv-map-config\n required\n [selectOptions]="originatorFields"\n targetKeyPrefix="originator"\n formControlName="dataMapping"\n [requiredText]="\'tb.rulenode.attr-mapping-required\' | translate"\n [labelText]="\'tb.rulenode.originator-fields-mapping\' | translate"\n [selectText]="\'tb.rulenode.source-field\' | translate"\n [selectRequiredText]="\'tb.rulenode.source-field-required\' | translate"\n [valText]="\'tb.rulenode.target-key\' | translate"\n [valRequiredText]="\'tb.rulenode.target-key-required\' | translate"\n [hintText]="\'tb.rulenode.originator-fields-sv-map-hint\' | translate"\n popupHelpLink="rulenode/originator_fields_node_fields_templatization">\n </tb-sv-map-config>\n <tb-msg-metadata-chip [labelText]="\'tb.rulenode.add-mapped-originator-fields-to\' | translate"\n formControlName="fetchTo">\n </tb-msg-metadata-chip>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.skip-empty-fields-tooltip\' | translate }}" class="tb-form-row same-padding">\n <mat-slide-toggle class="mat-slide margin" formControlName="ignoreNullStrings">\n {{ \'tb.rulenode.skip-empty-fields\' | translate }}\n </mat-slide-toggle>\n </div>\n</section>\n',dependencies:[{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:Un,selector:"tb-sv-map-config",inputs:["selectOptions","disabled","labelText","requiredText","targetKeyPrefix","selectText","selectRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:rr,decorators:[{type:n,args:[{selector:"tb-enrichment-node-originator-fields-config",template:'<section [formGroup]="originatorFieldsConfigForm" class="tb-form-panel no-padding no-border">\n <tb-sv-map-config\n required\n [selectOptions]="originatorFields"\n targetKeyPrefix="originator"\n formControlName="dataMapping"\n [requiredText]="\'tb.rulenode.attr-mapping-required\' | translate"\n [labelText]="\'tb.rulenode.originator-fields-mapping\' | translate"\n [selectText]="\'tb.rulenode.source-field\' | translate"\n [selectRequiredText]="\'tb.rulenode.source-field-required\' | translate"\n [valText]="\'tb.rulenode.target-key\' | translate"\n [valRequiredText]="\'tb.rulenode.target-key-required\' | translate"\n [hintText]="\'tb.rulenode.originator-fields-sv-map-hint\' | translate"\n popupHelpLink="rulenode/originator_fields_node_fields_templatization">\n </tb-sv-map-config>\n <tb-msg-metadata-chip [labelText]="\'tb.rulenode.add-mapped-originator-fields-to\' | translate"\n formControlName="fetchTo">\n </tb-msg-metadata-chip>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.skip-empty-fields-tooltip\' | translate }}" class="tb-form-row same-padding">\n <mat-slide-toggle class="mat-slide margin" formControlName="ignoreNullStrings">\n {{ \'tb.rulenode.skip-empty-fields\' | translate }}\n </mat-slide-toggle>\n </div>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder},{type:X.TranslateService}]}});class or extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.DataToFetch=zt,this.msgMetadataLabelTranslations=jt,this.originatorFields=[],this.fetchToData=[];for(const e of Object.keys(At))this.originatorFields.push({value:At[e].value,name:this.translate.instant(At[e].name)});for(const e of Ut.keys())this.fetchToData.push({value:e,name:this.translate.instant(Ut.get(e))})}configForm(){return this.relatedAttributesConfigForm}prepareOutputConfig(e){e.dataToFetch===zt.FIELDS?(e.dataMapping=e.svMap,delete e.svMap):(e.dataMapping=e.kvMap,delete e.kvMap);const t={};if(e&&e.dataMapping)for(const n of Object.keys(e.dataMapping))t[n.trim()]=e.dataMapping[n];return e.dataMapping=t,delete e.svMap,delete e.kvMap,xe(e)}prepareInputConfig(e){let t,n,r={[k.name.value]:`relatedEntity${this.translate.instant(k.name.name)}`},o={serialNumber:"sn"};return t=ye(e?.telemetry)?e.telemetry?zt.LATEST_TELEMETRY:zt.ATTRIBUTES:ye(e?.dataToFetch)?e.dataToFetch:zt.ATTRIBUTES,n=ye(e?.attrMapping)?e.attrMapping:ye(e?.dataMapping)?e.dataMapping:null,t===zt.FIELDS?r=n:o=n,{relationsQuery:ye(e?.relationsQuery)?e.relationsQuery:null,dataToFetch:t,svMap:r,kvMap:o,fetchTo:ye(e?.fetchTo)?e.fetchTo:sn.METADATA}}selectTranslation(e,t){return this.relatedAttributesConfigForm.get("dataToFetch").value===zt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.relatedAttributesConfigForm=this.fb.group({relationsQuery:[e.relationsQuery,[_.required]],dataToFetch:[e.dataToFetch,[]],kvMap:[e.kvMap,[_.required]],svMap:[e.svMap,[_.required]],fetchTo:[e.fetchTo,[]]})}validatorTriggers(){return["dataToFetch"]}updateValidators(e){this.relatedAttributesConfigForm.get("dataToFetch").value===zt.FIELDS?(this.relatedAttributesConfigForm.get("svMap").enable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").disable({emitEvent:!1}),this.relatedAttributesConfigForm.get("svMap").updateValueAndValidity()):(this.relatedAttributesConfigForm.get("svMap").disable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").enable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").updateValueAndValidity())}}e("RelatedAttributesConfigComponent",or),or.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:or,deps:[{token:R.Store},{token:O.FormBuilder},{token:X.TranslateService}],target:t.ɵɵFactoryTarget.Component}),or.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:or,selector:"tb-enrichment-node-related-attributes-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="relatedAttributesConfigForm" class="tb-form-panel no-padding no-border">\n <tb-relations-query-config\n required\n formControlName="relationsQuery">\n </tb-relations-query-config>\n <div class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.data-to-fetch</div>\n <tb-toggle-select formControlName="dataToFetch" appearance="fill">\n <tb-toggle-option *ngFor="let data of fetchToData" [value]="data.value">\n {{ data.name }}\n </tb-toggle-option>\n </tb-toggle-select>\n <tb-kv-map-config\n [hidden]="relatedAttributesConfigForm.get(\'dataToFetch\').value === DataToFetch.FIELDS"\n required\n formControlName="kvMap"\n [requiredText]="\'tb.rulenode.attr-mapping-required\' | translate"\n [labelText]="selectTranslation(\'tb.rulenode.latest-telemetry-mapping\',\'tb.rulenode.attributes-mapping\') | translate"\n [keyText]="selectTranslation(\'tb.rulenode.source-telemetry\',\'tb.rulenode.source-attribute\') | translate"\n [keyRequiredText]="selectTranslation(\'tb.rulenode.source-telemetry-required\',\'tb.rulenode.source-attribute-required\') | translate"\n [valText]="\'tb.rulenode.target-key\' | translate"\n [valRequiredText]="\'tb.rulenode.target-key-required\' | translate"\n [hintText]="\'tb.rulenode.kv-map-pattern-hint\'"\n popupHelpLink="rulenode/related_entity_data_node_fields_templatization">\n </tb-kv-map-config>\n <tb-sv-map-config\n [hidden]="relatedAttributesConfigForm.get(\'dataToFetch\').value !== DataToFetch.FIELDS"\n required\n [labelText]="\'tb.rulenode.fields-mapping\' | translate"\n targetKeyPrefix="relatedEntity"\n [selectOptions]="originatorFields"\n formControlName="svMap"\n [requiredText]="\'tb.rulenode.attr-mapping-required\' | translate"\n [selectText]="\'tb.rulenode.source-field\' | translate"\n [selectRequiredText]="\'tb.rulenode.source-field-required\' | translate"\n [valText]="\'tb.rulenode.target-key\' | translate"\n [valRequiredText]="\'tb.rulenode.target-key-required\' | translate"\n [hintText]="\'tb.rulenode.sv-map-hint\' | translate"\n popupHelpLink="rulenode/related_entity_data_node_fields_templatization">\n </tb-sv-map-config>\n <tb-msg-metadata-chip formControlName="fetchTo"\n [labelText]="msgMetadataLabelTranslations.get(relatedAttributesConfigForm.get(\'dataToFetch\').value) | translate">\n </tb-msg-metadata-chip>\n </div>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Me.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Ee.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination","fillHeight","extraPadding","primaryBackground"]},{kind:"component",type:Rn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:_n,selector:"tb-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:Un,selector:"tb-sv-map-config",inputs:["selectOptions","disabled","labelText","requiredText","targetKeyPrefix","selectText","selectRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:or,decorators:[{type:n,args:[{selector:"tb-enrichment-node-related-attributes-config",template:'<section [formGroup]="relatedAttributesConfigForm" class="tb-form-panel no-padding no-border">\n <tb-relations-query-config\n required\n formControlName="relationsQuery">\n </tb-relations-query-config>\n <div class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.data-to-fetch</div>\n <tb-toggle-select formControlName="dataToFetch" appearance="fill">\n <tb-toggle-option *ngFor="let data of fetchToData" [value]="data.value">\n {{ data.name }}\n </tb-toggle-option>\n </tb-toggle-select>\n <tb-kv-map-config\n [hidden]="relatedAttributesConfigForm.get(\'dataToFetch\').value === DataToFetch.FIELDS"\n required\n formControlName="kvMap"\n [requiredText]="\'tb.rulenode.attr-mapping-required\' | translate"\n [labelText]="selectTranslation(\'tb.rulenode.latest-telemetry-mapping\',\'tb.rulenode.attributes-mapping\') | translate"\n [keyText]="selectTranslation(\'tb.rulenode.source-telemetry\',\'tb.rulenode.source-attribute\') | translate"\n [keyRequiredText]="selectTranslation(\'tb.rulenode.source-telemetry-required\',\'tb.rulenode.source-attribute-required\') | translate"\n [valText]="\'tb.rulenode.target-key\' | translate"\n [valRequiredText]="\'tb.rulenode.target-key-required\' | translate"\n [hintText]="\'tb.rulenode.kv-map-pattern-hint\'"\n popupHelpLink="rulenode/related_entity_data_node_fields_templatization">\n </tb-kv-map-config>\n <tb-sv-map-config\n [hidden]="relatedAttributesConfigForm.get(\'dataToFetch\').value !== DataToFetch.FIELDS"\n required\n [labelText]="\'tb.rulenode.fields-mapping\' | translate"\n targetKeyPrefix="relatedEntity"\n [selectOptions]="originatorFields"\n formControlName="svMap"\n [requiredText]="\'tb.rulenode.attr-mapping-required\' | translate"\n [selectText]="\'tb.rulenode.source-field\' | translate"\n [selectRequiredText]="\'tb.rulenode.source-field-required\' | translate"\n [valText]="\'tb.rulenode.target-key\' | translate"\n [valRequiredText]="\'tb.rulenode.target-key-required\' | translate"\n [hintText]="\'tb.rulenode.sv-map-hint\' | translate"\n popupHelpLink="rulenode/related_entity_data_node_fields_templatization">\n </tb-sv-map-config>\n <tb-msg-metadata-chip formControlName="fetchTo"\n [labelText]="msgMetadataLabelTranslations.get(relatedAttributesConfigForm.get(\'dataToFetch\').value) | translate">\n </tb-msg-metadata-chip>\n </div>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder},{type:X.TranslateService}]}});class ar extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.fetchToData=[],this.DataToFetch=zt;for(const e of Ut.keys())e!==zt.FIELDS&&this.fetchToData.push({value:e,name:this.translate.instant(Ut.get(e))})}configForm(){return this.tenantAttributesConfigForm}prepareInputConfig(e){let t,n;return t=ye(e?.telemetry)?e.telemetry?zt.LATEST_TELEMETRY:zt.ATTRIBUTES:ye(e?.dataToFetch)?e.dataToFetch:zt.ATTRIBUTES,n=ye(e?.attrMapping)?e.attrMapping:ye(e?.dataMapping)?e.dataMapping:null,{dataToFetch:t,dataMapping:n,fetchTo:ye(e?.fetchTo)?e.fetchTo:sn.METADATA}}selectTranslation(e,t){return this.tenantAttributesConfigForm.get("dataToFetch").value===zt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.tenantAttributesConfigForm=this.fb.group({dataToFetch:[e.dataToFetch,[]],dataMapping:[e.dataMapping,[_.required]],fetchTo:[e.fetchTo,[]]})}}e("TenantAttributesConfigComponent",ar),ar.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ar,deps:[{token:R.Store},{token:O.FormBuilder},{token:X.TranslateService}],target:t.ɵɵFactoryTarget.Component}),ar.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ar,selector:"tb-enrichment-node-tenant-attributes-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="tenantAttributesConfigForm" class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.mapping-of-tenant</div>\n <div fxFlex fxLayoutAlign="center center">\n <div class="fetch-to-data-toggle">\n <tb-toggle-select class="fetch-to-data-toggle" formControlName="dataToFetch" appearance="fill">\n <tb-toggle-option *ngFor="let data of fetchToData" [value]="data.value">\n {{ data.name }}\n </tb-toggle-option>\n </tb-toggle-select>\n </div>\n </div>\n <tb-kv-map-config\n required\n formControlName="dataMapping"\n [requiredText]="\'tb.rulenode.attr-mapping-required\' | translate"\n [labelText]="selectTranslation(\'tb.rulenode.latest-telemetry-mapping\', \'tb.rulenode.attributes-mapping\') | translate"\n [keyText]="selectTranslation(\'tb.rulenode.source-telemetry\', \'tb.rulenode.source-attribute\') | translate"\n [keyRequiredText]="selectTranslation(\'tb.rulenode.source-telemetry-required\', \'tb.rulenode.source-attribute-required\') | translate"\n [valText]="\'tb.rulenode.target-key\' | translate"\n [valRequiredText]="\'tb.rulenode.target-key-required\' | translate"\n [hintText]="\'tb.rulenode.kv-map-pattern-hint\'"\n popupHelpLink="rulenode/tenant_attributes_node_fields_templatization">\n </tb-kv-map-config>\n <tb-msg-metadata-chip formControlName="fetchTo"\n [labelText]="tenantAttributesConfigForm.get(\'dataToFetch\').value === DataToFetch.LATEST_TELEMETRY ?\n (\'tb.rulenode.add-mapped-latest-telemetry-to\' | translate) : (\'tb.rulenode.add-mapped-attribute-to\' | translate)">\n </tb-msg-metadata-chip>\n</section>\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:Z.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Me.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Ee.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination","fillHeight","extraPadding","primaryBackground"]},{kind:"component",type:Rn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ar,decorators:[{type:n,args:[{selector:"tb-enrichment-node-tenant-attributes-config",template:'<section [formGroup]="tenantAttributesConfigForm" class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.mapping-of-tenant</div>\n <div fxFlex fxLayoutAlign="center center">\n <div class="fetch-to-data-toggle">\n <tb-toggle-select class="fetch-to-data-toggle" formControlName="dataToFetch" appearance="fill">\n <tb-toggle-option *ngFor="let data of fetchToData" [value]="data.value">\n {{ data.name }}\n </tb-toggle-option>\n </tb-toggle-select>\n </div>\n </div>\n <tb-kv-map-config\n required\n formControlName="dataMapping"\n [requiredText]="\'tb.rulenode.attr-mapping-required\' | translate"\n [labelText]="selectTranslation(\'tb.rulenode.latest-telemetry-mapping\', \'tb.rulenode.attributes-mapping\') | translate"\n [keyText]="selectTranslation(\'tb.rulenode.source-telemetry\', \'tb.rulenode.source-attribute\') | translate"\n [keyRequiredText]="selectTranslation(\'tb.rulenode.source-telemetry-required\', \'tb.rulenode.source-attribute-required\') | translate"\n [valText]="\'tb.rulenode.target-key\' | translate"\n [valRequiredText]="\'tb.rulenode.target-key-required\' | translate"\n [hintText]="\'tb.rulenode.kv-map-pattern-hint\'"\n popupHelpLink="rulenode/tenant_attributes_node_fields_templatization">\n </tb-kv-map-config>\n <tb-msg-metadata-chip formControlName="fetchTo"\n [labelText]="tenantAttributesConfigForm.get(\'dataToFetch\').value === DataToFetch.LATEST_TELEMETRY ?\n (\'tb.rulenode.add-mapped-latest-telemetry-to\' | translate) : (\'tb.rulenode.add-mapped-attribute-to\' | translate)">\n </tb-msg-metadata-chip>\n</section>\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"]}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder},{type:X.TranslateService}]}});class ir extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.fetchDeviceCredentialsConfigForm}prepareInputConfig(e){return{fetchTo:ye(e?.fetchTo)?e.fetchTo:sn.METADATA}}onConfigurationSet(e){this.fetchDeviceCredentialsConfigForm=this.fb.group({fetchTo:[e.fetchTo,[]]})}}e("FetchDeviceCredentialsConfigComponent",ir),ir.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ir,deps:[{token:R.Store},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),ir.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ir,selector:"./tb-enrichment-node-fetch-device-credentials-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="fetchDeviceCredentialsConfigForm">\n <tb-msg-metadata-chip\n [labelText]="\'tb.rulenode.fetch-credentials-to\' | translate"\n formControlName="fetchTo">\n </tb-msg-metadata-chip>\n</section>\n',dependencies:[{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ir,decorators:[{type:n,args:[{selector:"./tb-enrichment-node-fetch-device-credentials-config",template:'<section [formGroup]="fetchDeviceCredentialsConfigForm">\n <tb-msg-metadata-chip\n [labelText]="\'tb.rulenode.fetch-credentials-to\' | translate"\n formControlName="fetchTo">\n </tb-msg-metadata-chip>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder}]}});class lr{}e("RulenodeCoreConfigEnrichmentModule",lr),lr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:lr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),lr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:lr,declarations:[Zn,er,Xn,nr,rr,tr,or,ar,Wn,ir],imports:[J,E,Qn],exports:[Zn,er,Xn,nr,rr,tr,or,ar,Wn,ir]}),lr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:lr,imports:[J,E,Qn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:lr,decorators:[{type:d,args:[{declarations:[Zn,er,Xn,nr,rr,tr,or,ar,Wn,ir],imports:[J,E,Qn],exports:[Zn,er,Xn,nr,rr,tr,or,ar,Wn,ir]}]}]});class sr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.allAzureIotHubCredentialsTypes=Zt,this.azureIotHubCredentialsTypeTranslationsMap=Xt}configForm(){return this.azureIotHubConfigForm}onConfigurationSet(e){this.azureIotHubConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[_.required]],host:[e?e.host:null,[_.required]],port:[e?e.port:null,[_.required,_.min(1),_.max(65535)]],connectTimeoutSec:[e?e.connectTimeoutSec:null,[_.required,_.min(1),_.max(200)]],clientId:[e?e.clientId:null,[_.required]],cleanSession:[!!e&&e.cleanSession,[]],ssl:[!!e&&e.ssl,[]],credentials:this.fb.group({type:[e&&e.credentials?e.credentials.type:null,[_.required]],sasKey:[e&&e.credentials?e.credentials.sasKey:null,[]],caCert:[e&&e.credentials?e.credentials.caCert:null,[]],caCertFileName:[e&&e.credentials?e.credentials.caCertFileName:null,[]],privateKey:[e&&e.credentials?e.credentials.privateKey:null,[]],privateKeyFileName:[e&&e.credentials?e.credentials.privateKeyFileName:null,[]],cert:[e&&e.credentials?e.credentials.cert:null,[]],certFileName:[e&&e.credentials?e.credentials.certFileName:null,[]],password:[e&&e.credentials?e.credentials.password:null,[]]})})}prepareOutputConfig(e){const t=e.credentials.type;return"sas"===t&&(e.credentials={type:t,sasKey:e.credentials.sasKey,caCert:e.credentials.caCert,caCertFileName:e.credentials.caCertFileName}),e}validatorTriggers(){return["credentials.type"]}updateValidators(e){const t=this.azureIotHubConfigForm.get("credentials"),n=t.get("type").value;switch(e&&t.reset({type:n},{emitEvent:!1}),t.get("sasKey").setValidators([]),t.get("privateKey").setValidators([]),t.get("privateKeyFileName").setValidators([]),t.get("cert").setValidators([]),t.get("certFileName").setValidators([]),n){case"sas":t.get("sasKey").setValidators([_.required]);break;case"cert.PEM":t.get("privateKey").setValidators([_.required]),t.get("privateKeyFileName").setValidators([_.required]),t.get("cert").setValidators([_.required]),t.get("certFileName").setValidators([_.required])}t.get("sasKey").updateValueAndValidity({emitEvent:e}),t.get("privateKey").updateValueAndValidity({emitEvent:e}),t.get("privateKeyFileName").updateValueAndValidity({emitEvent:e}),t.get("cert").updateValueAndValidity({emitEvent:e}),t.get("certFileName").updateValueAndValidity({emitEvent:e})}}e("AzureIotHubConfigComponent",sr),sr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:sr,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),sr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:sr,selector:"tb-external-node-azure-iot-hub-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="azureIotHubConfigForm" fxLayout="column">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.topic</mat-label>\n <input required matInput formControlName="topicPattern">\n <mat-error *ngIf="azureIotHubConfigForm.get(\'topicPattern\').hasError(\'required\')">\n {{ \'tb.rulenode.topic-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.hostname</mat-label>\n <input required matInput formControlName="host">\n <mat-error *ngIf="azureIotHubConfigForm.get(\'host\').hasError(\'required\')">\n {{ \'tb.rulenode.hostname-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.device-id</mat-label>\n <input required matInput formControlName="clientId" autocomplete="new-clientId">\n <mat-error *ngIf="azureIotHubConfigForm.get(\'clientId\').hasError(\'required\')">\n {{ \'tb.rulenode.device-id-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-accordion>\n <mat-expansion-panel class="tb-mqtt-credentials-panel-group">\n <mat-expansion-panel-header>\n <mat-panel-title class="tb-required" translate>tb.rulenode.credentials</mat-panel-title>\n <mat-panel-description>\n {{ azureIotHubCredentialsTypeTranslationsMap.get(azureIotHubConfigForm.get(\'credentials.type\').value) | translate }}\n </mat-panel-description>\n </mat-expansion-panel-header>\n <section formGroupName="credentials" fxLayout="column">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.credentials-type</mat-label>\n <mat-select formControlName="type" required>\n <mat-option *ngFor="let credentialsType of allAzureIotHubCredentialsTypes" [value]="credentialsType">\n {{ azureIotHubCredentialsTypeTranslationsMap.get(credentialsType) | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf="azureIotHubConfigForm.get(\'credentials.type\').hasError(\'required\')">\n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <section fxLayout="column" [ngSwitch]="azureIotHubConfigForm.get(\'credentials.type\').value">\n <ng-template ngSwitchCase="anonymous">\n </ng-template>\n <ng-template ngSwitchCase="sas">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.sas-key</mat-label>\n <input type="password" required matInput formControlName="sasKey" autocomplete="new-password">\n <tb-toggle-password matSuffix></tb-toggle-password>\n <mat-error *ngIf="azureIotHubConfigForm.get(\'credentials.sasKey\').hasError(\'required\')">\n {{ \'tb.rulenode.sas-key-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <tb-file-input formControlName="caCert"\n inputId="caCertSelect"\n [existingFileName]="azureIotHubConfigForm.get(\'credentials.caCertFileName\').value"\n (fileNameChanged)="azureIotHubConfigForm.get(\'credentials.caCertFileName\').setValue($event)"\n label="{{\'tb.rulenode.azure-ca-cert\' | translate}}"\n noFileText="tb.rulenode.no-file"\n dropLabel="{{\'tb.rulenode.drop-file\' | translate}}">\n </tb-file-input>\n </ng-template>\n <ng-template ngSwitchCase="cert.PEM">\n <tb-file-input formControlName="caCert"\n inputId="caCertSelect"\n [existingFileName]="azureIotHubConfigForm.get(\'credentials.caCertFileName\').value"\n (fileNameChanged)="azureIotHubConfigForm.get(\'credentials.caCertFileName\').setValue($event)"\n label="{{\'tb.rulenode.azure-ca-cert\' | translate}}"\n noFileText="tb.rulenode.no-file"\n dropLabel="{{\'tb.rulenode.drop-file\' | translate}}">\n </tb-file-input>\n <tb-file-input formControlName="cert"\n inputId="CertSelect"\n [existingFileName]="azureIotHubConfigForm.get(\'credentials.certFileName\').value"\n (fileNameChanged)="azureIotHubConfigForm.get(\'credentials.certFileName\').setValue($event)"\n required\n requiredAsError\n label="{{\'tb.rulenode.cert\' | translate}}"\n noFileText="tb.rulenode.no-file"\n dropLabel="{{\'tb.rulenode.drop-file\' | translate}}">\n </tb-file-input>\n <tb-file-input style="padding-bottom: 8px;"\n formControlName="privateKey"\n inputId="privateKeySelect"\n [existingFileName]="azureIotHubConfigForm.get(\'credentials.privateKeyFileName\').value"\n (fileNameChanged)="azureIotHubConfigForm.get(\'credentials.privateKeyFileName\').setValue($event)"\n required\n requiredAsError\n label="{{\'tb.rulenode.private-key\' | translate}}"\n noFileText="tb.rulenode.no-file"\n dropLabel="{{\'tb.rulenode.drop-file\' | translate}}">\n </tb-file-input>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.private-key-password</mat-label>\n <input type="password" matInput formControlName="password" autocomplete="new-password">\n <tb-toggle-password matSuffix></tb-toggle-password>\n </mat-form-field>\n </ng-template>\n </section>\n </section>\n </mat-expansion-panel>\n </mat-accordion>\n</section>\n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:j.NgSwitch,selector:"[ngSwitch]",inputs:["ngSwitch"]},{kind:"directive",type:j.NgSwitchCase,selector:"[ngSwitchCase]",inputs:["ngSwitchCase"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ae.MatAccordion,selector:"mat-accordion",inputs:["multi","hideToggle","displayMode","togglePosition"],exportAs:["matAccordion"]},{kind:"component",type:ae.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:ae.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:ae.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:ae.MatExpansionPanelDescription,selector:"mat-panel-description"},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:O.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"component",type:Xe.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:et.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:sr,decorators:[{type:n,args:[{selector:"tb-external-node-azure-iot-hub-config",template:'<section [formGroup]="azureIotHubConfigForm" fxLayout="column">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.topic</mat-label>\n <input required matInput formControlName="topicPattern">\n <mat-error *ngIf="azureIotHubConfigForm.get(\'topicPattern\').hasError(\'required\')">\n {{ \'tb.rulenode.topic-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.hostname</mat-label>\n <input required matInput formControlName="host">\n <mat-error *ngIf="azureIotHubConfigForm.get(\'host\').hasError(\'required\')">\n {{ \'tb.rulenode.hostname-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.device-id</mat-label>\n <input required matInput formControlName="clientId" autocomplete="new-clientId">\n <mat-error *ngIf="azureIotHubConfigForm.get(\'clientId\').hasError(\'required\')">\n {{ \'tb.rulenode.device-id-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-accordion>\n <mat-expansion-panel class="tb-mqtt-credentials-panel-group">\n <mat-expansion-panel-header>\n <mat-panel-title class="tb-required" translate>tb.rulenode.credentials</mat-panel-title>\n <mat-panel-description>\n {{ azureIotHubCredentialsTypeTranslationsMap.get(azureIotHubConfigForm.get(\'credentials.type\').value) | translate }}\n </mat-panel-description>\n </mat-expansion-panel-header>\n <section formGroupName="credentials" fxLayout="column">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.credentials-type</mat-label>\n <mat-select formControlName="type" required>\n <mat-option *ngFor="let credentialsType of allAzureIotHubCredentialsTypes" [value]="credentialsType">\n {{ azureIotHubCredentialsTypeTranslationsMap.get(credentialsType) | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf="azureIotHubConfigForm.get(\'credentials.type\').hasError(\'required\')">\n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <section fxLayout="column" [ngSwitch]="azureIotHubConfigForm.get(\'credentials.type\').value">\n <ng-template ngSwitchCase="anonymous">\n </ng-template>\n <ng-template ngSwitchCase="sas">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.sas-key</mat-label>\n <input type="password" required matInput formControlName="sasKey" autocomplete="new-password">\n <tb-toggle-password matSuffix></tb-toggle-password>\n <mat-error *ngIf="azureIotHubConfigForm.get(\'credentials.sasKey\').hasError(\'required\')">\n {{ \'tb.rulenode.sas-key-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <tb-file-input formControlName="caCert"\n inputId="caCertSelect"\n [existingFileName]="azureIotHubConfigForm.get(\'credentials.caCertFileName\').value"\n (fileNameChanged)="azureIotHubConfigForm.get(\'credentials.caCertFileName\').setValue($event)"\n label="{{\'tb.rulenode.azure-ca-cert\' | translate}}"\n noFileText="tb.rulenode.no-file"\n dropLabel="{{\'tb.rulenode.drop-file\' | translate}}">\n </tb-file-input>\n </ng-template>\n <ng-template ngSwitchCase="cert.PEM">\n <tb-file-input formControlName="caCert"\n inputId="caCertSelect"\n [existingFileName]="azureIotHubConfigForm.get(\'credentials.caCertFileName\').value"\n (fileNameChanged)="azureIotHubConfigForm.get(\'credentials.caCertFileName\').setValue($event)"\n label="{{\'tb.rulenode.azure-ca-cert\' | translate}}"\n noFileText="tb.rulenode.no-file"\n dropLabel="{{\'tb.rulenode.drop-file\' | translate}}">\n </tb-file-input>\n <tb-file-input formControlName="cert"\n inputId="CertSelect"\n [existingFileName]="azureIotHubConfigForm.get(\'credentials.certFileName\').value"\n (fileNameChanged)="azureIotHubConfigForm.get(\'credentials.certFileName\').setValue($event)"\n required\n requiredAsError\n label="{{\'tb.rulenode.cert\' | translate}}"\n noFileText="tb.rulenode.no-file"\n dropLabel="{{\'tb.rulenode.drop-file\' | translate}}">\n </tb-file-input>\n <tb-file-input style="padding-bottom: 8px;"\n formControlName="privateKey"\n inputId="privateKeySelect"\n [existingFileName]="azureIotHubConfigForm.get(\'credentials.privateKeyFileName\').value"\n (fileNameChanged)="azureIotHubConfigForm.get(\'credentials.privateKeyFileName\').setValue($event)"\n required\n requiredAsError\n label="{{\'tb.rulenode.private-key\' | translate}}"\n noFileText="tb.rulenode.no-file"\n dropLabel="{{\'tb.rulenode.drop-file\' | translate}}">\n </tb-file-input>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.private-key-password</mat-label>\n <input type="password" matInput formControlName="password" autocomplete="new-password">\n <tb-toggle-password matSuffix></tb-toggle-password>\n </mat-form-field>\n </ng-template>\n </section>\n </section>\n </mat-expansion-panel>\n </mat-accordion>\n</section>\n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class mr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.ackValues=["all","-1","0","1"],this.ToByteStandartCharsetTypesValues=tn,this.ToByteStandartCharsetTypeTranslationMap=nn}configForm(){return this.kafkaConfigForm}onConfigurationSet(e){this.kafkaConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[_.required]],keyPattern:[e?e.keyPattern:null],bootstrapServers:[e?e.bootstrapServers:null,[_.required]],retries:[e?e.retries:null,[_.min(0)]],batchSize:[e?e.batchSize:null,[_.min(0)]],linger:[e?e.linger:null,[_.min(0)]],bufferMemory:[e?e.bufferMemory:null,[_.min(0)]],acks:[e?e.acks:null,[_.required]],keySerializer:[e?e.keySerializer:null,[_.required]],valueSerializer:[e?e.valueSerializer:null,[_.required]],otherProperties:[e?e.otherProperties:null,[]],addMetadataKeyValuesAsKafkaHeaders:[!!e&&e.addMetadataKeyValuesAsKafkaHeaders,[]],kafkaHeadersCharset:[e?e.kafkaHeadersCharset:null,[]]})}validatorTriggers(){return["addMetadataKeyValuesAsKafkaHeaders"]}updateValidators(e){this.kafkaConfigForm.get("addMetadataKeyValuesAsKafkaHeaders").value?this.kafkaConfigForm.get("kafkaHeadersCharset").setValidators([_.required]):this.kafkaConfigForm.get("kafkaHeadersCharset").setValidators([]),this.kafkaConfigForm.get("kafkaHeadersCharset").updateValueAndValidity({emitEvent:e})}}e("KafkaConfigComponent",mr),mr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:mr,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),mr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:mr,selector:"tb-external-node-kafka-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="kafkaConfigForm" fxLayout="column">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.topic-pattern</mat-label>\n <input required matInput formControlName="topicPattern">\n <mat-error *ngIf="kafkaConfigForm.get(\'topicPattern\').hasError(\'required\')">\n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.key-pattern</mat-label>\n <input matInput formControlName="keyPattern">\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <div class="tb-hint" translate>tb.rulenode.key-pattern-hint</div>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.bootstrap-servers</mat-label>\n <input required matInput formControlName="bootstrapServers">\n <mat-error *ngIf="kafkaConfigForm.get(\'bootstrapServers\').hasError(\'required\')">\n {{ \'tb.rulenode.bootstrap-servers-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.retries</mat-label>\n <input type="number" step="1" min="0" matInput formControlName="retries">\n <mat-error *ngIf="kafkaConfigForm.get(\'retries\').hasError(\'min\')">\n {{ \'tb.rulenode.min-retries-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.batch-size-bytes</mat-label>\n <input type="number" step="1" min="0" matInput formControlName="batchSize">\n <mat-error *ngIf="kafkaConfigForm.get(\'batchSize\').hasError(\'min\')">\n {{ \'tb.rulenode.min-batch-size-bytes-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.linger-ms</mat-label>\n <input type="number" step="1" min="0" matInput formControlName="linger">\n <mat-error *ngIf="kafkaConfigForm.get(\'linger\').hasError(\'min\')">\n {{ \'tb.rulenode.min-linger-ms-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.buffer-memory-bytes</mat-label>\n <input type="number" step="1" min="0" matInput formControlName="bufferMemory">\n <mat-error *ngIf="kafkaConfigForm.get(\'bufferMemory\').hasError(\'min\')">\n {{ \'tb.rulenode.min-buffer-memory-bytes-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.acks</mat-label>\n <mat-select formControlName="acks" required>\n <mat-option *ngFor="let ackValue of ackValues" [value]="ackValue">\n {{ ackValue }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.key-serializer</mat-label>\n <input required matInput formControlName="keySerializer">\n <mat-error *ngIf="kafkaConfigForm.get(\'keySerializer\').hasError(\'required\')">\n {{ \'tb.rulenode.key-serializer-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.value-serializer</mat-label>\n <input required matInput formControlName="valueSerializer">\n <mat-error *ngIf="kafkaConfigForm.get(\'valueSerializer\').hasError(\'required\')">\n {{ \'tb.rulenode.value-serializer-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <label translate class="tb-title">tb.rulenode.other-properties</label>\n <tb-kv-map-config-old\n required="false"\n formControlName="otherProperties"\n keyText="tb.rulenode.key"\n keyRequiredText="tb.rulenode.key-required"\n valText="tb.rulenode.value"\n valRequiredText="tb.rulenode.value-required">\n </tb-kv-map-config-old>\n <mat-checkbox fxFlex formControlName="addMetadataKeyValuesAsKafkaHeaders">\n {{ \'tb.rulenode.add-metadata-key-values-as-kafka-headers\' | translate }}\n </mat-checkbox>\n <div class="tb-hint" translate>tb.rulenode.add-metadata-key-values-as-kafka-headers-hint</div>\n <mat-form-field fxFlex class="mat-block" *ngIf="kafkaConfigForm.get(\'addMetadataKeyValuesAsKafkaHeaders\').value">\n <mat-label translate>tb.rulenode.charset-encoding</mat-label>\n <mat-select formControlName="kafkaHeadersCharset" required>\n <mat-option *ngFor="let charset of ToByteStandartCharsetTypesValues" [value]="charset">\n {{ ToByteStandartCharsetTypeTranslationMap.get(charset) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n</section>\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ie.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:mr,decorators:[{type:n,args:[{selector:"tb-external-node-kafka-config",template:'<section [formGroup]="kafkaConfigForm" fxLayout="column">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.topic-pattern</mat-label>\n <input required matInput formControlName="topicPattern">\n <mat-error *ngIf="kafkaConfigForm.get(\'topicPattern\').hasError(\'required\')">\n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.key-pattern</mat-label>\n <input matInput formControlName="keyPattern">\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <div class="tb-hint" translate>tb.rulenode.key-pattern-hint</div>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.bootstrap-servers</mat-label>\n <input required matInput formControlName="bootstrapServers">\n <mat-error *ngIf="kafkaConfigForm.get(\'bootstrapServers\').hasError(\'required\')">\n {{ \'tb.rulenode.bootstrap-servers-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.retries</mat-label>\n <input type="number" step="1" min="0" matInput formControlName="retries">\n <mat-error *ngIf="kafkaConfigForm.get(\'retries\').hasError(\'min\')">\n {{ \'tb.rulenode.min-retries-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.batch-size-bytes</mat-label>\n <input type="number" step="1" min="0" matInput formControlName="batchSize">\n <mat-error *ngIf="kafkaConfigForm.get(\'batchSize\').hasError(\'min\')">\n {{ \'tb.rulenode.min-batch-size-bytes-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.linger-ms</mat-label>\n <input type="number" step="1" min="0" matInput formControlName="linger">\n <mat-error *ngIf="kafkaConfigForm.get(\'linger\').hasError(\'min\')">\n {{ \'tb.rulenode.min-linger-ms-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.buffer-memory-bytes</mat-label>\n <input type="number" step="1" min="0" matInput formControlName="bufferMemory">\n <mat-error *ngIf="kafkaConfigForm.get(\'bufferMemory\').hasError(\'min\')">\n {{ \'tb.rulenode.min-buffer-memory-bytes-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.acks</mat-label>\n <mat-select formControlName="acks" required>\n <mat-option *ngFor="let ackValue of ackValues" [value]="ackValue">\n {{ ackValue }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.key-serializer</mat-label>\n <input required matInput formControlName="keySerializer">\n <mat-error *ngIf="kafkaConfigForm.get(\'keySerializer\').hasError(\'required\')">\n {{ \'tb.rulenode.key-serializer-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.value-serializer</mat-label>\n <input required matInput formControlName="valueSerializer">\n <mat-error *ngIf="kafkaConfigForm.get(\'valueSerializer\').hasError(\'required\')">\n {{ \'tb.rulenode.value-serializer-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <label translate class="tb-title">tb.rulenode.other-properties</label>\n <tb-kv-map-config-old\n required="false"\n formControlName="otherProperties"\n keyText="tb.rulenode.key"\n keyRequiredText="tb.rulenode.key-required"\n valText="tb.rulenode.value"\n valRequiredText="tb.rulenode.value-required">\n </tb-kv-map-config-old>\n <mat-checkbox fxFlex formControlName="addMetadataKeyValuesAsKafkaHeaders">\n {{ \'tb.rulenode.add-metadata-key-values-as-kafka-headers\' | translate }}\n </mat-checkbox>\n <div class="tb-hint" translate>tb.rulenode.add-metadata-key-values-as-kafka-headers-hint</div>\n <mat-form-field fxFlex class="mat-block" *ngIf="kafkaConfigForm.get(\'addMetadataKeyValuesAsKafkaHeaders\').value">\n <mat-label translate>tb.rulenode.charset-encoding</mat-label>\n <mat-select formControlName="kafkaHeadersCharset" required>\n <mat-option *ngFor="let charset of ToByteStandartCharsetTypesValues" [value]="charset">\n {{ ToByteStandartCharsetTypeTranslationMap.get(charset) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class pr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.mqttConfigForm}onConfigurationSet(e){this.mqttConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[_.required]],host:[e?e.host:null,[_.required]],port:[e?e.port:null,[_.required,_.min(1),_.max(65535)]],connectTimeoutSec:[e?e.connectTimeoutSec:null,[_.required,_.min(1),_.max(200)]],clientId:[e?e.clientId:null,[]],appendClientIdSuffix:[{value:!!e&&e.appendClientIdSuffix,disabled:!(e&&ve(e.clientId))},[]],parseToPlainText:[!!e&&e.parseToPlainText,[]],cleanSession:[!!e&&e.cleanSession,[]],retainedMessage:[!!e&&e.retainedMessage,[]],ssl:[!!e&&e.ssl,[]],credentials:[e?e.credentials:null,[]]})}updateValidators(e){ve(this.mqttConfigForm.get("clientId").value)?this.mqttConfigForm.get("appendClientIdSuffix").enable({emitEvent:!1}):this.mqttConfigForm.get("appendClientIdSuffix").disable({emitEvent:!1}),this.mqttConfigForm.get("appendClientIdSuffix").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["clientId"]}}e("MqttConfigComponent",pr),pr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:pr,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),pr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:pr,selector:"tb-external-node-mqtt-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="mqttConfigForm" fxLayout="column">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.topic-pattern</mat-label>\n <input required matInput formControlName="topicPattern">\n <mat-error *ngIf="mqttConfigForm.get(\'topicPattern\').hasError(\'required\')">\n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <div fxFlex fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap.gt-sm="8px">\n <mat-form-field fxFlex="60" class="mat-block">\n <mat-label translate>tb.rulenode.host</mat-label>\n <input required matInput formControlName="host">\n <mat-error *ngIf="mqttConfigForm.get(\'host\').hasError(\'required\')">\n {{ \'tb.rulenode.host-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex="40" class="mat-block">\n <mat-label translate>tb.rulenode.port</mat-label>\n <input required type="number" step="1" min="1" max="65535" matInput formControlName="port">\n <mat-error *ngIf="mqttConfigForm.get(\'port\').hasError(\'required\')">\n {{ \'tb.rulenode.port-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="mqttConfigForm.get(\'port\').hasError(\'min\')">\n {{ \'tb.rulenode.port-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="mqttConfigForm.get(\'port\').hasError(\'max\')">\n {{ \'tb.rulenode.port-range\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex="40" class="mat-block">\n <mat-label translate>tb.rulenode.connect-timeout</mat-label>\n <input required type="number" step="1" min="1" max="200" matInput formControlName="connectTimeoutSec">\n <mat-error *ngIf="mqttConfigForm.get(\'connectTimeoutSec\').hasError(\'required\')">\n {{ \'tb.rulenode.connect-timeout-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="mqttConfigForm.get(\'connectTimeoutSec\').hasError(\'min\')">\n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="mqttConfigForm.get(\'connectTimeoutSec\').hasError(\'max\')">\n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.client-id</mat-label>\n <input matInput formControlName="clientId">\n <mat-hint>{{\'tb.rulenode.client-id-hint\' | translate}}</mat-hint>\n </mat-form-field>\n <mat-checkbox formControlName="appendClientIdSuffix">\n {{ \'tb.rulenode.append-client-id-suffix\' | translate }}\n </mat-checkbox>\n <div class="tb-hint">{{ "tb.rulenode.client-id-suffix-hint" | translate }}</div>\n <mat-checkbox formControlName="parseToPlainText">\n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n </mat-checkbox>\n <div class="tb-hint">{{ "tb.rulenode.parse-to-plain-text-hint" | translate }}</div>\n <mat-checkbox formControlName="cleanSession">\n {{ \'tb.rulenode.clean-session\' | translate }}\n </mat-checkbox>\n <mat-checkbox formControlName="retainedMessage">\n {{ "tb.rulenode.retained-message" | translate }}\n </mat-checkbox>\n <mat-checkbox formControlName="ssl">\n {{ \'tb.rulenode.enable-ssl\' | translate }}\n </mat-checkbox>\n <tb-credentials-config formControlName="credentials" [passwordFieldRequired]="false"></tb-credentials-config>\n</section>\n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n"],dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ie.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Kn,selector:"tb-credentials-config",inputs:["required","disableCertPemCredentials","passwordFieldRequired"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:pr,decorators:[{type:n,args:[{selector:"tb-external-node-mqtt-config",template:'<section [formGroup]="mqttConfigForm" fxLayout="column">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.topic-pattern</mat-label>\n <input required matInput formControlName="topicPattern">\n <mat-error *ngIf="mqttConfigForm.get(\'topicPattern\').hasError(\'required\')">\n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <div fxFlex fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap.gt-sm="8px">\n <mat-form-field fxFlex="60" class="mat-block">\n <mat-label translate>tb.rulenode.host</mat-label>\n <input required matInput formControlName="host">\n <mat-error *ngIf="mqttConfigForm.get(\'host\').hasError(\'required\')">\n {{ \'tb.rulenode.host-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex="40" class="mat-block">\n <mat-label translate>tb.rulenode.port</mat-label>\n <input required type="number" step="1" min="1" max="65535" matInput formControlName="port">\n <mat-error *ngIf="mqttConfigForm.get(\'port\').hasError(\'required\')">\n {{ \'tb.rulenode.port-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="mqttConfigForm.get(\'port\').hasError(\'min\')">\n {{ \'tb.rulenode.port-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="mqttConfigForm.get(\'port\').hasError(\'max\')">\n {{ \'tb.rulenode.port-range\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex="40" class="mat-block">\n <mat-label translate>tb.rulenode.connect-timeout</mat-label>\n <input required type="number" step="1" min="1" max="200" matInput formControlName="connectTimeoutSec">\n <mat-error *ngIf="mqttConfigForm.get(\'connectTimeoutSec\').hasError(\'required\')">\n {{ \'tb.rulenode.connect-timeout-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="mqttConfigForm.get(\'connectTimeoutSec\').hasError(\'min\')">\n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="mqttConfigForm.get(\'connectTimeoutSec\').hasError(\'max\')">\n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.client-id</mat-label>\n <input matInput formControlName="clientId">\n <mat-hint>{{\'tb.rulenode.client-id-hint\' | translate}}</mat-hint>\n </mat-form-field>\n <mat-checkbox formControlName="appendClientIdSuffix">\n {{ \'tb.rulenode.append-client-id-suffix\' | translate }}\n </mat-checkbox>\n <div class="tb-hint">{{ "tb.rulenode.client-id-suffix-hint" | translate }}</div>\n <mat-checkbox formControlName="parseToPlainText">\n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n </mat-checkbox>\n <div class="tb-hint">{{ "tb.rulenode.parse-to-plain-text-hint" | translate }}</div>\n <mat-checkbox formControlName="cleanSession">\n {{ \'tb.rulenode.clean-session\' | translate }}\n </mat-checkbox>\n <mat-checkbox formControlName="retainedMessage">\n {{ "tb.rulenode.retained-message" | translate }}\n </mat-checkbox>\n <mat-checkbox formControlName="ssl">\n {{ \'tb.rulenode.enable-ssl\' | translate }}\n </mat-checkbox>\n <tb-credentials-config formControlName="credentials" [passwordFieldRequired]="false"></tb-credentials-config>\n</section>\n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n"]}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class dr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.notificationType=D,this.entityType=C}configForm(){return this.notificationConfigForm}onConfigurationSet(e){this.notificationConfigForm=this.fb.group({templateId:[e?e.templateId:null,[_.required]],targets:[e?e.targets:[],[_.required]]})}}e("NotificationConfigComponent",dr),dr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dr,deps:[{token:R.Store},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),dr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:dr,selector:"tb-external-node-notification-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="notificationConfigForm" fxLayout="column">\n <tb-template-autocomplete\n required\n allowCreate\n formControlName="templateId"\n [notificationTypes]="notificationType.RULE_NODE">\n </tb-template-autocomplete>\n <tb-entity-list\n required\n formControlName="targets"\n labelText="{{ \'notification.recipients\' | translate }}"\n placeholderText="{{ \'notification.recipient\' | translate }}"\n requiredText="{{ \'notification.recipients-required\' | translate }}"\n entityType="{{ entityType.NOTIFICATION_TARGET }}"\n subType="{{ notificationType.RULE_NODE }}">\n </tb-entity-list>\n</section>\n',dependencies:[{kind:"component",type:nt.EntityListComponent,selector:"tb-entity-list",inputs:["entityType","subType","labelText","placeholderText","requiredText","required","disabled","subscriptSizing","hint","syncIdsWithDB"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:rt.TemplateAutocompleteComponent,selector:"tb-template-autocomplete",inputs:["required","allowCreate","allowEdit","disabled","notificationTypes"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dr,decorators:[{type:n,args:[{selector:"tb-external-node-notification-config",template:'<section [formGroup]="notificationConfigForm" fxLayout="column">\n <tb-template-autocomplete\n required\n allowCreate\n formControlName="templateId"\n [notificationTypes]="notificationType.RULE_NODE">\n </tb-template-autocomplete>\n <tb-entity-list\n required\n formControlName="targets"\n labelText="{{ \'notification.recipients\' | translate }}"\n placeholderText="{{ \'notification.recipient\' | translate }}"\n requiredText="{{ \'notification.recipients-required\' | translate }}"\n entityType="{{ entityType.NOTIFICATION_TARGET }}"\n subType="{{ notificationType.RULE_NODE }}">\n </tb-entity-list>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder}]}});class ur extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.pubSubConfigForm}onConfigurationSet(e){this.pubSubConfigForm=this.fb.group({projectId:[e?e.projectId:null,[_.required]],topicName:[e?e.topicName:null,[_.required]],serviceAccountKey:[e?e.serviceAccountKey:null,[_.required]],serviceAccountKeyFileName:[e?e.serviceAccountKeyFileName:null,[_.required]],messageAttributes:[e?e.messageAttributes:null,[]]})}}e("PubSubConfigComponent",ur),ur.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ur,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ur.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ur,selector:"tb-external-node-pub-sub-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="pubSubConfigForm" fxLayout="column">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.gcp-project-id</mat-label>\n <input required matInput formControlName="projectId">\n <mat-error *ngIf="pubSubConfigForm.get(\'projectId\').hasError(\'required\')">\n {{ \'tb.rulenode.gcp-project-id-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.pubsub-topic-name</mat-label>\n <input required matInput formControlName="topicName">\n <mat-error *ngIf="pubSubConfigForm.get(\'topicName\').hasError(\'required\')">\n {{ \'tb.rulenode.pubsub-topic-name-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <tb-file-input style="padding-bottom: 24px;"\n formControlName="serviceAccountKey"\n [existingFileName]="pubSubConfigForm.get(\'serviceAccountKeyFileName\').value"\n (fileNameChanged)="pubSubConfigForm.get(\'serviceAccountKeyFileName\').setValue($event)"\n required\n requiredAsError\n label="{{\'tb.rulenode.gcp-service-account-key\' | translate}}"\n noFileText="tb.rulenode.no-file"\n dropLabel="{{\'tb.rulenode.drop-file\' | translate}}">\n </tb-file-input>\n <label translate class="tb-title">tb.rulenode.message-attributes</label>\n <div class="tb-hint" [innerHTML]="\'tb.rulenode.message-attributes-hint\' | translate | safe: \'html\'"></div>\n <tb-kv-map-config-old\n required="false"\n formControlName="messageAttributes"\n keyText="tb.rulenode.name"\n keyRequiredText="tb.rulenode.name-required"\n valText="tb.rulenode.value"\n valRequiredText="tb.rulenode.value-required">\n </tb-kv-map-config-old>\n</section>\n',dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Xe.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:ce.SafePipe,name:"safe"},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ur,decorators:[{type:n,args:[{selector:"tb-external-node-pub-sub-config",template:'<section [formGroup]="pubSubConfigForm" fxLayout="column">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.gcp-project-id</mat-label>\n <input required matInput formControlName="projectId">\n <mat-error *ngIf="pubSubConfigForm.get(\'projectId\').hasError(\'required\')">\n {{ \'tb.rulenode.gcp-project-id-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.pubsub-topic-name</mat-label>\n <input required matInput formControlName="topicName">\n <mat-error *ngIf="pubSubConfigForm.get(\'topicName\').hasError(\'required\')">\n {{ \'tb.rulenode.pubsub-topic-name-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <tb-file-input style="padding-bottom: 24px;"\n formControlName="serviceAccountKey"\n [existingFileName]="pubSubConfigForm.get(\'serviceAccountKeyFileName\').value"\n (fileNameChanged)="pubSubConfigForm.get(\'serviceAccountKeyFileName\').setValue($event)"\n required\n requiredAsError\n label="{{\'tb.rulenode.gcp-service-account-key\' | translate}}"\n noFileText="tb.rulenode.no-file"\n dropLabel="{{\'tb.rulenode.drop-file\' | translate}}">\n </tb-file-input>\n <label translate class="tb-title">tb.rulenode.message-attributes</label>\n <div class="tb-hint" [innerHTML]="\'tb.rulenode.message-attributes-hint\' | translate | safe: \'html\'"></div>\n <tb-kv-map-config-old\n required="false"\n formControlName="messageAttributes"\n keyText="tb.rulenode.name"\n keyRequiredText="tb.rulenode.name-required"\n valText="tb.rulenode.value"\n valRequiredText="tb.rulenode.value-required">\n </tb-kv-map-config-old>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class cr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.messageProperties=[null,"BASIC","TEXT_PLAIN","MINIMAL_BASIC","MINIMAL_PERSISTENT_BASIC","PERSISTENT_BASIC","PERSISTENT_TEXT_PLAIN"]}configForm(){return this.rabbitMqConfigForm}onConfigurationSet(e){this.rabbitMqConfigForm=this.fb.group({exchangeNamePattern:[e?e.exchangeNamePattern:null,[]],routingKeyPattern:[e?e.routingKeyPattern:null,[]],messageProperties:[e?e.messageProperties:null,[]],host:[e?e.host:null,[_.required]],port:[e?e.port:null,[_.required,_.min(1),_.max(65535)]],virtualHost:[e?e.virtualHost:null,[]],username:[e?e.username:null,[]],password:[e?e.password:null,[]],automaticRecoveryEnabled:[!!e&&e.automaticRecoveryEnabled,[]],connectionTimeout:[e?e.connectionTimeout:null,[_.min(0)]],handshakeTimeout:[e?e.handshakeTimeout:null,[_.min(0)]],clientProperties:[e?e.clientProperties:null,[]]})}}e("RabbitMqConfigComponent",cr),cr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cr,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),cr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:cr,selector:"tb-external-node-rabbit-mq-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="rabbitMqConfigForm" fxLayout="column">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.exchange-name-pattern</mat-label>\n <input matInput formControlName="exchangeNamePattern">\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.routing-key-pattern</mat-label>\n <input matInput formControlName="routingKeyPattern">\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.message-properties</mat-label>\n <mat-select formControlName="messageProperties">\n <mat-option *ngFor="let property of messageProperties" [value]="property">\n {{ property }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <div fxLayout.gt-sm="row" fxLayoutGap.gt-sm="8px">\n <mat-form-field fxFlex="100" fxFlex.gt-sm="60" class="mat-block">\n <mat-label translate>tb.rulenode.host</mat-label>\n <input required matInput formControlName="host">\n <mat-error *ngIf="rabbitMqConfigForm.get(\'host\').hasError(\'required\')">\n {{ \'tb.rulenode.host-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex="100" fxFlex.gt-sm="40" class="mat-block">\n <mat-label translate>tb.rulenode.port</mat-label>\n <input required type="number" step="1" min="1" max="65535" matInput formControlName="port">\n <mat-error *ngIf="rabbitMqConfigForm.get(\'port\').hasError(\'required\')">\n {{ \'tb.rulenode.port-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="rabbitMqConfigForm.get(\'port\').hasError(\'min\')">\n {{ \'tb.rulenode.port-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="rabbitMqConfigForm.get(\'port\').hasError(\'max\')">\n {{ \'tb.rulenode.port-range\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.virtual-host</mat-label>\n <input matInput formControlName="virtualHost">\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.username</mat-label>\n <input matInput formControlName="username">\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.password</mat-label>\n <input type="password" matInput formControlName="password">\n <tb-toggle-password matSuffix></tb-toggle-password>\n </mat-form-field>\n <mat-checkbox formControlName="automaticRecoveryEnabled">\n {{ \'tb.rulenode.automatic-recovery\' | translate }}\n </mat-checkbox>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.connection-timeout-ms</mat-label>\n <input type="number" step="1" min="0" matInput formControlName="connectionTimeout">\n <mat-error *ngIf="rabbitMqConfigForm.get(\'connectionTimeout\').hasError(\'min\')">\n {{ \'tb.rulenode.min-connection-timeout-ms-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.handshake-timeout-ms</mat-label>\n <input type="number" step="1" min="0" matInput formControlName="handshakeTimeout">\n <mat-error *ngIf="rabbitMqConfigForm.get(\'handshakeTimeout\').hasError(\'min\')">\n {{ \'tb.rulenode.min-handshake-timeout-ms-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <label translate class="tb-title">tb.rulenode.client-properties</label>\n <tb-kv-map-config-old\n required="false"\n formControlName="clientProperties"\n keyText="tb.rulenode.key"\n keyRequiredText="tb.rulenode.key-required"\n valText="tb.rulenode.value"\n valRequiredText="tb.rulenode.value-required">\n </tb-kv-map-config-old>\n</section>\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ie.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:et.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cr,decorators:[{type:n,args:[{selector:"tb-external-node-rabbit-mq-config",template:'<section [formGroup]="rabbitMqConfigForm" fxLayout="column">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.exchange-name-pattern</mat-label>\n <input matInput formControlName="exchangeNamePattern">\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.routing-key-pattern</mat-label>\n <input matInput formControlName="routingKeyPattern">\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.message-properties</mat-label>\n <mat-select formControlName="messageProperties">\n <mat-option *ngFor="let property of messageProperties" [value]="property">\n {{ property }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <div fxLayout.gt-sm="row" fxLayoutGap.gt-sm="8px">\n <mat-form-field fxFlex="100" fxFlex.gt-sm="60" class="mat-block">\n <mat-label translate>tb.rulenode.host</mat-label>\n <input required matInput formControlName="host">\n <mat-error *ngIf="rabbitMqConfigForm.get(\'host\').hasError(\'required\')">\n {{ \'tb.rulenode.host-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex="100" fxFlex.gt-sm="40" class="mat-block">\n <mat-label translate>tb.rulenode.port</mat-label>\n <input required type="number" step="1" min="1" max="65535" matInput formControlName="port">\n <mat-error *ngIf="rabbitMqConfigForm.get(\'port\').hasError(\'required\')">\n {{ \'tb.rulenode.port-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="rabbitMqConfigForm.get(\'port\').hasError(\'min\')">\n {{ \'tb.rulenode.port-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="rabbitMqConfigForm.get(\'port\').hasError(\'max\')">\n {{ \'tb.rulenode.port-range\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.virtual-host</mat-label>\n <input matInput formControlName="virtualHost">\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.username</mat-label>\n <input matInput formControlName="username">\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.password</mat-label>\n <input type="password" matInput formControlName="password">\n <tb-toggle-password matSuffix></tb-toggle-password>\n </mat-form-field>\n <mat-checkbox formControlName="automaticRecoveryEnabled">\n {{ \'tb.rulenode.automatic-recovery\' | translate }}\n </mat-checkbox>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.connection-timeout-ms</mat-label>\n <input type="number" step="1" min="0" matInput formControlName="connectionTimeout">\n <mat-error *ngIf="rabbitMqConfigForm.get(\'connectionTimeout\').hasError(\'min\')">\n {{ \'tb.rulenode.min-connection-timeout-ms-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.handshake-timeout-ms</mat-label>\n <input type="number" step="1" min="0" matInput formControlName="handshakeTimeout">\n <mat-error *ngIf="rabbitMqConfigForm.get(\'handshakeTimeout\').hasError(\'min\')">\n {{ \'tb.rulenode.min-handshake-timeout-ms-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <label translate class="tb-title">tb.rulenode.client-properties</label>\n <tb-kv-map-config-old\n required="false"\n formControlName="clientProperties"\n keyText="tb.rulenode.key"\n keyRequiredText="tb.rulenode.key-required"\n valText="tb.rulenode.value"\n valRequiredText="tb.rulenode.value-required">\n </tb-kv-map-config-old>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class gr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.proxySchemes=["http","https"],this.httpRequestTypes=Object.keys(en)}configForm(){return this.restApiCallConfigForm}onConfigurationSet(e){this.restApiCallConfigForm=this.fb.group({restEndpointUrlPattern:[e?e.restEndpointUrlPattern:null,[_.required]],requestMethod:[e?e.requestMethod:null,[_.required]],useSimpleClientHttpFactory:[!!e&&e.useSimpleClientHttpFactory,[]],parseToPlainText:[!!e&&e.parseToPlainText,[]],ignoreRequestBody:[!!e&&e.ignoreRequestBody,[]],enableProxy:[!!e&&e.enableProxy,[]],useSystemProxyProperties:[!!e&&e.enableProxy,[]],proxyScheme:[e?e.proxyHost:null,[]],proxyHost:[e?e.proxyHost:null,[]],proxyPort:[e?e.proxyPort:null,[]],proxyUser:[e?e.proxyUser:null,[]],proxyPassword:[e?e.proxyPassword:null,[]],readTimeoutMs:[e?e.readTimeoutMs:null,[]],maxParallelRequestsCount:[e?e.maxParallelRequestsCount:null,[_.min(0)]],headers:[e?e.headers:null,[]],credentials:[e?e.credentials:null,[]],maxInMemoryBufferSizeInKb:[e?e.maxInMemoryBufferSizeInKb:null,[_.min(1)]]})}validatorTriggers(){return["useSimpleClientHttpFactory","enableProxy","useSystemProxyProperties"]}updateValidators(e){const t=this.restApiCallConfigForm.get("useSimpleClientHttpFactory").value,n=this.restApiCallConfigForm.get("enableProxy").value,r=this.restApiCallConfigForm.get("useSystemProxyProperties").value;n&&!r?(this.restApiCallConfigForm.get("proxyHost").setValidators(n?[_.required]:[]),this.restApiCallConfigForm.get("proxyPort").setValidators(n?[_.required,_.min(1),_.max(65535)]:[])):(this.restApiCallConfigForm.get("proxyHost").setValidators([]),this.restApiCallConfigForm.get("proxyPort").setValidators([]),t?this.restApiCallConfigForm.get("readTimeoutMs").setValidators([]):this.restApiCallConfigForm.get("readTimeoutMs").setValidators([_.min(0)])),this.restApiCallConfigForm.get("readTimeoutMs").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("proxyHost").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("proxyPort").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("credentials").updateValueAndValidity({emitEvent:e})}}e("RestApiCallConfigComponent",gr),gr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gr,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),gr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:gr,selector:"tb-external-node-rest-api-call-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="restApiCallConfigForm" fxLayout="column">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.endpoint-url-pattern</mat-label>\n <input required matInput formControlName="restEndpointUrlPattern">\n <mat-error *ngIf="restApiCallConfigForm.get(\'restEndpointUrlPattern\').hasError(\'required\')">\n {{ \'tb.rulenode.endpoint-url-pattern-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.request-method</mat-label>\n <mat-select formControlName="requestMethod">\n <mat-option *ngFor="let requestType of httpRequestTypes" [value]="requestType">\n {{ requestType }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-checkbox formControlName="enableProxy">\n {{ \'tb.rulenode.enable-proxy\' | translate }}\n </mat-checkbox>\n <mat-checkbox *ngIf="!restApiCallConfigForm.get(\'enableProxy\').value" formControlName="useSimpleClientHttpFactory">\n {{ \'tb.rulenode.use-simple-client-http-factory\' | translate }}\n </mat-checkbox>\n <mat-checkbox formControlName="parseToPlainText">\n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n </mat-checkbox>\n <div class="tb-hint" style="padding-bottom: 5px;" translate>tb.rulenode.parse-to-plain-text-hint</div>\n <mat-checkbox formControlName="ignoreRequestBody">\n {{ \'tb.rulenode.ignore-request-body\' | translate }}\n </mat-checkbox>\n <div *ngIf="restApiCallConfigForm.get(\'enableProxy\').value">\n <mat-checkbox formControlName="useSystemProxyProperties">\n {{ \'tb.rulenode.use-system-proxy-properties\' | translate }}\n </mat-checkbox>\n <div *ngIf="!restApiCallConfigForm.get(\'useSystemProxyProperties\').value">\n <div fxLayout.gt-sm="row" fxLayoutGap.gt-sm="8px">\n <mat-form-field class="mat-block" fxFlex="100" fxFlex.gt-sm="10">\n <mat-label translate>tb.rulenode.proxy-scheme</mat-label>\n <mat-select formControlName="proxyScheme">\n <mat-option *ngFor="let proxyScheme of proxySchemes" [value]="proxyScheme">\n {{ proxyScheme }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="md-block" fxFlex="100" fxFlex.gt-sm="50">\n <mat-label translate>tb.rulenode.proxy-host</mat-label>\n <input matInput required formControlName="proxyHost">\n <mat-error *ngIf="restApiCallConfigForm.get(\'proxyHost\').hasError(\'required\')">\n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block" fxFlex="100" fxFlex.gt-sm="40">\n <mat-label translate>tb.rulenode.proxy-port</mat-label>\n <input matInput required formControlName="proxyPort" type="number" step="1">\n <mat-error *ngIf="restApiCallConfigForm.get(\'proxyPort\').hasError(\'required\')">\n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n </mat-error>\n <mat-error\n *ngIf="restApiCallConfigForm.get(\'proxyPort\').hasError(\'min\') || restApiCallConfigForm.get(\'proxyPort\').hasError(\'max\')">\n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.proxy-user</mat-label>\n <input matInput formControlName="proxyUser">\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.proxy-password</mat-label>\n <input matInput formControlName="proxyPassword">\n </mat-form-field>\n </div>\n </div>\n <mat-form-field *ngIf="!restApiCallConfigForm.get(\'useSimpleClientHttpFactory\').value || restApiCallConfigForm.get(\'enableProxy\').value" class="mat-block"\n subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.read-timeout</mat-label>\n <input type="number" step="1" min="0" matInput formControlName="readTimeoutMs">\n <mat-hint translate>tb.rulenode.read-timeout-hint</mat-hint>\n </mat-form-field>\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.max-parallel-requests-count</mat-label>\n <input type="number" step="1" min="0" matInput formControlName="maxParallelRequestsCount">\n <mat-hint translate>tb.rulenode.max-parallel-requests-count-hint</mat-hint>\n </mat-form-field>\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.max-response-size</mat-label>\n <input type="number" step="1" min="1" matInput formControlName="maxInMemoryBufferSizeInKb">\n <mat-hint translate>tb.rulenode.max-response-size-hint</mat-hint>\n </mat-form-field>\n <label translate class="tb-title">tb.rulenode.headers</label>\n <div class="tb-hint" [innerHTML]="\'tb.rulenode.headers-hint\' | translate | safe: \'html\'"> </div>\n <tb-kv-map-config-old\n required="false"\n formControlName="headers"\n keyText="tb.rulenode.header"\n keyRequiredText="tb.rulenode.header-required"\n valText="tb.rulenode.value"\n valRequiredText="tb.rulenode.value-required">\n </tb-kv-map-config-old>\n <tb-credentials-config formControlName="credentials" [disableCertPemCredentials]="restApiCallConfigForm.get(\'useSimpleClientHttpFactory\').value"></tb-credentials-config>\n</section>\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ie.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Kn,selector:"tb-credentials-config",inputs:["required","disableCertPemCredentials","passwordFieldRequired"]},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:ce.SafePipe,name:"safe"},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gr,decorators:[{type:n,args:[{selector:"tb-external-node-rest-api-call-config",template:'<section [formGroup]="restApiCallConfigForm" fxLayout="column">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.endpoint-url-pattern</mat-label>\n <input required matInput formControlName="restEndpointUrlPattern">\n <mat-error *ngIf="restApiCallConfigForm.get(\'restEndpointUrlPattern\').hasError(\'required\')">\n {{ \'tb.rulenode.endpoint-url-pattern-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.request-method</mat-label>\n <mat-select formControlName="requestMethod">\n <mat-option *ngFor="let requestType of httpRequestTypes" [value]="requestType">\n {{ requestType }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-checkbox formControlName="enableProxy">\n {{ \'tb.rulenode.enable-proxy\' | translate }}\n </mat-checkbox>\n <mat-checkbox *ngIf="!restApiCallConfigForm.get(\'enableProxy\').value" formControlName="useSimpleClientHttpFactory">\n {{ \'tb.rulenode.use-simple-client-http-factory\' | translate }}\n </mat-checkbox>\n <mat-checkbox formControlName="parseToPlainText">\n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n </mat-checkbox>\n <div class="tb-hint" style="padding-bottom: 5px;" translate>tb.rulenode.parse-to-plain-text-hint</div>\n <mat-checkbox formControlName="ignoreRequestBody">\n {{ \'tb.rulenode.ignore-request-body\' | translate }}\n </mat-checkbox>\n <div *ngIf="restApiCallConfigForm.get(\'enableProxy\').value">\n <mat-checkbox formControlName="useSystemProxyProperties">\n {{ \'tb.rulenode.use-system-proxy-properties\' | translate }}\n </mat-checkbox>\n <div *ngIf="!restApiCallConfigForm.get(\'useSystemProxyProperties\').value">\n <div fxLayout.gt-sm="row" fxLayoutGap.gt-sm="8px">\n <mat-form-field class="mat-block" fxFlex="100" fxFlex.gt-sm="10">\n <mat-label translate>tb.rulenode.proxy-scheme</mat-label>\n <mat-select formControlName="proxyScheme">\n <mat-option *ngFor="let proxyScheme of proxySchemes" [value]="proxyScheme">\n {{ proxyScheme }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="md-block" fxFlex="100" fxFlex.gt-sm="50">\n <mat-label translate>tb.rulenode.proxy-host</mat-label>\n <input matInput required formControlName="proxyHost">\n <mat-error *ngIf="restApiCallConfigForm.get(\'proxyHost\').hasError(\'required\')">\n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block" fxFlex="100" fxFlex.gt-sm="40">\n <mat-label translate>tb.rulenode.proxy-port</mat-label>\n <input matInput required formControlName="proxyPort" type="number" step="1">\n <mat-error *ngIf="restApiCallConfigForm.get(\'proxyPort\').hasError(\'required\')">\n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n </mat-error>\n <mat-error\n *ngIf="restApiCallConfigForm.get(\'proxyPort\').hasError(\'min\') || restApiCallConfigForm.get(\'proxyPort\').hasError(\'max\')">\n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.proxy-user</mat-label>\n <input matInput formControlName="proxyUser">\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.proxy-password</mat-label>\n <input matInput formControlName="proxyPassword">\n </mat-form-field>\n </div>\n </div>\n <mat-form-field *ngIf="!restApiCallConfigForm.get(\'useSimpleClientHttpFactory\').value || restApiCallConfigForm.get(\'enableProxy\').value" class="mat-block"\n subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.read-timeout</mat-label>\n <input type="number" step="1" min="0" matInput formControlName="readTimeoutMs">\n <mat-hint translate>tb.rulenode.read-timeout-hint</mat-hint>\n </mat-form-field>\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.max-parallel-requests-count</mat-label>\n <input type="number" step="1" min="0" matInput formControlName="maxParallelRequestsCount">\n <mat-hint translate>tb.rulenode.max-parallel-requests-count-hint</mat-hint>\n </mat-form-field>\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.max-response-size</mat-label>\n <input type="number" step="1" min="1" matInput formControlName="maxInMemoryBufferSizeInKb">\n <mat-hint translate>tb.rulenode.max-response-size-hint</mat-hint>\n </mat-form-field>\n <label translate class="tb-title">tb.rulenode.headers</label>\n <div class="tb-hint" [innerHTML]="\'tb.rulenode.headers-hint\' | translate | safe: \'html\'"> </div>\n <tb-kv-map-config-old\n required="false"\n formControlName="headers"\n keyText="tb.rulenode.header"\n keyRequiredText="tb.rulenode.header-required"\n valText="tb.rulenode.value"\n valRequiredText="tb.rulenode.value-required">\n </tb-kv-map-config-old>\n <tb-credentials-config formControlName="credentials" [disableCertPemCredentials]="restApiCallConfigForm.get(\'useSimpleClientHttpFactory\').value"></tb-credentials-config>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class fr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.smtpProtocols=["smtp","smtps"],this.tlsVersions=["TLSv1","TLSv1.1","TLSv1.2","TLSv1.3"]}configForm(){return this.sendEmailConfigForm}onConfigurationSet(e){this.sendEmailConfigForm=this.fb.group({useSystemSmtpSettings:[!!e&&e.useSystemSmtpSettings,[]],smtpProtocol:[e?e.smtpProtocol:null,[]],smtpHost:[e?e.smtpHost:null,[]],smtpPort:[e?e.smtpPort:null,[]],timeout:[e?e.timeout:null,[]],enableTls:[!!e&&e.enableTls,[]],tlsVersion:[e?e.tlsVersion:null,[]],enableProxy:[!!e&&e.enableProxy,[]],proxyHost:[e?e.proxyHost:null,[]],proxyPort:[e?e.proxyPort:null,[]],proxyUser:[e?e.proxyUser:null,[]],proxyPassword:[e?e.proxyPassword:null,[]],username:[e?e.username:null,[]],password:[e?e.password:null,[]]})}validatorTriggers(){return["useSystemSmtpSettings","enableProxy"]}updateValidators(e){const t=this.sendEmailConfigForm.get("useSystemSmtpSettings").value,n=this.sendEmailConfigForm.get("enableProxy").value;t?(this.sendEmailConfigForm.get("smtpProtocol").setValidators([]),this.sendEmailConfigForm.get("smtpHost").setValidators([]),this.sendEmailConfigForm.get("smtpPort").setValidators([]),this.sendEmailConfigForm.get("timeout").setValidators([]),this.sendEmailConfigForm.get("proxyHost").setValidators([]),this.sendEmailConfigForm.get("proxyPort").setValidators([])):(this.sendEmailConfigForm.get("smtpProtocol").setValidators([_.required]),this.sendEmailConfigForm.get("smtpHost").setValidators([_.required]),this.sendEmailConfigForm.get("smtpPort").setValidators([_.required,_.min(1),_.max(65535)]),this.sendEmailConfigForm.get("timeout").setValidators([_.required,_.min(0)]),this.sendEmailConfigForm.get("proxyHost").setValidators(n?[_.required]:[]),this.sendEmailConfigForm.get("proxyPort").setValidators(n?[_.required,_.min(1),_.max(65535)]:[])),this.sendEmailConfigForm.get("smtpProtocol").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("smtpHost").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("smtpPort").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("timeout").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("proxyHost").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("proxyPort").updateValueAndValidity({emitEvent:e})}}e("SendEmailConfigComponent",fr),fr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fr,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),fr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:fr,selector:"tb-external-node-send-email-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="sendEmailConfigForm" fxLayout="column">\n <mat-checkbox formControlName="useSystemSmtpSettings">\n {{ \'tb.rulenode.use-system-smtp-settings\' | translate }}\n </mat-checkbox>\n <section fxLayout="column" *ngIf="sendEmailConfigForm.get(\'useSystemSmtpSettings\').value === false">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.smtp-protocol</mat-label>\n <mat-select formControlName="smtpProtocol">\n <mat-option *ngFor="let smtpProtocol of smtpProtocols" [value]="smtpProtocol">\n {{ smtpProtocol.toUpperCase() }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <div fxLayout.gt-sm="row" fxLayoutGap.gt-sm="8px">\n <mat-form-field fxFlex="100" fxFlex.gt-sm="60" class="mat-block">\n <mat-label translate>tb.rulenode.smtp-host</mat-label>\n <input required matInput formControlName="smtpHost">\n <mat-error *ngIf="sendEmailConfigForm.get(\'smtpHost\').hasError(\'required\')">\n {{ \'tb.rulenode.smtp-host-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex="100" fxFlex.gt-sm="40" class="mat-block">\n <mat-label translate>tb.rulenode.smtp-port</mat-label>\n <input required type="number" step="1" min="1" max="65535" matInput formControlName="smtpPort">\n <mat-error *ngIf="sendEmailConfigForm.get(\'smtpPort\').hasError(\'required\')">\n {{ \'tb.rulenode.smtp-port-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="sendEmailConfigForm.get(\'smtpPort\').hasError(\'min\')">\n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="sendEmailConfigForm.get(\'smtpPort\').hasError(\'max\')">\n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.timeout-msec</mat-label>\n <input required type="number" step="1" min="0" matInput formControlName="timeout">\n <mat-error *ngIf="sendEmailConfigForm.get(\'timeout\').hasError(\'required\')">\n {{ \'tb.rulenode.timeout-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="sendEmailConfigForm.get(\'timeout\').hasError(\'min\')">\n {{ \'tb.rulenode.min-timeout-msec-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-checkbox formControlName="enableTls">\n {{ \'tb.rulenode.enable-tls\' | translate }}\n </mat-checkbox>\n <mat-form-field class="mat-block" *ngIf="sendEmailConfigForm.get(\'enableTls\').value === true">\n <mat-label translate>tb.rulenode.tls-version</mat-label>\n <mat-select formControlName="tlsVersion">\n <mat-option *ngFor="let tlsVersion of tlsVersions" [value]="tlsVersion">\n {{ tlsVersion }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <tb-checkbox formControlName="enableProxy">\n {{ \'tb.rulenode.enable-proxy\' | translate }}\n </tb-checkbox>\n <div *ngIf="sendEmailConfigForm.get(\'enableProxy\').value">\n <div fxLayout.gt-sm="row" fxLayoutGap.gt-sm="8px">\n <mat-form-field class="mat-block" fxFlex="100" fxFlex.gt-sm="60">\n <mat-label translate>tb.rulenode.proxy-host</mat-label>\n <input matInput required formControlName="proxyHost">\n <mat-error *ngIf="sendEmailConfigForm.get(\'proxyHost\').hasError(\'required\')">\n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block" fxFlex="100" fxFlex.gt-sm="40">\n <mat-label translate>tb.rulenode.proxy-port</mat-label>\n <input matInput required formControlName="proxyPort" type="number" step="1" min="1" max="65535">\n <mat-error *ngIf="sendEmailConfigForm.get(\'proxyPort\').hasError(\'required\')">\n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="sendEmailConfigForm.get(\'proxyPort\').hasError(\'min\') || sendEmailConfigForm.get(\'proxyPort\').hasError(\'max\')">\n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.proxy-user</mat-label>\n <input matInput formControlName="proxyUser">\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.proxy-password</mat-label>\n <input matInput formControlName="proxyPassword">\n </mat-form-field>\n </div>\n <mat-form-field class="mat-block" floatLabel="always">\n <mat-label translate>tb.rulenode.username</mat-label>\n <input matInput placeholder="{{ \'tb.rulenode.enter-username\' | translate }}" formControlName="username">\n </mat-form-field>\n <mat-form-field class="mat-block" floatLabel="always">\n <mat-label translate>tb.rulenode.password</mat-label>\n <input matInput type="password" placeholder="{{ \'tb.rulenode.enter-password\' | translate }}" formControlName="password">\n <tb-toggle-password matSuffix></tb-toggle-password>\n </mat-form-field>\n </section>\n</section>\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ot.TbCheckboxComponent,selector:"tb-checkbox",inputs:["disabled","trueValue","falseValue"],outputs:["valueChange"]},{kind:"component",type:Ie.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:et.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fr,decorators:[{type:n,args:[{selector:"tb-external-node-send-email-config",template:'<section [formGroup]="sendEmailConfigForm" fxLayout="column">\n <mat-checkbox formControlName="useSystemSmtpSettings">\n {{ \'tb.rulenode.use-system-smtp-settings\' | translate }}\n </mat-checkbox>\n <section fxLayout="column" *ngIf="sendEmailConfigForm.get(\'useSystemSmtpSettings\').value === false">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.smtp-protocol</mat-label>\n <mat-select formControlName="smtpProtocol">\n <mat-option *ngFor="let smtpProtocol of smtpProtocols" [value]="smtpProtocol">\n {{ smtpProtocol.toUpperCase() }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <div fxLayout.gt-sm="row" fxLayoutGap.gt-sm="8px">\n <mat-form-field fxFlex="100" fxFlex.gt-sm="60" class="mat-block">\n <mat-label translate>tb.rulenode.smtp-host</mat-label>\n <input required matInput formControlName="smtpHost">\n <mat-error *ngIf="sendEmailConfigForm.get(\'smtpHost\').hasError(\'required\')">\n {{ \'tb.rulenode.smtp-host-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex="100" fxFlex.gt-sm="40" class="mat-block">\n <mat-label translate>tb.rulenode.smtp-port</mat-label>\n <input required type="number" step="1" min="1" max="65535" matInput formControlName="smtpPort">\n <mat-error *ngIf="sendEmailConfigForm.get(\'smtpPort\').hasError(\'required\')">\n {{ \'tb.rulenode.smtp-port-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="sendEmailConfigForm.get(\'smtpPort\').hasError(\'min\')">\n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n </mat-error>\n <mat-error *ngIf="sendEmailConfigForm.get(\'smtpPort\').hasError(\'max\')">\n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.timeout-msec</mat-label>\n <input required type="number" step="1" min="0" matInput formControlName="timeout">\n <mat-error *ngIf="sendEmailConfigForm.get(\'timeout\').hasError(\'required\')">\n {{ \'tb.rulenode.timeout-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="sendEmailConfigForm.get(\'timeout\').hasError(\'min\')">\n {{ \'tb.rulenode.min-timeout-msec-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-checkbox formControlName="enableTls">\n {{ \'tb.rulenode.enable-tls\' | translate }}\n </mat-checkbox>\n <mat-form-field class="mat-block" *ngIf="sendEmailConfigForm.get(\'enableTls\').value === true">\n <mat-label translate>tb.rulenode.tls-version</mat-label>\n <mat-select formControlName="tlsVersion">\n <mat-option *ngFor="let tlsVersion of tlsVersions" [value]="tlsVersion">\n {{ tlsVersion }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <tb-checkbox formControlName="enableProxy">\n {{ \'tb.rulenode.enable-proxy\' | translate }}\n </tb-checkbox>\n <div *ngIf="sendEmailConfigForm.get(\'enableProxy\').value">\n <div fxLayout.gt-sm="row" fxLayoutGap.gt-sm="8px">\n <mat-form-field class="mat-block" fxFlex="100" fxFlex.gt-sm="60">\n <mat-label translate>tb.rulenode.proxy-host</mat-label>\n <input matInput required formControlName="proxyHost">\n <mat-error *ngIf="sendEmailConfigForm.get(\'proxyHost\').hasError(\'required\')">\n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block" fxFlex="100" fxFlex.gt-sm="40">\n <mat-label translate>tb.rulenode.proxy-port</mat-label>\n <input matInput required formControlName="proxyPort" type="number" step="1" min="1" max="65535">\n <mat-error *ngIf="sendEmailConfigForm.get(\'proxyPort\').hasError(\'required\')">\n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="sendEmailConfigForm.get(\'proxyPort\').hasError(\'min\') || sendEmailConfigForm.get(\'proxyPort\').hasError(\'max\')">\n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.proxy-user</mat-label>\n <input matInput formControlName="proxyUser">\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.proxy-password</mat-label>\n <input matInput formControlName="proxyPassword">\n </mat-form-field>\n </div>\n <mat-form-field class="mat-block" floatLabel="always">\n <mat-label translate>tb.rulenode.username</mat-label>\n <input matInput placeholder="{{ \'tb.rulenode.enter-username\' | translate }}" formControlName="username">\n </mat-form-field>\n <mat-form-field class="mat-block" floatLabel="always">\n <mat-label translate>tb.rulenode.password</mat-label>\n <input matInput type="password" placeholder="{{ \'tb.rulenode.enter-password\' | translate }}" formControlName="password">\n <tb-toggle-password matSuffix></tb-toggle-password>\n </mat-form-field>\n </section>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class yr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.sendSmsConfigForm}onConfigurationSet(e){this.sendSmsConfigForm=this.fb.group({numbersToTemplate:[e?e.numbersToTemplate:null,[_.required]],smsMessageTemplate:[e?e.smsMessageTemplate:null,[_.required]],useSystemSmsSettings:[!!e&&e.useSystemSmsSettings,[]],smsProviderConfiguration:[e?e.smsProviderConfiguration:null,[]]})}validatorTriggers(){return["useSystemSmsSettings"]}updateValidators(e){this.sendSmsConfigForm.get("useSystemSmsSettings").value?this.sendSmsConfigForm.get("smsProviderConfiguration").setValidators([]):this.sendSmsConfigForm.get("smsProviderConfiguration").setValidators([_.required]),this.sendSmsConfigForm.get("smsProviderConfiguration").updateValueAndValidity({emitEvent:e})}}e("SendSmsConfigComponent",yr),yr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yr,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),yr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:yr,selector:"tb-external-node-send-sms-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="sendSmsConfigForm" fxLayout="column">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.numbers-to-template</mat-label>\n <input required matInput formControlName="numbersToTemplate">\n <mat-error *ngIf="sendSmsConfigForm.get(\'numbersToTemplate\').hasError(\'required\')">\n {{ \'tb.rulenode.numbers-to-template-required\' | translate }}\n </mat-error>\n <mat-hint [innerHTML]="\'tb.rulenode.numbers-to-template-hint\' | translate | safe: \'html\'"></mat-hint>\n </mat-form-field>\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.sms-message-template</mat-label>\n <textarea required matInput formControlName="smsMessageTemplate" rows="6"></textarea>\n <mat-error *ngIf="sendSmsConfigForm.get(\'smsMessageTemplate\').hasError(\'required\')">\n {{ \'tb.rulenode.sms-message-template-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <mat-checkbox formControlName="useSystemSmsSettings">\n {{ \'tb.rulenode.use-system-sms-settings\' | translate }}\n </mat-checkbox>\n <tb-sms-provider-configuration\n *ngIf="sendSmsConfigForm.get(\'useSystemSmsSettings\').value === false"\n formControlName="smsProviderConfiguration"\n required>\n </tb-sms-provider-configuration>\n</section>\n',dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ie.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:at.SmsProviderConfigurationComponent,selector:"tb-sms-provider-configuration",inputs:["required","disabled"]},{kind:"pipe",type:ce.SafePipe,name:"safe"},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yr,decorators:[{type:n,args:[{selector:"tb-external-node-send-sms-config",template:'<section [formGroup]="sendSmsConfigForm" fxLayout="column">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.numbers-to-template</mat-label>\n <input required matInput formControlName="numbersToTemplate">\n <mat-error *ngIf="sendSmsConfigForm.get(\'numbersToTemplate\').hasError(\'required\')">\n {{ \'tb.rulenode.numbers-to-template-required\' | translate }}\n </mat-error>\n <mat-hint [innerHTML]="\'tb.rulenode.numbers-to-template-hint\' | translate | safe: \'html\'"></mat-hint>\n </mat-form-field>\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.sms-message-template</mat-label>\n <textarea required matInput formControlName="smsMessageTemplate" rows="6"></textarea>\n <mat-error *ngIf="sendSmsConfigForm.get(\'smsMessageTemplate\').hasError(\'required\')">\n {{ \'tb.rulenode.sms-message-template-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <mat-checkbox formControlName="useSystemSmsSettings">\n {{ \'tb.rulenode.use-system-sms-settings\' | translate }}\n </mat-checkbox>\n <tb-sms-provider-configuration\n *ngIf="sendSmsConfigForm.get(\'useSystemSmsSettings\').value === false"\n formControlName="smsProviderConfiguration"\n required>\n </tb-sms-provider-configuration>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class br extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.slackChanelTypes=Object.keys(V),this.slackChanelTypesTranslateMap=P}configForm(){return this.slackConfigForm}onConfigurationSet(e){this.slackConfigForm=this.fb.group({botToken:[e?e.botToken:null],useSystemSettings:[!!e&&e.useSystemSettings],messageTemplate:[e?e.messageTemplate:null,[_.required]],conversationType:[e?e.conversationType:null,[_.required]],conversation:[e?e.conversation:null,[_.required]]})}validatorTriggers(){return["useSystemSettings"]}updateValidators(e){this.slackConfigForm.get("useSystemSettings").value?this.slackConfigForm.get("botToken").clearValidators():this.slackConfigForm.get("botToken").setValidators([_.required]),this.slackConfigForm.get("botToken").updateValueAndValidity({emitEvent:e})}}e("SlackConfigComponent",br),br.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:br,deps:[{token:R.Store},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),br.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:br,selector:"tb-external-node-slack-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="slackConfigForm" fxLayout="column">\n <mat-form-field fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.message-template</mat-label>\n <input required matInput formControlName="messageTemplate">\n <mat-error *ngIf="slackConfigForm.get(\'messageTemplate\').hasError(\'required\')">\n {{ \'tb.rulenode.message-template-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <mat-checkbox formControlName="useSystemSettings">\n {{ \'tb.rulenode.use-system-slack-settings\' | translate }}\n </mat-checkbox>\n <mat-form-field *ngIf="!slackConfigForm.get(\'useSystemSettings\').value" class="mat-block">\n <mat-label translate>tb.rulenode.slack-api-token</mat-label>\n <input required matInput formControlName="botToken">\n <mat-error *ngIf="slackConfigForm.get(\'botToken\').hasError(\'required\')">\n {{ \'tb.rulenode.slack-api-token-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <label class="tb-title">{{ \'notification.slack-chanel-type\' | translate }}</label>\n <mat-radio-group formControlName="conversationType">\n <mat-radio-button *ngFor="let slackChanelType of slackChanelTypes" [value]="slackChanelType">\n {{ slackChanelTypesTranslateMap.get(slackChanelType) | translate }}\n </mat-radio-button>\n </mat-radio-group>\n <tb-slack-conversation-autocomplete\n formControlName="conversation"\n required\n [token]="slackConfigForm.get(\'useSystemSettings\').value ? \'\' : slackConfigForm.get(\'botToken\').value"\n [slackChanelType]="slackConfigForm.get(\'conversationType\').value">\n </tb-slack-conversation-autocomplete>\n</section>\n',styles:[":host .tb-title{display:block;padding-bottom:6px}:host ::ng-deep .mat-mdc-radio-group{display:flex;flex-direction:row;margin-bottom:22px;gap:12px}:host ::ng-deep .mat-mdc-radio-group .mat-mdc-radio-button{flex:1 1 100%;padding:4px;border:1px solid rgba(0,0,0,.12);border-radius:6px}@media screen and (max-width: 599px){:host ::ng-deep .mat-mdc-radio-group{flex-direction:column}}\n"],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ie.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:it.MatRadioGroup,selector:"mat-radio-group",exportAs:["matRadioGroup"]},{kind:"component",type:it.MatRadioButton,selector:"mat-radio-button",inputs:["disableRipple","tabIndex"],exportAs:["matRadioButton"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:lt.SlackConversationAutocompleteComponent,selector:"tb-slack-conversation-autocomplete",inputs:["labelText","requiredText","required","disabled","slackChanelType","token"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:br,decorators:[{type:n,args:[{selector:"tb-external-node-slack-config",template:'<section [formGroup]="slackConfigForm" fxLayout="column">\n <mat-form-field fxFlex class="mat-block">\n <mat-label translate>tb.rulenode.message-template</mat-label>\n <input required matInput formControlName="messageTemplate">\n <mat-error *ngIf="slackConfigForm.get(\'messageTemplate\').hasError(\'required\')">\n {{ \'tb.rulenode.message-template-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <mat-checkbox formControlName="useSystemSettings">\n {{ \'tb.rulenode.use-system-slack-settings\' | translate }}\n </mat-checkbox>\n <mat-form-field *ngIf="!slackConfigForm.get(\'useSystemSettings\').value" class="mat-block">\n <mat-label translate>tb.rulenode.slack-api-token</mat-label>\n <input required matInput formControlName="botToken">\n <mat-error *ngIf="slackConfigForm.get(\'botToken\').hasError(\'required\')">\n {{ \'tb.rulenode.slack-api-token-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <label class="tb-title">{{ \'notification.slack-chanel-type\' | translate }}</label>\n <mat-radio-group formControlName="conversationType">\n <mat-radio-button *ngFor="let slackChanelType of slackChanelTypes" [value]="slackChanelType">\n {{ slackChanelTypesTranslateMap.get(slackChanelType) | translate }}\n </mat-radio-button>\n </mat-radio-group>\n <tb-slack-conversation-autocomplete\n formControlName="conversation"\n required\n [token]="slackConfigForm.get(\'useSystemSettings\').value ? \'\' : slackConfigForm.get(\'botToken\').value"\n [slackChanelType]="slackConfigForm.get(\'conversationType\').value">\n </tb-slack-conversation-autocomplete>\n</section>\n',styles:[":host .tb-title{display:block;padding-bottom:6px}:host ::ng-deep .mat-mdc-radio-group{display:flex;flex-direction:row;margin-bottom:22px;gap:12px}:host ::ng-deep .mat-mdc-radio-group .mat-mdc-radio-button{flex:1 1 100%;padding:4px;border:1px solid rgba(0,0,0,.12);border-radius:6px}@media screen and (max-width: 599px){:host ::ng-deep .mat-mdc-radio-group{flex-direction:column}}\n"]}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder}]}});class xr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.snsConfigForm}onConfigurationSet(e){this.snsConfigForm=this.fb.group({topicArnPattern:[e?e.topicArnPattern:null,[_.required]],accessKeyId:[e?e.accessKeyId:null,[_.required]],secretAccessKey:[e?e.secretAccessKey:null,[_.required]],region:[e?e.region:null,[_.required]]})}}e("SnsConfigComponent",xr),xr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xr,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),xr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:xr,selector:"tb-external-node-sns-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="snsConfigForm" fxLayout="column">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.topic-arn-pattern</mat-label>\n <input required matInput formControlName="topicArnPattern">\n <mat-error *ngIf="snsConfigForm.get(\'topicArnPattern\').hasError(\'required\')">\n {{ \'tb.rulenode.topic-arn-pattern-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-access-key-id</mat-label>\n <input required matInput formControlName="accessKeyId">\n <mat-error *ngIf="snsConfigForm.get(\'accessKeyId\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-secret-access-key</mat-label>\n <input required matInput formControlName="secretAccessKey">\n <mat-error *ngIf="snsConfigForm.get(\'secretAccessKey\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-region</mat-label>\n <input required matInput formControlName="region">\n <mat-error *ngIf="snsConfigForm.get(\'region\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-region-required\' | translate }}\n </mat-error>\n </mat-form-field>\n</section>\n',dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xr,decorators:[{type:n,args:[{selector:"tb-external-node-sns-config",template:'<section [formGroup]="snsConfigForm" fxLayout="column">\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.topic-arn-pattern</mat-label>\n <input required matInput formControlName="topicArnPattern">\n <mat-error *ngIf="snsConfigForm.get(\'topicArnPattern\').hasError(\'required\')">\n {{ \'tb.rulenode.topic-arn-pattern-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-access-key-id</mat-label>\n <input required matInput formControlName="accessKeyId">\n <mat-error *ngIf="snsConfigForm.get(\'accessKeyId\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-secret-access-key</mat-label>\n <input required matInput formControlName="secretAccessKey">\n <mat-error *ngIf="snsConfigForm.get(\'secretAccessKey\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-region</mat-label>\n <input required matInput formControlName="region">\n <mat-error *ngIf="snsConfigForm.get(\'region\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-region-required\' | translate }}\n </mat-error>\n </mat-form-field>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class hr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.sqsQueueType=Jt,this.sqsQueueTypes=Object.keys(Jt),this.sqsQueueTypeTranslationsMap=Qt}configForm(){return this.sqsConfigForm}onConfigurationSet(e){this.sqsConfigForm=this.fb.group({queueType:[e?e.queueType:null,[_.required]],queueUrlPattern:[e?e.queueUrlPattern:null,[_.required]],delaySeconds:[e?e.delaySeconds:null,[_.min(0),_.max(900)]],messageAttributes:[e?e.messageAttributes:null,[]],accessKeyId:[e?e.accessKeyId:null,[_.required]],secretAccessKey:[e?e.secretAccessKey:null,[_.required]],region:[e?e.region:null,[_.required]]})}}e("SqsConfigComponent",hr),hr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hr,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),hr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:hr,selector:"tb-external-node-sqs-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="sqsConfigForm" fxLayout="column">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.queue-type</mat-label>\n <mat-select formControlName="queueType" required>\n <mat-option *ngFor="let type of sqsQueueTypes" [value]="type">\n {{ sqsQueueTypeTranslationsMap.get(type) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.queue-url-pattern</mat-label>\n <input required matInput formControlName="queueUrlPattern">\n <mat-error *ngIf="sqsConfigForm.get(\'queueUrlPattern\').hasError(\'required\')">\n {{ \'tb.rulenode.queue-url-pattern-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <mat-form-field *ngIf="sqsConfigForm.get(\'queueType\').value === sqsQueueType.STANDARD" class="mat-block">\n <mat-label translate>tb.rulenode.delay-seconds</mat-label>\n <input required type="number" min="0" max="900" step="1" matInput formControlName="delaySeconds">\n <mat-error *ngIf="sqsConfigForm.get(\'delaySeconds\').hasError(\'min\')">\n {{ \'tb.rulenode.min-delay-seconds-message\' | translate }}\n </mat-error>\n <mat-error *ngIf="sqsConfigForm.get(\'delaySeconds\').hasError(\'max\')">\n {{ \'tb.rulenode.max-delay-seconds-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <label translate class="tb-title">tb.rulenode.message-attributes</label>\n <div class="tb-hint" [innerHTML]="\'tb.rulenode.message-attributes-hint\' | translate | safe: \'html\'"></div>\n <tb-kv-map-config-old\n required="false"\n formControlName="messageAttributes"\n keyText="tb.rulenode.name"\n keyRequiredText="tb.rulenode.name-required"\n valText="tb.rulenode.value"\n valRequiredText="tb.rulenode.value-required">\n </tb-kv-map-config-old>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-access-key-id</mat-label>\n <input required matInput formControlName="accessKeyId">\n <mat-error *ngIf="sqsConfigForm.get(\'accessKeyId\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-secret-access-key</mat-label>\n <input required matInput formControlName="secretAccessKey">\n <mat-error *ngIf="sqsConfigForm.get(\'secretAccessKey\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-region</mat-label>\n <input required matInput formControlName="region">\n <mat-error *ngIf="sqsConfigForm.get(\'region\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-region-required\' | translate }}\n </mat-error>\n </mat-form-field>\n</section>\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:ce.SafePipe,name:"safe"},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hr,decorators:[{type:n,args:[{selector:"tb-external-node-sqs-config",template:'<section [formGroup]="sqsConfigForm" fxLayout="column">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.queue-type</mat-label>\n <mat-select formControlName="queueType" required>\n <mat-option *ngFor="let type of sqsQueueTypes" [value]="type">\n {{ sqsQueueTypeTranslationsMap.get(type) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="mat-block" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.queue-url-pattern</mat-label>\n <input required matInput formControlName="queueUrlPattern">\n <mat-error *ngIf="sqsConfigForm.get(\'queueUrlPattern\').hasError(\'required\')">\n {{ \'tb.rulenode.queue-url-pattern-required\' | translate }}\n </mat-error>\n <mat-hint translate>tb.rulenode.general-pattern-hint</mat-hint>\n </mat-form-field>\n <mat-form-field *ngIf="sqsConfigForm.get(\'queueType\').value === sqsQueueType.STANDARD" class="mat-block">\n <mat-label translate>tb.rulenode.delay-seconds</mat-label>\n <input required type="number" min="0" max="900" step="1" matInput formControlName="delaySeconds">\n <mat-error *ngIf="sqsConfigForm.get(\'delaySeconds\').hasError(\'min\')">\n {{ \'tb.rulenode.min-delay-seconds-message\' | translate }}\n </mat-error>\n <mat-error *ngIf="sqsConfigForm.get(\'delaySeconds\').hasError(\'max\')">\n {{ \'tb.rulenode.max-delay-seconds-message\' | translate }}\n </mat-error>\n </mat-form-field>\n <label translate class="tb-title">tb.rulenode.message-attributes</label>\n <div class="tb-hint" [innerHTML]="\'tb.rulenode.message-attributes-hint\' | translate | safe: \'html\'"></div>\n <tb-kv-map-config-old\n required="false"\n formControlName="messageAttributes"\n keyText="tb.rulenode.name"\n keyRequiredText="tb.rulenode.name-required"\n valText="tb.rulenode.value"\n valRequiredText="tb.rulenode.value-required">\n </tb-kv-map-config-old>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-access-key-id</mat-label>\n <input required matInput formControlName="accessKeyId">\n <mat-error *ngIf="sqsConfigForm.get(\'accessKeyId\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-secret-access-key</mat-label>\n <input required matInput formControlName="secretAccessKey">\n <mat-error *ngIf="sqsConfigForm.get(\'secretAccessKey\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-region</mat-label>\n <input required matInput formControlName="region">\n <mat-error *ngIf="sqsConfigForm.get(\'region\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-region-required\' | translate }}\n </mat-error>\n </mat-form-field>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class vr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.lambdaConfigForm}onConfigurationSet(e){this.lambdaConfigForm=this.fb.group({functionName:[e?e.functionName:null,[_.required]],qualifier:[e?e.qualifier:null,[]],accessKey:[e?e.accessKey:null,[_.required]],secretKey:[e?e.secretKey:null,[_.required]],region:[e?e.region:null,[_.required]],connectionTimeout:[e?e.connectionTimeout:null,[_.required,_.min(0)]],requestTimeout:[e?e.requestTimeout:null,[_.required,_.min(0)]],tellFailureIfFuncThrowsExc:[!!e&&e.tellFailureIfFuncThrowsExc,[]]})}}e("LambdaConfigComponent",vr),vr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vr,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),vr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:vr,selector:"tb-external-node-lambda-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="lambdaConfigForm" class="tb-form-panel no-padding no-border">\n <div class="tb-form-panel stroked">\n <div class="tb-form-row no-padding no-border">\n <div class="tb-form-panel-title tb-required" translate>tb.rulenode.function-configuration</div>\n </div>\n <tb-example-hint [hintText]="\'tb.rulenode.template-rules-hint\'"\n popupHelpLink="rulenode/node-templatization-doc">\n </tb-example-hint>\n <div class="tb-standard-fields">\n <mat-form-field class="mat-block">\n <mat-label>{{\'tb.rulenode.function-name\' | translate}}</mat-label>\n <input required matInput formControlName="functionName">\n <mat-error *ngIf="lambdaConfigForm.get(\'functionName\').hasError(\'required\')">\n {{\'tb.rulenode.function-name-required\' | translate}}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label>{{\'tb.rulenode.qualifier\' | translate}}</mat-label>\n <input matInput formControlName="qualifier">\n <mat-hint translate>tb.rulenode.qualifier-hint</mat-hint>\n </mat-form-field>\n </div>\n </div>\n\n <div class="tb-form-panel stroked">\n <mat-expansion-panel class="tb-settings" expanded>\n <mat-expansion-panel-header>\n <mat-panel-title class="tb-form-panel-title tb-required" translate>tb.rulenode.aws-credentials</mat-panel-title>\n </mat-expansion-panel-header>\n <div class="tb-standard-fields">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-access-key-id</mat-label>\n <input required matInput formControlName="accessKey">\n <mat-error *ngIf="lambdaConfigForm.get(\'accessKey\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-secret-access-key</mat-label>\n <input required matInput formControlName="secretKey">\n <mat-error *ngIf="lambdaConfigForm.get(\'secretKey\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-region</mat-label>\n <input required matInput formControlName="region">\n <mat-error *ngIf="lambdaConfigForm.get(\'region\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-region-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n </mat-expansion-panel>\n </div>\n <div class="tb-form-panel stroked no-padding">\n <mat-expansion-panel class="tb-settings">\n <mat-expansion-panel-header style="padding: 16px">\n <mat-panel-title translate>tb.rulenode.advanced-settings</mat-panel-title>\n </mat-expansion-panel-header>\n <div class="tb-form-panel no-border no-padding no-gap" style="margin-top: 0">\n <div class="tb-form-row no-border same-padding tb-standard-fields">\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.connection-timeout</mat-label>\n <input type="number" required min="0" matInput formControlName="connectionTimeout">\n <mat-error *ngIf="lambdaConfigForm.get(\'connectionTimeout\').hasError(\'required\')">\n {{ \'tb.rulenode.connection-timeout-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="lambdaConfigForm.get(\'connectionTimeout\').hasError(\'min\')">\n {{ \'tb.rulenode.connection-timeout-min\' | translate }}\n </mat-error>\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.connection-timeout-hint\' | translate }}">help</mat-icon>\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.request-timeout</mat-label>\n <input type="number" required min="0" matInput formControlName="requestTimeout">\n <mat-error *ngIf="lambdaConfigForm.get(\'requestTimeout\').hasError(\'required\')">\n {{ \'tb.rulenode.request-timeout-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="lambdaConfigForm.get(\'requestTimeout\').hasError(\'min\')">\n {{ \'tb.rulenode.request-timeout-min\' | translate }}\n </mat-error>\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.request-timeout-hint\' | translate }}">help</mat-icon>\n </mat-form-field>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.tell-failure-aws-lambda-hint\' | translate }}"\n class="tb-form-row no-border" style="margin-bottom: 16px">\n <mat-slide-toggle class="mat-slide" formControlName="tellFailureIfFuncThrowsExc">\n {{ \'tb.rulenode.tell-failure-aws-lambda\' | translate }}\n </mat-slide-toggle>\n </div>\n </div>\n </mat-expansion-panel>\n </div>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"component",type:ae.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:ae.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:ae.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:ht,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vr,decorators:[{type:n,args:[{selector:"tb-external-node-lambda-config",template:'<section [formGroup]="lambdaConfigForm" class="tb-form-panel no-padding no-border">\n <div class="tb-form-panel stroked">\n <div class="tb-form-row no-padding no-border">\n <div class="tb-form-panel-title tb-required" translate>tb.rulenode.function-configuration</div>\n </div>\n <tb-example-hint [hintText]="\'tb.rulenode.template-rules-hint\'"\n popupHelpLink="rulenode/node-templatization-doc">\n </tb-example-hint>\n <div class="tb-standard-fields">\n <mat-form-field class="mat-block">\n <mat-label>{{\'tb.rulenode.function-name\' | translate}}</mat-label>\n <input required matInput formControlName="functionName">\n <mat-error *ngIf="lambdaConfigForm.get(\'functionName\').hasError(\'required\')">\n {{\'tb.rulenode.function-name-required\' | translate}}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label>{{\'tb.rulenode.qualifier\' | translate}}</mat-label>\n <input matInput formControlName="qualifier">\n <mat-hint translate>tb.rulenode.qualifier-hint</mat-hint>\n </mat-form-field>\n </div>\n </div>\n\n <div class="tb-form-panel stroked">\n <mat-expansion-panel class="tb-settings" expanded>\n <mat-expansion-panel-header>\n <mat-panel-title class="tb-form-panel-title tb-required" translate>tb.rulenode.aws-credentials</mat-panel-title>\n </mat-expansion-panel-header>\n <div class="tb-standard-fields">\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-access-key-id</mat-label>\n <input required matInput formControlName="accessKey">\n <mat-error *ngIf="lambdaConfigForm.get(\'accessKey\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-secret-access-key</mat-label>\n <input required matInput formControlName="secretKey">\n <mat-error *ngIf="lambdaConfigForm.get(\'secretKey\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.aws-region</mat-label>\n <input required matInput formControlName="region">\n <mat-error *ngIf="lambdaConfigForm.get(\'region\').hasError(\'required\')">\n {{ \'tb.rulenode.aws-region-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n </mat-expansion-panel>\n </div>\n <div class="tb-form-panel stroked no-padding">\n <mat-expansion-panel class="tb-settings">\n <mat-expansion-panel-header style="padding: 16px">\n <mat-panel-title translate>tb.rulenode.advanced-settings</mat-panel-title>\n </mat-expansion-panel-header>\n <div class="tb-form-panel no-border no-padding no-gap" style="margin-top: 0">\n <div class="tb-form-row no-border same-padding tb-standard-fields">\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.connection-timeout</mat-label>\n <input type="number" required min="0" matInput formControlName="connectionTimeout">\n <mat-error *ngIf="lambdaConfigForm.get(\'connectionTimeout\').hasError(\'required\')">\n {{ \'tb.rulenode.connection-timeout-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="lambdaConfigForm.get(\'connectionTimeout\').hasError(\'min\')">\n {{ \'tb.rulenode.connection-timeout-min\' | translate }}\n </mat-error>\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.connection-timeout-hint\' | translate }}">help</mat-icon>\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.request-timeout</mat-label>\n <input type="number" required min="0" matInput formControlName="requestTimeout">\n <mat-error *ngIf="lambdaConfigForm.get(\'requestTimeout\').hasError(\'required\')">\n {{ \'tb.rulenode.request-timeout-required\' | translate }}\n </mat-error>\n <mat-error *ngIf="lambdaConfigForm.get(\'requestTimeout\').hasError(\'min\')">\n {{ \'tb.rulenode.request-timeout-min\' | translate }}\n </mat-error>\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.request-timeout-hint\' | translate }}">help</mat-icon>\n </mat-form-field>\n </div>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.tell-failure-aws-lambda-hint\' | translate }}"\n class="tb-form-row no-border" style="margin-bottom: 16px">\n <mat-slide-toggle class="mat-slide" formControlName="tellFailureIfFuncThrowsExc">\n {{ \'tb.rulenode.tell-failure-aws-lambda\' | translate }}\n </mat-slide-toggle>\n </div>\n </div>\n </mat-expansion-panel>\n </div>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class Cr{}e("RulenodeCoreConfigExternalModule",Cr),Cr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Cr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Cr,declarations:[xr,hr,vr,ur,mr,pr,dr,cr,gr,fr,sr,yr,br],imports:[J,E,Qe,Qn],exports:[xr,hr,vr,ur,mr,pr,dr,cr,gr,fr,sr,yr,br]}),Cr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cr,imports:[J,E,Qe,Qn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cr,decorators:[{type:d,args:[{declarations:[xr,hr,vr,ur,mr,pr,dr,cr,gr,fr,sr,yr,br],imports:[J,E,Qe,Qn],exports:[xr,hr,vr,ur,mr,pr,dr,cr,gr,fr,sr,yr,br]}]}]});class Fr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.searchText=""}configForm(){return this.alarmStatusConfigForm}prepareInputConfig(e){return{alarmStatusList:ye(e?.alarmStatusList)?e.alarmStatusList:null}}onConfigurationSet(e){this.alarmStatusConfigForm=this.fb.group({alarmStatusList:[e.alarmStatusList,[_.required]]})}}e("CheckAlarmStatusComponent",Fr),Fr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fr,deps:[{token:R.Store},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Fr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Fr,selector:"tb-filter-node-check-alarm-status-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="alarmStatusConfigForm" class="tb-form-panel stroked">\n <div class="tb-form-row no-padding no-border space-between">\n <div class="tb-form-panel-title tb-required" translate>tb.rulenode.alarm-status</div>\n <div class="tb-form-panel-hint tb-error" translate [hidden]="alarmStatusConfigForm.get(\'alarmStatusList\').valid">\n tb.rulenode.alarm-required\n </div>\n </div>\n <tb-alarm-status-select formControlName="alarmStatusList"></tb-alarm-status-select>\n</section>\n\n\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Jn,selector:"tb-alarm-status-select"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-alarm-status-config",template:'<section [formGroup]="alarmStatusConfigForm" class="tb-form-panel stroked">\n <div class="tb-form-row no-padding no-border space-between">\n <div class="tb-form-panel-title tb-required" translate>tb.rulenode.alarm-status</div>\n <div class="tb-form-panel-hint tb-error" translate [hidden]="alarmStatusConfigForm.get(\'alarmStatusList\').valid">\n tb.rulenode.alarm-required\n </div>\n </div>\n <tb-alarm-status-select formControlName="alarmStatusList"></tb-alarm-status-select>\n</section>\n\n\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder}]}});class kr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.checkMessageConfigForm}prepareInputConfig(e){return{messageNames:ye(e?.messageNames)?e.messageNames:[],metadataNames:ye(e?.metadataNames)?e.metadataNames:[],checkAllKeys:!!ye(e?.checkAllKeys)&&e.checkAllKeys}}prepareOutputConfig(e){return{messageNames:ye(e?.messageNames)?e.messageNames:[],metadataNames:ye(e?.metadataNames)?e.metadataNames:[],checkAllKeys:e.checkAllKeys}}atLeastOne(e,t=null){return n=>{t||(t=Object.keys(n.controls));return n?.controls&&t.some((t=>!e(n.controls[t])))?null:{atLeastOne:!0}}}onConfigurationSet(e){this.checkMessageConfigForm=this.fb.group({messageNames:[e.messageNames,[]],metadataNames:[e.metadataNames,[]],checkAllKeys:[e.checkAllKeys,[]]},{validators:this.atLeastOne(_.required,["messageNames","metadataNames"])})}get touchedValidationControl(){return["messageNames","metadataNames"].some((e=>this.checkMessageConfigForm.get(e).touched))}}e("CheckMessageConfigComponent",kr),kr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kr,deps:[{token:R.Store},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),kr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:kr,selector:"tb-filter-node-check-message-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="checkMessageConfigForm" class="tb-form-panel stroked">\n <div class="tb-form-row no-padding no-border space-between">\n <div class="tb-form-panel-title tb-required" translate>tb.rulenode.fields-to-check</div>\n <div class="tb-form-panel-hint tb-error" translate [hidden]="!(touchedValidationControl && checkMessageConfigForm.hasError(\'atLeastOne\'))">\n tb.rulenode.at-least-one-field-required\n </div>\n </div>\n <tb-string-items-list editable subscriptSizing="dynamic"\n [label]="\'tb.rulenode.data-keys\' | translate"\n [placeholder]="\'tb.rulenode.add-message-field\' | translate"\n formControlName="messageNames">\n <mat-icon matSuffix color="primary" class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n matTooltip="{{ \'tb.rulenode.chip-help\' | translate: { inputName: \'tb.rulenode.field-name\' | translate } }}">help</mat-icon>\n </tb-string-items-list>\n <tb-string-items-list editable subscriptSizing="dynamic"\n [label]="\'tb.rulenode.metadata-keys\' | translate"\n [placeholder]="\'tb.rulenode.add-metadata-field\' | translate"\n formControlName="metadataNames">\n <mat-icon matSuffix color="primary" class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n matTooltip="{{ \'tb.rulenode.chip-help\' | translate: { inputName: \'tb.rulenode.field-name\' | translate } }}">help</mat-icon>\n </tb-string-items-list>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.check-all-keys-tooltip\' | translate }}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="checkAllKeys">\n {{ \'tb.rulenode.check-all-keys\' | translate }}\n </mat-slide-toggle>\n </div>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:tt.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-message-config",template:'<section [formGroup]="checkMessageConfigForm" class="tb-form-panel stroked">\n <div class="tb-form-row no-padding no-border space-between">\n <div class="tb-form-panel-title tb-required" translate>tb.rulenode.fields-to-check</div>\n <div class="tb-form-panel-hint tb-error" translate [hidden]="!(touchedValidationControl && checkMessageConfigForm.hasError(\'atLeastOne\'))">\n tb.rulenode.at-least-one-field-required\n </div>\n </div>\n <tb-string-items-list editable subscriptSizing="dynamic"\n [label]="\'tb.rulenode.data-keys\' | translate"\n [placeholder]="\'tb.rulenode.add-message-field\' | translate"\n formControlName="messageNames">\n <mat-icon matSuffix color="primary" class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n matTooltip="{{ \'tb.rulenode.chip-help\' | translate: { inputName: \'tb.rulenode.field-name\' | translate } }}">help</mat-icon>\n </tb-string-items-list>\n <tb-string-items-list editable subscriptSizing="dynamic"\n [label]="\'tb.rulenode.metadata-keys\' | translate"\n [placeholder]="\'tb.rulenode.add-metadata-field\' | translate"\n formControlName="metadataNames">\n <mat-icon matSuffix color="primary" class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n matTooltip="{{ \'tb.rulenode.chip-help\' | translate: { inputName: \'tb.rulenode.field-name\' | translate } }}">help</mat-icon>\n </tb-string-items-list>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.check-all-keys-tooltip\' | translate }}"\n class="tb-form-row no-border no-padding">\n <mat-slide-toggle class="mat-slide" formControlName="checkAllKeys">\n {{ \'tb.rulenode.check-all-keys\' | translate }}\n </mat-slide-toggle>\n </div>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder}]}});class Tr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.entitySearchDirection=Object.values(v),this.entitySearchDirectionTranslationsMap=N}configForm(){return this.checkRelationConfigForm}prepareInputConfig(e){return{checkForSingleEntity:!!ye(e?.checkForSingleEntity)&&e.checkForSingleEntity,direction:ye(e?.direction)?e.direction:null,entityType:ye(e?.entityType)?e.entityType:null,entityId:ye(e?.entityId)?e.entityId:null,relationType:ye(e?.relationType)?e.relationType:null}}onConfigurationSet(e){this.checkRelationConfigForm=this.fb.group({checkForSingleEntity:[e.checkForSingleEntity,[]],direction:[e.direction,[]],entityType:[e.entityType,e&&e.checkForSingleEntity?[_.required]:[]],entityId:[e.entityId,e&&e.checkForSingleEntity?[_.required]:[]],relationType:[e.relationType,[_.required]]})}validatorTriggers(){return["checkForSingleEntity"]}updateValidators(e){const t=this.checkRelationConfigForm.get("checkForSingleEntity").value;this.checkRelationConfigForm.get("entityType").setValidators(t?[_.required]:[]),this.checkRelationConfigForm.get("entityType").updateValueAndValidity({emitEvent:e}),this.checkRelationConfigForm.get("entityId").setValidators(t?[_.required]:[]),this.checkRelationConfigForm.get("entityId").updateValueAndValidity({emitEvent:e})}}e("CheckRelationConfigComponent",Tr),Tr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tr,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Tr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Tr,selector:"tb-filter-node-check-relation-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="checkRelationConfigForm" class="tb-form-panel stroked no-padding-bottom">\n <div class="tb-form-panel-title" translate>tb.rulenode.relation-search-parameters</div>\n <div fxLayout="column">\n <mat-form-field class="mat-block" hideRequiredMarker>\n <mat-label>{{ \'relation.direction\' | translate }}</mat-label>\n <mat-select formControlName="direction" required>\n <mat-option *ngFor="let direction of entitySearchDirection" [value]="direction">\n {{ entitySearchDirectionTranslationsMap.get(direction) | translate }} <span translate>tb.rulenode.relations-query-config-direction-suffix</span>\n </mat-option>\n </mat-select>\n </mat-form-field>\n <tb-relation-type-autocomplete\n required\n formControlName="relationType">\n </tb-relation-type-autocomplete>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.check-relation-to-specific-entity-tooltip\' | translate }}"\n class="tb-form-row no-border no-padding slide-toggle">\n <mat-slide-toggle class="mat-slide" formControlName="checkForSingleEntity">\n {{ \'tb.rulenode.check-relation-to-specific-entity\' | translate }}\n </mat-slide-toggle>\n </div>\n <div *ngIf="checkRelationConfigForm.get(\'checkForSingleEntity\').value" class="same-width-component-row">\n <tb-entity-type-select\n style="min-width: 100px; flex: 1;"\n showLabel\n required\n formControlName="entityType">\n </tb-entity-type-select>\n <tb-entity-autocomplete\n fxFlex\n required\n *ngIf="checkRelationConfigForm.get(\'entityType\').value"\n [entityType]="checkRelationConfigForm.get(\'entityType\').value"\n formControlName="entityId">\n </tb-entity-autocomplete>\n </div>\n </div>\n</section>\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:st.EntityAutocompleteComponent,selector:"tb-entity-autocomplete",inputs:["entityType","entitySubtype","excludeEntityIds","labelText","requiredText","useFullEntityId","appearance","required","disabled"],outputs:["entityChanged"]},{kind:"component",type:Ne.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled","additionEntityTypes"]},{kind:"component",type:qe.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-relation-config",template:'<section [formGroup]="checkRelationConfigForm" class="tb-form-panel stroked no-padding-bottom">\n <div class="tb-form-panel-title" translate>tb.rulenode.relation-search-parameters</div>\n <div fxLayout="column">\n <mat-form-field class="mat-block" hideRequiredMarker>\n <mat-label>{{ \'relation.direction\' | translate }}</mat-label>\n <mat-select formControlName="direction" required>\n <mat-option *ngFor="let direction of entitySearchDirection" [value]="direction">\n {{ entitySearchDirectionTranslationsMap.get(direction) | translate }} <span translate>tb.rulenode.relations-query-config-direction-suffix</span>\n </mat-option>\n </mat-select>\n </mat-form-field>\n <tb-relation-type-autocomplete\n required\n formControlName="relationType">\n </tb-relation-type-autocomplete>\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.check-relation-to-specific-entity-tooltip\' | translate }}"\n class="tb-form-row no-border no-padding slide-toggle">\n <mat-slide-toggle class="mat-slide" formControlName="checkForSingleEntity">\n {{ \'tb.rulenode.check-relation-to-specific-entity\' | translate }}\n </mat-slide-toggle>\n </div>\n <div *ngIf="checkRelationConfigForm.get(\'checkForSingleEntity\').value" class="same-width-component-row">\n <tb-entity-type-select\n style="min-width: 100px; flex: 1;"\n showLabel\n required\n formControlName="entityType">\n </tb-entity-type-select>\n <tb-entity-autocomplete\n fxFlex\n required\n *ngIf="checkRelationConfigForm.get(\'entityType\').value"\n [entityType]="checkRelationConfigForm.get(\'entityType\').value"\n formControlName="entityId">\n </tb-entity-autocomplete>\n </div>\n </div>\n</section>\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class Lr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.perimeterType=Et,this.perimeterTypes=Object.values(Et),this.perimeterTypeTranslationMap=wt,this.rangeUnits=Object.values(Vt),this.rangeUnitTranslationMap=Pt,this.defaultPaddingEnable=!0}configForm(){return this.geoFilterConfigForm}prepareInputConfig(e){return{latitudeKeyName:ye(e?.latitudeKeyName)?e.latitudeKeyName:null,longitudeKeyName:ye(e?.longitudeKeyName)?e.longitudeKeyName:null,perimeterType:ye(e?.perimeterType)?e.perimeterType:null,fetchPerimeterInfoFromMessageMetadata:!!ye(e?.fetchPerimeterInfoFromMessageMetadata)&&e.fetchPerimeterInfoFromMessageMetadata,perimeterKeyName:ye(e?.perimeterKeyName)?e.perimeterKeyName:null,centerLatitude:ye(e?.centerLatitude)?e.centerLatitude:null,centerLongitude:ye(e?.centerLongitude)?e.centerLongitude:null,range:ye(e?.range)?e.range:null,rangeUnit:ye(e?.rangeUnit)?e.rangeUnit:null,polygonsDefinition:ye(e?.polygonsDefinition)?e.polygonsDefinition:null}}onConfigurationSet(e){this.geoFilterConfigForm=this.fb.group({latitudeKeyName:[e.latitudeKeyName,[_.required]],longitudeKeyName:[e.longitudeKeyName,[_.required]],perimeterType:[e.perimeterType,[_.required]],fetchPerimeterInfoFromMessageMetadata:[e.fetchPerimeterInfoFromMessageMetadata,[]],perimeterKeyName:[e.perimeterKeyName,[]],centerLatitude:[e.centerLatitude,[]],centerLongitude:[e.centerLongitude,[]],range:[e.range,[]],rangeUnit:[e.rangeUnit,[]],polygonsDefinition:[e.polygonsDefinition,[]]})}validatorTriggers(){return["fetchPerimeterInfoFromMessageMetadata","perimeterType"]}updateValidators(e){const t=this.geoFilterConfigForm.get("fetchPerimeterInfoFromMessageMetadata").value,n=this.geoFilterConfigForm.get("perimeterType").value;t?this.geoFilterConfigForm.get("perimeterKeyName").setValidators([_.required]):this.geoFilterConfigForm.get("perimeterKeyName").setValidators([]),t||n!==Et.CIRCLE?(this.geoFilterConfigForm.get("centerLatitude").setValidators([]),this.geoFilterConfigForm.get("centerLongitude").setValidators([]),this.geoFilterConfigForm.get("range").setValidators([]),this.geoFilterConfigForm.get("rangeUnit").setValidators([]),this.defaultPaddingEnable=!0):(this.geoFilterConfigForm.get("centerLatitude").setValidators([_.required,_.min(-90),_.max(90)]),this.geoFilterConfigForm.get("centerLongitude").setValidators([_.required,_.min(-180),_.max(180)]),this.geoFilterConfigForm.get("range").setValidators([_.required,_.min(0)]),this.geoFilterConfigForm.get("rangeUnit").setValidators([_.required]),this.defaultPaddingEnable=!1),t||n!==Et.POLYGON?this.geoFilterConfigForm.get("polygonsDefinition").setValidators([]):this.geoFilterConfigForm.get("polygonsDefinition").setValidators([_.required]),this.geoFilterConfigForm.get("perimeterKeyName").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("centerLatitude").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("centerLongitude").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("range").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("rangeUnit").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("polygonsDefinition").updateValueAndValidity({emitEvent:e})}}e("GpsGeoFilterConfigComponent",Lr),Lr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lr,deps:[{token:R.Store},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Lr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Lr,selector:"tb-filter-node-gps-geofencing-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="geoFilterConfigForm" class="tb-form-panel no-border no-padding">\n <section class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.coordinate-field-names</div>\n <section>\n <div fxLayout="row" fxLayoutGap="16px">\n <mat-form-field fxFlex="50" class="mat-block">\n <mat-label>{{ \'tb.rulenode.latitude-field-name\' | translate }}</mat-label>\n <input matInput formControlName="latitudeKeyName" required>\n <mat-error *ngIf="geoFilterConfigForm.get(\'latitudeKeyName\').hasError(\'required\')">\n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex="50" class="mat-block">\n <mat-label>{{ \'tb.rulenode.longitude-field-name\' | translate }}</mat-label>\n <input matInput formControlName="longitudeKeyName" required>\n <mat-error *ngIf="geoFilterConfigForm.get(\'longitudeKeyName\').hasError(\'required\')">\n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <div class="tb-form-hint tb-primary-fill" translate>tb.rulenode.coordinate-field-hint</div>\n </section>\n </section>\n <section class="tb-form-panel stroked" [class.no-padding-bottom]="!defaultPaddingEnable">\n <div class="tb-form-panel-title" translate>tb.rulenode.geofence-configuration</div>\n <section fxLayout="column">\n <mat-form-field fxFlex class="mat-block" hideRequiredMarker>\n <mat-label>{{ \'tb.rulenode.perimeter-type\' | translate }}</mat-label>\n <mat-select formControlName="perimeterType">\n <mat-option *ngFor="let type of perimeterTypes" [value]="type">\n {{ perimeterTypeTranslationMap.get(type) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <div tb-hint-tooltip-icon="{{ geoFilterConfigForm.get(\'perimeterType\').value === perimeterType.CIRCLE\n ? (\'tb.rulenode.fetch-circle-parameter-info-from-metadata-hint\'\n | translate : { perimeterKeyName: geoFilterConfigForm.get(\'perimeterKeyName\').valid\n ? geoFilterConfigForm.get(\'perimeterKeyName\').value\n : \'ss_perimeter\'})\n : (\'tb.rulenode.fetch-poligon-parameter-info-from-metadata-hint\'\n | translate : { perimeterKeyName: geoFilterConfigForm.get(\'perimeterKeyName\').valid\n ? geoFilterConfigForm.get(\'perimeterKeyName\').value\n : \'ss_perimeter\'}) }}"\n class="tb-form-row no-border no-padding slide-toggle">\n <mat-slide-toggle class="mat-slide" formControlName="fetchPerimeterInfoFromMessageMetadata">\n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n </mat-slide-toggle>\n </div>\n <mat-form-field *ngIf="geoFilterConfigForm.get(\'fetchPerimeterInfoFromMessageMetadata\').value" class="mat-block">\n <mat-label>{{ \'tb.rulenode.perimeter-key-name\' | translate }}</mat-label>\n <input matInput formControlName="perimeterKeyName" required>\n <mat-error *ngIf="geoFilterConfigForm.get(\'perimeterKeyName\').hasError(\'required\')">\n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n </mat-error>\n <mat-hint>{{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}</mat-hint>\n </mat-form-field>\n <div fxLayout="column"\n *ngIf="geoFilterConfigForm.get(\'perimeterType\').value === perimeterType.CIRCLE &&\n !geoFilterConfigForm.get(\'fetchPerimeterInfoFromMessageMetadata\').value">\n <div fxLayout="row" fxLayoutGap="16px">\n <mat-form-field fxFlex>\n <mat-label>{{ \'tb.rulenode.circle-center-latitude\' | translate }}</mat-label>\n <input type="number" min="-90" max="90" step="0.1" matInput formControlName="centerLatitude" required>\n <mat-error *ngIf="geoFilterConfigForm.get(\'centerLatitude\').hasError(\'required\')">\n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex>\n <mat-label>{{ \'tb.rulenode.circle-center-longitude\' | translate }}</mat-label>\n <input type="number" min="-180" max="180" step="0.1" matInput formControlName="centerLongitude" required>\n <mat-error *ngIf="geoFilterConfigForm.get(\'centerLongitude\').hasError(\'required\')">\n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <div fxLayout="row" fxLayoutGap="16px">\n <mat-form-field fxFlex>\n <mat-label>{{ \'tb.rulenode.range\' | translate }}</mat-label>\n <input type="number" min="0" step="0.1" matInput formControlName="range" required>\n <mat-error *ngIf="geoFilterConfigForm.get(\'range\').hasError(\'required\')">\n {{ \'tb.rulenode.range-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex>\n <mat-label>{{ \'tb.rulenode.range-units\' | translate }}</mat-label>\n <mat-select formControlName="rangeUnit" required>\n <mat-option *ngFor="let type of rangeUnits" [value]="type">\n {{ rangeUnitTranslationMap.get(type) | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf="geoFilterConfigForm.get(\'rangeUnit\').hasError(\'required\')">\n {{ \'tb.rulenode.range-units-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n </div>\n <mat-form-field class="mat-block" subscriptSizing="dynamic"\n *ngIf="geoFilterConfigForm.get(\'perimeterType\').value === perimeterType.POLYGON &&\n !geoFilterConfigForm.get(\'fetchPerimeterInfoFromMessageMetadata\').value">\n <mat-label>{{ \'tb.rulenode.polygon-definition\' | translate }}</mat-label>\n <input matInput formControlName="polygonsDefinition" required>\n <mat-hint>{{ \'tb.rulenode.polygon-definition-hint\' | translate }}</mat-hint>\n <mat-error *ngIf="geoFilterConfigForm.get(\'polygonsDefinition\').hasError(\'required\')">\n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </section>\n </section>\n</section>\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lr,decorators:[{type:n,args:[{selector:"tb-filter-node-gps-geofencing-config",template:'<section [formGroup]="geoFilterConfigForm" class="tb-form-panel no-border no-padding">\n <section class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.coordinate-field-names</div>\n <section>\n <div fxLayout="row" fxLayoutGap="16px">\n <mat-form-field fxFlex="50" class="mat-block">\n <mat-label>{{ \'tb.rulenode.latitude-field-name\' | translate }}</mat-label>\n <input matInput formControlName="latitudeKeyName" required>\n <mat-error *ngIf="geoFilterConfigForm.get(\'latitudeKeyName\').hasError(\'required\')">\n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex="50" class="mat-block">\n <mat-label>{{ \'tb.rulenode.longitude-field-name\' | translate }}</mat-label>\n <input matInput formControlName="longitudeKeyName" required>\n <mat-error *ngIf="geoFilterConfigForm.get(\'longitudeKeyName\').hasError(\'required\')">\n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <div class="tb-form-hint tb-primary-fill" translate>tb.rulenode.coordinate-field-hint</div>\n </section>\n </section>\n <section class="tb-form-panel stroked" [class.no-padding-bottom]="!defaultPaddingEnable">\n <div class="tb-form-panel-title" translate>tb.rulenode.geofence-configuration</div>\n <section fxLayout="column">\n <mat-form-field fxFlex class="mat-block" hideRequiredMarker>\n <mat-label>{{ \'tb.rulenode.perimeter-type\' | translate }}</mat-label>\n <mat-select formControlName="perimeterType">\n <mat-option *ngFor="let type of perimeterTypes" [value]="type">\n {{ perimeterTypeTranslationMap.get(type) | translate }}\n </mat-option>\n </mat-select>\n </mat-form-field>\n <div tb-hint-tooltip-icon="{{ geoFilterConfigForm.get(\'perimeterType\').value === perimeterType.CIRCLE\n ? (\'tb.rulenode.fetch-circle-parameter-info-from-metadata-hint\'\n | translate : { perimeterKeyName: geoFilterConfigForm.get(\'perimeterKeyName\').valid\n ? geoFilterConfigForm.get(\'perimeterKeyName\').value\n : \'ss_perimeter\'})\n : (\'tb.rulenode.fetch-poligon-parameter-info-from-metadata-hint\'\n | translate : { perimeterKeyName: geoFilterConfigForm.get(\'perimeterKeyName\').valid\n ? geoFilterConfigForm.get(\'perimeterKeyName\').value\n : \'ss_perimeter\'}) }}"\n class="tb-form-row no-border no-padding slide-toggle">\n <mat-slide-toggle class="mat-slide" formControlName="fetchPerimeterInfoFromMessageMetadata">\n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n </mat-slide-toggle>\n </div>\n <mat-form-field *ngIf="geoFilterConfigForm.get(\'fetchPerimeterInfoFromMessageMetadata\').value" class="mat-block">\n <mat-label>{{ \'tb.rulenode.perimeter-key-name\' | translate }}</mat-label>\n <input matInput formControlName="perimeterKeyName" required>\n <mat-error *ngIf="geoFilterConfigForm.get(\'perimeterKeyName\').hasError(\'required\')">\n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n </mat-error>\n <mat-hint>{{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}</mat-hint>\n </mat-form-field>\n <div fxLayout="column"\n *ngIf="geoFilterConfigForm.get(\'perimeterType\').value === perimeterType.CIRCLE &&\n !geoFilterConfigForm.get(\'fetchPerimeterInfoFromMessageMetadata\').value">\n <div fxLayout="row" fxLayoutGap="16px">\n <mat-form-field fxFlex>\n <mat-label>{{ \'tb.rulenode.circle-center-latitude\' | translate }}</mat-label>\n <input type="number" min="-90" max="90" step="0.1" matInput formControlName="centerLatitude" required>\n <mat-error *ngIf="geoFilterConfigForm.get(\'centerLatitude\').hasError(\'required\')">\n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex>\n <mat-label>{{ \'tb.rulenode.circle-center-longitude\' | translate }}</mat-label>\n <input type="number" min="-180" max="180" step="0.1" matInput formControlName="centerLongitude" required>\n <mat-error *ngIf="geoFilterConfigForm.get(\'centerLongitude\').hasError(\'required\')">\n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n <div fxLayout="row" fxLayoutGap="16px">\n <mat-form-field fxFlex>\n <mat-label>{{ \'tb.rulenode.range\' | translate }}</mat-label>\n <input type="number" min="0" step="0.1" matInput formControlName="range" required>\n <mat-error *ngIf="geoFilterConfigForm.get(\'range\').hasError(\'required\')">\n {{ \'tb.rulenode.range-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field fxFlex>\n <mat-label>{{ \'tb.rulenode.range-units\' | translate }}</mat-label>\n <mat-select formControlName="rangeUnit" required>\n <mat-option *ngFor="let type of rangeUnits" [value]="type">\n {{ rangeUnitTranslationMap.get(type) | translate }}\n </mat-option>\n </mat-select>\n <mat-error *ngIf="geoFilterConfigForm.get(\'rangeUnit\').hasError(\'required\')">\n {{ \'tb.rulenode.range-units-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n </div>\n <mat-form-field class="mat-block" subscriptSizing="dynamic"\n *ngIf="geoFilterConfigForm.get(\'perimeterType\').value === perimeterType.POLYGON &&\n !geoFilterConfigForm.get(\'fetchPerimeterInfoFromMessageMetadata\').value">\n <mat-label>{{ \'tb.rulenode.polygon-definition\' | translate }}</mat-label>\n <input matInput formControlName="polygonsDefinition" required>\n <mat-hint>{{ \'tb.rulenode.polygon-definition-hint\' | translate }}</mat-hint>\n <mat-error *ngIf="geoFilterConfigForm.get(\'polygonsDefinition\').hasError(\'required\')">\n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </section>\n </section>\n</section>\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder}]}});class Ir extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.messageTypeConfigForm}prepareInputConfig(e){return{messageTypes:ye(e?.messageTypes)?e.messageTypes:null}}onConfigurationSet(e){this.messageTypeConfigForm=this.fb.group({messageTypes:[e.messageTypes,[_.required]]})}}e("MessageTypeConfigComponent",Ir),Ir.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ir,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Ir.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ir,selector:"tb-filter-node-message-type-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="messageTypeConfigForm">\n <tb-message-types-config\n required\n [label]="\'tb.rulenode.select-message-types\' | translate"\n formControlName="messageTypes">\n </tb-message-types-config>\n</section>\n',dependencies:[{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Bn,selector:"tb-message-types-config",inputs:["required","label","placeholder","disabled"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ir,decorators:[{type:n,args:[{selector:"tb-filter-node-message-type-config",template:'<section [formGroup]="messageTypeConfigForm">\n <tb-message-types-config\n required\n [label]="\'tb.rulenode.select-message-types\' | translate"\n formControlName="messageTypes">\n </tb-message-types-config>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class Sr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.allowedEntityTypes=[C.DEVICE,C.ASSET,C.ENTITY_VIEW,C.TENANT,C.CUSTOMER,C.USER,C.DASHBOARD,C.RULE_CHAIN,C.RULE_NODE,C.EDGE]}configForm(){return this.originatorTypeConfigForm}prepareInputConfig(e){return{originatorTypes:ye(e?.originatorTypes)?e.originatorTypes:null}}onConfigurationSet(e){this.originatorTypeConfigForm=this.fb.group({originatorTypes:[e.originatorTypes,[_.required]]})}}e("OriginatorTypeConfigComponent",Sr),Sr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sr,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Sr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Sr,selector:"tb-filter-node-originator-type-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="originatorTypeConfigForm">\n <tb-entity-type-list fxFlex\n formControlName="originatorTypes"\n [allowedEntityTypes]="allowedEntityTypes"\n [ignoreAuthorityFilter]="true"\n [emptyInputPlaceholder]="\'tb.rulenode.add-entity-type\' | translate"\n [filledInputPlaceholder]="\'tb.rulenode.add-entity-type\' | translate"\n [label]="\'tb.rulenode.select-entity-types\' | translate"\n required>\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.chip-help\' | translate: { inputName: \'tb.rulenode.entity-type\' | translate } }}">help</mat-icon>\n </tb-entity-type-list>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:mt.EntityTypeListComponent,selector:"tb-entity-type-list",inputs:["required","additionalClasses","appearance","label","floatLabel","disabled","subscriptSizing","allowedEntityTypes","emptyInputPlaceholder","filledInputPlaceholder","ignoreAuthorityFilter"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sr,decorators:[{type:n,args:[{selector:"tb-filter-node-originator-type-config",template:'<section [formGroup]="originatorTypeConfigForm">\n <tb-entity-type-list fxFlex\n formControlName="originatorTypes"\n [allowedEntityTypes]="allowedEntityTypes"\n [ignoreAuthorityFilter]="true"\n [emptyInputPlaceholder]="\'tb.rulenode.add-entity-type\' | translate"\n [filledInputPlaceholder]="\'tb.rulenode.add-entity-type\' | translate"\n [label]="\'tb.rulenode.select-entity-types\' | translate"\n required>\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.chip-help\' | translate: { inputName: \'tb.rulenode.entity-type\' | translate } }}">help</mat-icon>\n </tb-entity-type-list>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class Nr extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ge(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-filter-function"}configForm(){return this.scriptConfigForm}onConfigurationSet(e){this.scriptConfigForm=this.fb.group({scriptLang:[e.scriptLang,[_.required]],jsScript:[e.jsScript,[]],tbelScript:[e.tbelScript,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.scriptConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.scriptConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.scriptConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.scriptConfigForm.get("jsScript").setValidators(t===b.JS?[_.required]:[]),this.scriptConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.scriptConfigForm.get("tbelScript").setValidators(t===b.TBEL?[_.required]:[]),this.scriptConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),{scriptLang:ye(e?.scriptLang)?e.scriptLang:b.JS,jsScript:ye(e?.jsScript)?e.jsScript:null,tbelScript:ye(e?.tbelScript)?e.tbelScript:null}}testScript(e){const t=this.scriptConfigForm.get("scriptLang").value,n=t===b.JS?"jsScript":"tbelScript",r=t===b.JS?"rulenode/filter_node_script_fn":"rulenode/tbel/filter_node_script_fn",o=this.scriptConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"filter",this.translate.instant("tb.rulenode.filter"),"Filter",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.scriptConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.scriptConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}e("ScriptConfigComponent",Nr),Nr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nr,deps:[{token:R.Store},{token:O.UntypedFormBuilder},{token:fe.NodeScriptTestService},{token:X.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Nr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Nr,selector:"tb-filter-node-script-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'<section [formGroup]="scriptConfigForm">\n <tb-script-lang formControlName="scriptLang" *ngIf="tbelEnabled"></tb-script-lang>\n <tb-js-func *ngIf="scriptConfigForm.get(\'scriptLang\').value === scriptLanguage.JS"\n #jsFuncComponent\n formControlName="jsScript"\n functionName="Filter"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n helpId="rulenode/filter_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <tb-js-func *ngIf="scriptConfigForm.get(\'scriptLang\').value === scriptLanguage.TBEL"\n #tbelFuncComponent\n formControlName="tbelScript"\n functionName="Filter"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n [disableUndefinedCheck]="true"\n [scriptLanguage]="scriptLanguage.TBEL"\n helpId="rulenode/tbel/filter_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <button mat-button mat-raised-button color="primary" (click)="testScript()">\n {{ testScriptLabel | translate }}\n </button>\n</section>\n',dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ce.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","propertyHighlightRules","objectHighlightRules","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:ee.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nr,decorators:[{type:n,args:[{selector:"tb-filter-node-script-config",template:'<section [formGroup]="scriptConfigForm">\n <tb-script-lang formControlName="scriptLang" *ngIf="tbelEnabled"></tb-script-lang>\n <tb-js-func *ngIf="scriptConfigForm.get(\'scriptLang\').value === scriptLanguage.JS"\n #jsFuncComponent\n formControlName="jsScript"\n functionName="Filter"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n helpId="rulenode/filter_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <tb-js-func *ngIf="scriptConfigForm.get(\'scriptLang\').value === scriptLanguage.TBEL"\n #tbelFuncComponent\n formControlName="tbelScript"\n functionName="Filter"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n [disableUndefinedCheck]="true"\n [scriptLanguage]="scriptLanguage.TBEL"\n helpId="rulenode/tbel/filter_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <button mat-button mat-raised-button color="primary" (click)="testScript()">\n {{ testScriptLabel | translate }}\n </button>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder},{type:fe.NodeScriptTestService},{type:X.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}});class qr extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ge(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-switch-function"}configForm(){return this.switchConfigForm}onConfigurationSet(e){this.switchConfigForm=this.fb.group({scriptLang:[e.scriptLang,[_.required]],jsScript:[e.jsScript,[]],tbelScript:[e.tbelScript,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.switchConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.switchConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.switchConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.switchConfigForm.get("jsScript").setValidators(t===b.JS?[_.required]:[]),this.switchConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.switchConfigForm.get("tbelScript").setValidators(t===b.TBEL?[_.required]:[]),this.switchConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),{scriptLang:ye(e?.scriptLang)?e.scriptLang:b.JS,jsScript:ye(e?.jsScript)?e.jsScript:null,tbelScript:ye(e?.tbelScript)?e.tbelScript:null}}testScript(e){const t=this.switchConfigForm.get("scriptLang").value,n=t===b.JS?"jsScript":"tbelScript",r=t===b.JS?"rulenode/switch_node_script_fn":"rulenode/tbel/switch_node_script_fn",o=this.switchConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"switch",this.translate.instant("tb.rulenode.switch"),"Switch",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.switchConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.switchConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}e("SwitchConfigComponent",qr),qr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qr,deps:[{token:R.Store},{token:O.UntypedFormBuilder},{token:fe.NodeScriptTestService},{token:X.TranslateService}],target:t.ɵɵFactoryTarget.Component}),qr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:qr,selector:"tb-filter-node-switch-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'<section [formGroup]="switchConfigForm">\n <tb-script-lang formControlName="scriptLang" *ngIf="tbelEnabled"></tb-script-lang>\n <tb-js-func *ngIf="switchConfigForm.get(\'scriptLang\').value === scriptLanguage.JS"\n #jsFuncComponent\n formControlName="jsScript"\n functionName="Switch"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n helpId="rulenode/switch_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <tb-js-func *ngIf="switchConfigForm.get(\'scriptLang\').value === scriptLanguage.TBEL"\n #tbelFuncComponent\n formControlName="tbelScript"\n functionName="Switch"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n [disableUndefinedCheck]="true"\n [scriptLanguage]="scriptLanguage.TBEL"\n helpId="rulenode/tbel/switch_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <button mat-button mat-raised-button color="primary" (click)="testScript()">\n {{ testScriptLabel | translate }}\n </button>\n</section>\n',dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ce.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","propertyHighlightRules","objectHighlightRules","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:ee.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qr,decorators:[{type:n,args:[{selector:"tb-filter-node-switch-config",template:'<section [formGroup]="switchConfigForm">\n <tb-script-lang formControlName="scriptLang" *ngIf="tbelEnabled"></tb-script-lang>\n <tb-js-func *ngIf="switchConfigForm.get(\'scriptLang\').value === scriptLanguage.JS"\n #jsFuncComponent\n formControlName="jsScript"\n functionName="Switch"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n helpId="rulenode/switch_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <tb-js-func *ngIf="switchConfigForm.get(\'scriptLang\').value === scriptLanguage.TBEL"\n #tbelFuncComponent\n formControlName="tbelScript"\n functionName="Switch"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n [disableUndefinedCheck]="true"\n [scriptLanguage]="scriptLanguage.TBEL"\n helpId="rulenode/tbel/switch_node_script_fn"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <button mat-button mat-raised-button color="primary" (click)="testScript()">\n {{ testScriptLabel | translate }}\n </button>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder},{type:fe.NodeScriptTestService},{type:X.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}});class Ar{}e("RuleNodeCoreConfigFilterModule",Ar),Ar.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ar,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Ar.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Ar,declarations:[kr,Tr,Lr,Ir,Sr,Nr,qr,Fr],imports:[J,E,Qn],exports:[kr,Tr,Lr,Ir,Sr,Nr,qr,Fr]}),Ar.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ar,imports:[J,E,Qn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ar,decorators:[{type:d,args:[{declarations:[kr,Tr,Lr,Ir,Sr,Nr,qr,Fr],imports:[J,E,Qn],exports:[kr,Tr,Lr,Ir,Sr,Nr,qr,Fr]}]}]});class Mr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.originatorSource=St,this.originatorSources=Object.keys(St),this.originatorSourceTranslationMap=Nt,this.originatorSourceDescTranslationMap=qt,this.allowedEntityTypes=[C.DEVICE,C.ASSET,C.ENTITY_VIEW,C.USER,C.EDGE]}configForm(){return this.changeOriginatorConfigForm}onConfigurationSet(e){this.changeOriginatorConfigForm=this.fb.group({originatorSource:[e?e.originatorSource:null,[_.required]],entityType:[e?e.entityType:null,[]],entityNamePattern:[e?e.entityNamePattern:null,[]],relationsQuery:[e?e.relationsQuery:null,[]]})}validatorTriggers(){return["originatorSource"]}updateValidators(e){const t=this.changeOriginatorConfigForm.get("originatorSource").value;t===St.RELATED?this.changeOriginatorConfigForm.get("relationsQuery").setValidators([_.required]):this.changeOriginatorConfigForm.get("relationsQuery").setValidators([]),t===St.ENTITY?(this.changeOriginatorConfigForm.get("entityType").setValidators([_.required]),this.changeOriginatorConfigForm.get("entityNamePattern").setValidators([_.required,_.pattern(/.*\S.*/)])):(this.changeOriginatorConfigForm.get("entityType").patchValue(null,{emitEvent:e}),this.changeOriginatorConfigForm.get("entityNamePattern").patchValue(null,{emitEvent:e}),this.changeOriginatorConfigForm.get("entityType").setValidators([]),this.changeOriginatorConfigForm.get("entityNamePattern").setValidators([])),this.changeOriginatorConfigForm.get("relationsQuery").updateValueAndValidity({emitEvent:e}),this.changeOriginatorConfigForm.get("entityType").updateValueAndValidity({emitEvent:e}),this.changeOriginatorConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e})}}e("ChangeOriginatorConfigComponent",Mr),Mr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mr,deps:[{token:R.Store},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Mr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Mr,selector:"tb-transformation-node-change-originator-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="changeOriginatorConfigForm" class="tb-form-panel no-border no-padding">\n <mat-form-field class="mat-block" subscriptSizing="dynamic" hideRequiredMarker>\n <mat-label translate>tb.rulenode.new-originator</mat-label>\n <mat-select formControlName="originatorSource" required>\n <mat-select-trigger>\n <span *ngIf="originatorSourceTranslationMap.get(changeOriginatorConfigForm.get(\'originatorSource\').value)">\n {{ originatorSourceTranslationMap.get(changeOriginatorConfigForm.get(\'originatorSource\').value) | translate }}\n </span>\n </mat-select-trigger>\n <mat-option *ngFor="let source of originatorSources" [value]="source">\n <span matListItemTitle>\n {{ originatorSourceTranslationMap.get(source) | translate }}\n </span>\n <br>\n <small matListItemMeta style="color: inherit">\n {{ originatorSourceDescTranslationMap.get(source) | translate }}\n </small>\n </mat-option>\n </mat-select>\n </mat-form-field>\n <div class="tb-form-panel stroked no-padding-bottom"\n *ngIf="changeOriginatorConfigForm.get(\'originatorSource\').value === \'ENTITY\'">\n <tb-example-hint [hintText]="\'tb.rulenode.entity-name-pattern-hint\'"\n popupHelpLink="rulenode/change_originator_node_fields_templatization">\n </tb-example-hint>\n <div class="tb-form-row no-border no-padding tb-standard-fields">\n <tb-entity-type-select\n showLabel\n required\n [allowedEntityTypes] = "allowedEntityTypes"\n formControlName="entityType"\n class="mat-mdc-form-field flex">\n </tb-entity-type-select>\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.entity-name-pattern</mat-label>\n <input required matInput formControlName="entityNamePattern">\n <mat-error *ngIf="changeOriginatorConfigForm.get(\'entityNamePattern\').hasError(\'required\') ||\n changeOriginatorConfigForm.get(\'entityNamePattern\').hasError(\'pattern\')">\n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n </div>\n <tb-relations-query-config\n required\n *ngIf="changeOriginatorConfigForm.get(\'originatorSource\').value === originatorSource.RELATED"\n formControlName="relationsQuery">\n </tb-relations-query-config>\n</section>\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ne.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled","additionEntityTypes"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:ne.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:Re.MatListItemTitle,selector:"[matListItemTitle]"},{kind:"directive",type:Re.MatListItemMeta,selector:"[matListItemMeta]"},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:_n,selector:"tb-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:ht,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mr,decorators:[{type:n,args:[{selector:"tb-transformation-node-change-originator-config",template:'<section [formGroup]="changeOriginatorConfigForm" class="tb-form-panel no-border no-padding">\n <mat-form-field class="mat-block" subscriptSizing="dynamic" hideRequiredMarker>\n <mat-label translate>tb.rulenode.new-originator</mat-label>\n <mat-select formControlName="originatorSource" required>\n <mat-select-trigger>\n <span *ngIf="originatorSourceTranslationMap.get(changeOriginatorConfigForm.get(\'originatorSource\').value)">\n {{ originatorSourceTranslationMap.get(changeOriginatorConfigForm.get(\'originatorSource\').value) | translate }}\n </span>\n </mat-select-trigger>\n <mat-option *ngFor="let source of originatorSources" [value]="source">\n <span matListItemTitle>\n {{ originatorSourceTranslationMap.get(source) | translate }}\n </span>\n <br>\n <small matListItemMeta style="color: inherit">\n {{ originatorSourceDescTranslationMap.get(source) | translate }}\n </small>\n </mat-option>\n </mat-select>\n </mat-form-field>\n <div class="tb-form-panel stroked no-padding-bottom"\n *ngIf="changeOriginatorConfigForm.get(\'originatorSource\').value === \'ENTITY\'">\n <tb-example-hint [hintText]="\'tb.rulenode.entity-name-pattern-hint\'"\n popupHelpLink="rulenode/change_originator_node_fields_templatization">\n </tb-example-hint>\n <div class="tb-form-row no-border no-padding tb-standard-fields">\n <tb-entity-type-select\n showLabel\n required\n [allowedEntityTypes] = "allowedEntityTypes"\n formControlName="entityType"\n class="mat-mdc-form-field flex">\n </tb-entity-type-select>\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.entity-name-pattern</mat-label>\n <input required matInput formControlName="entityNamePattern">\n <mat-error *ngIf="changeOriginatorConfigForm.get(\'entityNamePattern\').hasError(\'required\') ||\n changeOriginatorConfigForm.get(\'entityNamePattern\').hasError(\'pattern\')">\n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n </div>\n <tb-relations-query-config\n required\n *ngIf="changeOriginatorConfigForm.get(\'originatorSource\').value === originatorSource.RELATED"\n formControlName="relationsQuery">\n </tb-relations-query-config>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder}]}});class Er extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ge(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-transformer-function"}configForm(){return this.scriptConfigForm}onConfigurationSet(e){this.scriptConfigForm=this.fb.group({scriptLang:[e?e.scriptLang:b.JS,[_.required]],jsScript:[e?e.jsScript:null,[_.required]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.scriptConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.scriptConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.scriptConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.scriptConfigForm.get("jsScript").setValidators(t===b.JS?[_.required]:[]),this.scriptConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.scriptConfigForm.get("tbelScript").setValidators(t===b.TBEL?[_.required]:[]),this.scriptConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),e}testScript(e){const t=this.scriptConfigForm.get("scriptLang").value,n=t===b.JS?"jsScript":"tbelScript",r=t===b.JS?"rulenode/transformation_node_script_fn":"rulenode/tbel/transformation_node_script_fn",o=this.scriptConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"update",this.translate.instant("tb.rulenode.transformer"),"Transform",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.scriptConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.scriptConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}e("TransformScriptConfigComponent",Er),Er.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Er,deps:[{token:R.Store},{token:O.FormBuilder},{token:fe.NodeScriptTestService},{token:X.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Er.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Er,selector:"tb-transformation-node-script-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'<section [formGroup]="scriptConfigForm">\n <tb-script-lang formControlName="scriptLang" *ngIf="tbelEnabled"></tb-script-lang>\n <tb-js-func *ngIf="scriptConfigForm.get(\'scriptLang\').value === scriptLanguage.JS"\n #jsFuncComponent\n formControlName="jsScript"\n functionName="Transform"\n helpId="rulenode/transformation_node_script_fn"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <tb-js-func *ngIf="scriptConfigForm.get(\'scriptLang\').value === scriptLanguage.TBEL"\n #tbelFuncComponent\n formControlName="tbelScript"\n functionName="Transform"\n helpId="rulenode/tbel/transformation_node_script_fn"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n [disableUndefinedCheck]="true"\n [scriptLanguage]="scriptLanguage.TBEL"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <div>\n <button mat-button mat-raised-button color="primary" (click)="testScript()">\n {{ testScriptLabel | translate }}\n </button>\n </div>\n</section>\n',dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ce.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","propertyHighlightRules","objectHighlightRules","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:ee.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Er,decorators:[{type:n,args:[{selector:"tb-transformation-node-script-config",template:'<section [formGroup]="scriptConfigForm">\n <tb-script-lang formControlName="scriptLang" *ngIf="tbelEnabled"></tb-script-lang>\n <tb-js-func *ngIf="scriptConfigForm.get(\'scriptLang\').value === scriptLanguage.JS"\n #jsFuncComponent\n formControlName="jsScript"\n functionName="Transform"\n helpId="rulenode/transformation_node_script_fn"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <tb-js-func *ngIf="scriptConfigForm.get(\'scriptLang\').value === scriptLanguage.TBEL"\n #tbelFuncComponent\n formControlName="tbelScript"\n functionName="Transform"\n helpId="rulenode/tbel/transformation_node_script_fn"\n [functionArgs]="[\'msg\', \'metadata\', \'msgType\']"\n [disableUndefinedCheck]="true"\n [scriptLanguage]="scriptLanguage.TBEL"\n noValidate="true">\n <button toolbarSuffixButton\n mat-icon-button\n matTooltip="{{ testScriptLabel | translate }}"\n matTooltipPosition="above"\n class="tb-mat-32"\n (click)="testScript()">\n <mat-icon class="material-icons" color="primary">bug_report</mat-icon>\n </button>\n </tb-js-func>\n <div>\n <button mat-button mat-raised-button color="primary" (click)="testScript()">\n {{ testScriptLabel | translate }}\n </button>\n </div>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder},{type:fe.NodeScriptTestService},{type:X.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}}); + /** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + const wr=pt({passive:!0});class Gr{constructor(e,t){this._platform=e,this._ngZone=t,this._monitoredElements=new Map}monitor(e){if(!this._platform.isBrowser)return me;const t=Ge(e),n=this._monitoredElements.get(t);if(n)return n.subject;const r=new ie,o="cdk-text-field-autofilled",a=e=>{"cdk-text-field-autofill-start"!==e.animationName||t.classList.contains(o)?"cdk-text-field-autofill-end"===e.animationName&&t.classList.contains(o)&&(t.classList.remove(o),this._ngZone.run((()=>r.next({target:e.target,isAutofilled:!1})))):(t.classList.add(o),this._ngZone.run((()=>r.next({target:e.target,isAutofilled:!0}))))};return this._ngZone.runOutsideAngular((()=>{t.addEventListener("animationstart",a,wr),t.classList.add("cdk-text-field-autofill-monitored")})),this._monitoredElements.set(t,{subject:r,unlisten:()=>{t.removeEventListener("animationstart",a,wr)}}),r}stopMonitoring(e){const t=Ge(e),n=this._monitoredElements.get(t);n&&(n.unlisten(),n.subject.complete(),t.classList.remove("cdk-text-field-autofill-monitored"),t.classList.remove("cdk-text-field-autofilled"),this._monitoredElements.delete(t))}ngOnDestroy(){this._monitoredElements.forEach(((e,t)=>this.stopMonitoring(t)))}}Gr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Gr,deps:[{token:dt.Platform},{token:t.NgZone}],target:t.ɵɵFactoryTarget.Injectable}),Gr.ɵprov=t.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Gr,providedIn:"root"}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Gr,decorators:[{type:o,args:[{providedIn:"root"}]}],ctorParameters:function(){return[{type:dt.Platform},{type:t.NgZone}]}});class Dr{constructor(e,t){this._elementRef=e,this._autofillMonitor=t,this.cdkAutofill=new l}ngOnInit(){this._autofillMonitor.monitor(this._elementRef).subscribe((e=>this.cdkAutofill.emit(e)))}ngOnDestroy(){this._autofillMonitor.stopMonitoring(this._elementRef)}}Dr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Dr,deps:[{token:t.ElementRef},{token:Gr}],target:t.ɵɵFactoryTarget.Directive}),Dr.ɵdir=t.ɵɵngDeclareDirective({minVersion:"14.0.0",version:"15.2.0-rc.0",type:Dr,selector:"[cdkAutofill]",outputs:{cdkAutofill:"cdkAutofill"},ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Dr,decorators:[{type:s,args:[{selector:"[cdkAutofill]"}]}],ctorParameters:function(){return[{type:t.ElementRef},{type:Gr}]},propDecorators:{cdkAutofill:[{type:p}]}}); + /** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + class Vr{get minRows(){return this._minRows}set minRows(e){this._minRows=De(e),this._setMinHeight()}get maxRows(){return this._maxRows}set maxRows(e){this._maxRows=De(e),this._setMaxHeight()}get enabled(){return this._enabled}set enabled(e){e=we(e),this._enabled!==e&&((this._enabled=e)?this.resizeToFitContent(!0):this.reset())}get placeholder(){return this._textareaElement.placeholder}set placeholder(e){this._cachedPlaceholderHeight=void 0,e?this._textareaElement.setAttribute("placeholder",e):this._textareaElement.removeAttribute("placeholder"),this._cacheTextareaPlaceholderHeight()}constructor(e,t,n,r){this._elementRef=e,this._platform=t,this._ngZone=n,this._destroyed=new ie,this._enabled=!0,this._previousMinRows=-1,this._isViewInited=!1,this._handleFocusEvent=e=>{this._hasFocus="focus"===e.type},this._document=r,this._textareaElement=this._elementRef.nativeElement}_setMinHeight(){const e=this.minRows&&this._cachedLineHeight?this.minRows*this._cachedLineHeight+"px":null;e&&(this._textareaElement.style.minHeight=e)}_setMaxHeight(){const e=this.maxRows&&this._cachedLineHeight?this.maxRows*this._cachedLineHeight+"px":null;e&&(this._textareaElement.style.maxHeight=e)}ngAfterViewInit(){this._platform.isBrowser&&(this._initialHeight=this._textareaElement.style.height,this.resizeToFitContent(),this._ngZone.runOutsideAngular((()=>{const e=this._getWindow();pe(e,"resize").pipe(je(16),Ue(this._destroyed)).subscribe((()=>this.resizeToFitContent(!0))),this._textareaElement.addEventListener("focus",this._handleFocusEvent),this._textareaElement.addEventListener("blur",this._handleFocusEvent)})),this._isViewInited=!0,this.resizeToFitContent(!0))}ngOnDestroy(){this._textareaElement.removeEventListener("focus",this._handleFocusEvent),this._textareaElement.removeEventListener("blur",this._handleFocusEvent),this._destroyed.next(),this._destroyed.complete()}_cacheTextareaLineHeight(){if(this._cachedLineHeight)return;let e=this._textareaElement.cloneNode(!1);e.rows=1,e.style.position="absolute",e.style.visibility="hidden",e.style.border="none",e.style.padding="0",e.style.height="",e.style.minHeight="",e.style.maxHeight="",e.style.overflow="hidden",this._textareaElement.parentNode.appendChild(e),this._cachedLineHeight=e.clientHeight,e.remove(),this._setMinHeight(),this._setMaxHeight()}_measureScrollHeight(){const e=this._textareaElement,t=e.style.marginBottom||"",n=this._platform.FIREFOX,r=n&&this._hasFocus,o=n?"cdk-textarea-autosize-measuring-firefox":"cdk-textarea-autosize-measuring";r&&(e.style.marginBottom=`${e.clientHeight}px`),e.classList.add(o);const a=e.scrollHeight-4;return e.classList.remove(o),r&&(e.style.marginBottom=t),a}_cacheTextareaPlaceholderHeight(){if(!this._isViewInited||null!=this._cachedPlaceholderHeight)return;if(!this.placeholder)return void(this._cachedPlaceholderHeight=0);const e=this._textareaElement.value;this._textareaElement.value=this._textareaElement.placeholder,this._cachedPlaceholderHeight=this._measureScrollHeight(),this._textareaElement.value=e}ngDoCheck(){this._platform.isBrowser&&this.resizeToFitContent()}resizeToFitContent(e=!1){if(!this._enabled)return;if(this._cacheTextareaLineHeight(),this._cacheTextareaPlaceholderHeight(),!this._cachedLineHeight)return;const t=this._elementRef.nativeElement,n=t.value;if(!e&&this._minRows===this._previousMinRows&&n===this._previousValue)return;const r=this._measureScrollHeight(),o=Math.max(r,this._cachedPlaceholderHeight||0);t.style.height=`${o}px`,this._ngZone.runOutsideAngular((()=>{"undefined"!=typeof requestAnimationFrame?requestAnimationFrame((()=>this._scrollToCaretPosition(t))):setTimeout((()=>this._scrollToCaretPosition(t)))})),this._previousValue=n,this._previousMinRows=this._minRows}reset(){void 0!==this._initialHeight&&(this._textareaElement.style.height=this._initialHeight)}_noopInputHandler(){}_getDocument(){return this._document||document}_getWindow(){return this._getDocument().defaultView||window}_scrollToCaretPosition(e){const{selectionStart:t,selectionEnd:n}=e;!this._destroyed.isStopped&&this._hasFocus&&e.setSelectionRange(t,n)}}Vr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Vr,deps:[{token:t.ElementRef},{token:dt.Platform},{token:t.NgZone},{token:$,optional:!0}],target:t.ɵɵFactoryTarget.Directive}),Vr.ɵdir=t.ɵɵngDeclareDirective({minVersion:"14.0.0",version:"15.2.0-rc.0",type:Vr,selector:"textarea[cdkTextareaAutosize]",inputs:{minRows:["cdkAutosizeMinRows","minRows"],maxRows:["cdkAutosizeMaxRows","maxRows"],enabled:["cdkTextareaAutosize","enabled"],placeholder:"placeholder"},host:{attributes:{rows:"1"},listeners:{input:"_noopInputHandler()"},classAttribute:"cdk-textarea-autosize"},exportAs:["cdkTextareaAutosize"],ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Vr,decorators:[{type:s,args:[{selector:"textarea[cdkTextareaAutosize]",exportAs:"cdkTextareaAutosize",host:{class:"cdk-textarea-autosize",rows:"1","(input)":"_noopInputHandler()"}}]}],ctorParameters:function(){return[{type:t.ElementRef},{type:dt.Platform},{type:t.NgZone},{type:void 0,decorators:[{type:i},{type:a,args:[$]}]}]},propDecorators:{minRows:[{type:m,args:["cdkAutosizeMinRows"]}],maxRows:[{type:m,args:["cdkAutosizeMaxRows"]}],enabled:[{type:m,args:["cdkTextareaAutosize"]}],placeholder:[{type:m}]}}); + /** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + class Pr{}Pr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Pr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Pr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.0-rc.0",ngImport:t,type:Pr,declarations:[Dr,Vr],exports:[Dr,Vr]}),Pr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Pr}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Pr,decorators:[{type:d,args:[{declarations:[Dr,Vr],exports:[Dr,Vr]}]}]});class Rr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.mailBodyTypes=[{name:"tb.mail-body-type.plain-text",description:"tb.mail-body-type.plain-text-description",value:"false"},{name:"tb.mail-body-type.html",description:"tb.mail-body-type.html-text-description",value:"true"},{name:"tb.mail-body-type.use-body-type-template",description:"tb.mail-body-type.dynamic-text-description",value:"dynamic"}]}configForm(){return this.toEmailConfigForm}onConfigurationSet(e){this.toEmailConfigForm=this.fb.group({fromTemplate:[e?e.fromTemplate:null,[_.required]],toTemplate:[e?e.toTemplate:null,[_.required]],ccTemplate:[e?e.ccTemplate:null,[]],bccTemplate:[e?e.bccTemplate:null,[]],subjectTemplate:[e?e.subjectTemplate:null,[_.required]],mailBodyType:[e?e.mailBodyType:null],isHtmlTemplate:[e?e.isHtmlTemplate:null,[_.required]],bodyTemplate:[e?e.bodyTemplate:null,[_.required]]})}prepareInputConfig(e){return{fromTemplate:ye(e?.fromTemplate)?e.fromTemplate:null,toTemplate:ye(e?.toTemplate)?e.toTemplate:null,ccTemplate:ye(e?.ccTemplate)?e.ccTemplate:null,bccTemplate:ye(e?.bccTemplate)?e.bccTemplate:null,subjectTemplate:ye(e?.subjectTemplate)?e.subjectTemplate:null,mailBodyType:ye(e?.mailBodyType)?e.mailBodyType:null,isHtmlTemplate:ye(e?.isHtmlTemplate)?e.isHtmlTemplate:null,bodyTemplate:ye(e?.bodyTemplate)?e.bodyTemplate:null}}updateValidators(e){"dynamic"===this.toEmailConfigForm.get("mailBodyType").value?this.toEmailConfigForm.get("isHtmlTemplate").enable({emitEvent:!1}):this.toEmailConfigForm.get("isHtmlTemplate").disable({emitEvent:!1}),this.toEmailConfigForm.get("isHtmlTemplate").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["mailBodyType"]}getBodyTypeName(){return this.mailBodyTypes.find((e=>e.value===this.toEmailConfigForm.get("mailBodyType").value)).name}}e("ToEmailConfigComponent",Rr),Rr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rr,deps:[{token:R.Store},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Rr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Rr,selector:"tb-transformation-node-to-email-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="toEmailConfigForm" class="tb-form-panel no-border no-padding">\n <div class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.email-sender</div>\n <div class="tb-form-row no-border no-padding tb-standard-fields">\n <mat-form-field class="flex" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.from-template</mat-label>\n <input required matInput formControlName="fromTemplate">\n <mat-hint align="start">\n {{ \'tb.rulenode.email-from-template-hint\' | translate }}\n </mat-hint>\n <mat-hint align="end">\n <div class="input-bottom-double-hint">\n <div class="see-example"\n hintMode\n tb-help-popup="{{\'rulenode/to_email_node_fields_templatization\'}}"\n tb-help-popup-placement="right"\n trigger-style="letter-spacing:0.25px; font-size:12px;"\n [tb-help-popup-style]="{maxWidth: \'820px\'}"\n trigger-text="{{ \'tb.key-val.see-examples\' | translate }}"></div>\n </div>\n </mat-hint>\n <mat-error *ngIf="toEmailConfigForm.get(\'fromTemplate\').hasError(\'required\')">\n {{ \'tb.rulenode.from-template-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n </div>\n <div class="tb-form-panel stroked">\n <div class="tb-form-panel no-padding no-border">\n <div class="tb-form-panel-title" translate>tb.rulenode.recipients</div>\n <tb-example-hint [hintText]="\'tb.rulenode.recipients-block-main-hint\' | translate"\n popupHelpLink="rulenode/to_email_node_fields_templatization">\n </tb-example-hint>\n </div>\n <div class="tb-form-row no-border no-padding tb-standard-fields">\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.to-template</mat-label>\n <textarea required\n matInput\n class="tb-enable-vertical-resize"\n formControlName="toTemplate"\n cdkTextareaAutosize\n cdkAutosizeMinRows="1"></textarea>\n <mat-error *ngIf="toEmailConfigForm.get(\'toTemplate\').hasError(\'required\')">\n {{ \'tb.rulenode.to-template-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.cc-template</mat-label>\n <textarea matInput\n formControlName="ccTemplate"\n class="tb-enable-vertical-resize"\n cdkTextareaAutosize\n cdkAutosizeMinRows="1"></textarea>\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.bcc-template</mat-label>\n <textarea matInput\n formControlName="bccTemplate"\n class="tb-enable-vertical-resize"\n cdkTextareaAutosize\n cdkAutosizeMinRows="1"></textarea>\n </mat-form-field>\n </div>\n </div>\n <div class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.message-subject-and-content</div>\n <tb-example-hint [hintText]="\'tb.rulenode.kv-map-pattern-hint\' | translate"\n popupHelpLink="rulenode/to_email_node_fields_templatization">\n </tb-example-hint>\n <section>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.subject-template</mat-label>\n <textarea required\n matInput\n formControlName="subjectTemplate"\n class="tb-enable-vertical-resize"\n cdkTextareaAutosize\n cdkAutosizeMinRows="1"></textarea>\n <mat-error *ngIf="toEmailConfigForm.get(\'subjectTemplate\').hasError(\'required\')">\n {{ \'tb.rulenode.subject-template-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.mail-body-type</mat-label>\n <mat-select formControlName="mailBodyType">\n <mat-select-trigger>\n <span *ngIf="toEmailConfigForm.get(\'mailBodyType\').value">\n {{ getBodyTypeName() | translate }}\n </span>\n </mat-select-trigger>\n <mat-option *ngFor="let type of mailBodyTypes" [value]="type.value">\n <span matListItemTitle>\n {{ type.name | translate }}\n </span>\n <br>\n <small matListItemMeta style="color: inherit">\n {{ type.description | translate }}\n </small>\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="mat-block" *ngIf="toEmailConfigForm.get(\'mailBodyType\').value === \'dynamic\'">\n <mat-label translate>tb.rulenode.body-type-template</mat-label>\n <input required matInput formControlName="isHtmlTemplate">\n <mat-hint translate>tb.mail-body-type.after-template-evaluation-hint</mat-hint>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.body-template</mat-label>\n <textarea required\n matInput\n formControlName="bodyTemplate"\n class="tb-enable-vertical-resize"\n cdkTextareaAutosize\n cdkAutosizeMinRows="2"></textarea>\n <mat-error *ngIf="toEmailConfigForm.get(\'bodyTemplate\').hasError(\'required\')">\n {{ \'tb.rulenode.body-template-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </section>\n </div>\n</section>\n',styles:[":host .input-bottom-double-hint{display:inline-flex}:host .input-bottom-double-hint .see-example{flex-shrink:0;padding-right:16px}:host textarea.tb-enable-vertical-resize{resize:vertical}\n"],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ue.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Vr,selector:"textarea[cdkTextareaAutosize]",inputs:["cdkAutosizeMinRows","cdkAutosizeMaxRows","cdkTextareaAutosize","placeholder"],exportAs:["cdkTextareaAutosize"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:ne.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:Re.MatListItemTitle,selector:"[matListItemTitle]"},{kind:"directive",type:Re.MatListItemMeta,selector:"[matListItemMeta]"},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ht,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rr,decorators:[{type:n,args:[{selector:"tb-transformation-node-to-email-config",template:'<section [formGroup]="toEmailConfigForm" class="tb-form-panel no-border no-padding">\n <div class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.email-sender</div>\n <div class="tb-form-row no-border no-padding tb-standard-fields">\n <mat-form-field class="flex" subscriptSizing="dynamic">\n <mat-label translate>tb.rulenode.from-template</mat-label>\n <input required matInput formControlName="fromTemplate">\n <mat-hint align="start">\n {{ \'tb.rulenode.email-from-template-hint\' | translate }}\n </mat-hint>\n <mat-hint align="end">\n <div class="input-bottom-double-hint">\n <div class="see-example"\n hintMode\n tb-help-popup="{{\'rulenode/to_email_node_fields_templatization\'}}"\n tb-help-popup-placement="right"\n trigger-style="letter-spacing:0.25px; font-size:12px;"\n [tb-help-popup-style]="{maxWidth: \'820px\'}"\n trigger-text="{{ \'tb.key-val.see-examples\' | translate }}"></div>\n </div>\n </mat-hint>\n <mat-error *ngIf="toEmailConfigForm.get(\'fromTemplate\').hasError(\'required\')">\n {{ \'tb.rulenode.from-template-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </div>\n </div>\n <div class="tb-form-panel stroked">\n <div class="tb-form-panel no-padding no-border">\n <div class="tb-form-panel-title" translate>tb.rulenode.recipients</div>\n <tb-example-hint [hintText]="\'tb.rulenode.recipients-block-main-hint\' | translate"\n popupHelpLink="rulenode/to_email_node_fields_templatization">\n </tb-example-hint>\n </div>\n <div class="tb-form-row no-border no-padding tb-standard-fields">\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.to-template</mat-label>\n <textarea required\n matInput\n class="tb-enable-vertical-resize"\n formControlName="toTemplate"\n cdkTextareaAutosize\n cdkAutosizeMinRows="1"></textarea>\n <mat-error *ngIf="toEmailConfigForm.get(\'toTemplate\').hasError(\'required\')">\n {{ \'tb.rulenode.to-template-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.cc-template</mat-label>\n <textarea matInput\n formControlName="ccTemplate"\n class="tb-enable-vertical-resize"\n cdkTextareaAutosize\n cdkAutosizeMinRows="1"></textarea>\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label translate>tb.rulenode.bcc-template</mat-label>\n <textarea matInput\n formControlName="bccTemplate"\n class="tb-enable-vertical-resize"\n cdkTextareaAutosize\n cdkAutosizeMinRows="1"></textarea>\n </mat-form-field>\n </div>\n </div>\n <div class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.message-subject-and-content</div>\n <tb-example-hint [hintText]="\'tb.rulenode.kv-map-pattern-hint\' | translate"\n popupHelpLink="rulenode/to_email_node_fields_templatization">\n </tb-example-hint>\n <section>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.subject-template</mat-label>\n <textarea required\n matInput\n formControlName="subjectTemplate"\n class="tb-enable-vertical-resize"\n cdkTextareaAutosize\n cdkAutosizeMinRows="1"></textarea>\n <mat-error *ngIf="toEmailConfigForm.get(\'subjectTemplate\').hasError(\'required\')">\n {{ \'tb.rulenode.subject-template-required\' | translate }}\n </mat-error>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.mail-body-type</mat-label>\n <mat-select formControlName="mailBodyType">\n <mat-select-trigger>\n <span *ngIf="toEmailConfigForm.get(\'mailBodyType\').value">\n {{ getBodyTypeName() | translate }}\n </span>\n </mat-select-trigger>\n <mat-option *ngFor="let type of mailBodyTypes" [value]="type.value">\n <span matListItemTitle>\n {{ type.name | translate }}\n </span>\n <br>\n <small matListItemMeta style="color: inherit">\n {{ type.description | translate }}\n </small>\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field class="mat-block" *ngIf="toEmailConfigForm.get(\'mailBodyType\').value === \'dynamic\'">\n <mat-label translate>tb.rulenode.body-type-template</mat-label>\n <input required matInput formControlName="isHtmlTemplate">\n <mat-hint translate>tb.mail-body-type.after-template-evaluation-hint</mat-hint>\n </mat-form-field>\n <mat-form-field class="mat-block">\n <mat-label translate>tb.rulenode.body-template</mat-label>\n <textarea required\n matInput\n formControlName="bodyTemplate"\n class="tb-enable-vertical-resize"\n cdkTextareaAutosize\n cdkAutosizeMinRows="2"></textarea>\n <mat-error *ngIf="toEmailConfigForm.get(\'bodyTemplate\').hasError(\'required\')">\n {{ \'tb.rulenode.body-template-required\' | translate }}\n </mat-error>\n </mat-form-field>\n </section>\n </div>\n</section>\n',styles:[":host .input-bottom-double-hint{display:inline-flex}:host .input-bottom-double-hint .see-example{flex-shrink:0;padding-right:16px}:host textarea.tb-enable-vertical-resize{resize:vertical}\n"]}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder}]}});class Or extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.copyFrom=[],this.translation=mn;for(const e of this.translation.keys())this.copyFrom.push({value:e,name:this.translate.instant(this.translation.get(e))})}onConfigurationSet(e){this.copyKeysConfigForm=this.fb.group({copyFrom:[e.copyFrom,[_.required]],keys:[e?e.keys:null,[_.required]]})}configForm(){return this.copyKeysConfigForm}prepareInputConfig(e){let t;return t=ye(e?.fromMetadata)?e.copyFrom?sn.METADATA:sn.DATA:ye(e?.copyFrom)?e.copyFrom:sn.DATA,{keys:ye(e?.keys)?e.keys:null,copyFrom:t}}}e("CopyKeysConfigComponent",Or),Or.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Or,deps:[{token:R.Store},{token:O.FormBuilder},{token:X.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Or.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Or,selector:"tb-transformation-node-copy-keys-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="copyKeysConfigForm" class="tb-form-panel no-padding no-border">\n <tb-msg-metadata-chip\n [labelText]="(\'tb.key-val.copy-key-values-from\' | translate)"\n [translation]="translation"\n formControlName="copyFrom">\n </tb-msg-metadata-chip>\n <tb-string-items-list class="mat-block"\n required\n [label]="\'tb.rulenode.keys\' | translate"\n [placeholder]="\'tb.rulenode.add-key\' | translate"\n [requiredText]="\'tb.key-val.at-least-one-key-error\' | translate"\n formControlName="keys">\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.use-regular-expression-hint\' | translate }}">\n help\n </mat-icon>\n </tb-string-items-list>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:tt.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Or,decorators:[{type:n,args:[{selector:"tb-transformation-node-copy-keys-config",template:'<section [formGroup]="copyKeysConfigForm" class="tb-form-panel no-padding no-border">\n <tb-msg-metadata-chip\n [labelText]="(\'tb.key-val.copy-key-values-from\' | translate)"\n [translation]="translation"\n formControlName="copyFrom">\n </tb-msg-metadata-chip>\n <tb-string-items-list class="mat-block"\n required\n [label]="\'tb.rulenode.keys\' | translate"\n [placeholder]="\'tb.rulenode.add-key\' | translate"\n [requiredText]="\'tb.key-val.at-least-one-key-error\' | translate"\n formControlName="keys">\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.use-regular-expression-hint\' | translate }}">\n help\n </mat-icon>\n </tb-string-items-list>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder},{type:X.TranslateService}]}});class _r extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.renameIn=[],this.translation=dn;for(const e of this.translation.keys())this.renameIn.push({value:e,name:this.translate.instant(this.translation.get(e))})}configForm(){return this.renameKeysConfigForm}onConfigurationSet(e){this.renameKeysConfigForm=this.fb.group({renameIn:[e?e.renameIn:null,[_.required]],renameKeysMapping:[e?e.renameKeysMapping:null,[_.required]]})}prepareInputConfig(e){let t;return t=ye(e?.fromMetadata)?e.fromMetadata?sn.METADATA:sn.DATA:ye(e?.renameIn)?e?.renameIn:sn.DATA,{renameKeysMapping:ye(e?.renameKeysMapping)?e.renameKeysMapping:null,renameIn:t}}}e("RenameKeysConfigComponent",_r),_r.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_r,deps:[{token:R.Store},{token:O.FormBuilder},{token:X.TranslateService}],target:t.ɵɵFactoryTarget.Component}),_r.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:_r,selector:"tb-transformation-node-rename-keys-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="renameKeysConfigForm" class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.rename-keys-in</div>\n <div class="fx-centered">\n <div class="fetch-to-data-toggle">\n <tb-toggle-select class="fetch-to-data-toggle" formControlName="renameIn" appearance="fill">\n <tb-toggle-option *ngFor="let data of renameIn" [value]="data.value">\n {{ data.name }}\n </tb-toggle-option>\n </tb-toggle-select>\n </div>\n </div>\n <tb-kv-map-config\n required\n labelText="{{ translation.get(renameKeysConfigForm.get(\'renameIn\').value) | translate }} {{\'tb.rulenode.keys-mapping\' | translate}}"\n formControlName="renameKeysMapping"\n uniqueKeyValuePairValidator\n requiredText="{{\'tb.rulenode.attr-mapping-required\' | translate}}"\n keyText="{{\'tb.rulenode.current-key-name\' | translate}}"\n keyRequiredText="{{\'tb.rulenode.key-name-required\' | translate}}"\n valText="{{\'tb.rulenode.new-key-name\' | translate}}"\n valRequiredText="{{\'tb.rulenode.new-key-name-required\' | translate}}">\n </tb-kv-map-config>\n</section>\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}:host .fx-centered{display:flex;width:100%;justify-content:space-around}\n"],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Me.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Ee.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination","fillHeight","extraPadding","primaryBackground"]},{kind:"component",type:Rn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_r,decorators:[{type:n,args:[{selector:"tb-transformation-node-rename-keys-config",template:'<section [formGroup]="renameKeysConfigForm" class="tb-form-panel stroked">\n <div class="tb-form-panel-title" translate>tb.rulenode.rename-keys-in</div>\n <div class="fx-centered">\n <div class="fetch-to-data-toggle">\n <tb-toggle-select class="fetch-to-data-toggle" formControlName="renameIn" appearance="fill">\n <tb-toggle-option *ngFor="let data of renameIn" [value]="data.value">\n {{ data.name }}\n </tb-toggle-option>\n </tb-toggle-select>\n </div>\n </div>\n <tb-kv-map-config\n required\n labelText="{{ translation.get(renameKeysConfigForm.get(\'renameIn\').value) | translate }} {{\'tb.rulenode.keys-mapping\' | translate}}"\n formControlName="renameKeysMapping"\n uniqueKeyValuePairValidator\n requiredText="{{\'tb.rulenode.attr-mapping-required\' | translate}}"\n keyText="{{\'tb.rulenode.current-key-name\' | translate}}"\n keyRequiredText="{{\'tb.rulenode.key-name-required\' | translate}}"\n valText="{{\'tb.rulenode.new-key-name\' | translate}}"\n valRequiredText="{{\'tb.rulenode.new-key-name-required\' | translate}}">\n </tb-kv-map-config>\n</section>\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}:host .fx-centered{display:flex;width:100%;justify-content:space-around}\n"]}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder},{type:X.TranslateService}]}});class Br extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.jsonPathConfigForm}onConfigurationSet(e){this.jsonPathConfigForm=this.fb.group({jsonPath:[e?e.jsonPath:null,[_.required]]})}}e("NodeJsonPathConfigComponent",Br),Br.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Br,deps:[{token:R.Store},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Br.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Br,selector:"tb-transformation-node-json-path-config",usesInheritance:!0,ngImport:t,template:"<section [formGroup]=\"jsonPathConfigForm\">\n <mat-form-field subscriptSizing=\"dynamic\" class=\"mat-block\">\n <mat-label>{{ 'tb.rulenode.json-path-expression' | translate }}</mat-label>\n <input matInput formControlName=\"jsonPath\" required/>\n <mat-hint>{{ 'tb.rulenode.json-path-expression-hint' | translate }}</mat-hint>\n <mat-error *ngIf=\"jsonPathConfigForm.get('jsonPath').hasError('required')\">{{ 'tb.rulenode.json-path-expression-required' | translate }}</mat-error>\n </mat-form-field>\n</section>\n",dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Br,decorators:[{type:n,args:[{selector:"tb-transformation-node-json-path-config",template:"<section [formGroup]=\"jsonPathConfigForm\">\n <mat-form-field subscriptSizing=\"dynamic\" class=\"mat-block\">\n <mat-label>{{ 'tb.rulenode.json-path-expression' | translate }}</mat-label>\n <input matInput formControlName=\"jsonPath\" required/>\n <mat-hint>{{ 'tb.rulenode.json-path-expression-hint' | translate }}</mat-hint>\n <mat-error *ngIf=\"jsonPathConfigForm.get('jsonPath').hasError('required')\">{{ 'tb.rulenode.json-path-expression-required' | translate }}</mat-error>\n </mat-form-field>\n</section>\n"}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder}]}});class Kr extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.deleteFrom=[],this.translation=pn;for(const e of this.translation.keys())this.deleteFrom.push({value:e,name:this.translate.instant(this.translation.get(e))})}onConfigurationSet(e){this.deleteKeysConfigForm=this.fb.group({deleteFrom:[e.deleteFrom,[_.required]],keys:[e?e.keys:null,[_.required]]})}prepareInputConfig(e){let t;return t=ye(e?.fromMetadata)?e.fromMetadata?sn.METADATA:sn.DATA:ye(e?.deleteFrom)?e?.deleteFrom:sn.DATA,{keys:ye(e?.keys)?e.keys:null,deleteFrom:t}}configForm(){return this.deleteKeysConfigForm}}e("DeleteKeysConfigComponent",Kr),Kr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kr,deps:[{token:R.Store},{token:O.FormBuilder},{token:X.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Kr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Kr,selector:"tb-transformation-node-delete-keys-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="deleteKeysConfigForm" class="tb-form-panel no-border no-padding">\n <tb-msg-metadata-chip\n [labelText]="(\'tb.key-val.delete-key-values-from\' | translate)"\n formControlName="deleteFrom">\n </tb-msg-metadata-chip>\n <tb-string-items-list class="mat-block"\n required\n [label]="\'tb.rulenode.keys\' | translate"\n [placeholder]="\'tb.rulenode.add-key\' | translate"\n [requiredText]="\'tb.key-val.at-least-one-key-error\' | translate"\n formControlName="keys">\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.use-regular-expression-delete-hint\' | translate }}">\n help\n </mat-icon>\n </tb-string-items-list>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:tt.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kr,decorators:[{type:n,args:[{selector:"tb-transformation-node-delete-keys-config",template:'<section [formGroup]="deleteKeysConfigForm" class="tb-form-panel no-border no-padding">\n <tb-msg-metadata-chip\n [labelText]="(\'tb.key-val.delete-key-values-from\' | translate)"\n formControlName="deleteFrom">\n </tb-msg-metadata-chip>\n <tb-string-items-list class="mat-block"\n required\n [label]="\'tb.rulenode.keys\' | translate"\n [placeholder]="\'tb.rulenode.add-key\' | translate"\n [requiredText]="\'tb.key-val.at-least-one-key-error\' | translate"\n formControlName="keys">\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.use-regular-expression-delete-hint\' | translate }}">\n help\n </mat-icon>\n </tb-string-items-list>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder},{type:X.TranslateService}]}});class Hr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.deduplicationStrategie=_t,this.deduplicationStrategies=Object.keys(this.deduplicationStrategie),this.deduplicationStrategiesTranslations=Bt}configForm(){return this.deduplicationConfigForm}onConfigurationSet(e){this.deduplicationConfigForm=this.fb.group({interval:[ye(e?.interval)?e.interval:null,[_.required,_.min(1)]],strategy:[ye(e?.strategy)?e.strategy:null,[_.required]],outMsgType:[ye(e?.outMsgType)?e.outMsgType:null,[_.required]],maxPendingMsgs:[ye(e?.maxPendingMsgs)?e.maxPendingMsgs:null,[_.required,_.min(1),_.max(1e3)]],maxRetries:[ye(e?.maxRetries)?e.maxRetries:null,[_.required,_.min(0),_.max(100)]]})}prepareInputConfig(e){return e||(e={}),e.outMsgType||(e.outMsgType="POST_TELEMETRY_REQUEST"),super.prepareInputConfig(e)}updateValidators(e){this.deduplicationConfigForm.get("strategy").value===this.deduplicationStrategie.ALL?this.deduplicationConfigForm.get("outMsgType").enable({emitEvent:!1}):this.deduplicationConfigForm.get("outMsgType").disable({emitEvent:!1}),this.deduplicationConfigForm.get("outMsgType").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["strategy"]}}e("DeduplicationConfigComponent",Hr),Hr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hr,deps:[{token:R.Store},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Hr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Hr,selector:"tb-action-node-msg-deduplication-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="deduplicationConfigForm">\n <mat-form-field class="mat-block">\n <mat-label>{{\'tb.rulenode.interval\' | translate}}</mat-label>\n <input type=\'number\' required matInput formControlName="interval">\n <mat-error *ngIf="deduplicationConfigForm.get(\'interval\').hasError(\'required\')">\n {{\'tb.rulenode.interval-required\' | translate}}\n </mat-error>\n <mat-error *ngIf="deduplicationConfigForm.get(\'interval\').hasError(\'min\')">\n {{\'tb.rulenode.interval-min-error\' | translate}}\n </mat-error>\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.interval-hint\' | translate }}">help</mat-icon>\n </mat-form-field>\n <div class="tb-form-panel no-padding no-border">\n <div class="tb-form-panel stroked">\n <div class="tb-form-panel-title tb-required" translate>tb.rulenode.strategy</div>\n <tb-toggle-select class="fetch-to-data-toggle" formControlName="strategy" appearance="fill">\n <tb-toggle-option *ngFor="let strategy of deduplicationStrategies" [value]="strategy">\n {{ deduplicationStrategiesTranslations.get(strategy) | translate }}\n </tb-toggle-option>\n </tb-toggle-select>\n <tb-example-hint [hintText]="\'tb.rulenode.strategy-all-hint\' | translate"\n *ngIf="deduplicationConfigForm.get(\'strategy\').value === \'ALL\'">\n </tb-example-hint>\n <tb-example-hint [hintText]="\'tb.rulenode.strategy-first-hint\' | translate"\n textAlign="\'center\'"\n *ngIf="deduplicationConfigForm.get(\'strategy\').value === \'FIRST\'">\n </tb-example-hint>\n <tb-example-hint [hintText]="\'tb.rulenode.strategy-last-hint\' | translate"\n textAlign="\'center\'"\n *ngIf="deduplicationConfigForm.get(\'strategy\').value === \'LAST\'">\n </tb-example-hint>\n <div *ngIf="deduplicationConfigForm.get(\'strategy\').value === deduplicationStrategie.ALL">\n <tb-output-message-type-autocomplete\n required\n formControlName="outMsgType">\n </tb-output-message-type-autocomplete>\n </div>\n </div>\n <section class="tb-form-panel stroked">\n <mat-expansion-panel class="tb-settings">\n <mat-expansion-panel-header>\n <mat-panel-title translate>tb.rulenode.advanced-settings</mat-panel-title>\n </mat-expansion-panel-header>\n <div class="tb-form-row no-border no-padding tb-standard-fields">\n <mat-form-field class="flex">\n <mat-label>{{\'tb.rulenode.max-pending-msgs\' | translate}}</mat-label>\n <input type = \'number\' required matInput formControlName="maxPendingMsgs">\n <mat-error *ngIf="deduplicationConfigForm.get(\'maxPendingMsgs\').hasError(\'required\')">\n {{\'tb.rulenode.max-pending-msgs-required\' | translate}}\n </mat-error>\n <mat-error *ngIf="deduplicationConfigForm.get(\'maxPendingMsgs\').hasError(\'max\')">\n {{\'tb.rulenode.max-pending-msgs-max-error\' | translate}}\n </mat-error>\n <mat-error *ngIf="deduplicationConfigForm.get(\'maxPendingMsgs\').hasError(\'min\')">\n {{\'tb.rulenode.max-pending-msgs-min-error\' | translate}}\n </mat-error>\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.max-pending-msgs-hint\' | translate }}">help</mat-icon>\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label>{{\'tb.rulenode.max-retries\' | translate}}</mat-label>\n <input type = \'number\' required matInput formControlName="maxRetries">\n <mat-error *ngIf="deduplicationConfigForm.get(\'maxRetries\').hasError(\'required\')">\n {{\'tb.rulenode.max-retries-required\' | translate}}\n </mat-error>\n <mat-error *ngIf="deduplicationConfigForm.get(\'maxRetries\').hasError(\'max\')">\n {{\'tb.rulenode.max-retries-max-error\' | translate}}\n </mat-error>\n <mat-error *ngIf="deduplicationConfigForm.get(\'maxRetries\').hasError(\'min\')">\n {{\'tb.rulenode.max-retries-min-error\' | translate}}\n </mat-error>\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.max-retries-hint\' | translate }}">help</mat-icon>\n </mat-form-field>\n </div>\n </mat-expansion-panel>\n </section>\n </div>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:ae.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:ae.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:ae.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Me.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Ee.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination","fillHeight","extraPadding","primaryBackground"]},{kind:"component",type:Hn,selector:"tb-output-message-type-autocomplete",inputs:["subscriptSizing","disabled","required"]},{kind:"component",type:ht,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hr,decorators:[{type:n,args:[{selector:"tb-action-node-msg-deduplication-config",template:'<section [formGroup]="deduplicationConfigForm">\n <mat-form-field class="mat-block">\n <mat-label>{{\'tb.rulenode.interval\' | translate}}</mat-label>\n <input type=\'number\' required matInput formControlName="interval">\n <mat-error *ngIf="deduplicationConfigForm.get(\'interval\').hasError(\'required\')">\n {{\'tb.rulenode.interval-required\' | translate}}\n </mat-error>\n <mat-error *ngIf="deduplicationConfigForm.get(\'interval\').hasError(\'min\')">\n {{\'tb.rulenode.interval-min-error\' | translate}}\n </mat-error>\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.interval-hint\' | translate }}">help</mat-icon>\n </mat-form-field>\n <div class="tb-form-panel no-padding no-border">\n <div class="tb-form-panel stroked">\n <div class="tb-form-panel-title tb-required" translate>tb.rulenode.strategy</div>\n <tb-toggle-select class="fetch-to-data-toggle" formControlName="strategy" appearance="fill">\n <tb-toggle-option *ngFor="let strategy of deduplicationStrategies" [value]="strategy">\n {{ deduplicationStrategiesTranslations.get(strategy) | translate }}\n </tb-toggle-option>\n </tb-toggle-select>\n <tb-example-hint [hintText]="\'tb.rulenode.strategy-all-hint\' | translate"\n *ngIf="deduplicationConfigForm.get(\'strategy\').value === \'ALL\'">\n </tb-example-hint>\n <tb-example-hint [hintText]="\'tb.rulenode.strategy-first-hint\' | translate"\n textAlign="\'center\'"\n *ngIf="deduplicationConfigForm.get(\'strategy\').value === \'FIRST\'">\n </tb-example-hint>\n <tb-example-hint [hintText]="\'tb.rulenode.strategy-last-hint\' | translate"\n textAlign="\'center\'"\n *ngIf="deduplicationConfigForm.get(\'strategy\').value === \'LAST\'">\n </tb-example-hint>\n <div *ngIf="deduplicationConfigForm.get(\'strategy\').value === deduplicationStrategie.ALL">\n <tb-output-message-type-autocomplete\n required\n formControlName="outMsgType">\n </tb-output-message-type-autocomplete>\n </div>\n </div>\n <section class="tb-form-panel stroked">\n <mat-expansion-panel class="tb-settings">\n <mat-expansion-panel-header>\n <mat-panel-title translate>tb.rulenode.advanced-settings</mat-panel-title>\n </mat-expansion-panel-header>\n <div class="tb-form-row no-border no-padding tb-standard-fields">\n <mat-form-field class="flex">\n <mat-label>{{\'tb.rulenode.max-pending-msgs\' | translate}}</mat-label>\n <input type = \'number\' required matInput formControlName="maxPendingMsgs">\n <mat-error *ngIf="deduplicationConfigForm.get(\'maxPendingMsgs\').hasError(\'required\')">\n {{\'tb.rulenode.max-pending-msgs-required\' | translate}}\n </mat-error>\n <mat-error *ngIf="deduplicationConfigForm.get(\'maxPendingMsgs\').hasError(\'max\')">\n {{\'tb.rulenode.max-pending-msgs-max-error\' | translate}}\n </mat-error>\n <mat-error *ngIf="deduplicationConfigForm.get(\'maxPendingMsgs\').hasError(\'min\')">\n {{\'tb.rulenode.max-pending-msgs-min-error\' | translate}}\n </mat-error>\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.max-pending-msgs-hint\' | translate }}">help</mat-icon>\n </mat-form-field>\n <mat-form-field class="flex">\n <mat-label>{{\'tb.rulenode.max-retries\' | translate}}</mat-label>\n <input type = \'number\' required matInput formControlName="maxRetries">\n <mat-error *ngIf="deduplicationConfigForm.get(\'maxRetries\').hasError(\'required\')">\n {{\'tb.rulenode.max-retries-required\' | translate}}\n </mat-error>\n <mat-error *ngIf="deduplicationConfigForm.get(\'maxRetries\').hasError(\'max\')">\n {{\'tb.rulenode.max-retries-max-error\' | translate}}\n </mat-error>\n <mat-error *ngIf="deduplicationConfigForm.get(\'maxRetries\').hasError(\'min\')">\n {{\'tb.rulenode.max-retries-min-error\' | translate}}\n </mat-error>\n <mat-icon matSuffix class="help-icon margin-8 cursor-pointer" aria-hidden="false" aria-label="help-icon"\n color="primary"\n matTooltip="{{ \'tb.rulenode.max-retries-hint\' | translate }}">help</mat-icon>\n </mat-form-field>\n </div>\n </mat-expansion-panel>\n </section>\n </div>\n</section>\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder}]}});class zr{}e("RulenodeCoreConfigTransformModule",zr),zr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),zr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:zr,declarations:[Mr,Er,Rr,Or,_r,Br,Kr,Hr],imports:[J,E,Qn],exports:[Mr,Er,Rr,Or,_r,Br,Kr,Hr]}),zr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zr,imports:[J,E,Qn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zr,decorators:[{type:d,args:[{declarations:[Mr,Er,Rr,Or,_r,Br,Kr,Hr],imports:[J,E,Qn],exports:[Mr,Er,Rr,Or,_r,Br,Kr,Hr]}]}]});class Ur extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.entityType=C}configForm(){return this.ruleChainInputConfigForm}onConfigurationSet(e){this.ruleChainInputConfigForm=this.fb.group({forwardMsgToDefaultRuleChain:[!!e&&e?.forwardMsgToDefaultRuleChain,[]],ruleChainId:[e?e.ruleChainId:null,[_.required]]})}}e("RuleChainInputComponent",Ur),Ur.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ur,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Ur.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ur,selector:"tb-flow-node-rule-chain-input-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="ruleChainInputConfigForm" fxLayout="column">\n <div class="tb-form-panel no-padding no-border">\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.forward-msg-default-rule-chain-tooltip\' | translate }}"\n class="tb-form-row no-border">\n <mat-slide-toggle class="mat-slide" formControlName="forwardMsgToDefaultRuleChain">\n {{ \'tb.rulenode.forward-msg-default-rule-chain\' | translate }}\n </mat-slide-toggle>\n </div>\n <tb-entity-autocomplete required\n [excludeEntityIds]="[ruleChainId]"\n [entityType]="entityType.RULE_CHAIN"\n [entitySubtype]="ruleChainType"\n formControlName="ruleChainId">\n </tb-entity-autocomplete>\n </div>\n</section>\n',dependencies:[{kind:"component",type:st.EntityAutocompleteComponent,selector:"tb-entity-autocomplete",inputs:["entityType","entitySubtype","excludeEntityIds","labelText","requiredText","useFullEntityId","appearance","required","disabled"],outputs:["entityChanged"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ur,decorators:[{type:n,args:[{selector:"tb-flow-node-rule-chain-input-config",template:'<section [formGroup]="ruleChainInputConfigForm" fxLayout="column">\n <div class="tb-form-panel no-padding no-border">\n <div tb-hint-tooltip-icon="{{ \'tb.rulenode.forward-msg-default-rule-chain-tooltip\' | translate }}"\n class="tb-form-row no-border">\n <mat-slide-toggle class="mat-slide" formControlName="forwardMsgToDefaultRuleChain">\n {{ \'tb.rulenode.forward-msg-default-rule-chain\' | translate }}\n </mat-slide-toggle>\n </div>\n <tb-entity-autocomplete required\n [excludeEntityIds]="[ruleChainId]"\n [entityType]="entityType.RULE_CHAIN"\n [entitySubtype]="ruleChainType"\n formControlName="ruleChainId">\n </tb-entity-autocomplete>\n </div>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class jr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.ruleChainOutputConfigForm}onConfigurationSet(e){this.ruleChainOutputConfigForm=this.fb.group({})}}e("RuleChainOutputComponent",jr),jr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jr,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),jr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:jr,selector:"tb-flow-node-rule-chain-output-config",usesInheritance:!0,ngImport:t,template:'<section [formGroup]="ruleChainOutputConfigForm" fxLayout="column">\n <div innerHTML="{{ \'tb.rulenode.output-node-name-hint\' | translate }}"></div>\n</section>\n',dependencies:[{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jr,decorators:[{type:n,args:[{selector:"tb-flow-node-rule-chain-output-config",template:'<section [formGroup]="ruleChainOutputConfigForm" fxLayout="column">\n <div innerHTML="{{ \'tb.rulenode.output-node-name-hint\' | translate }}"></div>\n</section>\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class $r{}e("RuleNodeCoreConfigFlowModule",$r),$r.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$r,deps:[],target:t.ɵɵFactoryTarget.NgModule}),$r.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:$r,declarations:[Ur,jr],imports:[J,E,Qn],exports:[Ur,jr]}),$r.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$r,imports:[J,E,Qn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$r,decorators:[{type:d,args:[{declarations:[Ur,jr],imports:[J,E,Qn],exports:[Ur,jr]}]}]});class Jr{constructor(e){!function(e){e.setTranslation("en_US",{tb:{rulenode:{id:"Id","additional-info":"Additional Info","advanced-settings":"Advanced settings","create-entity-if-not-exists":"Create new entity if it doesn't exist","create-entity-if-not-exists-hint":"If enabled, a new entity with specified parameters will be created unless it already exists. Existing entities will be used as is for relation.","select-device-connectivity-event":"Select device connectivity event","entity-name-pattern":"Name pattern","device-name-pattern":"Device name","asset-name-pattern":"Asset name","entity-view-name-pattern":"Entity view name","customer-title-pattern":"Customer title","dashboard-name-pattern":"Dashboard title","user-name-pattern":"User email","edge-name-pattern":"Edge name","entity-name-pattern-required":"Name pattern is required","entity-name-pattern-hint":"Name pattern field support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","copy-message-type":"Copy message type","entity-type-pattern":"Type pattern","entity-type-pattern-required":"Type pattern is required","message-type-value":"Message type value","message-type-value-required":"Message type value is required","message-type-value-max-length":"Message type value should be less than 256","output-message-type":"Output message type","entity-cache-expiration":"Entities cache expiration time (sec)","entity-cache-expiration-hint":"Specifies maximum time interval allowed to store found entity records. 0 value means that records will never expire.","entity-cache-expiration-required":"Entities cache expiration time is required.","entity-cache-expiration-range":"Entities cache expiration time should be greater than or equal to 0.","customer-name-pattern":"Customer title","customer-name-pattern-required":"Customer title is required","customer-name-pattern-hint":"Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","create-customer-if-not-exists":"Create new customer if it doesn't exist","unassign-from-customer":"Unassign from specific customer if originator is dashboard","unassign-from-customer-tooltip":"Only dashboards can be assigned to multiple customers at once. \nIf the message originator is a dashboard, you need to explicitly specify the customer's title to unassign from.","customer-cache-expiration":"Customers cache expiration time (sec)","customer-cache-expiration-hint":"Specifies maximum time interval allowed to store found customer records. 0 value means that records will never expire.","customer-cache-expiration-required":"Customers cache expiration time is required.","customer-cache-expiration-range":"Customers cache expiration time should be greater than or equal to 0.","interval-start":"Interval start","interval-end":"Interval end","time-unit":"Time unit","fetch-mode":"Fetch mode","order-by-timestamp":"Order by timestamp",limit:"Limit","limit-hint":"Min limit value is 2, max - 1000. If you want to fetch a single entry, select fetch mode 'First' or 'Last'.","limit-required":"Limit is required.","limit-range":"Limit should be in a range from 2 to 1000.","time-unit-milliseconds":"Milliseconds","time-unit-seconds":"Seconds","time-unit-minutes":"Minutes","time-unit-hours":"Hours","time-unit-days":"Days","time-value-range":"Allowing range from 1 to 2147483647.","start-interval-value-required":"Interval start is required.","end-interval-value-required":"Interval end is required.",filter:"Filter",switch:"Switch","math-templatization-tooltip":"This field support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","add-message-type":"Add message type","select-message-types-required":"At least one message type should be selected.","select-message-types":"Select message types","no-message-types-found":"No message types found","no-message-type-matching":"'{{messageType}}' not found.","create-new-message-type":"Create a new one.","message-types-required":"Message types are required.","client-attributes":"Client attributes","shared-attributes":"Shared attributes","server-attributes":"Server attributes","attributes-keys":"Attributes keys","attributes-keys-required":"Attributes keys are required","attributes-scope":"Attributes scope","attributes-scope-value":"Attributes scope value","attributes-scope-value-copy":"Copy attributes scope value","attributes-scope-hint":"Use the 'scope' metadata key to dynamically set the attribute scope per message. If provided, this overrides the scope set in the configuration.","notify-device":"Force notification to the device","send-attributes-updated-notification":"Send attributes updated notification","send-attributes-updated-notification-hint":"Send notification about updated attributes as a separate message to the rule engine queue.","send-attributes-deleted-notification":"Send attributes deleted notification","send-attributes-deleted-notification-hint":"Send notification about deleted attributes as a separate message to the rule engine queue.","update-attributes-only-on-value-change":"Save attributes only if the value changes","update-attributes-only-on-value-change-hint":"Updates the attributes on every incoming message disregarding if their value has changed. Increases API usage and reduces performance.","update-attributes-only-on-value-change-hint-enabled":"Updates the attributes only if their value has changed. If the value is not changed, no update to the attribute timestamp nor attribute change notification will be sent.","fetch-credentials-to-metadata":"Fetch credentials to metadata","notify-device-on-update-hint":"If enabled, force notification to the device about shared attributes update. If disabled, the notification behavior is controlled by the 'notifyDevice' parameter from the incoming message metadata. To turn off the notification, the message metadata must contain the 'notifyDevice' parameter set to 'false'. Any other case will trigger the notification to the device.","notify-device-on-delete-hint":"If enabled, force notification to the device about shared attributes removal. If disabled, the notification behavior is controlled by the 'notifyDevice' parameter from the incoming message metadata. To turn on the notification, the message metadata must contain the 'notifyDevice' parameter set to 'true'. In any other case, the notification will not be triggered to the device.","latest-timeseries":"Latest time series data keys","timeseries-keys":"Time series keys","timeseries-keys-required":"At least one time series key should be selected.","add-timeseries-key":"Add time series key","add-message-field":"Add message field","relation-search-parameters":"Relation search parameters","relation-parameters":"Relation parameters","add-metadata-field":"Add metadata field","data-keys":"Message field names","copy-from":"Copy from","data-to-metadata":"Data to metadata","metadata-to-data":"Metadata to data","use-regular-expression-hint":"Use regular expression to copy keys by pattern.\n\nTips & tricks:\nPress 'Enter' to complete field name input.\nPress 'Backspace' to delete field name. Multiple field names supported.",interval:"Interval","interval-required":"Interval is required","interval-hint":"Deduplication interval in seconds.","interval-min-error":"Min allowed value is 1","max-pending-msgs":"Max pending messages","max-pending-msgs-hint":"Maximum number of messages that are stored in memory for each unique deduplication id.","max-pending-msgs-required":"Max pending messages is required","max-pending-msgs-max-error":"Max allowed value is 1000","max-pending-msgs-min-error":"Min allowed value is 1","max-retries":"Max retries","max-retries-required":"Max retries is required","max-retries-hint":"Maximum number of retries to push the deduplicated messages into the queue. 10 seconds delay is used between retries","max-retries-max-error":"Max allowed value is 100","max-retries-min-error":"Min allowed value is 0",strategy:"Strategy","strategy-required":"Strategy is required","strategy-all-hint":"Return all messages that arrived during deduplication period as a single JSON array message. Where each element represents object with msg and metadata inner properties.","strategy-first-hint":"Return first message that arrived during deduplication period.","strategy-last-hint":"Return last message that arrived during deduplication period.",first:"First",last:"Last",all:"All","output-msg-type-hint":"The message type of the deduplication result.","queue-name-hint":"The queue name where the deduplication result will be published.",keys:"Keys","keys-required":"Keys are required","rename-keys-in":"Rename keys in",data:"Data",message:"Message",metadata:"Metadata","current-key-name":"Current key name","key-name-required":"Key name is required","new-key-name":"New key name","new-key-name-required":"New key name is required","metadata-keys":"Metadata field names","json-path-expression":"JSON path expression","json-path-expression-required":"JSON path expression is required","json-path-expression-hint":"JSONPath specifies a path to an element or a set of elements in a JSON structure. '$' represents the root object or array.","relations-query":"Relations query","device-relations-query":"Device relations query","max-relation-level":"Max relation level","max-relation-level-error":"Value should be greater than 0 or unspecified.","relation-type":"Relation type","relation-type-pattern":"Relation type pattern","relation-type-pattern-required":"Relation type pattern is required","relation-types-list":"Relation types to propagate","relation-types-list-hint":"If Propagate relation types are not selected, alarms will be propagated without filtering by relation type.","unlimited-level":"Unlimited level","latest-telemetry":"Latest telemetry","add-telemetry-key":"Add telemetry key","delete-from":"Delete from","use-regular-expression-delete-hint":"Use regular expression to delete keys by pattern.\n\nTips & tricks:\nPress 'Enter' to complete field name input.\nPress 'Backspace' to delete field name.\nMultiple field names supported.","fetch-into":"Fetch into","attr-mapping":"Attributes mapping:","source-attribute":"Source attribute key","source-attribute-required":"Source attribute key is required.","source-telemetry":"Source telemetry key","source-telemetry-required":"Source telemetry key is required.","target-key":"Target key","target-key-required":"Target key is required.","attr-mapping-required":"At least one mapping entry should be specified.","fields-mapping":"Fields mapping","relations-query-config-direction-suffix":"originator","profile-name":"Profile name","fetch-circle-parameter-info-from-metadata-hint":'Metadata field \'{{perimeterKeyName}}\' should be defined in next format: {"latitude":48.196, "longitude":24.6532, "radius":100.0, "radiusUnit":"METER"}',"fetch-poligon-parameter-info-from-metadata-hint":"Metadata field '{{perimeterKeyName}}' should be defined in next format: [[48.19736,24.65235],[48.19800,24.65060],...,[48.19849,24.65420]]","short-templatization-tooltip":"Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","fields-mapping-required":"At least one field mapping should be specified.","at-least-one-field-required":"At least one input field must have a value(s) provided.","originator-fields-sv-map-hint":"Target key fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","sv-map-hint":"Only target key fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","source-field":"Source field","source-field-required":"Source field is required.","originator-source":"Originator source","new-originator":"New originator","originator-customer":"Customer","originator-tenant":"Tenant","originator-related":"Related entity","originator-alarm-originator":"Alarm Originator","originator-entity":"Entity by name pattern","clone-message":"Clone message",transform:"Transform","default-ttl":"Default TTL in seconds","default-ttl-required":"Default TTL is required.","default-ttl-hint":"Rule node will fetch Time-to-Live (TTL) value from the message metadata. If no value is present, it defaults to the TTL specified in the configuration. If the value is set to 0, the TTL from the tenant profile configuration will be applied.","min-default-ttl-message":"Only 0 minimum TTL is allowed.","generation-parameters":"Generation parameters","message-count":"Generated messages limit (0 - unlimited)","message-count-required":"Generated messages limit is required.","min-message-count-message":"Only 0 minimum message count is allowed.","period-seconds":"Generation frequency in seconds","period-seconds-required":"Period is required.","script-lang-tbel":"TBEL","script-lang-js":"JS","use-metadata-period-in-seconds-patterns":"Use period in seconds pattern","use-metadata-period-in-seconds-patterns-hint":"If selected, rule node use period in seconds interval pattern from message metadata or data assuming that intervals are in the seconds.","period-in-seconds-pattern":"Period in seconds pattern","period-in-seconds-pattern-required":"Period in seconds pattern is required","min-period-seconds-message":"Only 1 second minimum period is allowed.",originator:"Originator","message-body":"Message body","message-metadata":"Message metadata",generate:"Generate","current-rule-node":"Current Rule Node","generator-function":"Generator function","test-generator-function":"Test generator function",generator:"Generator","test-filter-function":"Test filter function","test-switch-function":"Test switch function","test-transformer-function":"Test transformer function",transformer:"Transformer","alarm-create-condition":"Alarm create condition","test-condition-function":"Test condition function","alarm-clear-condition":"Alarm clear condition","alarm-details-builder":"Alarm details builder","test-details-function":"Test details function","alarm-type":"Alarm type","select-entity-types":"Select entity types","alarm-type-required":"Alarm type is required.","alarm-severity":"Alarm severity","alarm-severity-required":"Alarm severity is required","alarm-severity-pattern":"Alarm severity pattern","alarm-status-filter":"Alarm status filter","alarm-status-list-empty":"Alarm status list is empty","no-alarm-status-matching":"No alarm status matching were found.",propagate:"Propagate alarm to related entities","propagate-to-owner":"Propagate alarm to entity owner (Customer or Tenant)","propagate-to-tenant":"Propagate alarm to Tenant",condition:"Condition",details:"Details","to-string":"To string","test-to-string-function":"Test to string function","from-template":"From","from-template-required":"From is required","message-to-metadata":"Message to metadata","metadata-to-message":"Metadata to message","from-message":"From message","from-metadata":"From metadata","to-template":"To","to-template-required":"To Template is required","mail-address-list-template-hint":'Comma separated address list, use <code><span style="color: #000;">$&#123;</span>metadataKey<span style="color: #000;">&#125;</span></code> for value from metadata, <code><span style="color: #000;">$[</span>messageKey<span style="color: #000;">]</span></code> for value from message body',"cc-template":"Cc","bcc-template":"Bcc","subject-template":"Subject","subject-template-required":"Subject Template is required","body-template":"Body","body-template-required":"Body Template is required","dynamic-mail-body-type":"Dynamic mail body type","mail-body-type":"Mail body type","body-type-template":"Body type template","reply-routing-configuration":"Reply Routing Configuration","rpc-reply-routing-configuration-hint":"These configuration parameters specify the metadata key names used to identify the service, session, and request for sending a reply back.","reply-routing-configuration-hint":"These configuration parameters specify the metadata key names used to identify the service and request for sending a reply back.","request-id-metadata-attribute":"Request Id","service-id-metadata-attribute":"Service Id","session-id-metadata-attribute":"Session Id","timeout-sec":"Timeout in seconds","timeout-required":"Timeout is required","min-timeout-message":"Only 0 minimum timeout value is allowed.","endpoint-url-pattern":"Endpoint URL pattern","endpoint-url-pattern-required":"Endpoint URL pattern is required","request-method":"Request method","use-simple-client-http-factory":"Use simple client HTTP factory","ignore-request-body":"Without request body","parse-to-plain-text":"Parse to plain text","parse-to-plain-text-hint":'If selected, request body message payload will be transformed from JSON string to plain text, e.g. msg = "Hello,\\t\\"world\\"" will be parsed to Hello, "world"',"read-timeout":"Read timeout in millis","read-timeout-hint":"The value of 0 means an infinite timeout","max-parallel-requests-count":"Max number of parallel requests","max-parallel-requests-count-hint":"The value of 0 specifies no limit in parallel processing","max-response-size":"Max response size (in KB)","max-response-size-hint":"The maximum amount of memory allocated for buffering data when decoding or encoding HTTP messages, such as JSON or XML payloads",headers:"Headers","headers-hint":'Use <code><span style="color: #000;">$&#123;</span>metadataKey<span style="color: #000;">&#125;</span></code> for value from metadata, <code><span style="color: #000;">$[</span>messageKey<span style="color: #000;">]</span></code> for value from message body in header/value fields',header:"Header","header-required":"Header is required",value:"Value","value-required":"Value is required","topic-pattern":"Topic pattern","key-pattern":"Key pattern","key-pattern-hint":"Optional. If a valid partition number is specified, it will be used when sending the record. If no partition is specified, the key will be used instead. If neither is specified, a partition will be assigned in a round-robin fashion.","topic-pattern-required":"Topic pattern is required",topic:"Topic","topic-required":"Topic is required","bootstrap-servers":"Bootstrap servers","bootstrap-servers-required":"Bootstrap servers value is required","other-properties":"Other properties",key:"Key","key-required":"Key is required",retries:"Automatically retry times if fails","min-retries-message":"Only 0 minimum retries is allowed.","batch-size-bytes":"Produces batch size in bytes","min-batch-size-bytes-message":"Only 0 minimum batch size is allowed.","linger-ms":"Time to buffer locally (ms)","min-linger-ms-message":"Only 0 ms minimum value is allowed.","buffer-memory-bytes":"Client buffer max size in bytes","min-buffer-memory-message":"Only 0 minimum buffer size is allowed.",acks:"Number of acknowledgments","key-serializer":"Key serializer","key-serializer-required":"Key serializer is required","value-serializer":"Value serializer","value-serializer-required":"Value serializer is required","topic-arn-pattern":"Topic ARN pattern","topic-arn-pattern-required":"Topic ARN pattern is required","aws-access-key-id":"AWS Access Key ID","aws-access-key-id-required":"AWS Access Key ID is required","aws-secret-access-key":"AWS Secret Access Key","aws-secret-access-key-required":"AWS Secret Access Key is required","aws-region":"AWS Region","aws-region-required":"AWS Region is required","exchange-name-pattern":"Exchange name pattern","routing-key-pattern":"Routing key pattern","message-properties":"Message properties",host:"Host","host-required":"Host is required",port:"Port","port-required":"Port is required","port-range":"Port should be in a range from 1 to 65535.","virtual-host":"Virtual host",username:"Username",password:"Password","automatic-recovery":"Automatic recovery","connection-timeout-ms":"Connection timeout (ms)","min-connection-timeout-ms-message":"Only 0 ms minimum value is allowed.","handshake-timeout-ms":"Handshake timeout (ms)","min-handshake-timeout-ms-message":"Only 0 ms minimum value is allowed.","client-properties":"Client properties","queue-url-pattern":"Queue URL pattern","queue-url-pattern-required":"Queue URL pattern is required","delay-seconds":"Delay (seconds)","min-delay-seconds-message":"Only 0 seconds minimum value is allowed.","max-delay-seconds-message":"Only 900 seconds maximum value is allowed.",name:"Name","name-required":"Name is required","queue-type":"Queue type","sqs-queue-standard":"Standard","sqs-queue-fifo":"FIFO","gcp-project-id":"GCP project ID","gcp-project-id-required":"GCP project ID is required","gcp-service-account-key":"GCP service account key file","gcp-service-account-key-required":"GCP service account key file is required","pubsub-topic-name":"Topic name","pubsub-topic-name-required":"Topic name is required","message-attributes":"Message attributes","message-attributes-hint":'Use <code><span style="color: #000;">$&#123;</span>metadataKey<span style="color: #000000;">&#125;</span></code> for value from metadata, <code><span style="color: #000;">$[</span>messageKey<span style="color: #000;">]</span></code> for value from message body in name/value fields',"connect-timeout":"Connection timeout (sec)","connect-timeout-required":"Connection timeout is required.","connect-timeout-range":"Connection timeout should be in a range from 1 to 200.","client-id":"Client ID","client-id-hint":'Optional. Leave empty for auto-generated Client ID. Be careful when specifying the Client ID. Majority of the MQTT brokers will not allow multiple connections with the same Client ID. To connect to such brokers, your mqtt Client ID must be unique. When platform is running in a micro-services mode, the copy of rule node is launched in each micro-service. This will automatically lead to multiple mqtt clients with the same ID and may cause failures of the rule node. To avoid such failures enable "Add Service ID as suffix to Client ID" option below.',"append-client-id-suffix":"Add Service ID as suffix to Client ID","client-id-suffix-hint":'Optional. Applied when "Client ID" specified explicitly. If selected then Service ID will be added to Client ID as a suffix. Helps to avoid failures when platform is running in a micro-services mode.',"device-id":"Device ID","device-id-required":"Device ID is required.","clean-session":"Clean session","enable-ssl":"Enable SSL",credentials:"Credentials","credentials-type":"Credentials type","credentials-type-required":"Credentials type is required.","credentials-anonymous":"Anonymous","credentials-basic":"Basic","credentials-pem":"PEM","credentials-pem-hint":"At least Server CA certificate file or a pair of Client certificate and Client private key files are required","credentials-sas":"Shared Access Signature","sas-key":"SAS Key","sas-key-required":"SAS Key is required.",hostname:"Hostname","hostname-required":"Hostname is required.","azure-ca-cert":"CA certificate file","username-required":"Username is required.","password-required":"Password is required.","ca-cert":"Server CA certificate file","private-key":"Client private key file",cert:"Client certificate file","no-file":"No file selected.","drop-file":"Drop a file or click to select a file to upload.","private-key-password":"Private key password","use-system-smtp-settings":"Use system SMTP settings","use-metadata-dynamic-interval":"Use dynamic interval","metadata-dynamic-interval-hint":"Interval start and end input fields support templatization. Note that the substituted template value should be set in milliseconds. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","use-metadata-interval-patterns-hint":"If selected, rule node use start and end interval patterns from message metadata or data assuming that intervals are in the milliseconds.","use-message-alarm-data":"Use message alarm data","overwrite-alarm-details":"Overwrite alarm details","use-alarm-severity-pattern":"Use alarm severity pattern","check-all-keys":"Check that all specified fields are present","check-all-keys-hint":"If selected, checks that all specified keys are present in the message data and metadata.","check-relation-to-specific-entity":"Check relation to specific entity","check-relation-to-specific-entity-tooltip":"If enabled, checks the presence of relation with a specific entity otherwise, checks the presence of relation with any entity. In both cases, relation lookup is based on configured direction and type.","check-relation-hint":"Checks existence of relation to specific entity or to any entity based on direction and relation type.","delete-relation-with-specific-entity":"Delete relation with specific entity","delete-relation-with-specific-entity-hint":"If enabled, will delete the relation with just one specific entity. Otherwise, the relation will be removed with all matching entities.","delete-relation-hint":"Deletes relation from the originator of the incoming message to the specified entity or list of entities based on direction and type.","remove-current-relations":"Remove current relations","remove-current-relations-hint":"Removes current relations from the originator of the incoming message based on direction and type.","change-originator-to-related-entity":"Change originator to related entity","change-originator-to-related-entity-hint":"Used to process submitted message as a message from another entity.","start-interval":"Interval start","end-interval":"Interval end","start-interval-required":"Interval start is required.","end-interval-required":"Interval end is required.","smtp-protocol":"Protocol","smtp-host":"SMTP host","smtp-host-required":"SMTP host is required.","smtp-port":"SMTP port","smtp-port-required":"You must supply a smtp port.","smtp-port-range":"SMTP port should be in a range from 1 to 65535.","timeout-msec":"Timeout ms","min-timeout-msec-message":"Only 0 ms minimum value is allowed.","enter-username":"Enter username","enter-password":"Enter password","enable-tls":"Enable TLS","tls-version":"TLS version","enable-proxy":"Enable proxy","use-system-proxy-properties":"Use system proxy properties","proxy-host":"Proxy host","proxy-host-required":"Proxy host is required.","proxy-port":"Proxy port","proxy-port-required":"Proxy port is required.","proxy-port-range":"Proxy port should be in a range from 1 to 65535.","proxy-user":"Proxy user","proxy-password":"Proxy password","proxy-scheme":"Proxy scheme","numbers-to-template":"Phone Numbers To Template","numbers-to-template-required":"Phone Numbers To Template is required","numbers-to-template-hint":'Comma separated Phone Numbers, use <code><span style="color: #000;">$&#123;</span>metadataKey<span style="color: #000;">&#125;</span></code> for value from metadata, <code><span style="color: #000;">$[</span>messageKey<span style="color: #000;">]</span></code> for value from message body',"sms-message-template":"SMS message Template","sms-message-template-required":"SMS message Template is required","use-system-sms-settings":"Use system SMS provider settings","min-period-0-seconds-message":"Only 0 second minimum period is allowed.","max-pending-messages":"Maximum pending messages","max-pending-messages-required":"Maximum pending messages is required.","max-pending-messages-range":"Maximum pending messages should be in a range from 1 to 100000.","originator-types-filter":"Originator types filter","interval-seconds":"Interval in seconds","interval-seconds-required":"Interval is required.","min-interval-seconds-message":"Only 1 second minimum interval is allowed.","output-timeseries-key-prefix":"Output time series key prefix","output-timeseries-key-prefix-required":"Output time series key prefix required.","separator-hint":'Press "Enter" to complete field input.',"select-details":"Select details","entity-details-id":"Id","entity-details-title":"Title","entity-details-country":"Country","entity-details-state":"State","entity-details-city":"City","entity-details-zip":"Zip","entity-details-address":"Address","entity-details-address2":"Address2","entity-details-additional_info":"Additional Info","entity-details-phone":"Phone","entity-details-email":"Email","email-sender":"Email sender","fields-to-check":"Fields to check","add-detail":"Add detail","check-all-keys-tooltip":"If enabled, checks the presence of all fields listed in the message and metadata field names within the incoming message and its metadata.","fields-to-check-hint":'Press "Enter" to complete field name input. Multiple field names supported.',"entity-details-list-empty":"At least one detail should be selected.","alarm-status":"Alarm status","alarm-required":"At least one alarm status should be selected.","no-entity-details-matching":"No entity details matching were found.","custom-table-name":"Custom table name","custom-table-name-required":"Table Name is required","custom-table-hint":"Enter the table name without prefix 'cs_tb_'.","message-field":"Message field","message-field-required":"Message field is required.","table-col":"Table column","table-col-required":"Table column is required.","latitude-field-name":"Latitude field name","longitude-field-name":"Longitude field name","latitude-field-name-required":"Latitude field name is required.","longitude-field-name-required":"Longitude field name is required.","fetch-perimeter-info-from-metadata":"Fetch perimeter information from metadata","fetch-perimeter-info-from-metadata-tooltip":"If perimeter type is set to 'Polygon' the value of metadata field '{{perimeterKeyName}}' will be set as perimeter definition without additional parsing of the value. Otherwise, if perimeter type is set to 'Circle' the value of '{{perimeterKeyName}}' metadata field will be parsed to extract 'latitude', 'longitude', 'radius', 'radiusUnit' fields that uses for circle perimeter definition.","perimeter-key-name":"Perimeter key name","perimeter-key-name-hint":"Metadata field name that includes perimeter information.","perimeter-key-name-required":"Perimeter key name is required.","perimeter-circle":"Circle","perimeter-polygon":"Polygon","perimeter-type":"Perimeter type","circle-center-latitude":"Center latitude","circle-center-latitude-required":"Center latitude is required.","circle-center-longitude":"Center longitude","circle-center-longitude-required":"Center longitude is required.","range-unit-meter":"Meter","range-unit-kilometer":"Kilometer","range-unit-foot":"Foot","range-unit-mile":"Mile","range-unit-nautical-mile":"Nautical mile","range-units":"Range units","range-units-required":"Range units is required.",range:"Range","range-required":"Range is required.","polygon-definition":"Polygon definition","polygon-definition-required":"Polygon definition is required.","polygon-definition-hint":"Use the following format for manual definition of polygon: [[lat1,lon1],[lat2,lon2], ... ,[latN,lonN]].","min-inside-duration":"Minimal inside duration","min-inside-duration-value-required":"Minimal inside duration is required","min-inside-duration-time-unit":"Minimal inside duration time unit","min-outside-duration":"Minimal outside duration","min-outside-duration-value-required":"Minimal outside duration is required","min-outside-duration-time-unit":"Minimal outside duration time unit","tell-failure-if-absent":"Tell Failure","tell-failure-if-absent-hint":'If at least one selected key doesn\'t exist the outbound message will report "Failure".',"get-latest-value-with-ts":"Fetch timestamp for the latest telemetry values","get-latest-value-with-ts-hint":'If selected, the latest telemetry values will also include timestamp, e.g: "temp": "&#123;"ts":1574329385897, "value":42&#125;"',"ignore-null-strings":"Ignore null strings","ignore-null-strings-hint":"If selected rule node will ignore entity fields with empty value.","add-metadata-key-values-as-kafka-headers":"Add Message metadata key-value pairs to Kafka record headers","add-metadata-key-values-as-kafka-headers-hint":"If selected, key-value pairs from message metadata will be added to the outgoing records headers as byte arrays with predefined charset encoding.","charset-encoding":"Charset encoding","charset-encoding-required":"Charset encoding is required.","charset-us-ascii":"US-ASCII","charset-iso-8859-1":"ISO-8859-1","charset-utf-8":"UTF-8","charset-utf-16be":"UTF-16BE","charset-utf-16le":"UTF-16LE","charset-utf-16":"UTF-16","select-queue-hint":"The queue name can be selected from a drop-down list or add a custom name.","device-profile-node-hint":"Useful if you have duration or repeating conditions to ensure continuity of alarm state evaluation.","persist-alarm-rules":"Persist state of alarm rules","persist-alarm-rules-hint":"If enabled, the rule node will store the state of processing to the database.","fetch-alarm-rules":"Fetch state of alarm rules","fetch-alarm-rules-hint":"If enabled, the rule node will restore the state of processing on initialization and ensure that alarms are raised even after server restarts. Otherwise, the state will be restored when the first message from the device arrives.","input-value-key":"Input value key","input-value-key-required":"Input value key is required.","output-value-key":"Output value key","output-value-key-required":"Output value key is required.","number-of-digits-after-floating-point":"Number of digits after floating point","number-of-digits-after-floating-point-range":"Number of digits after floating point should be in a range from 0 to 15.","failure-if-delta-negative":"Tell Failure if delta is negative","failure-if-delta-negative-tooltip":"Rule node forces failure of message processing if delta value is negative.","use-caching":"Use caching","use-caching-tooltip":'Rule node will cache the value of "{{inputValueKey}}" that arrives from the incoming message to improve performance. Note that the cache will not be updated if you modify the "{{inputValueKey}}" value elsewhere.',"add-time-difference-between-readings":'Add the time difference between "{{inputValueKey}}" readings',"add-time-difference-between-readings-tooltip":'If enabled, the rule node will add the "{{periodValueKey}}" to the outbound message.',"period-value-key":"Period value key","period-value-key-required":"Period value key is required.","general-pattern-hint":"Use ${metadataKey} for value from metadata, $[messageKey] for value from message body.","alarm-severity-pattern-hint":'Use <code><span style="color: #000;">$&#123;</span>metadataKey<span style="color: #000;">&#125;</span></code> for value from metadata, <code><span style="color: #000;">$[</span>messageKey<span style="color: #000;">]</span></code> for value from message body. Alarm severity should be system (CRITICAL, MAJOR etc.)',"output-node-name-hint":"The <b>rule node name</b> corresponds to the <b>relation type</b> of the output message, and it is used to forward messages to other rule nodes in the caller rule chain.","skip-latest-persistence":"Skip latest persistence","skip-latest-persistence-hint":"Rule node will not update values for incoming keys for the latest time series data. Useful for highly loaded use-cases to decrease the pressure on the DB.","use-server-ts":"Use server ts","use-server-ts-hint":"Rule node will use the timestamp of message processing instead of the timestamp from the message. Useful for all sorts of sequential processing if you merge messages from multiple sources (devices, assets, etc).","kv-map-pattern-hint":"All input fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","kv-map-single-pattern-hint":"Input field support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","shared-scope":"Shared scope","server-scope":"Server scope","client-scope":"Client scope","attribute-type":"Attribute","constant-type":"Constant","time-series-type":"Time series","message-body-type":"Message","message-metadata-type":"Metadata","argument-tile":"Arguments","no-arguments-prompt":"No arguments configured","result-title":"Result","functions-field-input":"Functions","no-option-found":"No option found","argument-source-field-input":"Source","argument-source-field-input-required":"Argument source is required.","argument-key-field-input":"Key","argument-key-field-input-required":"Argument key is required.","constant-value-field-input":"Constant value","constant-value-field-input-required":"Constant value is required.","attribute-scope-field-input":"Attribute scope","attribute-scope-field-input-required":"Attribute scope os required.","default-value-field-input":"Default value","type-field-input":"Type","type-field-input-required":"Type is required.","key-field-input":"Key","add-entity-type":"Add entity type","add-device-profile":"Add device profile","key-field-input-required":"Key is required.","number-floating-point-field-input":"Number of digits after floating point","number-floating-point-field-input-hint":"Use <i>0</i> to convert result to integer","add-to-message-field-input":"Add to message","add-to-metadata-field-input":"Add to metadata","custom-expression-field-input":"Mathematical Expression","custom-expression-field-input-required":"Mathematical expression is required","custom-expression-field-input-hint":"Specify a mathematical expression to evaluate. Default expression demonstrates how to transform Fahrenheit to Celsius","retained-message":"Retained","attributes-mapping":"Attributes mapping","latest-telemetry-mapping":"Latest telemetry mapping","add-mapped-attribute-to":"Add mapped attributes to","add-mapped-latest-telemetry-to":"Add mapped latest telemetry to","add-mapped-fields-to":"Add mapped fields to","add-selected-details-to":"Add selected details to","clear-selected-types":"Clear selected types","clear-selected-details":"Clear selected details","clear-selected-fields":"Clear selected fields","clear-selected-keys":"Clear selected keys","geofence-configuration":"Geofence configuration","coordinate-field-names":"Coordinate field names","coordinate-field-hint":"Rule node tries to retrieve the specified fields from the message. If they are not present, it will look them up in the metadata.","presence-monitoring-strategy":"Presence monitoring strategy","presence-monitoring-strategy-on-first-message":"On first message","presence-monitoring-strategy-on-each-message":"On each message","presence-monitoring-strategy-on-first-message-hint":"Reports presence status 'Inside' or 'Outside' on the first message after the configured minimal duration has passed since previous presence status 'Entered' or 'Left' update.","presence-monitoring-strategy-on-each-message-hint":"Reports presence status 'Inside' or 'Outside' on each message after presence status 'Entered' or 'Left' update.","fetch-credentials-to":"Fetch credentials to","add-originator-attributes-to":"Add originator attributes to","originator-attributes":"Originator attributes","fetch-latest-telemetry-with-timestamp":"Fetch latest telemetry with timestamp","fetch-latest-telemetry-with-timestamp-tooltip":'If selected, latest telemetry values will be added to the outbound metadata with timestamp, e.g: "{{latestTsKeyName}}": "{"ts":1574329385897, "value":42}"',"tell-failure":"Tell failure if any of the attributes are missing","tell-failure-tooltip":'If at least one selected key doesn\'t exist the outbound message will report "Failure".',"created-time":"Created time","chip-help":"Press 'Enter' to complete {{inputName}} input. \nPress 'Backspace' to delete {{inputName}}. \nMultiple values supported.",detail:"detail","field-name":"field name","device-profile":"device profile","entity-type":"entity type","message-type":"message type","timeseries-key":"time series key",type:"Type","first-name":"First name","last-name":"Last name",label:"Label","originator-fields-mapping":"Originator fields mapping","add-mapped-originator-fields-to":"Add mapped originator fields to",fields:"Fields","skip-empty-fields":"Skip empty fields","skip-empty-fields-tooltip":"Fields with empty values will not be added to the output message/output metadata.","fetch-interval":"Fetch interval","fetch-strategy":"Fetch strategy","fetch-timeseries-from-to":"Fetch time series from {{startInterval}} {{startIntervalTimeUnit}} ago to {{endInterval}} {{endIntervalTimeUnit}} ago.","fetch-timeseries-from-to-invalid":'Fetch time series invalid ("Interval start" should be less than "Interval end").',"use-metadata-dynamic-interval-tooltip":"If selected, the rule node will use dynamic interval start and end based on the message and metadata patterns.","all-mode-hint":'If selected fetch mode "All" rule node will retrieve telemetry from the fetch interval with configurable query parameters.',"first-mode-hint":'If selected fetch mode "First" rule node will retrieve the closest telemetry to the fetch interval\'s start.',"last-mode-hint":'If selected fetch mode "Last" rule node will retrieve the closest telemetry to the fetch interval\'s end.',ascending:"Ascending",descending:"Descending",min:"Min",max:"Max",average:"Average",sum:"Sum",count:"Count",none:"None","last-level-relation-tooltip":"If selected, the rule node will search related entities only on the level set in the max relation level.","last-level-device-relation-tooltip":"If selected, the rule node will search related devices only on the level set in the max relation level.","data-to-fetch":"Data to fetch","mapping-of-customers":"Mapping of customer's","map-fields-required":"All mapping fields are required.",attributes:"Attributes","related-device-attributes":"Related device attributes","add-selected-attributes-to":"Add selected attributes to","device-profiles":"Device profiles","mapping-of-tenant":"Mapping of tenant's","add-attribute-key":"Add attribute key","message-template":"Message template","message-template-required":"Message template is required","use-system-slack-settings":"Use system slack settings","slack-api-token":"Slack API token","slack-api-token-required":"Slack API token is required","keys-mapping":"keys mapping","add-key":"Add key",recipients:"Recipients","message-subject-and-content":"Message subject and content","template-rules-hint":"Both input fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the message metadata.","originator-customer-desc":"Use customer of incoming message originator as new originator.","originator-tenant-desc":"Use current tenant as new originator.","originator-related-entity-desc":"Use related entity as new originator. Lookup based on configured relation type and direction.","originator-alarm-originator-desc":"Use alarm originator as new originator. Only if incoming message originator is alarm entity.","originator-entity-by-name-pattern-desc":"Use entity fetched from DB as new originator. Lookup based on entity type and specified name pattern.","email-from-template-hint":"Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","recipients-block-main-hint":"Comma-separated address list. All input fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","forward-msg-default-rule-chain":"Forward message to the originator's default rule chain","forward-msg-default-rule-chain-tooltip":"If enabled, message will be forwarded to the originator's default rule chain, or rule chain from configuration, if originator has no default rule chain defined in the entity profile.","exclude-zero-deltas":"Exclude zero deltas from outbound message","exclude-zero-deltas-hint":'If enabled, the "{{outputValueKey}}" output key will be added to the outbound message if its value is not zero.',"exclude-zero-deltas-time-difference-hint":'If enabled, the "{{outputValueKey}}" and "{{periodValueKey}}" output keys will be added to the outbound message only if the "{{outputValueKey}}" value is not zero.',"search-direction-from":"From originator to target entity","search-direction-to":"From target entity to originator","del-relation-direction-from":"From originator","del-relation-direction-to":"To originator","target-entity":"Target entity","function-configuration":"Function configuration","function-name":"Function name","function-name-required":"Function name is required.",qualifier:"Qualifier","qualifier-hint":'If the qualifier is not specified, the default qualifier "$LATEST" will be used.',"aws-credentials":"AWS Credentials","connection-timeout":"Connection timeout","connection-timeout-required":"Connection timeout is required.","connection-timeout-min":"Min connection timeout is 0.","connection-timeout-hint":"The amount of time to wait in seconds when initially establishing a connection before giving up and timing out. A value of 0 means infinity, and is not recommended.","request-timeout":"Request timeout","request-timeout-required":"Request timeout is required","request-timeout-min":"Min request timeout is 0","request-timeout-hint":"The amount of time to wait in seconds for the request to complete before giving up and timing out. A value of 0 means infinity, and is not recommended.","tell-failure-aws-lambda":"Tell Failure if AWS Lambda function execution raises exception","tell-failure-aws-lambda-hint":"Rule node forces failure of message processing if AWS Lambda function execution raises exception."},"key-val":{key:"Key",value:"Value","see-examples":"See examples.","remove-entry":"Remove entry","remove-mapping-entry":"Remove mapping entry","add-mapping-entry":"Add mapping","add-entry":"Add entry","copy-key-values-from":"Copy key-values from","delete-key-values":"Delete key-values","delete-key-values-from":"Delete key-values from","at-least-one-key-error":"At least one key should be selected.","unique-key-value-pair-error":"'{{keyText}}' must be different from the '{{valText}}'!"},"mail-body-type":{"plain-text":"Plain text",html:"HTML",dynamic:"Dynamic","use-body-type-template":"Use body type template","plain-text-description":"Simple, unformatted text with no special styling or formating.","html-text-description":"Allows you to use HTML tags for formatting, links and images in your mai body.","dynamic-text-description":"Allows to use Plain Text or HTML body type dynamically based on templatization feature.","after-template-evaluation-hint":"After template evaluation value should be true for HTML, and false for Plain text."}}},!0)}(e)}}e("RuleNodeCoreConfigModule",Jr),Jr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jr,deps:[{token:X.TranslateService}],target:t.ɵɵFactoryTarget.NgModule}),Jr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Jr,declarations:[ut],imports:[J,E],exports:[Yn,Ar,lr,Cr,zr,$r,ut]}),Jr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jr,imports:[J,E,Yn,Ar,lr,Cr,zr,$r]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jr,decorators:[{type:d,args:[{declarations:[ut],imports:[J,E],exports:[Yn,Ar,lr,Cr,zr,$r,ut]}]}],ctorParameters:function(){return[{type:X.TranslateService}]}})}}}));//# sourceMappingURL=rulenode-core-config.js.map diff --git a/ui-ngx/src/app/core/api/alias-controller.ts b/ui-ngx/src/app/core/api/alias-controller.ts index bf7399cf6d..83dd4e102f 100644 --- a/ui-ngx/src/app/core/api/alias-controller.ts +++ b/ui-ngx/src/app/core/api/alias-controller.ts @@ -68,10 +68,11 @@ export class AliasController implements IAliasController { private translate: TranslateService, private stateControllerHolder: StateControllerHolder, private origEntityAliases: EntityAliases, - private origFilters: Filters) { + private origFilters: Filters, + private origUserFilters?: Filters) { this.entityAliases = deepClone(this.origEntityAliases) || {}; this.filters = deepClone(this.origFilters) || {}; - this.userFilters = {}; + this.userFilters = deepClone(this.origUserFilters) || {}; } updateEntityAliases(newEntityAliases: EntityAliases) { @@ -166,6 +167,10 @@ export class AliasController implements IAliasController { return this.filters; } + getUserFilters(): Filters { + return this.userFilters; + } + getFilterInfo(filterId: string): FilterInfo { if (this.userFilters[filterId]) { return this.userFilters[filterId]; diff --git a/ui-ngx/src/app/core/api/widget-api.models.ts b/ui-ngx/src/app/core/api/widget-api.models.ts index 71bfa32ee6..bca6a05644 100644 --- a/ui-ngx/src/app/core/api/widget-api.models.ts +++ b/ui-ngx/src/app/core/api/widget-api.models.ts @@ -137,6 +137,7 @@ export interface IAliasController { resolveAlarmSource(alarmSource: Datasource): Observable<Datasource>; getEntityAliases(): EntityAliases; getFilters(): Filters; + getUserFilters(): Filters; getFilterInfo(filterId: string): FilterInfo; getKeyFilters(filterId: string): Array<KeyFilter>; updateCurrentAliasEntity(aliasId: string, currentEntity: EntityInfo): void; diff --git a/ui-ngx/src/app/core/http/user.service.ts b/ui-ngx/src/app/core/http/user.service.ts index 1d5ce28998..695bae3cc1 100644 --- a/ui-ngx/src/app/core/http/user.service.ts +++ b/ui-ngx/src/app/core/http/user.service.ts @@ -16,7 +16,7 @@ import { Injectable } from '@angular/core'; import { defaultHttpOptionsFromConfig, RequestConfig } from './http-utils'; -import { User, UserEmailInfo } from '@shared/models/user.model'; +import { ActivationLinkInfo, User, UserEmailInfo } from '@shared/models/user.model'; import { Observable } from 'rxjs'; import { HttpClient, HttpParams } from '@angular/common/http'; import { PageLink } from '@shared/models/page/page-link'; @@ -77,6 +77,10 @@ export class UserService { {...{responseType: 'text'}, ...defaultHttpOptionsFromConfig(config)}); } + public getActivationLinkInfo(userId: string, config?: RequestConfig): Observable<ActivationLinkInfo> { + return this.http.get<ActivationLinkInfo>(`/api/user/${userId}/activationLinkInfo`, defaultHttpOptionsFromConfig(config)); + } + public sendActivationEmail(email: string, config?: RequestConfig) { const encodeEmail = encodeURIComponent(email); return this.http.post(`/api/user/sendActivationMail?email=${encodeEmail}`, null, defaultHttpOptionsFromConfig(config)); diff --git a/ui-ngx/src/app/core/services/dashboard-utils.service.ts b/ui-ngx/src/app/core/services/dashboard-utils.service.ts index 5c2363789d..b31c603814 100644 --- a/ui-ngx/src/app/core/services/dashboard-utils.service.ts +++ b/ui-ngx/src/app/core/services/dashboard-utils.service.ts @@ -31,7 +31,7 @@ import { DashboardLayoutsInfo, DashboardState, DashboardStateLayouts, - GridSettings, + GridSettings, LayoutType, WidgetLayout } from '@shared/models/dashboard.models'; import { deepClone, isDefined, isDefinedAndNotNull, isNotEmptyStr, isString, isUndefined } from '@core/utils'; @@ -406,6 +406,7 @@ export class DashboardUtilsService { private createDefaultGridSettings(): GridSettings { return { + layoutType: LayoutType.default, backgroundColor: '#eeeeee', columns: 24, margin: 10, @@ -491,12 +492,15 @@ export class DashboardUtilsService { if (!layout.gridSettings) { layout.gridSettings = this.createDefaultGridSettings(); } - if (layout.gridSettings.margins && layout.gridSettings.margins.length === 2) { - layout.gridSettings.margin = layout.gridSettings.margins[0]; - delete layout.gridSettings.margins; + if ((layout.gridSettings as any).margins && (layout.gridSettings as any).margins.length === 2) { + layout.gridSettings.margin = (layout.gridSettings as any).margins[0]; + delete (layout.gridSettings as any).margins; } layout.gridSettings.outerMargin = isDefined(layout.gridSettings.outerMargin) ? layout.gridSettings.outerMargin : true; layout.gridSettings.margin = isDefined(layout.gridSettings.margin) ? layout.gridSettings.margin : 10; + if (!layout.gridSettings.layoutType) { + layout.gridSettings.layoutType = LayoutType.default; + } } public setLayouts(dashboard: Dashboard, targetState: string, newLayouts: DashboardStateLayouts) { diff --git a/ui-ngx/src/app/core/services/dynamic-component-factory.service.ts b/ui-ngx/src/app/core/services/dynamic-component-factory.service.ts index 8414e6ff0e..d18797a1be 100644 --- a/ui-ngx/src/app/core/services/dynamic-component-factory.service.ts +++ b/ui-ngx/src/app/core/services/dynamic-component-factory.service.ts @@ -22,7 +22,7 @@ import { NgModule, NgModuleRef, OnDestroy, - Type, + Type, ɵNG_COMP_DEF, ɵresetCompiledComponents } from '@angular/core'; import { from, Observable, of } from 'rxjs'; @@ -64,7 +64,6 @@ export class DynamicComponentFactoryService { template: string, modules?: Type<any>[], preserveWhitespaces?: boolean, - compileAttempt = 1, styles?: string[]): Observable<DynamicComponentData<T>> { return from(import('@angular/compiler')).pipe( mergeMap(() => { @@ -78,32 +77,26 @@ export class DynamicComponentFactoryService { declarations: [comp], imports: moduleImports })(class DynamicComponentInstanceModule extends DynamicComponentModule {}); + + const module = this.compiler.compileModuleSync(dynamicComponentInstanceModule); + let moduleRef: NgModuleRef<any>; try { - const module = this.compiler.compileModuleSync(dynamicComponentInstanceModule); - let moduleRef: NgModuleRef<any>; - try { - moduleRef = module.create(this.injector); - } catch (e) { - this.compiler.clearCacheFor(module.moduleType); - throw e; - } - this.dynamicComponentModulesMap.set(comp, { - moduleRef, - moduleType: module.moduleType - }); - return of( { - componentType: comp, - componentModuleRef: moduleRef - }); - } catch (error) { - if (compileAttempt === 1) { - ɵresetCompiledComponents(); - return this.createDynamicComponent(componentType, template, modules, preserveWhitespaces, ++compileAttempt, styles); - } else { - console.error(error); - throw error; - } + moduleRef = module.create(this.injector); + // eslint-disable-next-line + comp[ɵNG_COMP_DEF]; + } catch (e) { + this.compiler.clearCacheFor(module.moduleType); + ɵresetCompiledComponents(); + throw e; } + this.dynamicComponentModulesMap.set(comp, { + moduleRef, + moduleType: module.moduleType + }); + return of( { + componentType: comp, + componentModuleRef: moduleRef + }); }) ); } diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.html b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.html index 44785be367..6944f79545 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.html +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.html @@ -277,7 +277,7 @@ 'tb-dashboard-toolbar-animated': isToolbarOpenedAnimate, 'tb-dashboard-toolbar-closed': !toolbarOpened }"> <mat-drawer-container hasBackdrop="false" class="tb-absolute-fill tb-dashboard-drawer-container"> - <mat-drawer-content fxLayout="column" fxLayoutAlign="center start"> + <mat-drawer-content #dashboardContent fxLayout="column" fxLayoutAlign="center start"> <section *ngIf="!widgetEditMode" class="tb-dashboard-title" [ngStyle]="{'color': dashboard.configuration.settings.titleColor}"> <h3 [fxShow]="!isEdit && displayTitle()">{{ translatedDashboardTitle }}</h3> diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts index 84c5c752ca..1919bee9b9 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts @@ -222,6 +222,8 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC @ViewChild('dashboardContainer') dashboardContainer: ElementRef<HTMLElement>; + @ViewChild('dashboardContent', {read: ElementRef}) dashboardContent: ElementRef<HTMLElement>; + prevDashboard: Dashboard; iframeMode = this.utils.iframeMode; @@ -520,7 +522,8 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC this.translate, () => this.dashboardCtx.stateController, this.dashboardConfiguration.entityAliases, - this.dashboardConfiguration.filters); + this.dashboardConfiguration.filters, + this.parentDashboard?.aliasController.getUserFilters()); this.updateDashboardCss(); @@ -1166,8 +1169,6 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC this.filtersUpdated(); this.updateLayouts(); } - } else if (!this.widgetEditMode) { - this.dashboard.configuration.timewindow = this.dashboardCtx.dashboardTimewindow; } } } @@ -1214,6 +1215,7 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC this.setEditMode(false, false); } else { let reInitDashboard = false; + this.dashboard.configuration.timewindow = this.dashboardCtx.dashboardTimewindow; this.dashboardService.saveDashboard(this.dashboard).pipe( catchError((err) => { if (err.status === HttpStatusCode.Conflict) { diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.models.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.models.ts index 8ce2ab0679..90b838171c 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.models.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.models.ts @@ -56,6 +56,7 @@ export interface DashboardContext { export interface IDashboardController { dashboardCtx: DashboardContext; dashboardContainer: ElementRef; + dashboardContent: ElementRef; elRef: ElementRef; openRightLayout(); openDashboardState(stateId: string, openRightLayout: boolean); diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-settings-dialog.component.html b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-settings-dialog.component.html index 0a1733e851..5137f6128d 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-settings-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-settings-dialog.component.html @@ -119,20 +119,15 @@ </div> <div class="tb-form-row space-between"> <div translate>dashboard.columns-count</div> - <mat-form-field *ngIf="!isScada()" - appearance="outline" class="number medium-width tb-suffix-absolute" subscriptSizing="dynamic"> + <mat-form-field *ngIf="!isScada()" appearance="outline" class="number medium-width tb-suffix-absolute" subscriptSizing="dynamic" + matTooltipPosition="above" + matTooltipClass="tb-error-tooltip" + [matTooltipDisabled]="!(gridSettingsFormGroup.get('columns').invalid && gridSettingsFormGroup.get('columns').touched)" + [matTooltip]="(gridSettingsFormGroup.get('columns').hasError('required') ? 'dashboard.columns-count-required' : + (gridSettingsFormGroup.get('columns').hasError('min') ? 'dashboard.min-columns-count-message' : 'dashboard.max-columns-count-message')) | translate"> <input matInput formControlName="columns" type="number" min="10" max="1008" step="1" required placeholder="{{ 'widget-config.set' | translate }}"> - <mat-icon matSuffix - matTooltipPosition="above" - matTooltipClass="tb-error-tooltip" - [matTooltip]="(gridSettingsFormGroup.get('columns').hasError('required') ? 'dashboard.columns-count-required' : - (gridSettingsFormGroup.get('columns').hasError('min') ? 'dashboard.min-columns-count-message' : 'dashboard.max-columns-count-message')) | translate" - *ngIf="gridSettingsFormGroup.get('columns').invalid && gridSettingsFormGroup.get('columns').touched" - class="tb-error"> - warning - </mat-icon> </mat-form-field> <mat-form-field *ngIf="isScada()" class="medium-width" appearance="outline" subscriptSizing="dynamic"> @@ -145,37 +140,29 @@ </div> <div class="tb-form-row space-between"> <div translate>dashboard.min-layout-width</div> - <mat-form-field appearance="outline" class="number medium-width tb-suffix-absolute" subscriptSizing="dynamic"> + <mat-form-field appearance="outline" class="number medium-width" subscriptSizing="dynamic" + matTooltipPosition="above" + matTooltipClass="tb-error-tooltip" + [matTooltipDisabled]="!(gridSettingsFormGroup.get('minColumns').invalid && gridSettingsFormGroup.get('minColumns').touched)" + [matTooltip]="(gridSettingsFormGroup.get('minColumns').hasError('required') ? 'dashboard.columns-count-required' : + (gridSettingsFormGroup.get('minColumns').hasError('min') ? 'dashboard.min-columns-count-message' : 'dashboard.max-columns-count-message')) | translate"> <input matInput formControlName="minColumns" type="number" min="10" max="1008" step="1" required placeholder="{{ 'widget-config.set' | translate }}"> - <mat-icon matSuffix - matTooltipPosition="above" - matTooltipClass="tb-error-tooltip" - [matTooltip]="(gridSettingsFormGroup.get('minColumns').hasError('required') ? 'dashboard.columns-count-required' : - (gridSettingsFormGroup.get('minColumns').hasError('min') ? 'dashboard.min-columns-count-message' : 'dashboard.max-columns-count-message')) | translate" - *ngIf="gridSettingsFormGroup.get('minColumns').invalid && gridSettingsFormGroup.get('minColumns').touched" - class="tb-error"> - warning - </mat-icon> <span translate matSuffix>dashboard.columns-suffix</span> </mat-form-field> </div> <div *ngIf="!isScada()" class="tb-form-row space-between"> <div translate>dashboard.widgets-margins</div> - <mat-form-field appearance="outline" class="number medium-width tb-suffix-absolute" subscriptSizing="dynamic"> + <mat-form-field appearance="outline" class="number medium-width tb-suffix-absolute" subscriptSizing="dynamic" + matTooltipPosition="above" + matTooltipClass="tb-error-tooltip" + [matTooltipDisabled]="!(gridSettingsFormGroup.get('margin').invalid && gridSettingsFormGroup.get('margin').touched)" + [matTooltip]="(gridSettingsFormGroup.get('margin').hasError('required') ? 'dashboard.margin-required' : + (gridSettingsFormGroup.get('margin').hasError('min') ? 'dashboard.min-margin-message' : 'dashboard.max-margin-message')) | translate"> <input matInput formControlName="margin" type="number" min="0" max="50" step="any" required placeholder="{{ 'widget-config.set' | translate }}"> - <mat-icon matSuffix - matTooltipPosition="above" - matTooltipClass="tb-error-tooltip" - [matTooltip]="(gridSettingsFormGroup.get('margin').hasError('required') ? 'dashboard.margin-required' : - (gridSettingsFormGroup.get('margin').hasError('min') ? 'dashboard.min-margin-message' : 'dashboard.max-margin-message')) | translate" - *ngIf="gridSettingsFormGroup.get('margin').invalid && gridSettingsFormGroup.get('margin').touched" - class="tb-error"> - warning - </mat-icon> </mat-form-field> </div> <div *ngIf="!isScada()" class="tb-form-row"> @@ -190,20 +177,16 @@ </div> <div *ngIf="isDefaultLayout && !isDefaultBreakpoint" class="tb-form-row space-between"> <div translate>dashboard.row-height</div> - <mat-form-field appearance="outline" class="number medium-width tb-suffix-absolute" subscriptSizing="dynamic"> + <mat-form-field appearance="outline" class="number medium-width" subscriptSizing="dynamic" + matTooltipPosition="above" + matTooltipClass="tb-error-tooltip" + [matTooltipDisabled]="!(gridSettingsFormGroup.get('rowHeight').invalid && gridSettingsFormGroup.get('rowHeight').touched)" + [matTooltip]="(gridSettingsFormGroup.get('rowHeight').hasError('required') ? 'dashboard.row-height-required' : + (gridSettingsFormGroup.get('rowHeight').hasError('min') ? + 'dashboard.min-row-height-message' : 'dashboard.max-row-height-message')) | translate"> <input matInput formControlName="rowHeight" type="number" min="5" max="200" step="any" required placeholder="{{ 'widget-config.set' | translate }}"> - <mat-icon matSuffix - matTooltipPosition="above" - matTooltipClass="tb-error-tooltip" - [matTooltip]="(gridSettingsFormGroup.get('rowHeight').hasError('required') ? 'dashboard.row-height-required' : - (gridSettingsFormGroup.get('rowHeight').hasError('min') ? - 'dashboard.min-row-height-message' : 'dashboard.max-row-height-message')) | translate" - *ngIf="gridSettingsFormGroup.get('rowHeight').invalid && gridSettingsFormGroup.get('rowHeight').touched" - class="tb-error"> - warning - </mat-icon> <span matSuffix>px</span> </mat-form-field> </div> @@ -245,20 +228,16 @@ </div> <div *ngIf="!isScada()" class="tb-form-row space-between"> <div translate>dashboard.mobile-row-height</div> - <mat-form-field appearance="outline" class="number medium-width tb-suffix-absolute" subscriptSizing="dynamic"> + <mat-form-field appearance="outline" class="number medium-width" subscriptSizing="dynamic" + matTooltipPosition="above" + matTooltipClass="tb-error-tooltip" + [matTooltipDisabled]="!(gridSettingsFormGroup.get('mobileRowHeight').invalid && gridSettingsFormGroup.get('mobileRowHeight').touched)" + [matTooltip]="(gridSettingsFormGroup.get('mobileRowHeight').hasError('required') ? 'dashboard.mobile-row-height-required' : + (gridSettingsFormGroup.get('mobileRowHeight').hasError('min') ? + 'dashboard.min-mobile-row-height-message' : 'dashboard.max-mobile-row-height-message')) | translate"> <input matInput formControlName="mobileRowHeight" type="number" min="5" max="200" step="any" required placeholder="{{ 'widget-config.set' | translate }}"> - <mat-icon matSuffix - matTooltipPosition="above" - matTooltipClass="tb-error-tooltip" - [matTooltip]="(gridSettingsFormGroup.get('mobileRowHeight').hasError('required') ? 'dashboard.mobile-row-height-required' : - (gridSettingsFormGroup.get('mobileRowHeight').hasError('min') ? - 'dashboard.min-mobile-row-height-message' : 'dashboard.max-mobile-row-height-message')) | translate" - *ngIf="gridSettingsFormGroup.get('mobileRowHeight').invalid && gridSettingsFormGroup.get('mobileRowHeight').touched" - class="tb-error"> - warning - </mat-icon> <span matSuffix>px</span> </mat-form-field> </div> diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/value-card-basic-config.component.html b/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/value-card-basic-config.component.html index 44e288d2e0..c1f0d7e635 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/value-card-basic-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/value-card-basic-config.component.html @@ -126,6 +126,12 @@ <input matInput formControlName="borderRadius" placeholder="{{ 'widget-config.set' | translate }}"> </mat-form-field> </div> + <div class="tb-form-row space-between"> + <div>{{ 'widget-config.card-padding' | translate }}</div> + <mat-form-field appearance="outline" subscriptSizing="dynamic"> + <input matInput formControlName="padding" placeholder="{{ 'widget-config.set' | translate }}"> + </mat-form-field> + </div> </div> <tb-widget-actions-panel formControlName="actions"> diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/value-card-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/value-card-basic-config.component.ts index 0bffd39ce4..5f14b7569e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/value-card-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/value-card-basic-config.component.ts @@ -144,6 +144,7 @@ export class ValueCardBasicConfigComponent extends BasicWidgetConfigComponent { cardButtons: [this.getCardButtons(configData.config), []], borderRadius: [configData.config.borderRadius, []], + padding: [settings.padding, []], actions: [configData.config.actions || {}, []] }); @@ -183,6 +184,7 @@ export class ValueCardBasicConfigComponent extends BasicWidgetConfigComponent { this.setCardButtons(config.cardButtons, this.widgetConfig.config); this.widgetConfig.config.borderRadius = config.borderRadius; + this.widgetConfig.config.settings.padding = config.padding; this.widgetConfig.config.actions = config.actions; return this.widgetConfig; diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/status-widget-basic-config.component.html b/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/status-widget-basic-config.component.html index 52563a1b46..e43dd1665a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/status-widget-basic-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/status-widget-basic-config.component.html @@ -94,6 +94,12 @@ <input matInput formControlName="borderRadius" placeholder="{{ 'widget-config.set' | translate }}"> </mat-form-field> </div> + <div class="tb-form-row space-between"> + <div>{{ 'widget-config.card-padding' | translate }}</div> + <mat-form-field appearance="outline" subscriptSizing="dynamic"> + <input matInput formControlName="padding" placeholder="{{ 'widget-config.set' | translate }}"> + </mat-form-field> + </div> </div> <tb-widget-actions-panel formControlName="actions"> diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/status-widget-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/status-widget-basic-config.component.ts index d2110026f6..0e012cefe7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/status-widget-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/status-widget-basic-config.component.ts @@ -79,6 +79,7 @@ export class StatusWidgetBasicConfigComponent extends BasicWidgetConfigComponent cardButtons: [this.getCardButtons(configData.config), []], borderRadius: [configData.config.borderRadius, []], + padding: [settings.padding, []], actions: [configData.config.actions || {}, []] }); @@ -99,6 +100,7 @@ export class StatusWidgetBasicConfigComponent extends BasicWidgetConfigComponent this.setCardButtons(config.cardButtons, this.widgetConfig.config); this.widgetConfig.config.borderRadius = config.borderRadius; + this.widgetConfig.config.settings.padding = config.padding; this.widgetConfig.config.actions = config.actions; return this.widgetConfig; diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/rpc/single-switch-basic-config.component.html b/ui-ngx/src/app/modules/home/components/widget/config/basic/rpc/single-switch-basic-config.component.html index 7a638c70f3..9fa2d1b1a5 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/rpc/single-switch-basic-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/rpc/single-switch-basic-config.component.html @@ -211,6 +211,12 @@ <tb-background-settings formControlName="background"> </tb-background-settings> </div> + <div class="tb-form-row space-between"> + <div>{{ 'widget-config.card-padding' | translate }}</div> + <mat-form-field appearance="outline" subscriptSizing="dynamic"> + <input matInput formControlName="padding" placeholder="{{ 'widget-config.set' | translate }}"> + </mat-form-field> + </div> <div class="tb-form-row space-between column-lt-md"> <div translate>widget-config.show-card-buttons</div> <mat-chip-listbox multiple formControlName="cardButtons"> diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/rpc/single-switch-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/rpc/single-switch-basic-config.component.ts index 75c93bc852..dfdc9e8eb0 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/rpc/single-switch-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/rpc/single-switch-basic-config.component.ts @@ -108,6 +108,7 @@ export class SingleSwitchBasicConfigComponent extends BasicWidgetConfigComponent cardButtons: [this.getCardButtons(configData.config), []], borderRadius: [configData.config.borderRadius, []], + padding: [settings.padding, []], actions: [configData.config.actions || {}, []] }); @@ -159,6 +160,7 @@ export class SingleSwitchBasicConfigComponent extends BasicWidgetConfigComponent this.setCardButtons(config.cardButtons, this.widgetConfig.config); this.widgetConfig.config.borderRadius = config.borderRadius; + this.widgetConfig.config.settings.padding = config.padding; this.widgetConfig.config.actions = config.actions; return this.widgetConfig; diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/weather/wind-speed-direction-basic-config.component.html b/ui-ngx/src/app/modules/home/components/widget/config/basic/weather/wind-speed-direction-basic-config.component.html index 7854a9f3b3..0dd9a2ebd9 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/weather/wind-speed-direction-basic-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/weather/wind-speed-direction-basic-config.component.html @@ -208,6 +208,12 @@ <input matInput formControlName="borderRadius" placeholder="{{ 'widget-config.set' | translate }}"> </mat-form-field> </div> + <div class="tb-form-row space-between"> + <div>{{ 'widget-config.card-padding' | translate }}</div> + <mat-form-field appearance="outline" subscriptSizing="dynamic"> + <input matInput formControlName="padding" placeholder="{{ 'widget-config.set' | translate }}"> + </mat-form-field> + </div> </div> <tb-widget-actions-panel formControlName="actions"> diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/weather/wind-speed-direction-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/weather/wind-speed-direction-basic-config.component.ts index fca3bd2502..08e7003b65 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/weather/wind-speed-direction-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/weather/wind-speed-direction-basic-config.component.ts @@ -147,6 +147,7 @@ export class WindSpeedDirectionBasicConfigComponent extends BasicWidgetConfigCom cardButtons: [this.getCardButtons(configData.config), []], borderRadius: [configData.config.borderRadius, []], + padding: [settings.padding, []], actions: [configData.config.actions || {}, []] }); @@ -198,6 +199,7 @@ export class WindSpeedDirectionBasicConfigComponent extends BasicWidgetConfigCom this.setCardButtons(config.cardButtons, this.widgetConfig.config); this.widgetConfig.config.borderRadius = config.borderRadius; + this.widgetConfig.config.settings.padding = config.padding; this.widgetConfig.config.actions = config.actions; return this.widgetConfig; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.component.html index 72598a4cdf..814f9f08d8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.component.html @@ -15,41 +15,41 @@ limitations under the License. --> -<div #valueCardPanel class="tb-value-card-panel" [class]="this.layout" [style]="backgroundStyle$ | async"> +<div #valueCardPanel class="tb-value-card-panel" [class]="this.layout" [style.padding]="padding" [style]="backgroundStyle$ | async"> <div class="tb-value-card-overlay" [style]="overlayStyle"></div> <div class="tb-value-card-title-panel"> <ng-container *ngTemplateOutlet="widgetTitlePanel"></ng-container> </div> <div #valueCardContent class="tb-value-card-content" [class]="this.layout"> <ng-container [ngSwitch]="layout"> - <ng-template [ngSwitchCase]="valueCardLayout.square"> - <ng-container *ngTemplateOutlet="iconWithLabelTpl"></ng-container> - <ng-container *ngTemplateOutlet="valueTpl"></ng-container> - </ng-template> - <ng-template [ngSwitchCase]="valueCardLayout.vertical"> - <ng-container *ngTemplateOutlet="labelTpl"></ng-container> - <ng-container *ngTemplateOutlet="valueTpl"></ng-container> - <ng-container *ngTemplateOutlet="iconTpl"></ng-container> - </ng-template> - <ng-template [ngSwitchCase]="valueCardLayout.centered"> - <ng-container *ngTemplateOutlet="labelTpl"></ng-container> - <div class="tb-value-card-icon-row"> + <ng-template [ngSwitchCase]="valueCardLayout.square"> + <ng-container *ngTemplateOutlet="iconWithLabelTpl"></ng-container> + <ng-container *ngTemplateOutlet="valueTpl"></ng-container> + </ng-template> + <ng-template [ngSwitchCase]="valueCardLayout.vertical"> + <ng-container *ngTemplateOutlet="labelTpl"></ng-container> + <ng-container *ngTemplateOutlet="valueTpl"></ng-container> <ng-container *ngTemplateOutlet="iconTpl"></ng-container> + </ng-template> + <ng-template [ngSwitchCase]="valueCardLayout.centered"> + <ng-container *ngTemplateOutlet="labelTpl"></ng-container> + <div class="tb-value-card-icon-row"> + <ng-container *ngTemplateOutlet="iconTpl"></ng-container> + <ng-container *ngTemplateOutlet="valueTpl"></ng-container> + </div> + <ng-container *ngTemplateOutlet="dateTpl"></ng-container> + </ng-template> + <ng-template [ngSwitchCase]="valueCardLayout.simplified"> <ng-container *ngTemplateOutlet="valueTpl"></ng-container> - </div> - <ng-container *ngTemplateOutlet="dateTpl"></ng-container> - </ng-template> - <ng-template [ngSwitchCase]="valueCardLayout.simplified"> - <ng-container *ngTemplateOutlet="valueTpl"></ng-container> - <ng-container *ngTemplateOutlet="labelTpl"></ng-container> - </ng-template> - <ng-template [ngSwitchCase]="layout === valueCardLayout.horizontal || - layout === valueCardLayout.horizontal_reversed ? layout : ''"> - <ng-container *ngTemplateOutlet="iconWithLabelTpl"></ng-container> - <div fxFlex></div> - <ng-container *ngTemplateOutlet="valueTpl"></ng-container> - </ng-template> - </ng-container> + <ng-container *ngTemplateOutlet="labelTpl"></ng-container> + </ng-template> + <ng-template [ngSwitchCase]="layout === valueCardLayout.horizontal || + layout === valueCardLayout.horizontal_reversed ? layout : ''"> + <ng-container *ngTemplateOutlet="iconWithLabelTpl"></ng-container> + <div fxFlex></div> + <ng-container *ngTemplateOutlet="valueTpl"></ng-container> + </ng-template> + </ng-container> </div> </div> <ng-template #iconWithLabelTpl> diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.component.ts index ed361c1e76..96ec634362 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.component.ts @@ -38,6 +38,7 @@ import { getSingleTsValue, iconStyle, overlayStyle, + resolveCssSize, textStyle } from '@shared/models/widget-settings.models'; import { valueCardDefaultSettings, ValueCardLayout, ValueCardWidgetSettings } from './value-card-widget.models'; @@ -48,7 +49,6 @@ import { ImagePipe } from '@shared/pipe/image.pipe'; import { DomSanitizer } from '@angular/platform-browser'; const squareLayoutSize = 160; -const squareLayoutPadding = 48; const horizontalLayoutHeight = 80; @Component({ @@ -96,6 +96,7 @@ export class ValueCardWidgetComponent implements OnInit, AfterViewInit, OnDestro backgroundStyle$: Observable<ComponentStyle>; overlayStyle: ComponentStyle = {}; + padding: string; private panelResize$: ResizeObserver; @@ -148,6 +149,7 @@ export class ValueCardWidgetComponent implements OnInit, AfterViewInit, OnDestro this.backgroundStyle$ = backgroundStyle(this.settings.background, this.imagePipe, this.sanitizer); this.overlayStyle = overlayStyle(this.settings.background.overlay); + this.padding = this.settings.background.overlay.enabled ? undefined : this.settings.padding; } public ngAfterViewInit() { @@ -199,8 +201,13 @@ export class ValueCardWidgetComponent implements OnInit, AfterViewInit, OnDestro } private onResize() { - const panelWidth = this.valueCardPanel.nativeElement.getBoundingClientRect().width - squareLayoutPadding; - const panelHeight = this.valueCardPanel.nativeElement.getBoundingClientRect().height - (this.horizontal ? 0 : squareLayoutPadding); + const computedStyle = getComputedStyle(this.valueCardPanel.nativeElement); + const [pLeft, pRight, pTop, pBottom] = ['paddingLeft', 'paddingRight', 'paddingTop', 'paddingBottom'] + .map(side => resolveCssSize(computedStyle[side])[0]); + + const widgetBoundingClientRect = this.valueCardPanel.nativeElement.getBoundingClientRect(); + const panelWidth = widgetBoundingClientRect.width - (pLeft + pRight); + const panelHeight = widgetBoundingClientRect.height - (pTop + pBottom); let scale: number; if (!this.horizontal) { const size = Math.min(panelWidth, panelHeight); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.models.ts index df5fc78e9a..2ca299cb6e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.models.ts @@ -19,8 +19,10 @@ import { BackgroundType, ColorSettings, constantColor, - cssUnit, DateFormatSettings, - Font, lastUpdateAgoDateFormat + cssUnit, + DateFormatSettings, + Font, + lastUpdateAgoDateFormat } from '@shared/models/widget-settings.models'; export enum ValueCardLayout { @@ -80,6 +82,7 @@ export interface ValueCardWidgetSettings { dateFont: Font; dateColor: ColorSettings; background: BackgroundSettings; + padding: string; } export const valueCardDefaultSettings = (horizontal: boolean): ValueCardWidgetSettings => ({ @@ -128,5 +131,6 @@ export const valueCardDefaultSettings = (horizontal: boolean): ValueCardWidgetSe color: 'rgba(255,255,255,0.72)', blur: 3 } - } + }, + padding: '' }); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/configuration/basic/gateway-basic-configuration.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/configuration/basic/gateway-basic-configuration.component.ts index 4b47dd15c4..e63a60372e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/configuration/basic/gateway-basic-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/configuration/basic/gateway-basic-configuration.component.ts @@ -43,7 +43,7 @@ import { } from '@home/components/widget/lib/gateway/gateway-remote-configuration-dialog'; import { DeviceService } from '@core/http/device.service'; import { Subject } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; +import { take, takeUntil } from 'rxjs/operators'; import { DeviceCredentials, DeviceCredentialsType } from '@shared/models/device.models'; import { GatewayLogLevel, @@ -61,7 +61,9 @@ import { CommonModule } from '@angular/common'; import { coerceBoolean } from '@shared/decorators/coercion'; import { GatewayConfigCommand, - GatewayConfigValue, LogConfig + GatewayConfigSecurity, + GatewayConfigValue, + LogConfig } from '@home/components/widget/lib/gateway/configuration/models/gateway-configuration.models'; @Component({ @@ -99,13 +101,14 @@ export class GatewayBasicConfigurationComponent implements OnDestroy, ControlVal initialCredentialsUpdated = new EventEmitter<DeviceCredentials>(); StorageTypes = StorageTypes; - storageTypes = Object.values(StorageTypes) as StorageTypes[]; + storageTypes = Object.values(StorageTypes); storageTypesTranslationMap = StorageTypesTranslationMap; logSavingPeriods = LogSavingPeriodTranslations; localLogsConfigs = Object.keys(LocalLogsConfigs) as LocalLogsConfigs[]; localLogsConfigTranslateMap = LocalLogsConfigTranslateMap; securityTypes = GecurityTypesTranslationsMap; gatewayLogLevel = Object.values(GatewayLogLevel); + logSelector: FormControl; basicFormGroup: FormGroup; @@ -119,6 +122,7 @@ export class GatewayBasicConfigurationComponent implements OnDestroy, ControlVal private cd: ChangeDetectorRef, private dialog: MatDialog) { this.initBasicFormGroup(); + this.observeFormChanges(); this.basicFormGroup.valueChanges .pipe(takeUntil(this.destroy$)) .subscribe(value => { @@ -142,14 +146,12 @@ export class GatewayBasicConfigurationComponent implements OnDestroy, ControlVal writeValue(basicConfig: GatewayConfigValue): void { this.basicFormGroup.patchValue(basicConfig, {emitEvent: false}); - if (basicConfig?.thingsboard?.security) { - this.checkAndFetchCredentials(basicConfig.thingsboard.security); - } + this.checkAndFetchCredentials(basicConfig?.thingsboard?.security ?? {} as GatewayConfigSecurity); if (basicConfig?.grpc) { this.toggleRpcFields(basicConfig.grpc.enabled); } - const commands = basicConfig?.thingsboard?.statistics?.commands || []; - commands.forEach(command => this.addCommand(command, false)); + const commands = basicConfig?.thingsboard?.statistics?.commands ?? []; + commands.forEach((command: GatewayConfigCommand) => this.addCommand(command, false)); } validate(): ValidationErrors | null { @@ -251,7 +253,7 @@ export class GatewayBasicConfigurationComponent implements OnDestroy, ControlVal data: { gatewayName: gateway.name } - }).afterClosed().subscribe( + }).afterClosed().pipe(take(1)).subscribe( (res) => { if (!res) { this.basicFormGroup.get('thingsboard.remoteConfiguration').setValue(true, {emitEvent: false}); @@ -273,214 +275,294 @@ export class GatewayBasicConfigurationComponent implements OnDestroy, ControlVal this.commandFormArray().push(commandFormGroup, { emitEvent }); } - private initBasicFormGroup(): void { this.basicFormGroup = this.fb.group({ - thingsboard: this.fb.group({ - host: [window.location.hostname, [Validators.required, Validators.pattern(/^[^\s]+$/)]], - port: [1883, [Validators.required, Validators.min(1), Validators.max(65535), Validators.pattern(/^-?[0-9]+$/)]], - remoteShell: [false, []], - remoteConfiguration: [true, []], - checkConnectorsConfigurationInSeconds: [60, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], - statistics: this.fb.group({ - enable: [true, []], - statsSendPeriodInSeconds: [3600, [Validators.required, Validators.min(60), Validators.pattern(/^-?[0-9]+$/)]], - commands: this.fb.array([], []) - }), - maxPayloadSizeBytes: [8196, [Validators.required, Validators.min(100), Validators.pattern(/^-?[0-9]+$/)]], - minPackSendDelayMS: [50, [Validators.required, Validators.min(10), Validators.pattern(/^-?[0-9]+$/)]], - minPackSizeToSend: [500, [Validators.required, Validators.min(100), Validators.pattern(/^-?[0-9]+$/)]], - handleDeviceRenaming: [true, []], - checkingDeviceActivity: this.fb.group({ - checkDeviceInactivity: [false, []], - inactivityTimeoutSeconds: [200, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], - inactivityCheckPeriodSeconds: [500, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]] - }), - security: this.fb.group({ - type: [SecurityTypes.ACCESS_TOKEN, [Validators.required]], - accessToken: [null, [Validators.required, Validators.pattern(/^[^.\s]+$/)]], - clientId: [null, [Validators.pattern(/^[^.\s]+$/)]], - username: [null, [Validators.pattern(/^[^.\s]+$/)]], - password: [null, [Validators.pattern(/^[^.\s]+$/)]], - caCert: [null, []], - cert: [null, []], - privateKey: [null, []], - }), - qos: [1, [Validators.min(0), Validators.max(1), Validators.required, Validators.pattern(/^[^.\s]+$/)]] - }), - storage: this.fb.group({ - type: [StorageTypes.MEMORY, [Validators.required]], - read_records_count: [ - 100, [Validators.min(1), - Validators.pattern(/^-?[0-9]+$/), Validators.required, Validators.pattern(/^[^.\s]+$/)] - ], - max_records_count: [ - 100000, - [Validators.min(1), Validators.pattern(/^-?[0-9]+$/), Validators.required, Validators.pattern(/^[^.\s]+$/)] - ], - data_folder_path: ['./data/', [Validators.required]], - max_file_count: [10, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], - max_read_records_count: [10, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], - max_records_per_file: [10000, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], - data_file_path: ['./data/data.db', [Validators.required]], - messages_ttl_check_in_hours: [1, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], - messages_ttl_in_days: [7, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], + thingsboard: this.initThingsboardFormGroup(), + storage: this.initStorageFormGroup(), + grpc: this.initGrpcFormGroup(), + connectors: this.fb.array([]), + logs: this.initLogsFormGroup(), + }); + } + private initThingsboardFormGroup(): FormGroup { + return this.fb.group({ + host: [window.location.hostname, [Validators.required, Validators.pattern(/^[^\s]+$/)]], + port: [1883, [Validators.required, Validators.min(1), Validators.max(65535), Validators.pattern(/^-?[0-9]+$/)]], + remoteShell: [false], + remoteConfiguration: [true], + checkConnectorsConfigurationInSeconds: [60, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], + statistics: this.fb.group({ + enable: [true], + statsSendPeriodInSeconds: [3600, [Validators.required, Validators.min(60), Validators.pattern(/^-?[0-9]+$/)]], + commands: this.fb.array([]) }), - grpc: this.fb.group({ - enabled: [false, []], - serverPort: [9595, [Validators.required, Validators.min(1), Validators.max(65535), Validators.pattern(/^-?[0-9]+$/)]], - keepAliveTimeMs: [10000, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], - keepAliveTimeoutMs: [5000, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], - keepalivePermitWithoutCalls: [true, []], - maxPingsWithoutData: [0, [Validators.required, Validators.min(0), Validators.pattern(/^-?[0-9]+$/)]], - minTimeBetweenPingsMs: [10000, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], - minPingIntervalWithoutDataMs: [5000, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], + maxPayloadSizeBytes: [8196, [Validators.required, Validators.min(100), Validators.pattern(/^-?[0-9]+$/)]], + minPackSendDelayMS: [50, [Validators.required, Validators.min(10), Validators.pattern(/^-?[0-9]+$/)]], + minPackSizeToSend: [500, [Validators.required, Validators.min(100), Validators.pattern(/^-?[0-9]+$/)]], + handleDeviceRenaming: [true], + checkingDeviceActivity: this.initCheckingDeviceActivityFormGroup(), + security: this.initSecurityFormGroup(), + qos: [1, [Validators.required, Validators.min(0), Validators.max(1), Validators.pattern(/^[^.\s]+$/)]] + }); + } + + private initStorageFormGroup(): FormGroup { + return this.fb.group({ + type: [StorageTypes.MEMORY, [Validators.required]], + read_records_count: [100, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], + max_records_count: [100000, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], + data_folder_path: ['./data/', [Validators.required]], + max_file_count: [10, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], + max_read_records_count: [10, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], + max_records_per_file: [10000, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], + data_file_path: ['./data/data.db', [Validators.required]], + messages_ttl_check_in_hours: [1, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], + messages_ttl_in_days: [7, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]] + }); + } + + private initGrpcFormGroup(): FormGroup { + return this.fb.group({ + enabled: [false], + serverPort: [9595, [Validators.required, Validators.min(1), Validators.max(65535), Validators.pattern(/^-?[0-9]+$/)]], + keepAliveTimeMs: [10000, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], + keepAliveTimeoutMs: [5000, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], + keepalivePermitWithoutCalls: [true], + maxPingsWithoutData: [0, [Validators.required, Validators.min(0), Validators.pattern(/^-?[0-9]+$/)]], + minTimeBetweenPingsMs: [10000, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], + minPingIntervalWithoutDataMs: [5000, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]] + }); + } + + private initLogsFormGroup(): FormGroup { + return this.fb.group({ + dateFormat: ['%Y-%m-%d %H:%M:%S', [Validators.required, Validators.pattern(/^[^\s].*[^\s]$/)]], + logFormat: [ + '%(asctime)s - |%(levelname)s| - [%(filename)s] - %(module)s - %(funcName)s - %(lineno)d - %(message)s', + [Validators.required, Validators.pattern(/^[^\s].*[^\s]$/)] + ], + type: ['remote', [Validators.required]], + remote: this.fb.group({ + enabled: [false], + logLevel: [GatewayLogLevel.INFO, [Validators.required]] }), - connectors: this.fb.array([]), - logs: this.fb.group({ - dateFormat: ['%Y-%m-%d %H:%M:%S', [Validators.required, Validators.pattern(/^[^\s].*[^\s]$/)]], - logFormat: ['%(asctime)s - |%(levelname)s| - [%(filename)s] - %(module)s - %(funcName)s - %(lineno)d - %(message)s', - [Validators.required, Validators.pattern(/^[^\s].*[^\s]$/)]], - type: ['remote', [Validators.required]], - remote: this.fb.group({ - enabled: [false], - logLevel: [GatewayLogLevel.INFO, [Validators.required]], - }), - local: this.fb.group({}) - }) + local: this.fb.group({}) + }); + } + + private initCheckingDeviceActivityFormGroup(): FormGroup { + return this.fb.group({ + checkDeviceInactivity: [false], + inactivityTimeoutSeconds: [200, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], + inactivityCheckPeriodSeconds: [500, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]] }); + } - this.basicFormGroup.get('thingsboard.security.password').valueChanges.subscribe(password => { + private initSecurityFormGroup(): FormGroup { + return this.fb.group({ + type: [SecurityTypes.ACCESS_TOKEN, [Validators.required]], + accessToken: [null, [Validators.required, Validators.pattern(/^[^.\s]+$/)]], + clientId: [null, [Validators.pattern(/^[^.\s]+$/)]], + username: [null, [Validators.pattern(/^[^.\s]+$/)]], + password: [null, [Validators.pattern(/^[^.\s]+$/)]], + caCert: [null], + cert: [null], + privateKey: [null] + }); + } + + private observeFormChanges(): void { + this.observeSecurityPasswordChanges(); + this.observeRemoteConfigurationChanges(); + this.observeDeviceActivityChanges(); + this.observeSecurityTypeChanges(); + this.observeStorageTypeChanges(); + } + + private observeSecurityPasswordChanges(): void { + const securityUsername = this.basicFormGroup.get('thingsboard.security.username'); + this.basicFormGroup.get('thingsboard.security.password').valueChanges.pipe(takeUntil(this.destroy$)).subscribe(password => { if (password && password !== '') { - this.basicFormGroup.get('thingsboard.security.username').setValidators([Validators.required]); + securityUsername.setValidators([Validators.required]); } else { - this.basicFormGroup.get('thingsboard.security.username').clearValidators(); + securityUsername.clearValidators(); } - this.basicFormGroup.get('thingsboard.security.username').updateValueAndValidity({emitEvent: false}); + securityUsername.updateValueAndValidity({ emitEvent: false }); }); + } - this.toggleRpcFields(false); - - this.basicFormGroup.get('thingsboard.remoteConfiguration').valueChanges.subscribe(enabled => { + private observeRemoteConfigurationChanges(): void { + this.basicFormGroup.get('thingsboard.remoteConfiguration').valueChanges.pipe(takeUntil(this.destroy$)).subscribe(enabled => { if (!enabled) { this.openConfigurationConfirmDialog(); } }); this.logSelector = this.fb.control(LocalLogsConfigs.service); - - for (const localLogsConfigsKey of Object.keys(LocalLogsConfigs)) { - this.addLocalLogConfig(localLogsConfigsKey, {} as LogConfig); + for (const key of Object.keys(LocalLogsConfigs)) { + this.addLocalLogConfig(key, {} as LogConfig); } + } + private observeDeviceActivityChanges(): void { const checkingDeviceActivityGroup = this.basicFormGroup.get('thingsboard.checkingDeviceActivity') as FormGroup; - checkingDeviceActivityGroup.get('checkDeviceInactivity').valueChanges.subscribe(enabled => { + checkingDeviceActivityGroup.get('checkDeviceInactivity').valueChanges.pipe(takeUntil(this.destroy$)).subscribe(enabled => { checkingDeviceActivityGroup.updateValueAndValidity(); + const validators = [Validators.min(1), Validators.required, Validators.pattern(/^-?[0-9]+$/)]; + if (enabled) { - checkingDeviceActivityGroup.get('inactivityTimeoutSeconds') - .setValidators([Validators.min(1), Validators.required, Validators.pattern(/^-?[0-9]+$/)]); - checkingDeviceActivityGroup.get('inactivityCheckPeriodSeconds') - .setValidators([Validators.min(1), Validators.required, Validators.pattern(/^-?[0-9]+$/)]); + checkingDeviceActivityGroup.get('inactivityTimeoutSeconds').setValidators(validators); + checkingDeviceActivityGroup.get('inactivityCheckPeriodSeconds').setValidators(validators); } else { checkingDeviceActivityGroup.get('inactivityTimeoutSeconds').clearValidators(); checkingDeviceActivityGroup.get('inactivityCheckPeriodSeconds').clearValidators(); } - checkingDeviceActivityGroup.get('inactivityTimeoutSeconds').updateValueAndValidity({emitEvent: false}); - checkingDeviceActivityGroup.get('inactivityCheckPeriodSeconds').updateValueAndValidity({emitEvent: false}); + checkingDeviceActivityGroup.get('inactivityTimeoutSeconds').updateValueAndValidity({ emitEvent: false }); + checkingDeviceActivityGroup.get('inactivityCheckPeriodSeconds').updateValueAndValidity({ emitEvent: false }); }); - this.basicFormGroup.get('grpc.enabled').valueChanges.subscribe(value => { + this.basicFormGroup.get('grpc.enabled').valueChanges.pipe(takeUntil(this.destroy$)).subscribe(value => { this.toggleRpcFields(value); }); + } + private observeSecurityTypeChanges(): void { const securityGroup = this.basicFormGroup.get('thingsboard.security') as FormGroup; - securityGroup.get('type').valueChanges.subscribe(type => { + + securityGroup.get('type').valueChanges.pipe(takeUntil(this.destroy$)).subscribe(type => { this.removeAllSecurityValidators(); - if (type === SecurityTypes.ACCESS_TOKEN) { - securityGroup.get('accessToken').addValidators([Validators.required, Validators.pattern(/^[^.\s]+$/)]); - securityGroup.get('accessToken').updateValueAndValidity(); - } else if (type === SecurityTypes.TLS_PRIVATE_KEY) { - securityGroup.get('caCert').addValidators([Validators.required]); - securityGroup.get('caCert').updateValueAndValidity(); - securityGroup.get('privateKey').addValidators([Validators.required]); - securityGroup.get('privateKey').updateValueAndValidity(); - securityGroup.get('cert').addValidators([Validators.required]); - securityGroup.get('cert').updateValueAndValidity(); - } else if (type === SecurityTypes.TLS_ACCESS_TOKEN) { - securityGroup.get('accessToken').addValidators([Validators.required, Validators.pattern(/^[^.\s]+$/)]); - securityGroup.get('accessToken').updateValueAndValidity(); - securityGroup.get('caCert').addValidators([Validators.required]); - securityGroup.get('caCert').updateValueAndValidity(); - } else if (type === SecurityTypes.USERNAME_PASSWORD) { - securityGroup.addValidators([this.atLeastOneRequired(Validators.required, ['clientId', 'username'])]); + + switch (type) { + case SecurityTypes.ACCESS_TOKEN: + this.addAccessTokenValidators(securityGroup); + break; + case SecurityTypes.TLS_PRIVATE_KEY: + this.addTlsPrivateKeyValidators(securityGroup); + break; + case SecurityTypes.TLS_ACCESS_TOKEN: + this.addTlsAccessTokenValidators(securityGroup); + break; + case SecurityTypes.USERNAME_PASSWORD: + securityGroup.addValidators([this.atLeastOneRequired(Validators.required, ['clientId', 'username'])]); + break; } + securityGroup.updateValueAndValidity(); }); - securityGroup.get('caCert').valueChanges.subscribe(() => this.cd.detectChanges()); - securityGroup.get('privateKey').valueChanges.subscribe(() => this.cd.detectChanges()); - securityGroup.get('cert').valueChanges.subscribe(() => this.cd.detectChanges()); + ['caCert', 'privateKey', 'cert'].forEach(field => { + securityGroup.get(field).valueChanges.pipe(takeUntil(this.destroy$)).subscribe(() => this.cd.detectChanges()); + }); + } + private observeStorageTypeChanges(): void { const storageGroup = this.basicFormGroup.get('storage') as FormGroup; - storageGroup.get('type').valueChanges.subscribe(type => { + + storageGroup.get('type').valueChanges.pipe(takeUntil(this.destroy$)).subscribe(type => { this.removeAllStorageValidators(); - if (type === StorageTypes.MEMORY) { - storageGroup.get('read_records_count').addValidators( - [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]); - storageGroup.get('max_records_count').addValidators( - [Validators.min(1), Validators.pattern(/^-?[0-9]+$/), Validators.required]); - storageGroup.get('read_records_count').updateValueAndValidity({emitEvent: false}); - storageGroup.get('max_records_count').updateValueAndValidity({emitEvent: false}); - } else if (type === StorageTypes.FILE) { - storageGroup.get('data_folder_path').addValidators([Validators.required]); - storageGroup.get('max_file_count').addValidators( - [Validators.min(1), Validators.pattern(/^-?[0-9]+$/), Validators.required]); - storageGroup.get('max_read_records_count').addValidators( - [Validators.min(1), Validators.pattern(/^-?[0-9]+$/), Validators.required]); - storageGroup.get('max_records_per_file').addValidators( - [Validators.min(1), Validators.pattern(/^-?[0-9]+$/), Validators.required]); - storageGroup.get('data_folder_path').updateValueAndValidity({emitEvent: false}); - storageGroup.get('max_file_count').updateValueAndValidity({emitEvent: false}); - storageGroup.get('max_read_records_count').updateValueAndValidity({emitEvent: false}); - storageGroup.get('max_records_per_file').updateValueAndValidity({emitEvent: false}); - } else if (type === StorageTypes.SQLITE) { - storageGroup.get('data_file_path').addValidators([Validators.required]); - storageGroup.get('messages_ttl_check_in_hours').addValidators( - [Validators.min(1), Validators.pattern(/^-?[0-9]+$/), Validators.required]); - storageGroup.get('messages_ttl_in_days').addValidators( - [Validators.min(1), Validators.pattern(/^-?[0-9]+$/), Validators.required]); - storageGroup.get('data_file_path').updateValueAndValidity({emitEvent: false}); - storageGroup.get('messages_ttl_check_in_hours').updateValueAndValidity({emitEvent: false}); - storageGroup.get('messages_ttl_in_days').updateValueAndValidity({emitEvent: false}); + + switch (type) { + case StorageTypes.MEMORY: + this.addMemoryStorageValidators(storageGroup); + break; + case StorageTypes.FILE: + this.addFileStorageValidators(storageGroup); + break; + case StorageTypes.SQLITE: + this.addSqliteStorageValidators(storageGroup); + break; } }); } - private checkAndFetchCredentials(security: any = {}): void { - if (security.type !== SecurityTypes.TLS_PRIVATE_KEY) { - this.deviceService.getDeviceCredentials(this.device.id).subscribe(credentials => { - this.initialCredentialsUpdated.emit(credentials); - if (credentials.credentialsType === DeviceCredentialsType.ACCESS_TOKEN || security.type === SecurityTypes.TLS_ACCESS_TOKEN) { - this.basicFormGroup.get('thingsboard.security.type') - .setValue(security.type === SecurityTypes.TLS_ACCESS_TOKEN - ? SecurityTypes.TLS_ACCESS_TOKEN - : SecurityTypes.ACCESS_TOKEN, {emitEvent: false}); - this.basicFormGroup.get('thingsboard.security.accessToken').setValue(credentials.credentialsId, {emitEvent: false}); - if(security.type === SecurityTypes.TLS_ACCESS_TOKEN) { - this.basicFormGroup.get('thingsboard.security.caCert').setValue(security.caCert, {emitEvent: false}); - } - } else if (credentials.credentialsType === DeviceCredentialsType.MQTT_BASIC) { - const parsedValue = JSON.parse(credentials.credentialsValue); - this.basicFormGroup.get('thingsboard.security.type').setValue(SecurityTypes.USERNAME_PASSWORD, {emitEvent: false}); - this.basicFormGroup.get('thingsboard.security.clientId').setValue(parsedValue.clientId, {emitEvent: false}); - this.basicFormGroup.get('thingsboard.security.username').setValue(parsedValue.userName, {emitEvent: false}); - this.basicFormGroup.get('thingsboard.security.password') - .setValue(parsedValue.password, {emitEvent: false}); - } else if (credentials.credentialsType === DeviceCredentialsType.X509_CERTIFICATE) { - //if sertificate is present set sertificate as present - } - }); + private addAccessTokenValidators(group: FormGroup): void { + group.get('accessToken').addValidators([Validators.required, Validators.pattern(/^[^.\s]+$/)]); + group.get('accessToken').updateValueAndValidity(); + } + + private addTlsPrivateKeyValidators(group: FormGroup): void { + ['caCert', 'privateKey', 'cert'].forEach(field => { + group.get(field).addValidators([Validators.required]); + group.get(field).updateValueAndValidity(); + }); + } + + private addTlsAccessTokenValidators(group: FormGroup): void { + this.addAccessTokenValidators(group); + group.get('caCert').addValidators([Validators.required]); + group.get('caCert').updateValueAndValidity(); + } + + private addMemoryStorageValidators(group: FormGroup): void { + group.get('read_records_count').addValidators([Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]); + group.get('max_records_count').addValidators([Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]); + group.get('read_records_count').updateValueAndValidity({ emitEvent: false }); + group.get('max_records_count').updateValueAndValidity({ emitEvent: false }); + } + + private addFileStorageValidators(group: FormGroup): void { + ['data_folder_path', 'max_file_count', 'max_read_records_count', 'max_records_per_file'].forEach(field => { + group.get(field).addValidators([Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]); + group.get(field).updateValueAndValidity({ emitEvent: false }); + }); + } + + private addSqliteStorageValidators(group: FormGroup): void { + ['data_file_path', 'messages_ttl_check_in_hours', 'messages_ttl_in_days'].forEach(field => { + group.get(field).addValidators([Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]); + group.get(field).updateValueAndValidity({ emitEvent: false }); + }); + } + + private checkAndFetchCredentials(security: GatewayConfigSecurity): void { + if (security.type === SecurityTypes.TLS_PRIVATE_KEY) { + return; + } + + this.deviceService.getDeviceCredentials(this.device.id).pipe(takeUntil(this.destroy$)).subscribe(credentials => { + this.initialCredentialsUpdated.emit(credentials); + this.updateSecurityType(security, credentials); + this.updateCredentials(credentials, security); + }); + } + + private updateSecurityType(security, credentials: DeviceCredentials): void { + const isAccessToken = credentials.credentialsType === DeviceCredentialsType.ACCESS_TOKEN + || security.type === SecurityTypes.TLS_ACCESS_TOKEN; + const securityType = isAccessToken + ? (security.type === SecurityTypes.TLS_ACCESS_TOKEN ? SecurityTypes.TLS_ACCESS_TOKEN : SecurityTypes.ACCESS_TOKEN) + : (credentials.credentialsType === DeviceCredentialsType.MQTT_BASIC ? SecurityTypes.USERNAME_PASSWORD : null); + + if (securityType) { + this.basicFormGroup.get('thingsboard.security.type').setValue(securityType, { emitEvent: false }); } } + + private updateCredentials(credentials: DeviceCredentials, security: GatewayConfigSecurity): void { + switch (credentials.credentialsType) { + case DeviceCredentialsType.ACCESS_TOKEN: + this.updateAccessTokenCredentials(credentials, security); + break; + case DeviceCredentialsType.MQTT_BASIC: + this.updateMqttBasicCredentials(credentials); + break; + case DeviceCredentialsType.X509_CERTIFICATE: + break; + } + } + + private updateAccessTokenCredentials(credentials: DeviceCredentials, security: GatewayConfigSecurity): void { + this.basicFormGroup.get('thingsboard.security.accessToken').setValue(credentials.credentialsId, { emitEvent: false }); + if (security.type === SecurityTypes.TLS_ACCESS_TOKEN) { + this.basicFormGroup.get('thingsboard.security.caCert').setValue(security.caCert, { emitEvent: false }); + } + } + + private updateMqttBasicCredentials(credentials: DeviceCredentials): void { + const parsedValue = JSON.parse(credentials.credentialsValue); + this.basicFormGroup.get('thingsboard.security.clientId').setValue(parsedValue.clientId, { emitEvent: false }); + this.basicFormGroup.get('thingsboard.security.username').setValue(parsedValue.userName, { emitEvent: false }); + this.basicFormGroup.get('thingsboard.security.password').setValue(parsedValue.password, { emitEvent: false }); + } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/configuration/gateway-configuration.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/configuration/gateway-configuration.component.ts index 317b616110..056628dd6a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/configuration/gateway-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/configuration/gateway-configuration.component.ts @@ -69,8 +69,8 @@ export class GatewayConfigurationComponent implements AfterViewInit, OnDestroy { constructor(private fb: FormBuilder, private attributeService: AttributeService, private deviceService: DeviceService, - private cd: ChangeDetectorRef, - private dialog: MatDialog) { + private cd: ChangeDetectorRef + ) { this.gatewayConfigGroup = this.fb.group({ basicConfig: [], @@ -361,7 +361,7 @@ export class GatewayConfigurationComponent implements AfterViewInit, OnDestroy { } private updateFormControls(thingsboard: GatewayGeneralConfig): void { - const { type, accessToken, ...securityConfig } = thingsboard.security || {}; + const { type, accessToken, ...securityConfig } = thingsboard.security ?? {}; this.initialCredentials = { deviceId: this.device as DeviceId, diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.html index 391ade6228..95eb4a0ba1 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.html @@ -20,7 +20,7 @@ <div class="tb-status-widget-title-panel"> <ng-container *ngTemplateOutlet="widgetTitlePanel"></ng-container> </div> - <div #statusWidgetContent class="tb-status-widget-content" [class]="this.layout"> + <div #statusWidgetContent class="tb-status-widget-content" [class]="this.layout" [style.padding]="padding"> <div class="tb-status-widget-icon-container"> <tb-icon [style]="iconStyle">{{ icon }}</tb-icon> </div> diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.ts index 5b59b0210f..d8d5b48ff6 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.ts @@ -21,14 +21,16 @@ import { ElementRef, OnDestroy, OnInit, - Renderer2, ViewChild, + Renderer2, + ViewChild, ViewEncapsulation } from '@angular/core'; import { BasicActionWidgetComponent } from '@home/components/widget/lib/action/action-widget.models'; import { statusWidgetDefaultSettings, StatusWidgetLayout, - StatusWidgetSettings, StatusWidgetStateSettings + StatusWidgetSettings, + StatusWidgetStateSettings } from '@home/components/widget/lib/indicator/status-widget.models'; import { Observable } from 'rxjs'; import { @@ -36,12 +38,12 @@ import { ComponentStyle, iconStyle, overlayStyle, + resolveCssSize, textStyle } from '@shared/models/widget-settings.models'; import { ResizeObserver } from '@juggle/resize-observer'; import { ImagePipe } from '@shared/pipe/image.pipe'; import { DomSanitizer } from '@angular/platform-browser'; -import { UtilsService } from '@core/services/utils.service'; import { ValueType } from '@shared/models/constants'; const initialStatusWidgetSize = 147; @@ -65,6 +67,7 @@ export class StatusWidgetComponent extends backgroundStyle$: Observable<ComponentStyle>; overlayStyle: ComponentStyle = {}; + padding: string; overlayInset = '12px'; borderRadius = ''; @@ -101,9 +104,7 @@ export class StatusWidgetComponent extends constructor(protected imagePipe: ImagePipe, protected sanitizer: DomSanitizer, private renderer: Renderer2, - private utils: UtilsService, - protected cd: ChangeDetectorRef, - private elementRef: ElementRef) { + protected cd: ChangeDetectorRef) { super(cd); } @@ -191,8 +192,13 @@ export class StatusWidgetComponent extends } private onResize() { - const panelWidth = this.statusWidgetPanel.nativeElement.getBoundingClientRect().width; - const panelHeight = this.statusWidgetPanel.nativeElement.getBoundingClientRect().height; + const computedStyle = getComputedStyle(this.statusWidgetPanel.nativeElement); + const [pLeft, pRight, pTop, pBottom] = ['paddingLeft', 'paddingRight', 'paddingTop', 'paddingBottom'] + .map(side => resolveCssSize(computedStyle[side])[0]); + + const widgetBoundingClientRect = this.statusWidgetPanel.nativeElement.getBoundingClientRect(); + const panelWidth = widgetBoundingClientRect.width - (pLeft + pRight); + const panelHeight = widgetBoundingClientRect.height - (pTop + pBottom); const targetSize = Math.min(panelWidth, panelHeight); const scale = targetSize / initialStatusWidgetSize; const width = initialStatusWidgetSize; @@ -220,6 +226,9 @@ export class StatusWidgetComponent extends this.showLabel = stateSettings.showLabel && this.layout !== StatusWidgetLayout.icon; this.showStatus = stateSettings.showStatus && this.layout !== StatusWidgetLayout.icon; this.icon = stateSettings.icon; + this.padding = stateSettings.backgroundDisabled.overlay.enabled || stateSettings.background.overlay.enabled + ? undefined + : this.settings.padding; const primaryColor = disabled ? stateSettings.primaryColorDisabled : stateSettings.primaryColor; const secondaryColor = disabled ? stateSettings.secondaryColorDisabled : stateSettings.secondaryColor; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.models.ts index 2ef999c6f2..4dbea591f9 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.models.ts @@ -65,6 +65,7 @@ export interface StatusWidgetSettings { layout: StatusWidgetLayout; onState: StatusWidgetStateSettings; offState: StatusWidgetStateSettings; + padding: string } export const statusWidgetDefaultSettings: StatusWidgetSettings = { @@ -200,5 +201,6 @@ export const statusWidgetDefaultSettings: StatusWidgetSettings = { blur: 3 } } - } + }, + padding: '' }; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.component.html index fd9aaca4a6..a8dde3ed4c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.component.html @@ -15,7 +15,7 @@ limitations under the License. --> -<div #singleSwitchPanel class="tb-single-switch-panel" [class.auto-scale]="autoScale" [style.pointer-events]="ctx.isEdit ? 'none' : 'all'" [style]="backgroundStyle$ | async"> +<div #singleSwitchPanel class="tb-single-switch-panel" [class.auto-scale]="autoScale" [style.pointer-events]="ctx.isEdit ? 'none' : 'all'" [style.padding]="padding" [style]="backgroundStyle$ | async"> <div class="tb-single-switch-overlay" [style]="overlayStyle" [style.inset]="overlayInset"></div> <div class="tb-single-switch-title-panel"> <ng-container *ngTemplateOutlet="widgetTitlePanel"></ng-container> diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.component.ts index 2c15634893..63ed57628b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.component.ts @@ -36,6 +36,7 @@ import { ComponentStyle, iconStyle, overlayStyle, + resolveCssSize, textStyle } from '@shared/models/widget-settings.models'; import { Observable } from 'rxjs'; @@ -74,6 +75,7 @@ export class SingleSwitchWidgetComponent extends backgroundStyle$: Observable<ComponentStyle>; overlayStyle: ComponentStyle = {}; + padding: string; overlayInset = '12px'; value = false; @@ -123,6 +125,7 @@ export class SingleSwitchWidgetComponent extends this.backgroundStyle$ = backgroundStyle(this.settings.background, this.imagePipe, this.sanitizer); this.overlayStyle = overlayStyle(this.settings.background.overlay); + this.padding = this.settings.background.overlay.enabled ? undefined : this.settings.padding; this.layout = this.settings.layout; @@ -231,11 +234,15 @@ export class SingleSwitchWidgetComponent extends } private onResize() { - const height = this.singleSwitchPanel.nativeElement.getBoundingClientRect().height; + const widgetBoundingClientRect = this.singleSwitchPanel.nativeElement.getBoundingClientRect(); + const height = widgetBoundingClientRect.height; const switchScale = height / initialSwitchHeight; const paddingScale = Math.min(switchScale, 1); - const panelWidth = this.singleSwitchPanel.nativeElement.getBoundingClientRect().width - (horizontalLayoutPadding * paddingScale); - const panelHeight = this.singleSwitchPanel.nativeElement.getBoundingClientRect().height - (verticalLayoutPadding * paddingScale); + const computedStyle = getComputedStyle(this.singleSwitchPanel.nativeElement); + const [pLeft, pRight, pTop, pBottom] = ['paddingLeft', 'paddingRight', 'paddingTop', 'paddingBottom'] + .map(side => resolveCssSize(computedStyle[side])[0]); + const panelWidth = widgetBoundingClientRect.width - ((pLeft + pRight) || horizontalLayoutPadding * paddingScale); + const panelHeight = widgetBoundingClientRect.height - ((pTop + pBottom) || verticalLayoutPadding * paddingScale); this.renderer.setStyle(this.singleSwitchContent.nativeElement, 'transform', `scale(1)`); this.renderer.setStyle(this.singleSwitchContent.nativeElement, 'width', 'auto'); let contentWidth = this.singleSwitchToggleRow.nativeElement.getBoundingClientRect().width; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.models.ts index 94586c31de..62aae25816 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.models.ts @@ -80,6 +80,7 @@ export interface SingleSwitchWidgetSettings { offLabelFont: Font; offLabelColor: string; background: BackgroundSettings; + padding: string; } export const singleSwitchDefaultSettings: SingleSwitchWidgetSettings = { @@ -217,5 +218,6 @@ export const singleSwitchDefaultSettings: SingleSwitchWidgetSettings = { color: 'rgba(255,255,255,0.72)', blur: 3 } - } + }, + padding: '' }; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts index ff74bc58ac..263297ee75 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts @@ -191,10 +191,10 @@ export interface ScadaSymbolMetadata { properties: ScadaSymbolProperty[]; } -export const emptyMetadata = (): ScadaSymbolMetadata => ({ +export const emptyMetadata = (width?: number, height?: number): ScadaSymbolMetadata => ({ title: '', - widgetSizeX: 3, - widgetSizeY: 3, + widgetSizeX: width ? width/100 : 3, + widgetSizeY: height ? height/100 : 3, tags: [], behavior: [], properties: [] @@ -255,7 +255,17 @@ const parseScadaSymbolMetadataFromDom = (svgDoc: Document): ScadaSymbolMetadata if (elements.length) { return JSON.parse(elements[0].textContent); } else { - return emptyMetadata(); + const svg = svgDoc.getElementsByTagName('svg')[0]; + let width = null; + let height = null; + if (svg.viewBox.baseVal.width && svg.viewBox.baseVal.height) { + width = svg.viewBox.baseVal.width; + height = svg.viewBox.baseVal.height; + } else if (svg.width.baseVal.value && svg.height.baseVal.value) { + width = svg.width.baseVal.value; + height = svg.height.baseVal.value; + } + return emptyMetadata(width, height); } } catch (_e) { console.error(_e); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/value-card-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/value-card-widget-settings.component.html index 76f46862a6..5077c93d8e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/value-card-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/value-card-widget-settings.component.html @@ -93,5 +93,11 @@ <tb-background-settings formControlName="background"> </tb-background-settings> </div> + <div class="tb-form-row space-between"> + <div>{{ 'widget-config.card-padding' | translate }}</div> + <mat-form-field appearance="outline" subscriptSizing="dynamic"> + <input matInput formControlName="padding" placeholder="{{ 'widget-config.set' | translate }}"> + </mat-form-field> + </div> </div> </ng-container> diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/value-card-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/value-card-widget-settings.component.ts index 9693ca22d4..be7794802c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/value-card-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/value-card-widget-settings.component.ts @@ -110,7 +110,8 @@ export class ValueCardWidgetSettingsComponent extends WidgetSettingsComponent { dateFont: [settings.dateFont, []], dateColor: [settings.dateColor, []], - background: [settings.background, []] + background: [settings.background, []], + padding: [settings.padding, []] }); } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/single-switch-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/single-switch-widget-settings.component.html index db6d0371f9..2709266f2f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/single-switch-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/single-switch-widget-settings.component.html @@ -123,6 +123,12 @@ <tb-background-settings formControlName="background"> </tb-background-settings> </div> + <div class="tb-form-row space-between"> + <div>{{ 'widget-config.card-padding' | translate }}</div> + <mat-form-field appearance="outline" subscriptSizing="dynamic"> + <input matInput formControlName="padding" placeholder="{{ 'widget-config.set' | translate }}"> + </mat-form-field> + </div> </div> <div class="tb-form-panel"> <div class="tb-form-panel-title" translate>widgets.single-switch.switch</div> diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/single-switch-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/single-switch-widget-settings.component.ts index a1a3e951f2..a4a76e5294 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/single-switch-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/single-switch-widget-settings.component.ts @@ -102,7 +102,8 @@ export class SingleSwitchWidgetSettingsComponent extends WidgetSettingsComponent offLabelFont: [settings.offLabelFont, []], offLabelColor: [settings.offLabelColor, []], - background: [settings.background, []] + background: [settings.background, []], + padding: [settings.padding, []] }); } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/status-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/status-widget-settings.component.html index 21b7bc5cf0..892311733c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/status-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/status-widget-settings.component.html @@ -78,5 +78,11 @@ [layout]="statusWidgetSettingsForm.get('layout').value" formControlName="offState"> </tb-status-widget-state-settings> + <div class="tb-form-row space-between"> + <div>{{ 'widget-config.card-padding' | translate }}</div> + <mat-form-field appearance="outline" subscriptSizing="dynamic"> + <input matInput formControlName="padding" placeholder="{{ 'widget-config.set' | translate }}"> + </mat-form-field> + </div> </div> </ng-container> diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/status-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/status-widget-settings.component.ts index 03da985a0e..1130b58b21 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/status-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/status-widget-settings.component.ts @@ -73,7 +73,8 @@ export class StatusWidgetSettingsComponent extends WidgetSettingsComponent { disabledState: [settings.disabledState, []], layout: [settings.layout, []], onState: [settings.onState, []], - offState: [settings.offState, []] + offState: [settings.offState, []], + padding: [settings.padding, []] }); } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/weather/wind-speed-direction-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/weather/wind-speed-direction-widget-settings.component.html index 9265164c52..5271825ccf 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/weather/wind-speed-direction-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/weather/wind-speed-direction-widget-settings.component.html @@ -100,5 +100,11 @@ <tb-background-settings formControlName="background"> </tb-background-settings> </div> + <div class="tb-form-row space-between"> + <div>{{ 'widget-config.card-padding' | translate }}</div> + <mat-form-field appearance="outline" subscriptSizing="dynamic"> + <input matInput formControlName="padding" placeholder="{{ 'widget-config.set' | translate }}"> + </mat-form-field> + </div> </div> </ng-container> diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/weather/wind-speed-direction-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/weather/wind-speed-direction-widget-settings.component.ts index e6b8880758..2d16a030b7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/weather/wind-speed-direction-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/weather/wind-speed-direction-widget-settings.component.ts @@ -91,7 +91,8 @@ export class WindSpeedDirectionWidgetSettingsComponent extends WidgetSettingsCom arrowColor: [settings.arrowColor, []], - background: [settings.background, []] + background: [settings.background, []], + padding: [settings.padding, []] }); } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.html index 80ca1960f9..0ec08c2a05 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.html @@ -15,7 +15,7 @@ limitations under the License. --> -<div class="tb-wind-speed-direction-panel" [style]="backgroundStyle$ | async" [class.tb-wind-speed-direction-pointer]="hasCardClickAction" (click)="cardClick($event)"> +<div class="tb-wind-speed-direction-panel" [style.padding]="padding" [style]="backgroundStyle$ | async" [class.tb-wind-speed-direction-pointer]="hasCardClickAction" (click)="cardClick($event)"> <div class="tb-wind-speed-direction-overlay" [style]="overlayStyle"></div> <ng-container *ngTemplateOutlet="widgetTitlePanel"></ng-container> <div class="tb-wind-speed-direction-content"> diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.ts index 4ce5cf21d7..929f41fe48 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.ts @@ -42,7 +42,6 @@ import { getSingleTsValueByDataKey, overlayStyle } from '@shared/models/widget-settings.models'; -import { WidgetComponent } from '@home/components/widget/widget.component'; import { formatValue, isDefinedAndNotNull, isNumeric } from '@core/utils'; import { ResizeObserver } from '@juggle/resize-observer'; import { Path, Svg, SVG, Text } from '@svgdotjs/svg.js'; @@ -92,6 +91,7 @@ export class WindSpeedDirectionWidgetComponent implements OnInit, OnDestroy, Aft backgroundStyle$: Observable<ComponentStyle>; overlayStyle: ComponentStyle = {}; + padding: string; shapeResize$: ResizeObserver; @@ -111,8 +111,7 @@ export class WindSpeedDirectionWidgetComponent implements OnInit, OnDestroy, Aft private windDirection = 0; private centerValueText = 'N/A'; - constructor(private widgetComponent: WidgetComponent, - private imagePipe: ImagePipe, + constructor(private imagePipe: ImagePipe, private sanitizer: DomSanitizer, private renderer: Renderer2, private cd: ChangeDetectorRef) { @@ -142,6 +141,7 @@ export class WindSpeedDirectionWidgetComponent implements OnInit, OnDestroy, Aft this.backgroundStyle$ = backgroundStyle(this.settings.background, this.imagePipe, this.sanitizer); this.overlayStyle = overlayStyle(this.settings.background.overlay); + this.padding = this.settings.background.overlay.enabled ? undefined : this.settings.padding; this.hasCardClickAction = this.ctx.actionsApi.getActionDescriptors('cardClick').length > 0; } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.models.ts index 7801f80a17..5daa9e3d68 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.models.ts @@ -14,7 +14,6 @@ /// limitations under the License. /// -import { BatteryLevelLayout } from '@home/components/widget/lib/indicator/battery-level-widget.models'; import { BackgroundSettings, BackgroundType, @@ -59,6 +58,7 @@ export interface WindSpeedDirectionWidgetSettings { minorTicksColor: string; minorTicksFont: Font; background: BackgroundSettings; + padding: string } export const windSpeedDirectionDefaultSettings: WindSpeedDirectionWidgetSettings = { @@ -101,5 +101,6 @@ export const windSpeedDirectionDefaultSettings: WindSpeedDirectionWidgetSettings color: 'rgba(255,255,255,0.72)', blur: 3 } - } + }, + padding: '' }; diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-container.component.scss b/ui-ngx/src/app/modules/home/components/widget/widget-container.component.scss index 02b6d2737b..c452054c90 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget-container.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/widget-container.component.scss @@ -173,6 +173,7 @@ gridster-item:hover { } .tooltipster-sidetip.tb-widget-edit-actions-tooltip { + position: absolute !important; .tooltipster-box { user-select: none; background: #fff; diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-container.component.ts b/ui-ngx/src/app/modules/home/components/widget/widget-container.component.ts index b45b3432c4..0032ef35b4 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget-container.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/widget-container.component.ts @@ -148,9 +148,9 @@ export class WidgetContainerComponent extends PageComponent implements OnInit, O $(this.gridsterItem.el).on('mousedown', (e) => this.onMouseDown(e.originalEvent)); $(this.gridsterItem.el).on('click', (e) => this.onClicked(e.originalEvent)); $(this.gridsterItem.el).on('contextmenu', (e) => this.onContextMenu(e.originalEvent)); - const dashboardElement = this.widget.widgetContext.dashboardPageElement; - if (dashboardElement) { - this.initEditWidgetActionTooltip(dashboardElement); + const dashboardContentElement = this.widget.widgetContext.dashboardContentElement; + if (dashboardContentElement) { + this.initEditWidgetActionTooltip(dashboardContentElement); } } diff --git a/ui-ngx/src/app/modules/home/models/services.map.ts b/ui-ngx/src/app/modules/home/models/services.map.ts index cca04d8dc9..073bbd5b43 100644 --- a/ui-ngx/src/app/modules/home/models/services.map.ts +++ b/ui-ngx/src/app/modules/home/models/services.map.ts @@ -50,6 +50,8 @@ import { TenantService } from '@core/http/tenant.service'; import { TenantProfileService } from '@core/http/tenant-profile.service'; import { UiSettingsService } from '@core/http/ui-settings.service'; import { UsageInfoService } from '@core/http/usage-info.service'; +import { EventService } from '@core/http/event.service'; +import { AuditLogService } from '@core/http/audit-log.service'; export const ServicesMap = new Map<string, Type<any>>( [ @@ -87,6 +89,8 @@ export const ServicesMap = new Map<string, Type<any>>( ['userSettingsService', UserSettingsService], ['uiSettingsService', UiSettingsService], ['usageInfoService', UsageInfoService], - ['notificationService', NotificationService] + ['notificationService', NotificationService], + ['eventService', EventService], + ['auditLogService', AuditLogService] ] ); diff --git a/ui-ngx/src/app/modules/home/models/widget-component.models.ts b/ui-ngx/src/app/modules/home/models/widget-component.models.ts index fa4d367959..5a1a28472e 100644 --- a/ui-ngx/src/app/modules/home/models/widget-component.models.ts +++ b/ui-ngx/src/app/modules/home/models/widget-component.models.ts @@ -184,6 +184,10 @@ export class WidgetContext { return this.dashboard?.stateController?.dashboardCtrl?.elRef?.nativeElement; } + get dashboardContentElement(): HTMLElement { + return this.dashboard?.stateController?.dashboardCtrl?.dashboardContent?.nativeElement; + } + authService: AuthService; deviceService: DeviceService; assetService: AssetService; diff --git a/ui-ngx/src/app/modules/home/pages/admin/oauth2/clients/clients-table-config.resolver.ts b/ui-ngx/src/app/modules/home/pages/admin/oauth2/clients/clients-table-config.resolver.ts index 3c3bbe3a54..178b817175 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/oauth2/clients/clients-table-config.resolver.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/oauth2/clients/clients-table-config.resolver.ts @@ -64,9 +64,8 @@ export class ClientsTableConfigResolver implements Resolve<EntityTableConfig<OAu this.config.columns.push( new DateEntityTableColumn<OAuth2ClientInfo>('createdTime', 'common.created-time', this.datePipe, '170px'), - new EntityTableColumn<OAuth2ClientInfo>('title', 'admin.oauth2.title', '35%'), - new EntityTableColumn<OAuth2ClientInfo>('providerName', 'admin.oauth2.provider', '170px'), - new EntityTableColumn<OAuth2ClientInfo>('platforms', 'admin.oauth2.allowed-platforms', '170px', + new EntityTableColumn<OAuth2ClientInfo>('title', 'admin.oauth2.title', '350px'), + new EntityTableColumn<OAuth2ClientInfo>('platforms', 'admin.oauth2.allowed-platforms', '100%', (clientInfo) => { return clientInfo.platforms && clientInfo.platforms.length ? clientInfo.platforms.map(platform => this.translate.instant(platformTypeTranslations.get(platform))).join(', ') : diff --git a/ui-ngx/src/app/modules/home/pages/admin/security-settings.component.html b/ui-ngx/src/app/modules/home/pages/admin/security-settings.component.html index 3d399d01a1..0b9df7c5ae 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/security-settings.component.html +++ b/ui-ngx/src/app/modules/home/pages/admin/security-settings.component.html @@ -46,6 +46,44 @@ <input matInput type="email" formControlName="userLockoutNotificationEmail"/> </mat-form-field> + <mat-form-field class="mat-block"> + <mat-label translate>admin.user-activation-token-ttl</mat-label> + <input matInput type="number" + formControlName="userActivationTokenTtl" + step="1" + min="1" + max="24"/> + <mat-error *ngIf="securitySettingsFormGroup.get('userActivationTokenTtl').hasError('min')"> + {{ 'admin.user-activation-token-ttl-range' | translate }} + </mat-error> + <mat-error *ngIf="securitySettingsFormGroup.get('userActivationTokenTtl').hasError('max')"> + {{ 'admin.user-activation-token-ttl-range' | translate }} + </mat-error> + </mat-form-field> + <mat-form-field class="mat-block"> + <mat-label translate>admin.password-reset-token-ttl</mat-label> + <input matInput type="number" + formControlName="passwordResetTokenTtl" + step="1" + min="1" + max="24"/> + <mat-error *ngIf="securitySettingsFormGroup.get('passwordResetTokenTtl').hasError('min')"> + {{ 'admin.password-reset-token-ttl-range' | translate }} + </mat-error> + <mat-error *ngIf="securitySettingsFormGroup.get('passwordResetTokenTtl').hasError('max')"> + {{ 'admin.password-reset-token-ttl-range' | translate }} + </mat-error> + </mat-form-field> + <mat-form-field class="mat-block"> + <mat-label translate>admin.mobile-secret-key-length</mat-label> + <input matInput type="number" + formControlName="mobileSecretKeyLength" + step="1" + min="1"/> + <mat-error *ngIf="securitySettingsFormGroup.get('mobileSecretKeyLength').hasError('min')"> + {{ 'admin.mobile-secret-key-length-range' | translate }} + </mat-error> + </mat-form-field> </fieldset> <fieldset class="fields-group"> diff --git a/ui-ngx/src/app/modules/home/pages/admin/security-settings.component.ts b/ui-ngx/src/app/modules/home/pages/admin/security-settings.component.ts index c7ac489753..712e2bb358 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/security-settings.component.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/security-settings.component.ts @@ -75,6 +75,9 @@ export class SecuritySettingsComponent extends PageComponent implements HasConfi this.securitySettingsFormGroup = this.fb.group({ maxFailedLoginAttempts: [null, [Validators.min(0)]], userLockoutNotificationEmail: ['', []], + userActivationTokenTtl: [24, [Validators.required, Validators.min(1), Validators.max(24)]], + passwordResetTokenTtl: [24, [Validators.required, Validators.min(1), Validators.max(24)]], + mobileSecretKeyLength: [null, [Validators.min(1)]], passwordPolicy: this.fb.group( { minimumLength: [null, [Validators.required, Validators.min(6), Validators.max(50)]], diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag-function-panel.component.html b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag-function-panel.component.html index 27c22df7a8..940be57364 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag-function-panel.component.html +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag-function-panel.component.html @@ -30,8 +30,7 @@ <tb-js-func #tagFunctionComponent minHeight="300px" formControlName="tagFunction" - [objectHighlightRules]="objectHighlightRules" - [propertyHighlightRules]="propertyHighlightRules" + [highlightRules]="highlightRules" [editorCompleter]="completer" [functionArgs]="tagFunctionArgs" [helpId]="tagFunctionHelpId"> diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag-function-panel.component.ts b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag-function-panel.component.ts index d46ba364d7..3da729c442 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag-function-panel.component.ts +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag-function-panel.component.ts @@ -28,12 +28,10 @@ import { TbPopoverComponent } from '@shared/components/popover.component'; import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; import { WidgetService } from '@core/http/widget.service'; import { TbEditorCompleter } from '@shared/models/ace/completion.models'; -import { TbHighlightRule } from '@shared/models/ace/ace.models'; +import { AceHighlightRules } from '@shared/models/ace/ace.models'; import { scadaSymbolClickActionHighlightRules, - scadaSymbolClickActionPropertiesHighlightRules, - scadaSymbolElementStateRenderHighlightRules, - scadaSymbolElementStateRenderPropertiesHighlightRules + scadaSymbolRenderFunctionHighlightRules } from '@home/pages/scada-symbol/scada-symbol-editor.models'; import { JsFuncComponent } from '@shared/components/js-func.component'; @@ -79,9 +77,7 @@ export class ScadaSymbolMetadataTagFunctionPanelComponent implements OnInit, Aft tagFunctionHelpId: string; - objectHighlightRules: TbHighlightRule[]; - - propertyHighlightRules: TbHighlightRule[]; + highlightRules: AceHighlightRules; constructor(private fb: UntypedFormBuilder, private widgetService: WidgetService) { @@ -99,14 +95,12 @@ export class ScadaSymbolMetadataTagFunctionPanelComponent implements OnInit, Aft if (this.tagFunctionType === 'renderFunction') { this.panelTitle = 'scada.state-render-function'; this.tagFunctionArgs = ['ctx', 'element']; - this.objectHighlightRules = scadaSymbolElementStateRenderHighlightRules; - this.propertyHighlightRules = scadaSymbolElementStateRenderPropertiesHighlightRules; + this.highlightRules = scadaSymbolRenderFunctionHighlightRules; this.tagFunctionHelpId = 'scada/tag_state_render_fn'; } else if (this.tagFunctionType === 'clickAction') { this.panelTitle = 'scada.tag.on-click-action'; this.tagFunctionArgs = ['ctx', 'element', 'event']; - this.objectHighlightRules = scadaSymbolClickActionHighlightRules; - this.propertyHighlightRules = scadaSymbolClickActionPropertiesHighlightRules; + this.highlightRules = scadaSymbolClickActionHighlightRules; this.tagFunctionHelpId = 'scada/tag_click_action_fn'; } } diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.html b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.html index 9e5d22fa94..67c77f7f2a 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.html +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.html @@ -80,8 +80,7 @@ <tb-js-func formControlName="stateRenderFunction" minHeight="300px" [editorCompleter]="generalStateRenderFunctionCompleter" - [objectHighlightRules]="scadaSymbolGeneralStateRenderHighlightRules" - [propertyHighlightRules]="scadaSymbolGeneralStateRenderPropertiesHighlightRules" + [highlightRules]="highlightRules" [functionArgs]="['ctx', 'svg']" helpId="scada/symbol_state_render_fn"> </tb-js-func> diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.ts b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.ts index f5ecaab3d2..a5d38991b9 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.ts +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.ts @@ -49,8 +49,7 @@ import { elementStateRenderFunctionCompletions, generalStateRenderFunctionCompletions, scadaSymbolContextCompletion, - scadaSymbolGeneralStateRenderHighlightRules, - scadaSymbolGeneralStateRenderPropertiesHighlightRules + scadaSymbolGeneralStateHighlightRules } from '@home/pages/scada-symbol/scada-symbol-editor.models'; import { CustomTranslatePipe } from '@shared/pipe/custom-translate.pipe'; import { IAliasController } from '@core/api/widget-api.models'; @@ -122,9 +121,7 @@ export class ScadaSymbolMetadataComponent extends PageComponent implements OnIni elementStateRenderFunctionCompleter: TbEditorCompleter; clickActionFunctionCompleter: TbEditorCompleter; - scadaSymbolGeneralStateRenderHighlightRules = scadaSymbolGeneralStateRenderHighlightRules; - - scadaSymbolGeneralStateRenderPropertiesHighlightRules = scadaSymbolGeneralStateRenderPropertiesHighlightRules; + highlightRules = scadaSymbolGeneralStateHighlightRules; constructor(protected store: Store<AppState>, private fb: UntypedFormBuilder, diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-property-panel.component.html b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-property-panel.component.html index 9fd461c229..15322b38d4 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-property-panel.component.html +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-property-panel.component.html @@ -136,6 +136,7 @@ <div class="fixed-title-width" translate>scada.property.disable-on-property</div> <mat-form-field class="flex" appearance="outline" subscriptSizing="dynamic"> <mat-select formControlName="disableOnProperty" placeholder="{{ 'widget-config.set' | translate }}"> + <mat-option [value]="null"></mat-option> <mat-option *ngFor="let prop of booleanPropertyIds" [value]="prop"> {{ prop }} </mat-option> diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-editor.models.ts b/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-editor.models.ts index ddc935d202..433e311fb7 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-editor.models.ts +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-editor.models.ts @@ -34,7 +34,7 @@ import { } from '@home/components/widget/lib/scada/scada-symbol.models'; import { TbEditorCompletion, TbEditorCompletions } from '@shared/models/ace/completion.models'; import { CustomTranslatePipe } from '@shared/pipe/custom-translate.pipe'; -import { TbHighlightRule } from '@shared/models/ace/ace.models'; +import { AceHighlightRule, AceHighlightRules } from '@shared/models/ace/ace.models'; import { ValueType } from '@shared/models/constants'; import ITooltipsterInstance = JQueryTooltipster.ITooltipsterInstance; import TooltipPositioningSide = JQueryTooltipster.TooltipPositioningSide; @@ -916,91 +916,184 @@ export class ScadaSymbolElement { } -const scadaSymbolCtxObjectHighlightRules: TbHighlightRule[] = [ - { - class: 'scada-symbol-ctx', - regex: /(?<=\W|^)(ctx)(?=\W|$)\b/ - } -]; +const identifierRe = /[a-zA-Z$_\u00a1-\uffff][a-zA-Z\d$_\u00a1-\uffff]*/; -export const scadaSymbolGeneralStateRenderHighlightRules: TbHighlightRule[] = - scadaSymbolCtxObjectHighlightRules.concat({ - class: 'scada-symbol-svg', - regex: /(?<=\W|^)(svg)(?=\W|$)\b/ - }); +const dotOperatorHighlightRule: AceHighlightRule = { + token: 'punctuation.operator', + regex: /[.](?![.])/, +}; -export const scadaSymbolElementStateRenderHighlightRules: TbHighlightRule[] = - scadaSymbolCtxObjectHighlightRules.concat({ - class: 'scada-symbol-element', - regex: /(?<=\W|^)(element)(?=\W|$)\b/ - }); +const endGroupHighlightRule: AceHighlightRule = { + regex: '', + token: 'empty', + next: 'no_regex' +}; -export const scadaSymbolClickActionHighlightRules: TbHighlightRule[] = - scadaSymbolElementStateRenderHighlightRules.concat({ - class: 'scada-symbol-event', - regex: /(?<=\W|^)(event)(?=\W|$)\b/ - }); +const scadaSymbolCtxObjectHighlightRule: AceHighlightRule = { + token: 'tb.scada-symbol-ctx', + regex: /\bctx\b/, + next: 'scadaSymbolCtxApi' +}; -const scadaSymbolCtxPropertyHighlightRules: TbHighlightRule[] = [ - { - class: 'scada-symbol-ctx-properties', - regex: /(?<=ctx\.)(properties)\b/ - }, - { - class: 'scada-symbol-ctx-tags', - regex: /(?<=ctx\.)(tags)\b/ - }, - { - class: 'scada-symbol-ctx-values', - regex: /(?<=ctx\.)(values)\b/ - }, - { - class: 'scada-symbol-ctx-api', - regex: /(?<=ctx\.)(api)\b/ - }, - { - class: 'scada-symbol-ctx-svg', - regex: /(?<=ctx\.)(svg)\b/ - }, - { - class: 'scada-symbol-ctx-property', - regex: /(?<=ctx\.properties\.)([a-zA-Z$_\u00a1-\uffff][a-zA-Z\d$_\u00a1-\uffff]*)\b/ - }, - { - class: 'scada-symbol-ctx-tag', - regex: /(?<=ctx\.tags\.)([a-zA-Z$_\u00a1-\uffff][a-zA-Z\d$_\u00a1-\uffff]*)\b/ - }, - { - class: 'scada-symbol-ctx-value', - regex: /(?<=ctx\.values\.)([a-zA-Z$_\u00a1-\uffff][a-zA-Z\d$_\u00a1-\uffff]*)\b/ - }, - { - class: 'scada-symbol-ctx-api-method', - regex: /(?<=ctx\.api\.)([a-zA-Z$_\u00a1-\uffff][a-zA-Z\d$_\u00a1-\uffff]*)\b/ - }, - { - class: 'scada-symbol-ctx-svg-method', - regex: /(?<=ctx\.svg\.)([a-zA-Z$_\u00a1-\uffff][a-zA-Z\d$_\u00a1-\uffff]*)\b/ - } -]; - -export const scadaSymbolGeneralStateRenderPropertiesHighlightRules: TbHighlightRule[] = - scadaSymbolCtxPropertyHighlightRules.concat({ - class: 'scada-symbol-svg-properties', - regex: /(?<=svg\.)([a-zA-Z$_\u00a1-\uffff][a-zA-Z\d$_\u00a1-\uffff]*)\b/ - }); +const scadaSymbolSVGHighlightRule: AceHighlightRule = { + token: 'tb.scada-symbol-svg', + regex: /\bsvg\b/, + next: 'scadaSymbolSVGApi' +}; -export const scadaSymbolElementStateRenderPropertiesHighlightRules: TbHighlightRule[] = - scadaSymbolCtxPropertyHighlightRules.concat({ - class: 'scada-symbol-element-properties', - regex: /(?<=element\.)([a-zA-Z$_\u00a1-\uffff][a-zA-Z\d$_\u00a1-\uffff]*)\b/ - }); +const scadaSymbolElementHighlightRule: AceHighlightRule = { + token: 'tb.scada-symbol-element', + regex: /\belement\b/, + next: 'scadaSymbolElementApi' +}; -export const scadaSymbolClickActionPropertiesHighlightRules: TbHighlightRule[] = - scadaSymbolElementStateRenderPropertiesHighlightRules.concat({ - class: 'scada-symbol-event-properties', - regex: /(?<=event\.)([a-zA-Z$_\u00a1-\uffff][a-zA-Z\d$_\u00a1-\uffff]*)\b/ - }); +const scadaSymbolEventHighlightRule: AceHighlightRule = { + token: 'tb.scada-symbol-event', + regex: /\bevent\b/, + next: 'scadaSymbolEventApi' +}; + +const scadaSymbolCtxApiHighlightRules: AceHighlightRules = { + scadaSymbolCtxApi: [ + dotOperatorHighlightRule, + { + token: 'tb.scada-symbol-ctx-properties', + regex: /properties/, + next: 'scadaSymbolCtxPropertiesApi' + }, + { + token: 'tb.scada-symbol-ctx-tags', + regex: /tags/, + next: 'scadaSymbolCtxTagsApi' + }, + { + token: 'tb.scada-symbol-ctx-values', + regex: /values/, + next: 'scadaSymbolCtxValuesApi' + }, + { + token: 'tb.scada-symbol-ctx-api', + regex: /api/, + next: 'scadaSymbolCtxApiMethodApi' + }, + { + token: 'tb.scada-symbol-ctx-svg', + regex: /svg/, + next: 'scadaSymbolCtxSVGMethodApi' + }, + endGroupHighlightRule + ], + scadaSymbolCtxPropertiesApi: [ + dotOperatorHighlightRule, + { + token: 'tb.scada-symbol-ctx-property', + regex: identifierRe, + next: 'no_regex' + }, + endGroupHighlightRule + ], + scadaSymbolCtxTagsApi: [ + dotOperatorHighlightRule, + { + token: 'tb.scada-symbol-ctx-tag', + regex: identifierRe, + next: 'no_regex' + }, + endGroupHighlightRule + ], + scadaSymbolCtxValuesApi: [ + dotOperatorHighlightRule, + { + token: 'tb.scada-symbol-ctx-value', + regex: identifierRe, + next: 'no_regex' + }, + endGroupHighlightRule + ], + scadaSymbolCtxApiMethodApi: [ + dotOperatorHighlightRule, + { + token: 'tb.scada-symbol-ctx-api-method', + regex: identifierRe, + next: 'no_regex' + }, + endGroupHighlightRule + ], + scadaSymbolCtxSVGMethodApi: [ + dotOperatorHighlightRule, + { + token: 'tb.scada-symbol-ctx-svg-method', + regex: identifierRe, + next: 'no_regex' + }, + endGroupHighlightRule + ] +}; + +const scadaSymbolSVGPropertyHighlightRules: AceHighlightRules = { + scadaSymbolSVGApi: [ + dotOperatorHighlightRule, + { + token: 'tb.scada-symbol-svg-properties', + regex: identifierRe, + next: 'no_regex' + }, + endGroupHighlightRule + ] +}; + +const scadaSymbolElementPropertyHighlightRules: AceHighlightRules = { + scadaSymbolElementApi: [ + dotOperatorHighlightRule, + { + token: 'tb.scada-symbol-element-properties', + regex: identifierRe, + next: 'no_regex' + }, + endGroupHighlightRule + ] +}; + +const scadaSymbolEventPropertyHighlightRules: AceHighlightRules = { + scadaSymbolEventApi: [ + dotOperatorHighlightRule, + { + token: 'tb.scada-symbol-event-properties', + regex: identifierRe, + next: 'no_regex' + }, + endGroupHighlightRule + ] +}; + +export const scadaSymbolGeneralStateHighlightRules: AceHighlightRules = { + start: [ + scadaSymbolCtxObjectHighlightRule, + scadaSymbolSVGHighlightRule + ], + ...scadaSymbolCtxApiHighlightRules, + ...scadaSymbolSVGPropertyHighlightRules +}; + +export const scadaSymbolRenderFunctionHighlightRules: AceHighlightRules = { + no_regex: [ + scadaSymbolCtxObjectHighlightRule, + scadaSymbolElementHighlightRule + ], + ...scadaSymbolCtxApiHighlightRules, + ...scadaSymbolElementPropertyHighlightRules +}; + +export const scadaSymbolClickActionHighlightRules: AceHighlightRules = { + start: [ + scadaSymbolCtxObjectHighlightRule, + scadaSymbolElementHighlightRule, + scadaSymbolEventHighlightRule + ], + ...scadaSymbolCtxApiHighlightRules, + ...scadaSymbolElementPropertyHighlightRules, + ...scadaSymbolEventPropertyHighlightRules +}; export const generalStateRenderFunctionCompletions = (ctxCompletion: TbEditorCompletion): TbEditorCompletions => ({ ctx: ctxCompletion, diff --git a/ui-ngx/src/app/modules/home/pages/user/activation-link-dialog.component.html b/ui-ngx/src/app/modules/home/pages/user/activation-link-dialog.component.html index cabb688525..d03b50418d 100644 --- a/ui-ngx/src/app/modules/home/pages/user/activation-link-dialog.component.html +++ b/ui-ngx/src/app/modules/home/pages/user/activation-link-dialog.component.html @@ -30,7 +30,7 @@ <div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div> <div mat-dialog-content tb-toast toastTarget="activationLinkDialogContent"> <div class="mat-content" fxLayout="column"> - <span [innerHTML]="'user.activation-link-text' | translate: {activationLink: activationLink}"></span> + <span [innerHTML]="'user.activation-link-text' | translate: {activationLink: activationLink, activationLinkTtl: activationLinkTtl}"></span> <div fxLayout="row" fxLayoutAlign="start center"> <pre class="tb-highlight" fxFlex><code>{{ activationLink }}</code></pre> <button mat-icon-button diff --git a/ui-ngx/src/app/modules/home/pages/user/activation-link-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/user/activation-link-dialog.component.ts index d2c2037d6b..598cda29ef 100644 --- a/ui-ngx/src/app/modules/home/pages/user/activation-link-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/user/activation-link-dialog.component.ts @@ -14,7 +14,7 @@ /// limitations under the License. /// -import { Component, Inject, OnInit } from '@angular/core'; +import { Component, Inject } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @@ -22,29 +22,31 @@ import { TranslateService } from '@ngx-translate/core'; import { ActionNotificationShow } from '@core/notification/notification.actions'; import { DialogComponent } from '@shared/components/dialog.component'; import { Router } from '@angular/router'; +import { ActivationLinkInfo } from '@shared/models/user.model'; +import { MillisecondsToTimeStringPipe } from '@shared/pipe/milliseconds-to-time-string.pipe'; export interface ActivationLinkDialogData { - activationLink: string; + activationLinkInfo: ActivationLinkInfo; } @Component({ selector: 'tb-activation-link-dialog', templateUrl: './activation-link-dialog.component.html' }) -export class ActivationLinkDialogComponent extends DialogComponent<ActivationLinkDialogComponent, void> implements OnInit { +export class ActivationLinkDialogComponent extends DialogComponent<ActivationLinkDialogComponent, void> { activationLink: string; + activationLinkTtl: string; constructor(protected store: Store<AppState>, protected router: Router, @Inject(MAT_DIALOG_DATA) public data: ActivationLinkDialogData, public dialogRef: MatDialogRef<ActivationLinkDialogComponent, void>, - private translate: TranslateService) { + private translate: TranslateService, + private millisecondsToTimeStringPipe: MillisecondsToTimeStringPipe) { super(store, router, dialogRef); - this.activationLink = this.data.activationLink; - } - - ngOnInit(): void { + this.activationLink = this.data.activationLinkInfo.value; + this.activationLinkTtl = this.millisecondsToTimeStringPipe.transform(this.data.activationLinkInfo.ttlMs); } close(): void { diff --git a/ui-ngx/src/app/modules/home/pages/user/add-user-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/user/add-user-dialog.component.ts index 73bacc4c17..37c55c40c2 100644 --- a/ui-ngx/src/app/modules/home/pages/user/add-user-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/pages/user/add-user-dialog.component.ts @@ -21,7 +21,7 @@ import { AppState } from '@core/core.state'; import { UntypedFormGroup } from '@angular/forms'; import { UserComponent } from '@modules/home/pages/user/user.component'; import { Authority } from '@shared/models/authority.enum'; -import { ActivationMethod, activationMethodTranslations, User } from '@shared/models/user.model'; +import { ActivationLinkInfo, ActivationMethod, activationMethodTranslations, User } from '@shared/models/user.model'; import { CustomerId } from '@shared/models/id/customer-id'; import { UserService } from '@core/http/user.service'; import { Observable } from 'rxjs'; @@ -88,7 +88,7 @@ export class AddUserDialogComponent extends DialogComponent<AddUserDialogCompone this.userService.saveUser(this.user, sendActivationEmail).subscribe( (user) => { if (this.activationMethod === ActivationMethod.DISPLAY_ACTIVATION_LINK) { - this.userService.getActivationLink(user.id.id).subscribe( + this.userService.getActivationLinkInfo(user.id.id).subscribe( (activationLink) => { this.displayActivationLink(activationLink).subscribe( () => { @@ -105,13 +105,13 @@ export class AddUserDialogComponent extends DialogComponent<AddUserDialogCompone } } - displayActivationLink(activationLink: string): Observable<void> { + displayActivationLink(activationLinkInfo: ActivationLinkInfo): Observable<void> { return this.dialog.open<ActivationLinkDialogComponent, ActivationLinkDialogData, void>(ActivationLinkDialogComponent, { disableClose: true, panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], data: { - activationLink + activationLinkInfo } }).afterClosed(); } diff --git a/ui-ngx/src/app/modules/home/pages/user/users-table-config.resolver.ts b/ui-ngx/src/app/modules/home/pages/user/users-table-config.resolver.ts index 6e762064cc..a8f7df963f 100644 --- a/ui-ngx/src/app/modules/home/pages/user/users-table-config.resolver.ts +++ b/ui-ngx/src/app/modules/home/pages/user/users-table-config.resolver.ts @@ -193,14 +193,14 @@ export class UsersTableConfigResolver implements Resolve<EntityTableConfig<User> if ($event) { $event.stopPropagation(); } - this.userService.getActivationLink(user.id.id).subscribe( - (activationLink) => { + this.userService.getActivationLinkInfo(user.id.id).subscribe( + (activationLinkInfo) => { this.dialog.open<ActivationLinkDialogComponent, ActivationLinkDialogData, void>(ActivationLinkDialogComponent, { disableClose: true, panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], data: { - activationLink + activationLinkInfo } }); } diff --git a/ui-ngx/src/app/modules/home/pages/widget/save-widget-type-as-dialog.component.html b/ui-ngx/src/app/modules/home/pages/widget/save-widget-type-as-dialog.component.html index 8d0f6bd6f5..804730dbfe 100644 --- a/ui-ngx/src/app/modules/home/pages/widget/save-widget-type-as-dialog.component.html +++ b/ui-ngx/src/app/modules/home/pages/widget/save-widget-type-as-dialog.component.html @@ -39,6 +39,7 @@ </mat-form-field> <tb-widgets-bundle-select formControlName="widgetsBundle" + createNew bundlesScope="{{bundlesScope}}"> </tb-widgets-bundle-select> </div> diff --git a/ui-ngx/src/app/modules/home/pages/widget/widget-library.module.ts b/ui-ngx/src/app/modules/home/pages/widget/widget-library.module.ts index 1ee25529b0..80438b4f4d 100644 --- a/ui-ngx/src/app/modules/home/pages/widget/widget-library.module.ts +++ b/ui-ngx/src/app/modules/home/pages/widget/widget-library.module.ts @@ -28,6 +28,7 @@ import { WidgetTypeComponent } from '@home/pages/widget/widget-type.component'; import { WidgetTypeTabsComponent } from '@home/pages/widget/widget-type-tabs.component'; import { WidgetsBundleWidgetsComponent } from '@home/pages/widget/widgets-bundle-widgets.component'; import { WidgetTypeAutocompleteComponent } from '@home/pages/widget/widget-type-autocomplete.component'; +import { WidgetsBundleDialogComponent } from '@home/pages/widget/widgets-bundle-dialog.component'; @NgModule({ declarations: [ @@ -39,7 +40,8 @@ import { WidgetTypeAutocompleteComponent } from '@home/pages/widget/widget-type- SelectWidgetTypeDialogComponent, SaveWidgetTypeAsDialogComponent, WidgetTypeTabsComponent, - WidgetsBundleTabsComponent + WidgetsBundleTabsComponent, + WidgetsBundleDialogComponent ], imports: [ CommonModule, diff --git a/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle-dialog.component.html b/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle-dialog.component.html new file mode 100644 index 0000000000..592be51486 --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle-dialog.component.html @@ -0,0 +1,53 @@ +<!-- + + Copyright © 2016-2024 The Thingsboard Authors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +--> +<form (ngSubmit)="save()" style="width: 650px;"> + <mat-toolbar color="primary"> + <h2 translate>widgets-bundle.add</h2> + <span fxFlex></span> + <button mat-icon-button + (click)="cancel()" + type="button"> + <mat-icon class="material-icons">close</mat-icon> + </button> + </mat-toolbar> + <mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async"> + </mat-progress-bar> + <div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div> + <div mat-dialog-content> + <tb-widgets-bundle + #widgetsBundleComponent + [isEdit]="true" + [entity]="widgetsBundle" + [standalone]="true"> + </tb-widgets-bundle> + </div> + <div mat-dialog-actions fxLayoutAlign="end center"> + <button mat-button color="primary" + type="button" + cdkFocusInitial + [disabled]="(isLoading$ | async)" + (click)="cancel()"> + {{ 'action.cancel' | translate }} + </button> + <button mat-raised-button color="primary" + type="submit" + [disabled]="(isLoading$ | async) || widgetsBundleComponent.entityForm?.invalid || !widgetsBundleComponent.entityForm?.dirty"> + {{ 'action.add' | translate }} + </button> + </div> +</form> diff --git a/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle-dialog.component.scss b/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle-dialog.component.scss new file mode 100644 index 0000000000..0556c6bd25 --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle-dialog.component.scss @@ -0,0 +1,22 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +:host ::ng-deep { + tb-widgets-bundle { + .mat-padding { + padding: 0; + } + } +} diff --git a/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle-dialog.component.ts new file mode 100644 index 0000000000..bb5f93cb66 --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle-dialog.component.ts @@ -0,0 +1,78 @@ +/// +/// Copyright © 2016-2024 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { Component, Inject, SkipSelf, ViewChild } from '@angular/core'; +import { ErrorStateMatcher } from '@angular/material/core'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { FormGroupDirective, NgForm, UntypedFormControl } from '@angular/forms'; +import { DialogComponent } from '@shared/components/dialog.component'; +import { Router } from '@angular/router'; +import { WidgetsBundle } from '@shared/models/widgets-bundle.model'; +import { WidgetsBundleComponent } from '@home/pages/widget/widgets-bundle.component'; +import { WidgetService } from '@core/http/widget.service'; + +export interface WidgetsBundleDialogData { + widgetsBundle: WidgetsBundle; +} + +@Component({ + selector: 'tb-widgets-bundle-dialog', + templateUrl: './widgets-bundle-dialog.component.html', + providers: [{provide: ErrorStateMatcher, useExisting: WidgetsBundleDialogComponent}], + styleUrls: ['widgets-bundle-dialog.component.scss'] +}) +export class WidgetsBundleDialogComponent extends + DialogComponent<WidgetsBundleDialogComponent, WidgetsBundle> implements ErrorStateMatcher { + + widgetsBundle: WidgetsBundle; + + submitted = false; + + @ViewChild('widgetsBundleComponent', {static: true}) widgetsBundleComponent: WidgetsBundleComponent; + + constructor(protected store: Store<AppState>, + protected router: Router, + @Inject(MAT_DIALOG_DATA) public data: WidgetsBundleDialogData, + public dialogRef: MatDialogRef<WidgetsBundleDialogComponent, WidgetsBundle>, + @SkipSelf() private errorStateMatcher: ErrorStateMatcher, + private widgetsService: WidgetService) { + super(store, router, dialogRef); + this.widgetsBundle = this.data.widgetsBundle; + } + + isErrorState(control: UntypedFormControl | null, form: FormGroupDirective | NgForm | null): boolean { + const originalErrorState = this.errorStateMatcher.isErrorState(control, form); + const customErrorState = !!(control && control.invalid && this.submitted); + return originalErrorState || customErrorState; + } + + cancel(): void { + this.dialogRef.close(null); + } + + save(): void { + this.submitted = true; + if (this.widgetsBundleComponent.entityForm.valid) { + this.widgetsBundle = {...this.widgetsBundle, ...this.widgetsBundleComponent.entityFormValue()}; + this.widgetsService.saveWidgetsBundle(this.widgetsBundle).subscribe((widgetBundle) => { + this.dialogRef.close(widgetBundle); + }); + } + } + +} diff --git a/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle.component.html b/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle.component.html index f95d085688..df66eee579 100644 --- a/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle.component.html +++ b/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle.component.html @@ -15,7 +15,7 @@ limitations under the License. --> -<div class="tb-details-buttons" fxLayout.xs="column"> +<div class="tb-details-buttons" fxLayout.xs="column" *ngIf="!standalone"> <button mat-raised-button color="primary" [disabled]="(isLoading$ | async)" (click)="onEntityAction($event, 'open')" diff --git a/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle.component.ts b/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle.component.ts index ca0912ea11..5b0d118313 100644 --- a/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle.component.ts +++ b/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle.component.ts @@ -14,7 +14,7 @@ /// limitations under the License. /// -import { ChangeDetectorRef, Component, Inject } from '@angular/core'; +import { ChangeDetectorRef, Component, Inject, Input, Optional } from '@angular/core'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; import { EntityComponent } from '../../components/entity/entity.component'; @@ -29,9 +29,12 @@ import { EntityTableConfig } from '@home/models/entity/entities-table-config.mod }) export class WidgetsBundleComponent extends EntityComponent<WidgetsBundle> { + @Input() + standalone = false; + constructor(protected store: Store<AppState>, - @Inject('entity') protected entityValue: WidgetsBundle, - @Inject('entitiesTableConfig') protected entitiesTableConfigValue: EntityTableConfig<WidgetsBundle>, + @Optional() @Inject('entity') protected entityValue: WidgetsBundle, + @Optional() @Inject('entitiesTableConfig') protected entitiesTableConfigValue: EntityTableConfig<WidgetsBundle>, public fb: UntypedFormBuilder, protected cd: ChangeDetectorRef) { super(store, fb, entityValue, entitiesTableConfigValue, cd); diff --git a/ui-ngx/src/app/modules/login/login-routing.module.ts b/ui-ngx/src/app/modules/login/login-routing.module.ts index bfebce37a1..4b569f2e9f 100644 --- a/ui-ngx/src/app/modules/login/login-routing.module.ts +++ b/ui-ngx/src/app/modules/login/login-routing.module.ts @@ -24,6 +24,7 @@ import { ResetPasswordComponent } from '@modules/login/pages/login/reset-passwor import { CreatePasswordComponent } from '@modules/login/pages/login/create-password.component'; import { TwoFactorAuthLoginComponent } from '@modules/login/pages/login/two-factor-auth-login.component'; import { Authority } from '@shared/models/authority.enum'; +import { LinkExpiredComponent } from '@modules/login/pages/login/link-expired.component'; const routes: Routes = [ { @@ -81,6 +82,25 @@ const routes: Routes = [ module: 'public' }, canActivate: [AuthGuard] + }, + { + path: 'activationLinkExpired', + component: LinkExpiredComponent, + data: { + title: 'login.activation-link-expired', + module: 'public' + }, + canActivate: [AuthGuard] + }, + { + path: 'passwordResetLinkExpired', + component: LinkExpiredComponent, + data: { + title: 'login.reset-password-link-expired', + module: 'public', + passwordLinkExpired: true + }, + canActivate: [AuthGuard] } ]; diff --git a/ui-ngx/src/app/modules/login/login.module.ts b/ui-ngx/src/app/modules/login/login.module.ts index 0a664133e4..d995d9b2a6 100644 --- a/ui-ngx/src/app/modules/login/login.module.ts +++ b/ui-ngx/src/app/modules/login/login.module.ts @@ -24,6 +24,7 @@ import { ResetPasswordRequestComponent } from '@modules/login/pages/login/reset- import { ResetPasswordComponent } from '@modules/login/pages/login/reset-password.component'; import { CreatePasswordComponent } from '@modules/login/pages/login/create-password.component'; import { TwoFactorAuthLoginComponent } from '@modules/login/pages/login/two-factor-auth-login.component'; +import { LinkExpiredComponent } from '@modules/login/pages/login/link-expired.component'; @NgModule({ declarations: [ @@ -31,7 +32,8 @@ import { TwoFactorAuthLoginComponent } from '@modules/login/pages/login/two-fact ResetPasswordRequestComponent, ResetPasswordComponent, CreatePasswordComponent, - TwoFactorAuthLoginComponent + TwoFactorAuthLoginComponent, + LinkExpiredComponent ], imports: [ CommonModule, diff --git a/ui-ngx/src/app/modules/login/pages/login/link-expired.component.html b/ui-ngx/src/app/modules/login/pages/login/link-expired.component.html new file mode 100644 index 0000000000..a1d52f0735 --- /dev/null +++ b/ui-ngx/src/app/modules/login/pages/login/link-expired.component.html @@ -0,0 +1,40 @@ +<!-- + + Copyright © 2016-2024 The Thingsboard Authors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +--> +<div class="tb-expired-link-content mat-app-background tb-dark tb-flex row center align-center" + style="width: 100%;"> + <mat-card appearance="raised" class="tb-expired-link-card"> + <mat-card-header style="justify-content: center"> + <mat-card-title> + <span class="mat-headline-5">{{ title | translate }}</span> + </mat-card-title> + </mat-card-header> + <mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async"> + </mat-progress-bar> + <span style="height: 4px;" *ngIf="!(isLoading$ | async)"></span> + <mat-card-content style="padding: 24px 16px"> + <div>{{ message | translate }}</div> + </mat-card-content> + <mat-card-actions class="tb-flex row center"> + <button mat-raised-button color="accent" + [disabled]="(isLoading$ | async)" + (click)="navigateToLoginPage()"> + {{ 'login.login' | translate }} + </button> + </mat-card-actions> + </mat-card> +</div> diff --git a/ui-ngx/src/app/modules/login/pages/login/link-expired.component.scss b/ui-ngx/src/app/modules/login/pages/login/link-expired.component.scss new file mode 100644 index 0000000000..323437e66b --- /dev/null +++ b/ui-ngx/src/app/modules/login/pages/login/link-expired.component.scss @@ -0,0 +1,32 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@import '../../../../../scss/constants'; + +:host { + display: flex; + flex: 1 1 0; + .tb-expired-link-content { + background-color: #eee; + .tb-expired-link-card { + letter-spacing: 0.15px; + line-height: 24px; + padding: 24px; + @media #{$mat-gt-xs} { + width: 486px !important; + } + } + } +} diff --git a/ui-ngx/src/app/modules/login/pages/login/link-expired.component.ts b/ui-ngx/src/app/modules/login/pages/login/link-expired.component.ts new file mode 100644 index 0000000000..d394e426dd --- /dev/null +++ b/ui-ngx/src/app/modules/login/pages/login/link-expired.component.ts @@ -0,0 +1,47 @@ +/// +/// Copyright © 2016-2024 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { Component } from '@angular/core'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { PageComponent } from '@shared/components/page.component'; +import { ActivatedRoute, Router } from '@angular/router'; + +@Component({ + selector: 'tb-link-expired', + templateUrl: './link-expired.component.html', + styleUrls: ['./link-expired.component.scss'] +}) +export class LinkExpiredComponent extends PageComponent { + + isPasswordLinkExpired: boolean; + title: string; + message: string; + + constructor(protected store: Store<AppState>, + private route: ActivatedRoute, + private router: Router) { + super(store); + this.isPasswordLinkExpired = this.route.snapshot.data.passwordLinkExpired; + this.title = this.isPasswordLinkExpired ? 'login.reset-password-link-expired' : 'login.activation-link-expired'; + this.message = this.isPasswordLinkExpired ? 'login.reset-password-link-expired-message' : + 'login.activation-link-expired-message'; + } + + navigateToLoginPage() { + this.router.navigateByUrl('login'); + } +} diff --git a/ui-ngx/src/app/shared/components/image/image-gallery.component.ts b/ui-ngx/src/app/shared/components/image/image-gallery.component.ts index 23f489d78c..24a4c3dde7 100644 --- a/ui-ngx/src/app/shared/components/image/image-gallery.component.ts +++ b/ui-ngx/src/app/shared/components/image/image-gallery.component.ts @@ -639,11 +639,15 @@ export class ImageGalleryComponent extends PageComponent implements OnInit, OnDe } rowClick($event, image: ImageResourceInfo) { - if (this.selectionMode) { - this.selectImage($event, image); + if (this.isScada) { + this.editImage($event, image); } else { - if (this.deleteEnabled(image)) { - this.dataSource.selection.toggle(image); + if (this.selectionMode) { + this.selectImage($event, image); + } else { + if (this.deleteEnabled(image)) { + this.dataSource.selection.toggle(image); + } } } } diff --git a/ui-ngx/src/app/shared/components/js-func.component.ts b/ui-ngx/src/app/shared/components/js-func.component.ts index 8c3fa0a423..e15535391f 100644 --- a/ui-ngx/src/app/shared/components/js-func.component.ts +++ b/ui-ngx/src/app/shared/components/js-func.component.ts @@ -25,15 +25,15 @@ import { ViewChild, ViewEncapsulation } from '@angular/core'; -import { ControlValueAccessor, UntypedFormControl, NG_VALIDATORS, NG_VALUE_ACCESSOR, Validator } from '@angular/forms'; +import { ControlValueAccessor, NG_VALIDATORS, NG_VALUE_ACCESSOR, UntypedFormControl, Validator } from '@angular/forms'; import { Ace } from 'ace-builds'; -import { getAce, Range, TbHighlightRule } from '@shared/models/ace/ace.models'; +import { AceHighlightRules, getAce, Range } from '@shared/models/ace/ace.models'; import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { ActionNotificationHide, ActionNotificationShow } from '@core/notification/notification.actions'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; import { UtilsService } from '@core/services/utils.service'; -import { deepClone, guid, isUndefined } from '@app/core/utils'; +import { guid, isUndefined } from '@app/core/utils'; import { TranslateService } from '@ngx-translate/core'; import { CancelAnimationFrame, RafService } from '@core/services/raf.service'; import { ResizeObserver } from '@juggle/resize-observer'; @@ -90,9 +90,7 @@ export class JsFuncComponent implements OnInit, OnDestroy, ControlValueAccessor, @Input() editorCompleter: TbEditorCompleter; - @Input() propertyHighlightRules: TbHighlightRule[]; - - @Input() objectHighlightRules: TbHighlightRule[]; + @Input() highlightRules: AceHighlightRules; @Input() globalVariables: Array<string>; @@ -220,27 +218,16 @@ export class JsFuncComponent implements OnInit, OnDestroy, ControlValueAccessor, }); } // @ts-ignore - if ((this.propertyHighlightRules?.length || this.objectHighlightRules?.length) && !!this.jsEditor.session.$mode) { + if (!!this.highlightRules && !!this.jsEditor.session.$mode) { // @ts-ignore const newMode = new this.jsEditor.session.$mode.constructor(); newMode.$highlightRules = new newMode.HighlightRules(); - if (this.propertyHighlightRules?.length) { - const propertiesRules: { token: string; regex: RegExp }[] = newMode.$highlightRules.$rules.property; - const index = propertiesRules.findIndex(p => p.token === 'support.constant'); - const additionalPropertyRules: { token: string; regex: RegExp }[] = this.propertyHighlightRules.map(r => ({ - token: `tb.${r.class}`, - regex: r.regex - })); - propertiesRules.splice(index, 0, ...additionalPropertyRules); - } - if (this.objectHighlightRules?.length) { - const noRegexRules: { token: string; regex: RegExp }[] = newMode.$highlightRules.$rules.no_regex; - const index = noRegexRules.findIndex(p => Array.isArray(p.token) && p.token[0] === 'support.constant'); - const additionalNoRegexRules: { token: string; regex: RegExp }[] = this.objectHighlightRules.map(r => ({ - token: `tb.${r.class}`, - regex: r.regex - })); - noRegexRules.splice(index, 0, ...additionalNoRegexRules); + for(const group in this.highlightRules) { + if(!!newMode.$highlightRules.$rules[group]) { + newMode.$highlightRules.$rules[group].unshift(...this.highlightRules[group]); + } else { + newMode.$highlightRules.$rules[group] = this.highlightRules[group]; + } } // @ts-ignore this.jsEditor.session.$onChangeMode(newMode); diff --git a/ui-ngx/src/app/shared/components/markdown.component.ts b/ui-ngx/src/app/shared/components/markdown.component.ts index fc7c2d0d8d..069bca2b2d 100644 --- a/ui-ngx/src/app/shared/components/markdown.component.ts +++ b/ui-ngx/src/app/shared/components/markdown.component.ts @@ -160,7 +160,7 @@ export class TbMarkdownComponent implements OnChanges { }, template, compileModules, - true, 1, styles + true, styles ).subscribe((componentData) => { this.tbMarkdownInstanceComponentType = componentData.componentType; const injector: Injector = Injector.create({providers: [], parent: this.markdownContainer.injector}); diff --git a/ui-ngx/src/app/shared/components/widgets-bundle-select.component.html b/ui-ngx/src/app/shared/components/widgets-bundle-select.component.html index 2f3f0199e4..2826d06d42 100644 --- a/ui-ngx/src/app/shared/components/widgets-bundle-select.component.html +++ b/ui-ngx/src/app/shared/components/widgets-bundle-select.component.html @@ -22,6 +22,7 @@ panelClass="tb-widgets-bundle-select" placeholder="{{ 'widget.select-widgets-bundle' | translate }}" (blur)="onTouched()" + [compareWith]="compareById" (ngModelChange)="widgetsBundleChanged()"> <mat-select-trigger> <div class="tb-bundle-item"> @@ -29,8 +30,12 @@ <span translate class="tb-bundle-system" *ngIf="isSystem(widgetsBundle)">widgets-bundle.system</span> </div> </mat-select-trigger> - <mat-option [value]="null" *ngIf="!required"> + <mat-option *ngIf="createNew; else empty" [value]="null" (click)="openWidgetsBundleDialog($event)"> + <a translate>widgets-bundle.create-new</a> </mat-option> + <ng-template #empty> + <mat-option [value]="null" *ngIf="!required"></mat-option> + </ng-template> <mat-option *ngFor="let widgetsBundle of widgetsBundles$ | async" [value]="widgetsBundle"> <div class="tb-bundle-item"> <span>{{widgetsBundle.title}}</span> diff --git a/ui-ngx/src/app/shared/components/widgets-bundle-select.component.ts b/ui-ngx/src/app/shared/components/widgets-bundle-select.component.ts index d81fcbe88e..b5baccc893 100644 --- a/ui-ngx/src/app/shared/components/widgets-bundle-select.component.ts +++ b/ui-ngx/src/app/shared/components/widgets-bundle-select.component.ts @@ -14,9 +14,18 @@ /// limitations under the License. /// -import { Component, forwardRef, Input, OnChanges, OnInit, SimpleChanges, ViewEncapsulation } from '@angular/core'; +import { + ChangeDetectorRef, + Component, + forwardRef, + Input, + OnChanges, + OnInit, + SimpleChanges, + ViewEncapsulation +} from '@angular/core'; import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; -import { Observable } from 'rxjs'; +import { Observable, of } from 'rxjs'; import { map, share, tap } from 'rxjs/operators'; import { Store } from '@ngrx/store'; import { AppState } from '@app/core/core.state'; @@ -26,6 +35,11 @@ import { isDefined } from '@core/utils'; import { NULL_UUID } from '@shared/models/id/has-uuid'; import { getCurrentAuthState } from '@core/auth/auth.selectors'; import { coerceBoolean } from '@shared/decorators/coercion'; +import { MatDialog } from '@angular/material/dialog'; +import { + WidgetsBundleDialogComponent, + WidgetsBundleDialogData +} from '@home/pages/widget/widgets-bundle-dialog.component'; @Component({ selector: 'tb-widgets-bundle-select', @@ -60,6 +74,10 @@ export class WidgetsBundleSelectComponent implements ControlValueAccessor, OnIni @Input() excludeBundleIds: Array<string>; + @Input() + @coerceBoolean() + createNew: boolean; + widgetsBundles$: Observable<Array<WidgetsBundle>>; widgetsBundles: Array<WidgetsBundle>; @@ -70,7 +88,9 @@ export class WidgetsBundleSelectComponent implements ControlValueAccessor, OnIni private propagateChange: (value: any) => void = () => {}; constructor(private store: Store<AppState>, - private widgetService: WidgetService) { + private widgetService: WidgetService, + private dialog: MatDialog, + private cd: ChangeDetectorRef) { } registerOnChange(fn: any): void { @@ -171,4 +191,35 @@ export class WidgetsBundleSelectComponent implements ControlValueAccessor, OnIni return widgetsBundlesObservable; } + compareById(f1: WidgetsBundle, f2: WidgetsBundle): boolean { + return f1 && f2 && f1.id.id === f2.id.id; + } + + openWidgetsBundleDialog($event) { + $event.preventDefault(); + const widgetsBundle: WidgetsBundle = { + title: '', + image: '', + description: '', + scada: true, + order: null + }; + this.dialog.open<WidgetsBundleDialogComponent, WidgetsBundleDialogData, + WidgetsBundle>(WidgetsBundleDialogComponent, { + disableClose: true, + panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], + data: { + widgetsBundle + } + }).afterClosed().subscribe( + (savedWidgetBundle) => { + if (savedWidgetBundle) { + this.widgetsBundles$ = of([...this.widgetsBundles, savedWidgetBundle]); + this.widgetsBundle = savedWidgetBundle; + this.widgetsBundleChanged(); + } + } + ); + } + } diff --git a/ui-ngx/src/app/shared/models/ace/ace.models.ts b/ui-ngx/src/app/shared/models/ace/ace.models.ts index 221e68564b..381d897066 100644 --- a/ui-ngx/src/app/shared/models/ace/ace.models.ts +++ b/ui-ngx/src/app/shared/models/ace/ace.models.ts @@ -352,8 +352,15 @@ export class Range implements Ace.Range { } -export interface TbHighlightRule { - class: string; - regex: RegExp; +export interface AceHighlightRules { + [group: string]: Array<AceHighlightRule>; } +export interface AceHighlightRule { + regex: RegExp | string; + token: string; + next?: string; +} + + + diff --git a/ui-ngx/src/app/shared/models/dashboard.models.ts b/ui-ngx/src/app/shared/models/dashboard.models.ts index c4e767b314..45f4eb8cf2 100644 --- a/ui-ngx/src/app/shared/models/dashboard.models.ts +++ b/ui-ngx/src/app/shared/models/dashboard.models.ts @@ -97,7 +97,6 @@ export interface GridSettings { mobileRowHeight?: number; mobileDisplayLayoutFirst?: boolean; layoutDimension?: LayoutDimension; - [key: string]: any; } export interface DashboardLayout { diff --git a/ui-ngx/src/app/shared/models/settings.models.ts b/ui-ngx/src/app/shared/models/settings.models.ts index 113bc1a789..e0a31e4eea 100644 --- a/ui-ngx/src/app/shared/models/settings.models.ts +++ b/ui-ngx/src/app/shared/models/settings.models.ts @@ -111,6 +111,11 @@ export interface UserPasswordPolicy { export interface SecuritySettings { passwordPolicy: UserPasswordPolicy; + maxFailedLoginAttempts: number; + userLockoutNotificationEmail: string; + mobileSecretKeyLength: number; + userActivationTokenTtl: number; + passwordResetTokenTtl: number; } export interface JwtSettings { diff --git a/ui-ngx/src/app/shared/models/user.model.ts b/ui-ngx/src/app/shared/models/user.model.ts index 5b2cdec08b..a17cf040a8 100644 --- a/ui-ngx/src/app/shared/models/user.model.ts +++ b/ui-ngx/src/app/shared/models/user.model.ts @@ -44,6 +44,11 @@ export const activationMethodTranslations = new Map<ActivationMethod, string>( ] ); +export interface ActivationLinkInfo { + value: string; + ttlMs: number; +} + export interface AuthUser { sub: string; scopes: string[]; diff --git a/ui-ngx/src/app/shared/models/widgets-bundle.model.ts b/ui-ngx/src/app/shared/models/widgets-bundle.model.ts index 7066defdf7..d0d2731ac2 100644 --- a/ui-ngx/src/app/shared/models/widgets-bundle.model.ts +++ b/ui-ngx/src/app/shared/models/widgets-bundle.model.ts @@ -20,8 +20,7 @@ import { WidgetsBundleId } from '@shared/models/id/widgets-bundle-id'; import { HasTenantId, HasVersion } from '@shared/models/entity.models'; export interface WidgetsBundle extends BaseData<WidgetsBundleId>, HasTenantId, HasVersion, ExportableEntity<WidgetsBundleId> { - tenantId: TenantId; - alias: string; + alias?: string; title: string; image: string; scada: boolean; diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index 369985740d..2b5a33a9b3 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -205,6 +205,12 @@ "max-failed-login-attempts": "Maximum number of failed login attempts, before account is locked", "minimum-max-failed-login-attempts-range": "Maximum number of failed login attempts can't be negative", "user-lockout-notification-email": "In case user account lockout, send notification to email", + "user-activation-token-ttl": "User activation link TTL in hours", + "user-activation-token-ttl-range": "User activation link TTL must be in range from 1 to 24 hours", + "password-reset-token-ttl": "Password reset link TTL in hours", + "password-reset-token-ttl-range": "Password reset link TTL must be in range from 1 to 24 hours", + "mobile-secret-key-length": "Mobile secret key length", + "mobile-secret-key-length-range": "Mobile secret key length must be positive", "domain-name": "Domain name", "domain-name-unique": "Domain name and protocol need to unique.", "domain-name-max-length": "Domain name should be less than 256", @@ -4014,7 +4020,11 @@ "email-auth-description": "A security code has been sent to your email address at {{contact}}.", "email-auth-placeholder": "Email code", "backup-code-auth-description": "Please enter one of your backup codes.", - "backup-code-auth-placeholder": "Backup code" + "backup-code-auth-placeholder": "Backup code", + "activation-link-expired": "Activation link has expired", + "activation-link-expired-message": "The link to activate your profile has expired. You can return to the login page to receive a new email.", + "reset-password-link-expired": "Password reset link has expired", + "reset-password-link-expired-message": "The link to reset your password has expired. You can return to the login page to receive a new email." }, "markdown": { "edit": "Edit", @@ -5634,7 +5644,7 @@ "display-activation-link": "Display activation link", "send-activation-mail": "Send activation mail", "activation-link": "User activation link", - "activation-link-text": "In order to activate user use the following <a href='{{activationLink}}' target='_blank'>activation link</a> :", + "activation-link-text": "In order to activate user use the following <a href='{{activationLink}}' target='_blank'>activation link</a> (expires in {{activationLinkTtl}}) :", "copy-activation-link": "Copy activation link", "activation-link-copied-message": "User activation link has been copied to clipboard", "details": "Details", @@ -5951,7 +5961,8 @@ "search": "Search widget bundles", "selected-widgets-bundles": "{ count, plural, =1 {1 widgets bundle} other {# widgets bundles} } selected", "open-widgets-bundle": "Open widgets bundle", - "loading-widgets-bundles": "Loading widgets bundles..." + "loading-widgets-bundles": "Loading widgets bundles...", + "create-new": "Create new widget bundle" }, "widget-config": { "data": "Data",