stand2026_10_06
This commit is contained in:
1 parent
41f80ce947
commit
266f8c3b4f
199 files changed
+17061
-87
No files matched your search
Vendored
+2
@@ -0,0 +1,2 @@
|
|||||||
|
{
|
||||||
|
}
|
||||||
Generated
+151
-3
@@ -8,9 +8,18 @@
|
|||||||
"name": "rk-frontend",
|
"name": "rk-frontend",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@dnd-kit/core": "^6.3.1",
|
||||||
|
"@dnd-kit/sortable": "^10.0.0",
|
||||||
|
"@radix-ui/react-slot": "^1.3.3",
|
||||||
|
"@xmldom/xmldom": "^0.9.11",
|
||||||
|
"class-variance-authority": "^0.7.1",
|
||||||
|
"clsx": "^2.1.1",
|
||||||
|
"lucide-react": "^1.34.0",
|
||||||
"next": "16.1.6",
|
"next": "16.1.6",
|
||||||
"react": "19.2.3",
|
"react": "19.2.3",
|
||||||
"react-dom": "19.2.3"
|
"react-dom": "19.2.3",
|
||||||
|
"react-hook-form": "^7.71.2",
|
||||||
|
"tailwind-merge": "^3.6.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/postcss": "^4",
|
"@tailwindcss/postcss": "^4",
|
||||||
@@ -33,6 +42,55 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@dnd-kit/accessibility": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw==",
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=16.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@dnd-kit/core": {
|
||||||
|
"version": "6.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.3.1.tgz",
|
||||||
|
"integrity": "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@dnd-kit/accessibility": "^3.1.1",
|
||||||
|
"@dnd-kit/utilities": "^3.2.2",
|
||||||
|
"tslib": "^2.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=16.8.0",
|
||||||
|
"react-dom": ">=16.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@dnd-kit/sortable": {
|
||||||
|
"version": "10.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@dnd-kit/sortable/-/sortable-10.0.0.tgz",
|
||||||
|
"integrity": "sha512-+xqhmIIzvAYMGfBYYnbKuNicfSsk4RksY2XdmJhT+HAC01nix6fHCztU68jooFiMUB01Ky3F0FyOvhG/BZrWkg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@dnd-kit/utilities": "^3.2.2",
|
||||||
|
"tslib": "^2.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@dnd-kit/core": "^6.3.0",
|
||||||
|
"react": ">=16.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@dnd-kit/utilities": {
|
||||||
|
"version": "3.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@dnd-kit/utilities/-/utilities-3.2.2.tgz",
|
||||||
|
"integrity": "sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==",
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=16.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@emnapi/runtime": {
|
"node_modules/@emnapi/runtime": {
|
||||||
"version": "1.8.1",
|
"version": "1.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz",
|
||||||
@@ -653,6 +711,37 @@
|
|||||||
"node": ">= 10"
|
"node": ">= 10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@radix-ui/react-compose-refs": {
|
||||||
|
"version": "1.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.5.tgz",
|
||||||
|
"integrity": "sha512-+48PbAAbq3didjJxa+OaWY2ZwgAKsNiRGyeHKszblZMQ+kcpd9pAaT11cMkGEie0vsOi3QdeTE6d5Fe3Gn61kA==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@radix-ui/react-slot": {
|
||||||
|
"version": "1.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.3.3.tgz",
|
||||||
|
"integrity": "sha512-qx7oqnYbxnK9kYI9m317qmFmEgo6ywqWvbTogdj7cL9p3/yx4M48p7Rnw5z3H890cL/ow/EeWJsuTykeZVXP5Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"@radix-ui/react-compose-refs": "1.1.5"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@swc/helpers": {
|
"node_modules/@swc/helpers": {
|
||||||
"version": "0.5.15",
|
"version": "0.5.15",
|
||||||
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
|
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
|
||||||
@@ -930,7 +1019,7 @@
|
|||||||
"version": "19.2.14",
|
"version": "19.2.14",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz",
|
||||||
"integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==",
|
"integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==",
|
||||||
"dev": true,
|
"devOptional": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"csstype": "^3.2.2"
|
"csstype": "^3.2.2"
|
||||||
}
|
}
|
||||||
@@ -944,6 +1033,14 @@
|
|||||||
"@types/react": "^19.2.0"
|
"@types/react": "^19.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@xmldom/xmldom": {
|
||||||
|
"version": "0.9.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.9.11.tgz",
|
||||||
|
"integrity": "sha512-tW8bcK3hsG0/uqSnNz6TK4BkcuZSezoU7DlnYssILmZDktPnSHHuDJJFM0AJv+13gz2r0iGdrj6qqKeUnxXEDg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/baseline-browser-mapping": {
|
"node_modules/baseline-browser-mapping": {
|
||||||
"version": "2.10.0",
|
"version": "2.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz",
|
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz",
|
||||||
@@ -974,16 +1071,35 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"node_modules/class-variance-authority": {
|
||||||
|
"version": "0.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz",
|
||||||
|
"integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==",
|
||||||
|
"dependencies": {
|
||||||
|
"clsx": "^2.1.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://polar.sh/cva"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/client-only": {
|
"node_modules/client-only": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
|
||||||
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
|
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/clsx": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/csstype": {
|
"node_modules/csstype": {
|
||||||
"version": "3.2.3",
|
"version": "3.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
|
||||||
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
|
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
|
||||||
"dev": true
|
"devOptional": true
|
||||||
},
|
},
|
||||||
"node_modules/detect-libc": {
|
"node_modules/detect-libc": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
@@ -1271,6 +1387,14 @@
|
|||||||
"url": "https://opencollective.com/parcel"
|
"url": "https://opencollective.com/parcel"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/lucide-react": {
|
||||||
|
"version": "1.34.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.34.0.tgz",
|
||||||
|
"integrity": "sha512-vnjGJNI7Htk5+oWW8gXGuaLgwgAb0T6/iZbBrp9JCfRFwdNWZ0YTm3eyxjOLgwN6r8iyAf3UA70zNmBRBNv7yg==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/magic-string": {
|
"node_modules/magic-string": {
|
||||||
"version": "0.30.21",
|
"version": "0.30.21",
|
||||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
|
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
|
||||||
@@ -1428,6 +1552,21 @@
|
|||||||
"react": "^19.2.3"
|
"react": "^19.2.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-hook-form": {
|
||||||
|
"version": "7.71.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.71.2.tgz",
|
||||||
|
"integrity": "sha512-1CHvcDYzuRUNOflt4MOq3ZM46AronNJtQ1S7tnX6YN4y72qhgiUItpacZUAQ0TyWYci3yz1X+rXaSxiuEm86PA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/react-hook-form"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.8.0 || ^17 || ^18 || ^19"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/scheduler": {
|
"node_modules/scheduler": {
|
||||||
"version": "0.27.0",
|
"version": "0.27.0",
|
||||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
|
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
|
||||||
@@ -1519,6 +1658,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tailwind-merge": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==",
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/dcastil"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/tailwindcss": {
|
"node_modules/tailwindcss": {
|
||||||
"version": "4.2.0",
|
"version": "4.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.0.tgz",
|
||||||
|
|||||||
+11
-2
@@ -5,12 +5,21 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"start": "next start"
|
"start": "next start -p 4010"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@dnd-kit/core": "^6.3.1",
|
||||||
|
"@dnd-kit/sortable": "^10.0.0",
|
||||||
|
"@radix-ui/react-slot": "^1.3.3",
|
||||||
|
"@xmldom/xmldom": "^0.9.11",
|
||||||
|
"class-variance-authority": "^0.7.1",
|
||||||
|
"clsx": "^2.1.1",
|
||||||
|
"lucide-react": "^1.34.0",
|
||||||
"next": "16.1.6",
|
"next": "16.1.6",
|
||||||
"react": "19.2.3",
|
"react": "19.2.3",
|
||||||
"react-dom": "19.2.3"
|
"react-dom": "19.2.3",
|
||||||
|
"react-hook-form": "^7.71.2",
|
||||||
|
"tailwind-merge": "^3.6.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/postcss": "^4",
|
"@tailwindcss/postcss": "^4",
|
||||||
|
|||||||
@@ -0,0 +1,171 @@
|
|||||||
|
<mxfile host="65bd71144e">
|
||||||
|
<diagram id="Bpvn5WHq1YyJgIW7uXgr" name="Page-1">
|
||||||
|
<mxGraphModel dx="1354" dy="462" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
|
||||||
|
<root>
|
||||||
|
<mxCell id="0"/>
|
||||||
|
<mxCell id="1" parent="0"/>
|
||||||
|
<mxCell id="2" value="MainPage" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="150" y="130" width="120" height="60" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="5" style="edgeStyle=none;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="3" edge="1">
|
||||||
|
<mxGeometry relative="1" as="geometry">
|
||||||
|
<mxPoint x="400" y="215" as="targetPoint"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="3" value="SelectAnlage" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="160" y="200" width="110" height="30" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="4" value="NewAnlage" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="160" y="240" width="110" height="30" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="6" value="Anlagen Übersicht" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="400" y="130" width="120" height="60" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="7" value="Gruppen" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="405" y="200" width="110" height="30" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="8" value="Elemente" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="405" y="240" width="110" height="30" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="9" value="EA'S" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="405" y="280" width="110" height="30" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="10" value="xaml<div>von Procon</div>" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="120" y="430" width="120" height="60" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="14" value="" style="edgeStyle=none;html=1;" parent="1" source="11" target="13" edge="1">
|
||||||
|
<mxGeometry relative="1" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="11" value="svg/xaml<div>creator</div>" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="120" y="530" width="120" height="60" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="13" value="Erzeugt<div>XAML/SVG</div>" style="whiteSpace=wrap;html=1;rounded=0;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="350" y="530" width="120" height="60" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="15" value="Visu/Web" style="whiteSpace=wrap;html=1;rounded=0;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="120" y="700" width="120" height="60" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="17" value="RK" style="shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=15;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="590" y="700" width="60" height="80" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="18" value="Holt SVG Daten" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="380" y="700" width="120" height="30" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="19" style="edgeStyle=none;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" source="18" target="17" edge="1">
|
||||||
|
<mxGeometry relative="1" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="20" value="Backend" style="whiteSpace=wrap;html=1;rounded=0;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="380" y="670" width="120" height="30" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="21" value="" style="swimlane;startSize=0;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="160" y="860" width="380" height="200" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="23" value="" style="endArrow=none;html=1;" parent="1" edge="1">
|
||||||
|
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||||
|
<mxPoint x="620" y="1000" as="sourcePoint"/>
|
||||||
|
<mxPoint x="640" y="880" as="targetPoint"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="24" value="" style="endArrow=none;html=1;" parent="1" edge="1">
|
||||||
|
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||||
|
<mxPoint x="640" y="880" as="sourcePoint"/>
|
||||||
|
<mxPoint x="800" y="850" as="targetPoint"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="25" value="" style="endArrow=none;html=1;" parent="1" edge="1">
|
||||||
|
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||||
|
<mxPoint x="620" y="1000" as="sourcePoint"/>
|
||||||
|
<mxPoint x="820" y="1000" as="targetPoint"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="26" value="" style="endArrow=none;html=1;" parent="1" edge="1">
|
||||||
|
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||||
|
<mxPoint x="800" y="850" as="sourcePoint"/>
|
||||||
|
<mxPoint x="820" y="1000" as="targetPoint"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="27" value="" style="endArrow=none;html=1;" parent="1" edge="1">
|
||||||
|
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||||
|
<mxPoint x="640" y="880" as="sourcePoint"/>
|
||||||
|
<mxPoint x="820" y="1000" as="targetPoint"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="28" value="" style="endArrow=none;html=1;" parent="1" edge="1">
|
||||||
|
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||||
|
<mxPoint x="800" y="850" as="sourcePoint"/>
|
||||||
|
<mxPoint x="620" y="1000" as="targetPoint"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="29" value="" style="endArrow=none;html=1;" parent="1" edge="1">
|
||||||
|
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||||
|
<mxPoint x="640" y="880" as="sourcePoint"/>
|
||||||
|
<mxPoint x="630" y="1000" as="targetPoint"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
</root>
|
||||||
|
</mxGraphModel>
|
||||||
|
</diagram>
|
||||||
|
<diagram id="cASbCO5rFMgaGpc82weQ" name="Page-2">
|
||||||
|
<mxGraphModel dx="1354" dy="634" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
|
||||||
|
<root>
|
||||||
|
<mxCell id="0"/>
|
||||||
|
<mxCell id="1" parent="0"/>
|
||||||
|
<mxCell id="130gX1RrYmnBiqMe9CBA-1" value="Unit" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="365" y="220" width="120" height="60" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="130gX1RrYmnBiqMe9CBA-2" value="Component<div><br></div>" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="365" y="330" width="120" height="30" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="130gX1RrYmnBiqMe9CBA-3" value="<div>Properties</div>" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="365" y="450" width="120" height="30" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="130gX1RrYmnBiqMe9CBA-4" value="<div>Signals</div>" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="620" y="390" width="120" height="30" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="130gX1RrYmnBiqMe9CBA-5" value="<div>_id</div>" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="365" y="360" width="120" height="30" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="130gX1RrYmnBiqMe9CBA-6" value="<div>_id</div>" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="365" y="280" width="120" height="30" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="130gX1RrYmnBiqMe9CBA-14" style="edgeStyle=none;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="130gX1RrYmnBiqMe9CBA-7" target="130gX1RrYmnBiqMe9CBA-8">
|
||||||
|
<mxGeometry relative="1" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="130gX1RrYmnBiqMe9CBA-15" value="n:1" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="130gX1RrYmnBiqMe9CBA-14">
|
||||||
|
<mxGeometry x="-0.0322" y="-2" relative="1" as="geometry">
|
||||||
|
<mxPoint as="offset"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="130gX1RrYmnBiqMe9CBA-7" value="<div>signalIds[]</div>" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="365" y="390" width="120" height="30" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="130gX1RrYmnBiqMe9CBA-8" value="<div>_id</div>" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="620" y="420" width="120" height="30" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="130gX1RrYmnBiqMe9CBA-13" style="edgeStyle=none;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="130gX1RrYmnBiqMe9CBA-9" target="130gX1RrYmnBiqMe9CBA-12">
|
||||||
|
<mxGeometry relative="1" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="130gX1RrYmnBiqMe9CBA-16" value="1:n" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="130gX1RrYmnBiqMe9CBA-13">
|
||||||
|
<mxGeometry x="0.1" relative="1" as="geometry">
|
||||||
|
<mxPoint as="offset"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="130gX1RrYmnBiqMe9CBA-9" value="<div>ioId</div>" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="620" y="520" width="120" height="30" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="130gX1RrYmnBiqMe9CBA-10" value="<div>name</div>" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="620" y="490" width="120" height="30" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="130gX1RrYmnBiqMe9CBA-11" value="<div>IOs</div>" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="820" y="390" width="120" height="30" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="130gX1RrYmnBiqMe9CBA-12" value="<div>_id</div>" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="820" y="420" width="120" height="30" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="130gX1RrYmnBiqMe9CBA-17" value="<div>componentId</div>" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="620" y="450" width="120" height="30" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</root>
|
||||||
|
</mxGraphModel>
|
||||||
|
</diagram>
|
||||||
|
</mxfile>
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
import { difference } from "next/dist/build/utils"
|
||||||
|
|
||||||
|
const rkPrefix = '/rk'
|
||||||
|
|
||||||
|
export const Sites = {
|
||||||
|
main: { url: '/', name: 'Home' },
|
||||||
|
anlagen: {
|
||||||
|
url: `${rkPrefix}/anlagen`,
|
||||||
|
name: 'Anlagen',
|
||||||
|
new: { url: `${rkPrefix}/anlagen/new` },
|
||||||
|
update: { url: `${rkPrefix}/anlagen/update`, param: 'id' }
|
||||||
|
},
|
||||||
|
groups: {
|
||||||
|
url: `${rkPrefix}/groups`,
|
||||||
|
name: 'Gruppen',
|
||||||
|
new: { url: `${rkPrefix}/groups/new`, name:'Neue Gruppe' },
|
||||||
|
update: { url: `${rkPrefix}/groups/update`, param: 'id' }
|
||||||
|
},
|
||||||
|
elements: {
|
||||||
|
url: `${rkPrefix}/elements`,
|
||||||
|
name: 'Elemente',
|
||||||
|
new: { url: `${rkPrefix}/elements/new`, name:'Neues Element Anlegen' },
|
||||||
|
update: { url: `${rkPrefix}/elements/update`, param: 'id' }
|
||||||
|
},
|
||||||
|
peripheries: {
|
||||||
|
url: `${rkPrefix}/peripheries`,
|
||||||
|
name: 'Ein/Ausgänge',
|
||||||
|
new: { url: `${rkPrefix}/peripheries/new` },
|
||||||
|
update: { url: `${rkPrefix}/peripheries/update`, param: 'id' },
|
||||||
|
differences: { url: `${rkPrefix}/peripheries/differences`, name: "Unterschiede EA Liste -Excel" }
|
||||||
|
},
|
||||||
|
logNote: {
|
||||||
|
url: `${rkPrefix}/log-note`,
|
||||||
|
name: 'Notizen',
|
||||||
|
new: { url: `${rkPrefix}/log-note/new`,name:"Neue Notiz" },
|
||||||
|
update: { url: `${rkPrefix}/log-note/update`, name:"Notiz Bearbeiten", param: 'id' },
|
||||||
|
},
|
||||||
|
visu: {
|
||||||
|
url: `visu`,
|
||||||
|
name: 'Visualisierung',
|
||||||
|
create: { url: `visu/create`, name:"Create Element" },
|
||||||
|
elements: { url: `visu/elements`, name:"Visu Elemente" },
|
||||||
|
selectGroups: { url: `visu/groups_add`, name:"Gruppen zu Visu hinzufügen" },
|
||||||
|
},
|
||||||
|
procon: {
|
||||||
|
url: `/procon`,
|
||||||
|
name: 'DB Procon',
|
||||||
|
aggregate: { url: `/procon/aggregate`, name:"Übersicht Aggregate" },
|
||||||
|
texteVisu: { url: `/procon/visu_texte`, name:"Visualisierung Texte" },
|
||||||
|
sensoren: { url: `/procon/sensoren`, name:"Visualisierung Texte" },
|
||||||
|
anzeigen: { url: `/procon/anzeigen`, name:"Visualisierung Anzeigen" },
|
||||||
|
svgTest: { url: `/procon/svg`, name:"SVG test" },
|
||||||
|
},
|
||||||
|
rk2: {
|
||||||
|
url: `/rk2`,
|
||||||
|
name: 'Anlagen (neu-RK2)',
|
||||||
|
groups: {
|
||||||
|
url: `/rk2/groups`, name:"Gruppen RK2" ,
|
||||||
|
new:{url: `/rk2/groups/edit/new`, name:"Neue Gruppe" },
|
||||||
|
edit:{url: `/rk2/groups/edit`, name:"Gruppe Ändern" }
|
||||||
|
},
|
||||||
|
units: {
|
||||||
|
url: `/rk2/units`,
|
||||||
|
name:"Units",
|
||||||
|
new:{url: `/rk2/units//edit/new`, name:"Neue Unit" }
|
||||||
|
},
|
||||||
|
signals: { url: `/rk2/signale`, name:"Signale" },
|
||||||
|
ios: { url: `/rk2/ios`, name:"IO " },
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import { VisuElement } from "@/types/visu/visuElements.types";
|
||||||
|
|
||||||
|
export type DragMode = "idle" | "canvas" | "element";
|
||||||
|
|
||||||
|
export interface HistoryState<T> {
|
||||||
|
past: T[];
|
||||||
|
present: T;
|
||||||
|
future: T[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DragState {
|
||||||
|
mode: DragMode;
|
||||||
|
elementId?: string;
|
||||||
|
startX: number;
|
||||||
|
startY: number;
|
||||||
|
lastX: number;
|
||||||
|
lastY: number;
|
||||||
|
}
|
||||||
|
export type VisuElementsState = {
|
||||||
|
drag: DragState;
|
||||||
|
elements: VisuElement[];
|
||||||
|
selectedElement: VisuElement | undefined;
|
||||||
|
editSession: {
|
||||||
|
active: boolean;
|
||||||
|
source: "drag" | "panel" | null;
|
||||||
|
};
|
||||||
|
test: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type VisuHistoryState = HistoryState<VisuElementsState>;
|
||||||
|
|
||||||
|
|
||||||
|
export type VisuElementsActions =
|
||||||
|
| { type: "SET_ELEMENTS"; payload: VisuElement[] }
|
||||||
|
| { type: "SELECT_ELEMENT"; payload: VisuElement }
|
||||||
|
| { type: "DESELECT_ELEMENT" }
|
||||||
|
| { type: "DRAG_START"; payload: { mode: "canvas" | "element"; elementId?: string; x: number; y: number } }
|
||||||
|
| { type: "DRAG_MOVE"; payload: { x: number; y: number } }
|
||||||
|
| { type: "DRAG_END" }
|
||||||
|
| { type: "MOVE_SELECTED_ELEMENT"; payload: { dx: number, dy: number } }
|
||||||
|
| { type: "UPDATE_ELEMENT"; payload: VisuElement }
|
||||||
|
| { type: "UNDO" }
|
||||||
|
| { type: "REDO" }
|
||||||
|
| { type: "SET_STATE"; payload: VisuElementsState }
|
||||||
|
| { type: "UPDATE_SCALE"; payload: number }
|
||||||
|
| { type: "UPDATE_LINE_OFFSET"; payload: Partial<{x:number,y:number}> }
|
||||||
|
|
||||||
|
;
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import { createContext, Dispatch } from "react";
|
||||||
|
import { VisuElementsActions, VisuElementsState } from "./VisuElements.types";
|
||||||
|
|
||||||
|
type VisuElementsContextType = {
|
||||||
|
state: VisuElementsState;
|
||||||
|
dispatch: Dispatch<VisuElementsActions>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const VisuElementsContext = createContext<VisuElementsContextType | undefined>(undefined);
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
"use client";
|
||||||
|
import { useEffect, useReducer } from "react";
|
||||||
|
import { VisuElementsState } from "./VisuElements.types";
|
||||||
|
import { VisuElementsReducer } from "./VisuElementsReducer";
|
||||||
|
import { VisuElementsContext } from "./VisuElementsContext";
|
||||||
|
import { VisuElement } from "@/types/visu/visuElements.types";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const initialState: VisuElementsState = {
|
||||||
|
drag: {
|
||||||
|
mode: "idle",
|
||||||
|
startX: 0,
|
||||||
|
startY: 0,
|
||||||
|
lastX: 0,
|
||||||
|
lastY: 0,
|
||||||
|
},
|
||||||
|
elements: [],
|
||||||
|
selectedElement: undefined,
|
||||||
|
editSession: {active:false,source:null},
|
||||||
|
test: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export function VisuElementsProvider({ children, initialValues }: { children: React.ReactNode, initialValues: VisuElement[] }) {
|
||||||
|
const [state, dispatch] = useReducer(VisuElementsReducer, initialState);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
dispatch({ type: "SET_ELEMENTS", payload: initialValues })
|
||||||
|
}, [initialValues])
|
||||||
|
return (
|
||||||
|
<VisuElementsContext.Provider value={{ state, dispatch }}>
|
||||||
|
{children}
|
||||||
|
</VisuElementsContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,180 @@
|
|||||||
|
import { stat } from "fs";
|
||||||
|
import { VisuElementsActions, VisuElementsState } from "./VisuElements.types";
|
||||||
|
|
||||||
|
const helper = (state:VisuElementsState):VisuElementsState=>{
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
export function VisuElementsReducer(state: VisuElementsState, action: VisuElementsActions): VisuElementsState {
|
||||||
|
switch (action.type) {
|
||||||
|
|
||||||
|
// -----------------------
|
||||||
|
// SET ELEMENTS
|
||||||
|
// -----------------------
|
||||||
|
case "SET_ELEMENTS":
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
elements: action.payload,
|
||||||
|
test: "daten wurden gleaden"
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------
|
||||||
|
// SELECT
|
||||||
|
// -----------------------
|
||||||
|
case "SELECT_ELEMENT":
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
selectedElement: action.payload,
|
||||||
|
};
|
||||||
|
|
||||||
|
case "DESELECT_ELEMENT":
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
selectedElement: undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// -----------------------
|
||||||
|
// DRAG START
|
||||||
|
// -----------------------
|
||||||
|
case "DRAG_START":
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
drag: {
|
||||||
|
mode: action.payload.mode,
|
||||||
|
elementId: action.payload.elementId,
|
||||||
|
startX: action.payload.x,
|
||||||
|
startY: action.payload.y,
|
||||||
|
lastX: action.payload.x,
|
||||||
|
lastY: action.payload.y,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// -----------------------
|
||||||
|
// DRAG MOVE
|
||||||
|
// -----------------------
|
||||||
|
case "DRAG_MOVE": {
|
||||||
|
const drag = state.drag;
|
||||||
|
|
||||||
|
const dx = action.payload.x - drag.lastX;
|
||||||
|
const dy = action.payload.y - drag.lastY;
|
||||||
|
if (state.drag.mode !== "element") return state;
|
||||||
|
// -----------------------
|
||||||
|
// ELEMENT DRAG
|
||||||
|
// -----------------------
|
||||||
|
if (drag.mode === "element" && drag.elementId) {
|
||||||
|
let updatedElement: any = null;
|
||||||
|
|
||||||
|
const elements = state.elements.map((el) => {
|
||||||
|
if (el.id !== drag.elementId) return el;
|
||||||
|
|
||||||
|
const newX = el.posX + dx;
|
||||||
|
const newY = el.posY + dy;
|
||||||
|
|
||||||
|
updatedElement = {
|
||||||
|
...el,
|
||||||
|
posX: newX,
|
||||||
|
posY: newY,
|
||||||
|
};
|
||||||
|
|
||||||
|
return updatedElement;
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
elements,
|
||||||
|
drag: {
|
||||||
|
...drag,
|
||||||
|
lastX: action.payload.x,
|
||||||
|
lastY: action.payload.y,
|
||||||
|
},
|
||||||
|
selectedElement:
|
||||||
|
state.selectedElement?.id === drag.elementId
|
||||||
|
? updatedElement
|
||||||
|
: state.selectedElement,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------
|
||||||
|
// CANVAS DRAG
|
||||||
|
// -----------------------
|
||||||
|
if (drag.mode === "canvas") {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
drag: {
|
||||||
|
...drag,
|
||||||
|
lastX: action.payload.x,
|
||||||
|
lastY: action.payload.y,
|
||||||
|
},
|
||||||
|
// ❗ KEIN state change hier
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------
|
||||||
|
// DRAG END (snap)
|
||||||
|
// -----------------------
|
||||||
|
case "DRAG_END":
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
drag: {
|
||||||
|
mode: "idle",
|
||||||
|
elementId: undefined,
|
||||||
|
startX: 0,
|
||||||
|
startY: 0,
|
||||||
|
lastX: 0,
|
||||||
|
lastY: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// -----------------------
|
||||||
|
// KEYBOARD MOVE
|
||||||
|
// -----------------------
|
||||||
|
case "MOVE_SELECTED_ELEMENT":
|
||||||
|
if (!state.selectedElement) return state;
|
||||||
|
|
||||||
|
const moved = {
|
||||||
|
...state.selectedElement,
|
||||||
|
posX: state.selectedElement.posX + action.payload.dx,
|
||||||
|
posY: state.selectedElement.posY + action.payload.dy,
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
selectedElement: moved,
|
||||||
|
elements: state.elements.map((el) =>
|
||||||
|
el.id === moved.id ? moved : el
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
// -----------------------
|
||||||
|
// UPDATE
|
||||||
|
// -----------------------
|
||||||
|
case "UPDATE_ELEMENT":
|
||||||
|
const updated =state.elements.map(el =>
|
||||||
|
el.id === action.payload.id ? action.payload : el
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
elements: updated,
|
||||||
|
selectedElement:
|
||||||
|
state.selectedElement?.id === action.payload.id
|
||||||
|
? action.payload
|
||||||
|
: state.selectedElement,
|
||||||
|
};
|
||||||
|
// -----------------------
|
||||||
|
// UPDATE
|
||||||
|
// -----------------------
|
||||||
|
case "UPDATE_LINE_OFFSET":
|
||||||
|
|
||||||
|
return state;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import { useContext } from "react";
|
||||||
|
import { VisuElementsContext } from "./VisuElementsContext";
|
||||||
|
|
||||||
|
|
||||||
|
export function useVisuElementContext() {
|
||||||
|
const context = useContext(VisuElementsContext);
|
||||||
|
|
||||||
|
if (!context) {
|
||||||
|
throw new Error("useFormContext must be used within FormProvider");
|
||||||
|
}
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
"use server"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const url = "http://localhost:3000/draw";
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//--- Get Data of Grafik
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
export async function api_drawData(name?:string): Promise<any> {
|
||||||
|
name =name ? name: "anlageDurmin";
|
||||||
|
|
||||||
|
const result = await fetch(`${url}/${name}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
|
||||||
|
return (data);
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
"use server"
|
||||||
|
|
||||||
|
import { revalidatePath } from "next/cache";
|
||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import { ProConAggregate, ProConAggVisu } from "@/types/procon";
|
||||||
|
|
||||||
|
|
||||||
|
const url = "http://localhost:3000/procon/";
|
||||||
|
const url_aggrgate = url + "aggregate"
|
||||||
|
|
||||||
|
export async function api_ProconAggregate_GetAll(): Promise<ProConAggregate[]> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_aggrgate}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
|
||||||
|
return orderById(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function api_ProconAggregate_GetById(id:number): Promise<ProConAggVisu> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_aggrgate}/byAntriebsId/${id}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function orderById(data:ProConAggregate[]) {
|
||||||
|
return data.sort((a,b)=>a.SPSAntriebId-b.SPSAntriebId)
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
"use server"
|
||||||
|
|
||||||
|
import { ProConAnzeige, ProConAnzeigeVisuElement } from "@/types/procon/anzeigen";
|
||||||
|
|
||||||
|
|
||||||
|
const url = "http://localhost:3000/procon/";
|
||||||
|
const url_anzeigen = url + "anzeigen"
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//--- Anzeigen
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
export async function api_ProconAnzeigen(): Promise<ProConAnzeige[]> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_anzeigen}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
|
||||||
|
return orderByDatenNummer(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function api_ProconAnzeige_byId(id:number): Promise<ProConAnzeige> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_anzeigen}/byId/${id}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function api_ProconAnzeige_byDatenNumber(id:number): Promise<ProConAnzeige> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_anzeigen}/byDatenNummer/${id}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--- Visu Elemente
|
||||||
|
export async function api_ProconAnzeige_visuElements(id:number): Promise<ProConAnzeigeVisuElement[]> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_anzeigen}/VisuElements/${id}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function orderByDatenNummer(data:ProConAnzeige[]) {
|
||||||
|
return data.sort((a,b)=>a.DatenNummer-b.DatenNummer)
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
"use server"
|
||||||
|
|
||||||
|
import { ProConMeldung } from "@/types/procon/meldungen";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const url = "http://localhost:3000/procon/";
|
||||||
|
const url_meldungen = url + "meldungen"
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//--- Meldungen
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
export async function api_ProconMeldungen(): Promise<ProConMeldung[]> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_meldungen}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function api_ProconMeldung_byId(id:number): Promise<ProConMeldung> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_meldungen}/byId/${id}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function api_ProconMeldung_byAggregateId(id:number): Promise<ProConMeldung[]> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_meldungen}/byAggregateId/${id}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
"use server"
|
||||||
|
|
||||||
|
import { ProConSensor, ProConSensorVisuElement } from "@/types/procon/sensoren";
|
||||||
|
|
||||||
|
|
||||||
|
const url = "http://localhost:3000/procon/";
|
||||||
|
const url_sensoren = url + "sensoren"
|
||||||
|
const digital ="digital";
|
||||||
|
const analog = "analog";
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//--- Digital Sensoren
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
export async function api_ProconSensoren_digital(): Promise<ProConSensor[]> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_sensoren}/${digital}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
|
||||||
|
return orderByDatenNummer(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function api_ProconSensor_digital_byId(id:number): Promise<ProConSensor> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_sensoren}/${digital}/byId/${id}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function api_ProconSensor_digital_byTextNumber(id:number): Promise<ProConSensor> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_sensoren}/${digital}/byDatenNummer/${id}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--- Visu Elemente
|
||||||
|
export async function api_ProconSensor_digital_visuElements(id:number): Promise<ProConSensorVisuElement[]> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_sensoren}/${digital}/VisuElements/${id}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//--- Analog Sensoren
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
export async function api_ProconSensoren_analog(): Promise<ProConSensor[]> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_sensoren}/${analog}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
|
||||||
|
return orderByDatenNummer(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function api_ProconSensor_analog_byId(id:number): Promise<ProConSensor> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_sensoren}/${analog}/byId/${id}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function api_ProconSensor_analog_byTextNumber(id:number): Promise<ProConSensor> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_sensoren}/${analog}/byDatenNummer/${id}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--- Visu Elemente
|
||||||
|
export async function api_ProconSensor_analog_visuElements(id:number): Promise<ProConSensorVisuElement[]> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_sensoren}/${analog}/VisuElements/${id}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
function orderByDatenNummer(data:ProConSensor[]) {
|
||||||
|
return data.sort((a,b)=>a.DatenNummer-b.DatenNummer)
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
"use server"
|
||||||
|
|
||||||
|
import { ProConText } from "@/types/procon/texte";
|
||||||
|
|
||||||
|
|
||||||
|
const url = "http://localhost:3000/procon/";
|
||||||
|
const url_texte = url + "texte"
|
||||||
|
|
||||||
|
export async function api_ProconTexte_getTexte(): Promise<ProConText[]> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_texte}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
|
||||||
|
return orderByNummer(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function api_ProconTexte_byId(id:number): Promise<ProConText> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_texte}/byId/${id}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function api_ProconTexte_byTextNumber(id:number): Promise<ProConText> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_texte}/byTextNumber/${id}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function orderByNummer(data:ProConText[]) {
|
||||||
|
return data.sort((a,b)=>a.Nummer-b.Nummer)
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
"use server"
|
||||||
|
|
||||||
|
import { revalidatePath } from "next/cache";
|
||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
|
||||||
|
|
||||||
|
const url = "http://localhost:3000/procon/";
|
||||||
|
const url_views = url + "views"
|
||||||
|
|
||||||
|
export async function api_ProconViews_UpdateXAML(id: string, xamlBase64: string): Promise<ActionResult> {
|
||||||
|
|
||||||
|
let updateData = {
|
||||||
|
"xamlBase64": xamlBase64
|
||||||
|
}
|
||||||
|
console.log(updateData,id)
|
||||||
|
const result = await fetch(`${url_views}/xaml/${id}`, {
|
||||||
|
method: 'PATCH',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(updateData),
|
||||||
|
})
|
||||||
|
|
||||||
|
const resultData = await result.json();
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errors: resultData.message, // kommt aus NestJS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
revalidatePath(Sites.procon.url);
|
||||||
|
return { success: true };
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
"use server"
|
||||||
|
|
||||||
|
import { revalidatePath } from "next/cache";
|
||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import { ProConAggregate, ProConView } from "@/types/procon";
|
||||||
|
|
||||||
|
|
||||||
|
const url = "http://localhost:3000/procon/";
|
||||||
|
const url_visualisierungen = url + "visu"
|
||||||
|
|
||||||
|
export async function api_ProconVisualisierungen_Update(id: number, data: Partial<ProConView>): Promise<ActionResult> {
|
||||||
|
|
||||||
|
let updateData = {
|
||||||
|
"PositionX": data.posX,
|
||||||
|
"PositionY": data.posY,
|
||||||
|
"Height": data.height,
|
||||||
|
"Width": data.width,
|
||||||
|
"PositionZ":data.zIndex,
|
||||||
|
}
|
||||||
|
console.log(updateData,id)
|
||||||
|
const result = await fetch(`${url_visualisierungen}/${id}`, {
|
||||||
|
method: 'PATCH',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(updateData),
|
||||||
|
})
|
||||||
|
|
||||||
|
const resultData = await result.json();
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errors: resultData.message, // kommt aus NestJS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
revalidatePath(Sites.procon.url);
|
||||||
|
return { success: true };
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
'use server'
|
||||||
|
|
||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import { Anlage } from "@/types/rk";
|
||||||
|
import { revalidatePath } from "next/cache";
|
||||||
|
|
||||||
|
export async function api_anlagen_getAll(): Promise<Anlage[]> {
|
||||||
|
|
||||||
|
const result = await fetch(`http://localhost:3000/anlage`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function api_anlage_getSelected(): Promise<Anlage> {
|
||||||
|
|
||||||
|
const result = await fetch(`http://localhost:3000/anlage/selected`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function api_anlage_setSelected(id: string): Promise<Anlage> {
|
||||||
|
console.log(`http://localhost:3000/anlage/selected/${id}`);
|
||||||
|
|
||||||
|
const result = await fetch(`http://localhost:3000/anlage/selected/${id}`, {
|
||||||
|
method: 'PATCH',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
|
||||||
|
|
||||||
|
console.log(result.status, result.statusText);
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
const error = await result.text();
|
||||||
|
throw new Error(`API Fehler ${result.status}: ${error}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
revalidatePath(Sites.anlagen.url);
|
||||||
|
return data;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import { DrawShapeData, DrawShapeOptionen } from "@/types/draw/draw.types";
|
||||||
|
import { Anlage } from "@/types/rk";
|
||||||
|
|
||||||
|
export async function drawGetSvg(name: string, optionen?: DrawShapeOptionen): Promise<DrawShapeData> {
|
||||||
|
|
||||||
|
let optionenStr = '';
|
||||||
|
if (optionen) {
|
||||||
|
optionenStr = '?'
|
||||||
|
|
||||||
|
let separator = ''
|
||||||
|
for (const [key, value] of Object.entries(optionen)) {
|
||||||
|
|
||||||
|
optionenStr += separator + key + "=" + value;
|
||||||
|
separator = '&'
|
||||||
|
}
|
||||||
|
console.log(optionenStr)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await fetch(`http://localhost:3000/draw/gurtfoerderer${optionenStr}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json() as DrawShapeData;
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
"use server"
|
||||||
|
|
||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import { Element, ElementCreate, ElementFilterOptionen, ElementUpdate } from "@/types/rk";
|
||||||
|
import { revalidatePath } from "next/cache";
|
||||||
|
|
||||||
|
export async function api_ElementsGet(filter?: ElementFilterOptionen): Promise<Element[]> {
|
||||||
|
|
||||||
|
let filterStr = '';
|
||||||
|
|
||||||
|
if (filter) {
|
||||||
|
filterStr = '?'
|
||||||
|
|
||||||
|
let separator = ''
|
||||||
|
for (const [key, value] of Object.entries(filter)) {
|
||||||
|
|
||||||
|
filterStr += separator + key + "=" + value;
|
||||||
|
separator = '&'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const result = await fetch(`http://localhost:3000/element${filterStr}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function elementCreate(data: ElementCreate): Promise<ActionResult<Element>> {
|
||||||
|
|
||||||
|
const result = await fetch('http://localhost:3000/element', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
})
|
||||||
|
|
||||||
|
const resultData = await result.json();
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errors: resultData.message, // kommt aus NestJS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
revalidatePath(Sites.elements.url+"/")
|
||||||
|
return { success: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function elementUpdate(id: string, data: ElementUpdate): Promise<ActionResult<Element>> {
|
||||||
|
|
||||||
|
const result = await fetch(`http://localhost:3000/element/${id}`, {
|
||||||
|
method: 'PATCH',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
})
|
||||||
|
|
||||||
|
const resultData = await result.json();
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errors: resultData.message, // kommt aus NestJS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
revalidatePath(Sites.elements.url);
|
||||||
|
return { success: true };
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export async function api_elementDelete(id: string): Promise<ActionResult<Element>> {
|
||||||
|
|
||||||
|
const result = await fetch(`http://localhost:3000/element/${id}`, {
|
||||||
|
method: 'DELETE',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
})
|
||||||
|
|
||||||
|
const resultData = await result.json();
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errors: resultData.message, // kommt aus NestJS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
revalidatePath(Sites.elements.url);
|
||||||
|
return { success: true };
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
'use server';
|
||||||
|
|
||||||
|
export async function uploadFile(formData: FormData) {
|
||||||
|
const file = formData.get('file') as File;
|
||||||
|
|
||||||
|
if (!file) {
|
||||||
|
throw new Error('Keine Datei');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Neues FormData für NestJS
|
||||||
|
const backendForm = new FormData();
|
||||||
|
backendForm.append('file', file);
|
||||||
|
|
||||||
|
const res = await fetch('http://localhost:3000/draw/upload', {
|
||||||
|
method: 'POST',
|
||||||
|
body: backendForm,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
throw new Error('Upload fehlgeschlagen');
|
||||||
|
}
|
||||||
|
|
||||||
|
return await res.json();
|
||||||
|
}
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
"use server"
|
||||||
|
|
||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import { Group, GroupCreate, GroupFilterOptionen, GroupUpdate } from "@/types/rk";
|
||||||
|
import { revalidatePath } from "next/cache";
|
||||||
|
|
||||||
|
export async function api_GroupAll(filter?: GroupFilterOptionen): Promise<Group[]> {
|
||||||
|
|
||||||
|
let filterStr = '';
|
||||||
|
|
||||||
|
if (filter) {
|
||||||
|
filterStr = '?'
|
||||||
|
|
||||||
|
let separator = ''
|
||||||
|
for (const [key, value] of Object.entries(filter)) {
|
||||||
|
|
||||||
|
filterStr += separator + key + "=" + value;
|
||||||
|
separator = '&'
|
||||||
|
}
|
||||||
|
console.log(filterStr)
|
||||||
|
console.log(`http://localhost:3000/group${filter}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const result = await fetch(`http://localhost:3000/group${filterStr}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function groupCreate(data: GroupCreate): Promise<ActionResult<Group>> {
|
||||||
|
|
||||||
|
const result = await fetch('http://localhost:3000/group', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
})
|
||||||
|
|
||||||
|
const resultData = await result.json();
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errors: resultData.message, // kommt aus NestJS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
revalidatePath(Sites.groups.url)
|
||||||
|
return { success: true,data:resultData };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function groupUpdate(id: string, data: GroupUpdate): Promise<ActionResult<Group>> {
|
||||||
|
|
||||||
|
const result = await fetch(`http://localhost:3000/group/${id}`, {
|
||||||
|
method: 'PATCH',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
})
|
||||||
|
|
||||||
|
const resultData = await result.json();
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errors: resultData.message, // kommt aus NestJS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
revalidatePath(Sites.groups.url);
|
||||||
|
return { success: true,data:resultData };
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function api_groupDelete(id: string): Promise<ActionResult<Group>> {
|
||||||
|
console.log('delete Group')
|
||||||
|
const result = await fetch(`http://localhost:3000/group/${id}`, {
|
||||||
|
method: 'DELETE',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
})
|
||||||
|
|
||||||
|
const resultData = await result.json();
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errors: resultData.message, // kommt aus NestJS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
revalidatePath(Sites.groups.url);
|
||||||
|
return { success: true,data:resultData };
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
"use server"
|
||||||
|
|
||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import { LogNote, LogNoteCreate, LogNoteFilterOptionen, LogNoteUpdate } from "@/types/rk";
|
||||||
|
import { revalidatePath } from "next/cache";
|
||||||
|
|
||||||
|
const path ="log-note"
|
||||||
|
export async function api_LogNoteGet(filter?: LogNoteFilterOptionen): Promise<LogNote[]> {
|
||||||
|
|
||||||
|
let filterStr = '';
|
||||||
|
|
||||||
|
if (filter) {
|
||||||
|
filterStr = '?'
|
||||||
|
|
||||||
|
let separator = ''
|
||||||
|
for (const [key, value] of Object.entries(filter)) {
|
||||||
|
|
||||||
|
filterStr += separator + key + "=" + value;
|
||||||
|
separator = '&'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const result = await fetch(`http://localhost:3000/${path}${filterStr}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function api_logNoteCreate(data: LogNoteCreate): Promise<ActionResult<LogNote>> {
|
||||||
|
|
||||||
|
const result = await fetch(`http://localhost:3000/${path}`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
})
|
||||||
|
|
||||||
|
const resultData = await result.json();
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errors: resultData.message, // kommt aus NestJS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// revalidatePath(Sites.elements.url)
|
||||||
|
return { success: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function api_logNoteUpdate(id: string, data: LogNoteUpdate): Promise<ActionResult<LogNote>> {
|
||||||
|
|
||||||
|
const result = await fetch(`http://localhost:3000/${path}/${id}`, {
|
||||||
|
method: 'PATCH',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
})
|
||||||
|
|
||||||
|
const resultData = await result.json();
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errors: resultData.message, // kommt aus NestJS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
revalidatePath(Sites.logNote.url);
|
||||||
|
return { success: true };
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export async function api_logNoteDelete(id: string): Promise<ActionResult<LogNote>> {
|
||||||
|
|
||||||
|
const result = await fetch(`http://localhost:3000/${path}/${id}`, {
|
||||||
|
method: 'DELETE',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
})
|
||||||
|
|
||||||
|
const resultData = await result.json();
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errors: resultData.message, // kommt aus NestJS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
revalidatePath(Sites.logNote.url);
|
||||||
|
return { success: true };
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
"use server";
|
||||||
|
|
||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import { Group, Peripherie, PeripherieFilterOptionen, PeripherieUpdate } from "@/types/rk";
|
||||||
|
import { revalidatePath } from "next/cache";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export async function PeripherieFindApi(filter?: PeripherieFilterOptionen): Promise<Peripherie[]> {
|
||||||
|
let filterStr = '';
|
||||||
|
if (filter && (filter.adrByte || filter.elementId || filter.groupId)) {
|
||||||
|
filterStr = '?'
|
||||||
|
if (filter.adrByte) filterStr += 'adrByte=' + filter.adrByte;
|
||||||
|
if (filter.groupId) filterStr += 'groupId=' + filter.groupId;
|
||||||
|
if (filter.elementId) filterStr += 'elementId=' + filter.elementId;
|
||||||
|
}
|
||||||
|
console.log(`http://localhost:3000/peripherie` + filterStr)
|
||||||
|
const result = await fetch(`http://localhost:3000/peripherie` + filterStr, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GetEA_Differences(): Promise<Peripherie[]> {
|
||||||
|
|
||||||
|
const result = await fetch(`http://localhost:3000/peripherie/differences`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function api_peripherieUpdate(id: string, data: PeripherieUpdate): Promise<ActionResult<Peripherie>> {
|
||||||
|
|
||||||
|
const result = await fetch(`http://localhost:3000/peripherie/${id}`, {
|
||||||
|
method: 'PATCH',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
})
|
||||||
|
|
||||||
|
const resultData = await result.json();
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errors: resultData.message, // kommt aus NestJS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
revalidatePath(Sites.peripheries.url);
|
||||||
|
return { success: true };
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
'use server'
|
||||||
|
|
||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import { VisuElement, VisuElementCreate, VisuElementUpdate } from "@/types/visu/visuElements.types";
|
||||||
|
import { revalidatePath } from "next/cache";
|
||||||
|
|
||||||
|
export async function api_VisuElementsAll(): Promise<VisuElement[]> {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const result = await fetch(`http://localhost:3000/visu-elements`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json() as VisuElement[];
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
export async function api_VisuElementCreate(data: VisuElementCreate): Promise<ActionResult<VisuElement>> {
|
||||||
|
|
||||||
|
|
||||||
|
const result = await fetch(`http://localhost:3000/visu-elements/`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
})
|
||||||
|
|
||||||
|
const resultData = await result.json();
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errors: resultData.message, // kommt aus NestJS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
revalidatePath(Sites.visu.url);
|
||||||
|
return { success: true };
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function api_VisuElementUpdate(id: string, data: VisuElementUpdate): Promise<ActionResult<VisuElement>> {
|
||||||
|
|
||||||
|
|
||||||
|
const result = await fetch(`http://localhost:3000/visu-elements/${id}`, {
|
||||||
|
method: 'PATCH',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
})
|
||||||
|
|
||||||
|
const resultData = await result.json();
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errors: resultData.message, // kommt aus NestJS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
revalidatePath(Sites.visu.url);
|
||||||
|
return { success: true };
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,481 @@
|
|||||||
|
import { ComponentDefaults, ComponentTypeDefinition } from "@/types/anlagen/components";
|
||||||
|
import { SignalType } from "@/types/anlagen/signals";
|
||||||
|
|
||||||
|
export const componentTypeDefinitions: ComponentTypeDefinition[] = [
|
||||||
|
{
|
||||||
|
type: "Antrieb",
|
||||||
|
label: "Antrieb",
|
||||||
|
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
key: "linkslauf",
|
||||||
|
label: "Linkslauf",
|
||||||
|
type: "boolean",
|
||||||
|
defaultValue: false,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "direkt",
|
||||||
|
label: "Direkt",
|
||||||
|
type: "boolean",
|
||||||
|
defaultValue: true,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "sternDreieck",
|
||||||
|
label: "Ster-Dreieck",
|
||||||
|
type: "boolean",
|
||||||
|
defaultValue: false,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "fu",
|
||||||
|
label: "Frequenzumrichter",
|
||||||
|
type: "boolean",
|
||||||
|
defaultValue: false,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "rm",
|
||||||
|
label: "Rueckmeldung",
|
||||||
|
type: "boolean",
|
||||||
|
defaultValue: true,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "ms",
|
||||||
|
label: "Motorschutz",
|
||||||
|
type: "boolean",
|
||||||
|
defaultValue: true,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "ptc",
|
||||||
|
label: "PTC",
|
||||||
|
type: "boolean",
|
||||||
|
defaultValue: false,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "ts",
|
||||||
|
label: "Thermoschutz",
|
||||||
|
type: "boolean",
|
||||||
|
defaultValue: false,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
type: "Frequenzumrichter",
|
||||||
|
label: "Frequenzumrichter",
|
||||||
|
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
key: "manufacturer",
|
||||||
|
label: "Hersteller",
|
||||||
|
type: "text",
|
||||||
|
defaultValue: 'Schneider',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "power",
|
||||||
|
label: "Leistung [kW]",
|
||||||
|
type: "number",
|
||||||
|
defaultValue: "5",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "maxFrequency",
|
||||||
|
label: "Max. Frequenz [Hz]",
|
||||||
|
type: "number",
|
||||||
|
defaultValue: 50,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
type: "Reparaturschalter",
|
||||||
|
label: "Reparaturschalter",
|
||||||
|
|
||||||
|
properties: [
|
||||||
|
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
type: "Endschalter",
|
||||||
|
label: "Endschalter",
|
||||||
|
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
key: "normallyClosed",
|
||||||
|
label: "Öffner",
|
||||||
|
type: "boolean",
|
||||||
|
defaultValue: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
type: "Schieflaufwächter",
|
||||||
|
label: "Schieflaufwächter",
|
||||||
|
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
key: "warnung",
|
||||||
|
label: "Warnung",
|
||||||
|
type: "boolean",
|
||||||
|
defaultValue: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
type: "Reißleine",
|
||||||
|
label: "Reißleine",
|
||||||
|
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
key: "safty",
|
||||||
|
label: "Safety",
|
||||||
|
type: "boolean",
|
||||||
|
defaultValue: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
type: "Drehzahl",
|
||||||
|
label: "Drehzahl",
|
||||||
|
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
key: "impuls",
|
||||||
|
label: "Impulssignal",
|
||||||
|
type: "boolean",
|
||||||
|
defaultValue: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "dauer",
|
||||||
|
label: "Dauersignal",
|
||||||
|
type: "boolean",
|
||||||
|
defaultValue: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
type: "Vorortbedienung",
|
||||||
|
label: "Vorortbedienung",
|
||||||
|
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
key: "ta_ein",
|
||||||
|
label: "Ein Taster",
|
||||||
|
type: "boolean",
|
||||||
|
defaultValue: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "ta_ein_rtg2",
|
||||||
|
label: "Taster Ein Richtung 2",
|
||||||
|
type: "boolean",
|
||||||
|
defaultValue: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "ta_aus_no",
|
||||||
|
label: "Taster Aus (no)",
|
||||||
|
type: "boolean",
|
||||||
|
defaultValue: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "ta_aus_nc",
|
||||||
|
label: "Taster Aus (nc)",
|
||||||
|
type: "boolean",
|
||||||
|
defaultValue: false,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "Fuellstand",
|
||||||
|
label: "Füllstand",
|
||||||
|
|
||||||
|
properties: [
|
||||||
|
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "Überwachung",
|
||||||
|
label: "Überwachung",
|
||||||
|
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
key: "monitoringType",
|
||||||
|
label: "Überwachungstyp",
|
||||||
|
type: "select",
|
||||||
|
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
value: "strom",
|
||||||
|
label: "Strom",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "temperature",
|
||||||
|
label: "Temperatur",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "pressure",
|
||||||
|
label: "Druck",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "vibration",
|
||||||
|
label: "Vibration",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
defaultValue: "strom",
|
||||||
|
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
export const componentDefaults: ComponentDefaults[] = [
|
||||||
|
{
|
||||||
|
type: "Antrieb",
|
||||||
|
name: "M",
|
||||||
|
|
||||||
|
signals: [
|
||||||
|
{ name: "start", type: SignalType.DIGITAL_OUTPUT },
|
||||||
|
{ name: "startRtg2", type: SignalType.DIGITAL_OUTPUT },
|
||||||
|
{ name: "rm", type: SignalType.DIGITAL_INPUT },
|
||||||
|
{ name: "msOk", type: SignalType.DIGITAL_INPUT },
|
||||||
|
{ name: "tsOk", type: SignalType.DIGITAL_INPUT },
|
||||||
|
{ name: "ptcOk", type: SignalType.DIGITAL_INPUT },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
type: "Frequenzumrichter",
|
||||||
|
name: "Fu",
|
||||||
|
signals: [],
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
type: "Reparaturschalter",
|
||||||
|
name: "Hs",
|
||||||
|
signals: [
|
||||||
|
{ name: "HsEin", type: SignalType.DIGITAL_INPUT },
|
||||||
|
],
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "Endschalter",
|
||||||
|
name: "Es",
|
||||||
|
signals: [
|
||||||
|
{ name: "Pos", type: SignalType.DIGITAL_INPUT },
|
||||||
|
],
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
type: "Schieflaufwächter",
|
||||||
|
name: "Sl",
|
||||||
|
signals: [
|
||||||
|
{ name: "SlOk", type: SignalType.DIGITAL_INPUT },
|
||||||
|
{ name: "Sl_Warnung", type: SignalType.DIGITAL_INPUT },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
type: "Reißleine",
|
||||||
|
name: "Rl",
|
||||||
|
signals: [
|
||||||
|
{ name: "RlOk", type: SignalType.DIGITAL_INPUT },
|
||||||
|
{ name: "RlQuitt", type: SignalType.DIGITAL_OUTPUT },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
type: "Drehzahl",
|
||||||
|
name: "Dz",
|
||||||
|
signals: [
|
||||||
|
{ name: "DzOk", type: SignalType.DIGITAL_INPUT },
|
||||||
|
{ name: "DzImpuls", type: SignalType.DIGITAL_INPUT },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
type: "Vorortbedienung",
|
||||||
|
name: "Vorort",
|
||||||
|
signals: [
|
||||||
|
{ name: "TaEin", type: SignalType.DIGITAL_INPUT },
|
||||||
|
{ name: "TaNichtAus", type: SignalType.DIGITAL_INPUT },
|
||||||
|
],
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
type: "Überwachung",
|
||||||
|
name: "Ls",
|
||||||
|
signals: [
|
||||||
|
{ name: "MaxOk", type: SignalType.DIGITAL_INPUT },
|
||||||
|
{ name: "Min", type: SignalType.DIGITAL_INPUT },
|
||||||
|
],
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "Fuellstand",
|
||||||
|
name: "Fuellstand",
|
||||||
|
signals: [
|
||||||
|
{ name: "Value", type: SignalType.ANALOG_INPUT },
|
||||||
|
],
|
||||||
|
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
/* old
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Properties pro ComponentType
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
const componentProperties: Record<ComponentTypes, PropertyDefinition[]> = {
|
||||||
|
[ComponentTypes.UNKNOWN]: [],
|
||||||
|
|
||||||
|
[ComponentTypes.ANTRIEB]: [
|
||||||
|
{
|
||||||
|
name: "manufacturer",
|
||||||
|
label: "Hersteller",
|
||||||
|
type: "text",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "power",
|
||||||
|
label: "Leistung [kW]",
|
||||||
|
type: "number",
|
||||||
|
},
|
||||||
|
|
||||||
|
],
|
||||||
|
|
||||||
|
[ComponentTypes.FREQUENZUMRICHTER]: [
|
||||||
|
{
|
||||||
|
name: "manufacturer",
|
||||||
|
label: "Hersteller",
|
||||||
|
type: "text",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "power",
|
||||||
|
label: "Leistung [kW]",
|
||||||
|
type: "number",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "maxFrequency",
|
||||||
|
label: "Max. Frequenz [Hz]",
|
||||||
|
type: "number",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
[ComponentTypes.REPARATUR_SCHALTER]: [
|
||||||
|
{
|
||||||
|
name: "manufacturer",
|
||||||
|
label: "Hersteller",
|
||||||
|
type: "text",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "voltage",
|
||||||
|
label: "Spannung [V]",
|
||||||
|
type: "number",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
[ComponentTypes.LIMIT_SWITCH]: [
|
||||||
|
{
|
||||||
|
name: "manufacturer",
|
||||||
|
label: "Hersteller",
|
||||||
|
type: "text",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "normallyClosed",
|
||||||
|
label: "Öffner",
|
||||||
|
type: "boolean",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
[ComponentTypes.SCHIEFLAUF]: [
|
||||||
|
{
|
||||||
|
name: "manufacturer",
|
||||||
|
label: "Hersteller",
|
||||||
|
type: "text",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "sensitivity",
|
||||||
|
label: "Empfindlichkeit",
|
||||||
|
type: "number",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
[ComponentTypes.REISSLEINE]: [
|
||||||
|
{
|
||||||
|
name: "manufacturer",
|
||||||
|
label: "Hersteller",
|
||||||
|
type: "text",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "length",
|
||||||
|
label: "Seillänge [m]",
|
||||||
|
type: "number",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
[ComponentTypes.DREHZALHL]: [
|
||||||
|
{
|
||||||
|
name: "manufacturer",
|
||||||
|
label: "Hersteller",
|
||||||
|
type: "text",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "maxRpm",
|
||||||
|
label: "Max. Drehzahl [rpm]",
|
||||||
|
type: "number",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
[ComponentTypes.VORORT]: [
|
||||||
|
{
|
||||||
|
name: "manufacturer",
|
||||||
|
label: "Hersteller",
|
||||||
|
type: "text",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "buttonCount",
|
||||||
|
label: "Anzahl Taster",
|
||||||
|
type: "number",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
[ComponentTypes.UEBERWACHUNG]: [
|
||||||
|
{
|
||||||
|
name: "manufacturer",
|
||||||
|
label: "Hersteller",
|
||||||
|
type: "text",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "monitoringType",
|
||||||
|
label: "Überwachungstyp",
|
||||||
|
type: "select",
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
value: "temperature",
|
||||||
|
label: "Temperatur",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "pressure",
|
||||||
|
label: "Druck",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "vibration",
|
||||||
|
label: "Vibration",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
'use server'
|
||||||
|
|
||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import { ComponentCreate, ComponentOfUnit, ComponentResponse, ComponentUpdate } from "@/types/anlagen/components";
|
||||||
|
import { UnitResponse } from "@/types/anlagen/units";
|
||||||
|
import { revalidatePath } from "next/cache";
|
||||||
|
|
||||||
|
const url = "http://localhost:3000/rk2/";
|
||||||
|
const url_component = url + "components"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//--- Component by ID
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
export async function api_component_byId(id: string): Promise<ActionResult<ComponentOfUnit>> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_component}/${id}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const resultData = await result.json();
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errors: resultData.message, // kommt aus NestJS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return { success: true, data:resultData as ComponentOfUnit };
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//--- Component CREATE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
export async function api_component_create(unitId:string,data: ComponentCreate): Promise<ActionResult<ComponentResponse>> {
|
||||||
|
console.log(data);
|
||||||
|
const result = await fetch(`${url_component}/${unitId}`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
})
|
||||||
|
|
||||||
|
const resultData = await result.json();
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errors: resultData.message, // kommt aus NestJS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
revalidatePath(Sites.rk2.units.url)
|
||||||
|
|
||||||
|
return { success: true, data:resultData };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//--- Component UPDATE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
export async function api_component_update(id:string,data: ComponentUpdate): Promise<ActionResult<UnitResponse>> {
|
||||||
|
console.log('Update unit' + id);
|
||||||
|
const result = await fetch(`${url_component}/${id}`, {
|
||||||
|
method: 'PATCH',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
})
|
||||||
|
|
||||||
|
const resultData = await result.json();
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errors: resultData.message, // kommt aus NestJS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
revalidatePath(Sites.rk2.units.url + "/")
|
||||||
|
return { success: true, data:resultData };
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//--- Component Delete
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
export async function api_component_remove(compId: string): Promise<ActionResult<any>> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_component}/${compId}`, {
|
||||||
|
method: 'DELETE',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
})
|
||||||
|
|
||||||
|
const resultData = await result.json();
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errors: resultData.message, // kommt aus NestJS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
revalidatePath(Sites.rk2.units.url);
|
||||||
|
return { success: true, data:resultData };
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//--- Component Delete
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
export async function api_componentPropertieDelete(compId: string,propName:string): Promise<ActionResult<any>> {
|
||||||
|
|
||||||
|
const result = await fetch(`url_component/${compId}/delteProp/${propName}`, {
|
||||||
|
method: 'DELETE',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
})
|
||||||
|
|
||||||
|
const resultData = await result.json();
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errors: resultData.message, // kommt aus NestJS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
revalidatePath(Sites.rk2.units.url);
|
||||||
|
return { success: true, data:resultData };
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
'use server'
|
||||||
|
|
||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import { GroupCreate, GroupResponse } from "@/types/anlagen/groups";
|
||||||
|
import { revalidatePath } from "next/cache";
|
||||||
|
|
||||||
|
const url = "http://localhost:3000/rk2/";
|
||||||
|
const url_groups = url + "groups"
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//--- Groups
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
export async function api_groups(): Promise<GroupResponse[]> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_groups}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//--- Group by ID
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
export async function api_groups_byId(id: string): Promise<ActionResult<GroupResponse>> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_groups}/${id}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const resultData = await result.json();
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errors: resultData.message, // kommt aus NestJS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return { success: true, data:resultData };
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//--- Groups CREATE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
export async function api_groups_create(data: GroupCreate): Promise<ActionResult<GroupResponse>> {
|
||||||
|
console.log('Create group');
|
||||||
|
const result = await fetch(`${url_groups}`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
})
|
||||||
|
|
||||||
|
const resultData = await result.json();
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errors: resultData.message, // kommt aus NestJS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
revalidatePath(Sites.rk2.groups.url + "/")
|
||||||
|
return { success: true, data:resultData };
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//--- Groups UPDATE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
export async function api_groups_update(id:string,data: GroupCreate): Promise<ActionResult<GroupResponse>> {
|
||||||
|
console.log('Update group' + id);
|
||||||
|
const result = await fetch(`${url_groups}/${id}`, {
|
||||||
|
method: 'PATCH',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
})
|
||||||
|
|
||||||
|
const resultData = await result.json();
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errors: resultData.message, // kommt aus NestJS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
revalidatePath(Sites.rk2.groups.url)
|
||||||
|
return { success: true, data:resultData };
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//--- Groups DELETE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
export async function api_groups_delete(id:string): Promise<ActionResult<GroupResponse>> {
|
||||||
|
console.log('Update group' + id);
|
||||||
|
const result = await fetch(`${url_groups}/${id}`, {
|
||||||
|
method: 'DELETE',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
})
|
||||||
|
|
||||||
|
const resultData = await result.json();
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errors: resultData.message, // kommt aus NestJS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
revalidatePath(Sites.rk2.groups.url)
|
||||||
|
return { success: true, data:resultData };
|
||||||
|
}
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
'use server'
|
||||||
|
|
||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import { IoCreate, IoResponse } from "@/types/anlagen/ios";
|
||||||
|
import { revalidatePath } from "next/cache";
|
||||||
|
|
||||||
|
const url = "http://localhost:3000/rk2/";
|
||||||
|
const url_ios = url + "ios"
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//--- ios
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
export async function api_ios(): Promise<IoResponse[]> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_ios}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//--- io by ID
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
export async function api_ios_byId(id: string): Promise<ActionResult<IoResponse>> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_ios}/${id}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const resultData = await result.json();
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errors: resultData.message, // kommt aus NestJS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return { success: true, data:resultData };
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//--- ios CREATE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
export async function api_ios_create(data: IoResponse): Promise<ActionResult<IoResponse>> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_ios}`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
})
|
||||||
|
|
||||||
|
const resultData = await result.json();
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errors: resultData.message, // kommt aus NestJS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
revalidatePath(Sites.rk2.ios.url + "/")
|
||||||
|
return { success: true, data:resultData };
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//--- ios UPDATE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
export async function api_ios_update(id:string,data: IoCreate): Promise<ActionResult<IoResponse>> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_ios}/${id}`, {
|
||||||
|
method: 'PATCH',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
})
|
||||||
|
|
||||||
|
const resultData = await result.json();
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errors: resultData.message, // kommt aus NestJS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
revalidatePath(Sites.rk2.ios.url)
|
||||||
|
return { success: true, data:resultData };
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
'use server'
|
||||||
|
|
||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import { SignalCreate, SignalResponse } from "@/types/anlagen/signals";
|
||||||
|
import { revalidatePath } from "next/cache";
|
||||||
|
|
||||||
|
const url = "http://localhost:3000/rk2/";
|
||||||
|
const url_signals = url + "signals"
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//--- Signals
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
export async function api_signals(): Promise<SignalResponse[]> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_signals}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//--- Signal by ID
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
export async function api_signals_byId(id: string): Promise<ActionResult<any>> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_signals}/${id}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const resultData = await result.json();
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errors: resultData.message, // kommt aus NestJS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return { success: true, data:resultData };
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//--- Signals by compId
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
export async function api_signalsByComp(compId:string): Promise<SignalResponse[]> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_signals}/byComponent/${compId}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//--- Signals CREATE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
export async function api_signals_create(data: SignalCreate): Promise<ActionResult<any>> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_signals}`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
})
|
||||||
|
|
||||||
|
const resultData = await result.json();
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errors: resultData.message, // kommt aus NestJS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
revalidatePath(Sites.rk2.signals.url + "/")
|
||||||
|
return { success: true, data:resultData };
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//--- Signals UPDATE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
export async function api_signals_update(id:string,data: SignalCreate): Promise<ActionResult<any>> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_signals}/${id}`, {
|
||||||
|
method: 'PATCH',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
})
|
||||||
|
|
||||||
|
const resultData = await result.json();
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errors: resultData.message, // kommt aus NestJS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
revalidatePath(Sites.rk2.signals.url)
|
||||||
|
return { success: true, data:resultData };
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
'use server'
|
||||||
|
|
||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import { ComponentCreate, ComponentUpdate } from "@/types/anlagen/components";
|
||||||
|
import { UnitCreate, UnitResponse } from "@/types/anlagen/units";
|
||||||
|
import { revalidatePath } from "next/cache";
|
||||||
|
|
||||||
|
const url = "http://localhost:3000/rk2/";
|
||||||
|
const url_units = url + "units"
|
||||||
|
const comp_update = "component"
|
||||||
|
const comp_add = "addComponent"
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//--- Units
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
export async function api_units(): Promise<UnitResponse[]> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_units}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await result.json();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//--- Units by ID
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
export async function api_units_byId(id: string): Promise<ActionResult<UnitResponse>> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_units}/${id}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const resultData = await result.json();
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errors: resultData.message, // kommt aus NestJS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return { success: true, data:resultData };
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//--- Units CREATE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
export async function api_units_create(data: UnitCreate): Promise<ActionResult<UnitResponse>> {
|
||||||
|
|
||||||
|
const result = await fetch(`${url_units}`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
})
|
||||||
|
|
||||||
|
const resultData = await result.json();
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errors: resultData.message, // kommt aus NestJS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
revalidatePath(Sites.rk2.units.url + "/")
|
||||||
|
return { success: true, data:resultData };
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//--- Units UPDATE
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
export async function api_units_update(id:string,data: UnitCreate): Promise<ActionResult<UnitResponse>> {
|
||||||
|
console.log('Update unit');
|
||||||
|
console.log(data);
|
||||||
|
const result = await fetch(`${url_units}/${id}`, {
|
||||||
|
method: 'PATCH',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
})
|
||||||
|
|
||||||
|
const resultData = await result.json();
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errors: resultData.message, // kommt aus NestJS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
revalidatePath(Sites.rk2.units.url + "/")
|
||||||
|
return { success: true, data:resultData };
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//--- Units UPDATE Component
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
export async function api_units_updateComponent(unitId: string, compId: string, data: ComponentUpdate): Promise<ActionResult<UnitResponse>> {
|
||||||
|
console.log('Create unit' );
|
||||||
|
const result = await fetch(`${url_units}${unitId}/${comp_update}/${compId}`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
})
|
||||||
|
|
||||||
|
const resultData = await result.json();
|
||||||
|
|
||||||
|
if (!result.ok) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
errors: resultData.message, // kommt aus NestJS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
revalidatePath(Sites.rk2.units.url + "/")
|
||||||
|
return { success: true, data:resultData };
|
||||||
|
}
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export default async function PageElements() {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="p-4">
|
||||||
|
<section>
|
||||||
|
<div className="font-bold">Gruppe</div>
|
||||||
|
<ul>
|
||||||
|
<li>G35</li>
|
||||||
|
<li>Name:Gurtförderr</li>
|
||||||
|
<li>Typ:Band</li>
|
||||||
|
<section className="ps-8">
|
||||||
|
<div className="font-bold">Elemente</div>
|
||||||
|
<ul className="ps-8">
|
||||||
|
<li className="flex gap-4">
|
||||||
|
<div className="w-15 font-bold">Name:</div>
|
||||||
|
<div className="">Motor</div>
|
||||||
|
</li>
|
||||||
|
<li>Seilzug</li>
|
||||||
|
<li>Repschalter</li>
|
||||||
|
<li>Schieflauf</li>
|
||||||
|
<li>Vorortbedienung</li>
|
||||||
|
<li>Endschalter</li>
|
||||||
|
<li>FU</li>
|
||||||
|
<li>Drehzahl</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
(Group)BA3
|
||||||
|
(Group)H-Förderer
|
||||||
|
(Group)G35 Band
|
||||||
|
(Element) Motor 1
|
||||||
|
(Element) Motor 2
|
||||||
|
(Element) Drehzahl vorne
|
||||||
|
(Element) Reperaturschalter
|
||||||
|
(Element) Reissleine
|
||||||
|
(Element) Endschalter
|
||||||
|
(Element) Visu
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
interface Group {
|
||||||
|
id: number,
|
||||||
|
name: string,
|
||||||
|
nr: string,
|
||||||
|
container: boolean
|
||||||
|
groups?: Group[]
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Unit {
|
||||||
|
group: Group
|
||||||
|
typ: string,
|
||||||
|
name: string,
|
||||||
|
componentes: Componente[]
|
||||||
|
}
|
||||||
|
|
||||||
|
type Componente = ComponenteMotor | ComponenteSchieflauf;
|
||||||
|
|
||||||
|
interface ComponenteBase {
|
||||||
|
name: string,
|
||||||
|
typ: string,
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ComponenteMotor extends ComponenteBase {
|
||||||
|
motorEigenschaften: string //nur Platzhalter momentan
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ComponenteSchieflauf {
|
||||||
|
name: string,
|
||||||
|
trueOK:boolean
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const beispielBand: Unit = {
|
||||||
|
group: {
|
||||||
|
id: 1,
|
||||||
|
name: "BA4",
|
||||||
|
nr: '100',
|
||||||
|
container: true
|
||||||
|
},
|
||||||
|
typ: "Band",
|
||||||
|
name: "Förderband zu 1234",
|
||||||
|
componentes: [{
|
||||||
|
name: "Antrieb",
|
||||||
|
typ: "Motor",
|
||||||
|
motorEigenschaften: "platzhalter Beispiel"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Schieflauf",
|
||||||
|
typ: "Schieflauf",
|
||||||
|
trueOK: true
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import Modal from "@/components/ui/Modal";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
|
||||||
|
interface Props{
|
||||||
|
test:string
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function AggregateDetails({test}:Props) {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal goBack={true}>
|
||||||
|
|
||||||
|
|
||||||
|
<h2>Produktdetails</h2>
|
||||||
|
|
||||||
|
<p>Hier stehen die detaillierten Informationen.</p>
|
||||||
|
|
||||||
|
<button onClick={() => router.back()}>
|
||||||
|
Schließen
|
||||||
|
</button>
|
||||||
|
|
||||||
|
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
export default function Default() {
|
||||||
|
return null
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
export default async function DetailsPage({
|
||||||
|
params,
|
||||||
|
}: {
|
||||||
|
params: Promise<{ id: string }>;
|
||||||
|
}) {
|
||||||
|
const { id } = await params;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<main>
|
||||||
|
<h1>Details für Produkt {id}</h1>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Diese Seite wird angezeigt, wenn man direkt
|
||||||
|
/produkte/{id}/details aufruft.
|
||||||
|
</p>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
export default function Layout({
|
||||||
|
children,
|
||||||
|
modal,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode;
|
||||||
|
modal: React.ReactNode;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{children}
|
||||||
|
{modal}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import { api_ProconAggregate_GetById } from "@/actions/procon/api-procon-aggregate";
|
||||||
|
import Visualisierungen from "@/components/procon/Visualsierungen";
|
||||||
|
|
||||||
|
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
params: Promise<{
|
||||||
|
id: string;
|
||||||
|
}>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default async function PageAggregateDetail({ params }: Props) {
|
||||||
|
const { id } = await params;
|
||||||
|
const data = await api_ProconAggregate_GetById(Number(id));
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className=" ">
|
||||||
|
|
||||||
|
{/* Überschrift Leiste */}
|
||||||
|
<div className="p-4 border-1 m-1 flex gap-4 mb-6">
|
||||||
|
<Link href={Sites.main.url}>{Sites.main.name}</Link>
|
||||||
|
<Link href={Sites.procon.aggregate.url}>{Sites.procon.aggregate.name}</Link>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Aggregat Base Data */}
|
||||||
|
<div>
|
||||||
|
<div className="ps-4 flex gap-4">
|
||||||
|
<div className="font-bold">Anlage :</div>
|
||||||
|
<div>{data.anlage}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="ps-8 flex gap-4">
|
||||||
|
<div className="font-bold w-30">Agg Nr :</div>
|
||||||
|
<div>{data.aggNr}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="ps-8 flex gap-4">
|
||||||
|
<div className="font-bold w-30">Bezeichnung :</div>
|
||||||
|
<div>{data.bezeichnung}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="ps-8 flex gap-4">
|
||||||
|
<div className="font-bold w-30">SPS Name :</div>
|
||||||
|
<div>{data.viewName}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="ps-8 flex gap-4">
|
||||||
|
<div className="font-bold w-30">BMK :</div>
|
||||||
|
<div>{data.bmk}</div>
|
||||||
|
</div>
|
||||||
|
<div>ss <Link href={`/procon/aggregate/${id}/details`}>Modal</Link></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Visualisrung Elemente Anzeigen */}
|
||||||
|
<div className="p-4 m-4 border-1 gap-8 w-400 rounded-lg border-gray-200">
|
||||||
|
{data.visuElements ?
|
||||||
|
<Visualisierungen visuElements={data.visuElements} />:
|
||||||
|
<div>Keine Daten</div>
|
||||||
|
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
{false &&
|
||||||
|
<div className="flex flex-col m-4 w-300 ">
|
||||||
|
{JSON.stringify(data, null, 2)}
|
||||||
|
{id}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import { api_ProconAggregate_GetAll } from "@/actions/procon/api-procon-aggregate";
|
||||||
|
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
|
||||||
|
export default async function PageAggregate() {
|
||||||
|
const aggregate = await api_ProconAggregate_GetAll();
|
||||||
|
return (
|
||||||
|
<div className="">
|
||||||
|
<Link href={Sites.main.url}>{Sites.main.name}</Link>
|
||||||
|
<Link href={Sites.procon.url}>{Sites.procon.name}</Link>
|
||||||
|
<div className="flex flex-col m-4 w-300 ">
|
||||||
|
{aggregate.map((anlage) => (
|
||||||
|
<div key={anlage.Id}
|
||||||
|
className="grid grid-cols-[50px_100px_200px_200px_200px_200px] gap-4 p-2 border-b-1 border-l-1 border-r-1 first:border-t-1">
|
||||||
|
<div>
|
||||||
|
{anlage.Id}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{anlage.SPSAntriebId}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{anlage.Bezeichnung}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{anlage.BMK}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{anlage.ViewName}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Link href={Sites.procon.aggregate.url+"/"+anlage.SPSAntriebId}>Auswahl</Link>
|
||||||
|
</div>
|
||||||
|
</div>))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import { api_ProconAggregate_GetAll } from "@/actions/procon/api-procon-aggregate";
|
||||||
|
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
|
||||||
|
export default async function PageAggregate() {
|
||||||
|
|
||||||
|
const topics = [
|
||||||
|
{ name: Sites.procon.aggregate.name, url: Sites.procon.aggregate.url },
|
||||||
|
{ name: Sites.procon.texteVisu.name, url: Sites.procon.texteVisu.url },
|
||||||
|
{ name: "Visu Texte",url: Sites.procon.texteVisu.url },
|
||||||
|
{ name: "SVG Test",url: Sites.procon.svgTest.url }
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="">
|
||||||
|
<Link href={Sites.main.url}>{Sites.main.name}</Link>
|
||||||
|
<div className="flex flex-col m-4 w-300 ">
|
||||||
|
{topics.map((top) => (
|
||||||
|
|
||||||
|
<Link href={top.url} key={top.name+top.url}>
|
||||||
|
{top.name}
|
||||||
|
</Link>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div >
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
"use client"
|
||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import { api_ProconAggregate_GetAll } from "@/actions/procon/api-procon-aggregate";
|
||||||
|
import SvgView from "@/components/procon/svg/SvgView";
|
||||||
|
import { xamlToSvg } from "@/components/procon/svg/xaml_to_svg";
|
||||||
|
|
||||||
|
import Link from "next/link";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
const x = `<?xml version="1.0" ?>
|
||||||
|
<Viewbox xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||||
|
<Canvas Width="24" Height="24">
|
||||||
|
|
||||||
|
<Canvas>
|
||||||
|
<Ellipse Canvas.Left="0" Canvas.Top="0" Width="24" Height="24" StrokeThickness="1" Stroke="#000000" Fill="#808080" ></Ellipse>
|
||||||
|
<TextBlock Canvas.Left="5"
|
||||||
|
Canvas.Top="0"
|
||||||
|
Foreground="#000000"
|
||||||
|
Text="M"
|
||||||
|
FontSize="16"
|
||||||
|
FontWeight="Bold"/>
|
||||||
|
</Canvas>
|
||||||
|
</Canvas>
|
||||||
|
</Viewbox>
|
||||||
|
`
|
||||||
|
export default function PageSVG() {
|
||||||
|
|
||||||
|
const [xaml, setXaml] = useState(x);
|
||||||
|
|
||||||
|
const getContent = () => {
|
||||||
|
try {
|
||||||
|
return <SvgView svg={xamlToSvg(xaml, { pretty: true })}></SvgView>;
|
||||||
|
} catch (error) {
|
||||||
|
|
||||||
|
|
||||||
|
console.log('Unbekannter fehler')
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="">
|
||||||
|
<textarea className="w-300" name="svg" id="1" value={xaml} onChange={(e) => setXaml(() => e.target.value)} >
|
||||||
|
|
||||||
|
</textarea>
|
||||||
|
{
|
||||||
|
getContent()
|
||||||
|
}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
|
||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import { api_anlage_getSelected, api_anlage_setSelected, api_anlagen_getAll } from "@/actions/rk/api-anlage";
|
||||||
|
import AnlageColumn from "@/components/rk/anlage/anlageColumn";
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
|
||||||
|
export default async function PageAnlagen() {
|
||||||
|
const anlagen = await api_anlagen_getAll();
|
||||||
|
const currentAnlage = await api_anlage_getSelected();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="">
|
||||||
|
<Link href={Sites.main.url}>{Sites.main.name}</Link>
|
||||||
|
<div className="flex flex-col m-4">
|
||||||
|
{anlagen.map((anlage) =>
|
||||||
|
<AnlageColumn key={anlage.id} data={anlage} isSelected={anlage.id === currentAnlage.id} />
|
||||||
|
)}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import { api_anlage_getSelected } from "@/actions/rk/api-anlage";
|
||||||
|
import { api_ElementsGet } from "@/actions/rk/api-element";
|
||||||
|
import { api_GroupAll } from "@/actions/rk/api-groups";
|
||||||
|
import ElementCreateView from "@/components/rk/elements/elementCreateView";
|
||||||
|
|
||||||
|
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
export default async function PageElementNew() {
|
||||||
|
const groups = await api_GroupAll();
|
||||||
|
const currentAnlage = await api_anlage_getSelected()
|
||||||
|
const elements = await api_ElementsGet();
|
||||||
|
return (
|
||||||
|
<div className="">
|
||||||
|
<div className="border-1 flex gap-4 p-4">
|
||||||
|
<div className="rounded-lg bg-gray-100 p-2">
|
||||||
|
<Link href={Sites.elements.url}>{Sites.elements.name}</Link>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Link href={Sites.main.url}>{Sites.main.name}</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ElementCreateView analge={currentAnlage} elements={elements} groups={groups} />
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import { api_ElementsGet } from "@/actions/rk/api-element";
|
||||||
|
import { api_GroupAll } from "@/actions/rk/api-groups";
|
||||||
|
import ElementView from "@/components/rk/elements/elementsView";
|
||||||
|
|
||||||
|
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
export default async function PageElements() {
|
||||||
|
const elements = await api_ElementsGet();
|
||||||
|
const groups = await api_GroupAll();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="">
|
||||||
|
<div className="border-1 flex gap-4 p-4">
|
||||||
|
<div className="rounded-lg bg-gray-100 p-2">
|
||||||
|
<Link href={Sites.main.url}>{Sites.main.name}</Link>
|
||||||
|
</div>
|
||||||
|
<div className="rounded-lg bg-gray-100 p-2">
|
||||||
|
<Link href={Sites.elements.new.url}>{Sites.elements.new.name}</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<ElementView elements={elements} groups={groups}></ElementView>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import { api_anlage_getSelected } from "@/actions/rk/api-anlage";
|
||||||
|
import { api_GroupAll } from "@/actions/rk/api-groups";
|
||||||
|
import { GroupEdit } from "@/components/rk/groups/group_Edit";
|
||||||
|
import { GroupEditList } from "@/components/rk/groups/group_edit_list";
|
||||||
|
import GroupView from "@/components/rk/groups/groupView";
|
||||||
|
|
||||||
|
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
export default async function PageGroupNew() {
|
||||||
|
const groups = await api_GroupAll();
|
||||||
|
const anlage = await api_anlage_getSelected()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="">
|
||||||
|
<div className="border-1 flex gap-4 p-4">
|
||||||
|
<div className="rounded-lg bg-gray-100 p-2">
|
||||||
|
<Link href={Sites.groups.url}>{Sites.groups.name}</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Link href={Sites.main.url}>{Sites.main.name}</Link>
|
||||||
|
{/*<GroupEdit anlage={anlage} debug={true}></GroupEdit>*/}
|
||||||
|
<GroupEditList data={groups} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import { api_GroupAll } from "@/actions/rk/api-groups";
|
||||||
|
import GroupView from "@/components/rk/groups/groupView";
|
||||||
|
|
||||||
|
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
export default async function PageGroups() {
|
||||||
|
const groups = await api_GroupAll();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="">
|
||||||
|
|
||||||
|
<div className="border-1 flex gap-4 p-4">
|
||||||
|
<div className="rounded-lg bg-gray-100 p-2">
|
||||||
|
<Link href={Sites.main.url}>{Sites.main.name}</Link>
|
||||||
|
</div>
|
||||||
|
<div className="rounded-lg bg-gray-100 p-2">
|
||||||
|
<Link href={Sites.groups.new.url}>{Sites.groups.new.name}</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<GroupView groups={groups}></GroupView>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import { api_GroupAll } from "@/actions/rk/api-groups";
|
||||||
|
import { api_LogNoteGet } from "@/actions/rk/api-logNote";
|
||||||
|
import GroupView from "@/components/rk/groups/groupView";
|
||||||
|
import LogNoteView from "@/components/rk/logNote/logNoteView";
|
||||||
|
|
||||||
|
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
export default async function PageGroups() {
|
||||||
|
const notes = await api_LogNoteGet();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="">
|
||||||
|
|
||||||
|
<div className="border-1 flex gap-4 p-4">
|
||||||
|
<div className="rounded-lg bg-gray-100 p-2">
|
||||||
|
<Link href={Sites.main.url}>{Sites.main.name}</Link>
|
||||||
|
</div>
|
||||||
|
<div className="rounded-lg bg-gray-100 p-2">
|
||||||
|
<Link href={Sites.logNote.new.url}>{Sites.logNote.new.name}</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<LogNoteView notes={notes}></LogNoteView>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import { PeripherieFindApi, GetEA_Differences } from "@/actions/rk/api-peripherie";
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
export default async function PagePeripherie() {
|
||||||
|
const peripheries = await GetEA_Differences();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="">
|
||||||
|
<div className="flex justify-center font-bold ">
|
||||||
|
<div className="text-[24px]">
|
||||||
|
|
||||||
|
E/A Unterschiede
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex gap-4 p-2 p-4 border-1">
|
||||||
|
<div className="bg-sky-200 p-2 rounded-md">
|
||||||
|
<Link href={Sites.main.url}>{Sites.main.name}</Link>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div className="bg-sky-200 p-2 rounded-md">
|
||||||
|
<Link href={Sites.peripheries.url}>{Sites.peripheries.name}</Link>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
{peripheries.map((p) => (<div key={p.id} className="grid grid-cols-[100px_600px_600px] mt-4 ms-4">
|
||||||
|
<div>
|
||||||
|
{p.adrType}{p.adrByte}.{p.adrBit}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{p.text}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{p.excelData?.functionText}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>))}
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import { api_ElementsGet } from "@/actions/rk/api-element";
|
||||||
|
import { api_GroupAll } from "@/actions/rk/api-groups";
|
||||||
|
import { PeripherieFindApi } from "@/actions/rk/api-peripherie";
|
||||||
|
import PeripherieListView from "@/components/rk/peripherie/peripherieListView";
|
||||||
|
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
|
||||||
|
export default async function PagePeripherie() {
|
||||||
|
const peripheries = await PeripherieFindApi(); //{ groupId: "exists" }
|
||||||
|
const groups = await api_GroupAll();
|
||||||
|
const elmente = await api_ElementsGet();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="">
|
||||||
|
<div className="border-1 m-4 flex gap-4 p-4">
|
||||||
|
<div className="bg-gray-100 p-2 rounded-lg">
|
||||||
|
<Link href={Sites.main.url}>{Sites.main.name}</Link>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div className="bg-gray-100 p-2 rounded-lg">
|
||||||
|
<Link href={Sites.peripheries.differences.url}>{Sites.peripheries.differences.name}</Link>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<PeripherieListView peripheries={peripheries} groups={groups} elemente={elmente} />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
|
||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import { api_units_byId } from "@/actions/rk2/api-units";
|
||||||
|
|
||||||
|
import { api_anlage_getSelected } from "@/actions/rk/api-anlage";
|
||||||
|
import { UnitCreateForm } from "@/components/rk2/units/unit_createForm";
|
||||||
|
|
||||||
|
import Link from "next/link";
|
||||||
|
import { UnitEdit } from "@/components/rk2/units/unitEdit";
|
||||||
|
import { api_groups, api_groups_byId } from "@/actions/rk2/api-groups";
|
||||||
|
import { componentDefaults, componentTypeDefinitions } from "@/actions/rk2/api-compTypes";
|
||||||
|
|
||||||
|
import Breadcrumbs from "@/components/ui/navigation/breadcrumbs";
|
||||||
|
import { GroupForm } from "@/components/rk2/groups/groupForm";
|
||||||
|
import { GroupEdit } from "@/components/rk2/groups/groupEdit";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
params: Promise<{
|
||||||
|
id: string;
|
||||||
|
}>;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export default async function PageGroupEdit({ params }: Props) {
|
||||||
|
|
||||||
|
const { id } = await params;
|
||||||
|
const resultFindGroupById = await api_groups_byId(id);
|
||||||
|
const anlage = await api_anlage_getSelected();
|
||||||
|
const group = resultFindGroupById.data;
|
||||||
|
const groups = await api_groups();
|
||||||
|
|
||||||
|
const breadcrumb = [{ label: "RK", href: "/" },{ label: "Anlage", href: "/rk2" },{ label: "Groups", href: "/rk2/groups" }, { label: "Edit" }, { label: group.name }]
|
||||||
|
|
||||||
|
if (!resultFindGroupById.success) return <div>Grouppe nicht gefunden {resultFindGroupById.errors} {id}</div>
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="">
|
||||||
|
<div>
|
||||||
|
<Breadcrumbs items={breadcrumb}/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col m-4 w-300 ">
|
||||||
|
|
||||||
|
<GroupEdit anlage={anlage} selectedGroup={group} groups={groups} />
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import { api_groups } from "@/actions/rk2/api-groups";
|
||||||
|
import { api_anlage_getSelected } from "@/actions/rk/api-anlage";
|
||||||
|
import { GroupEdit } from "@/components/rk2/groups/groupEdit";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import Link from "next/link";
|
||||||
|
import Breadcrumbs from "@/components/ui/navigation/breadcrumbs";
|
||||||
|
|
||||||
|
|
||||||
|
export default async function PageGroups() {
|
||||||
|
const currentAnlage= await api_anlage_getSelected();
|
||||||
|
const groups = await api_groups();
|
||||||
|
|
||||||
|
const breadcrumb = [{ label: "RK", href: "/" },{ label: "Anlage", href: "/rk2" },{ label: "Groups", href: "/rk2/groups" }, { label: "New" }]
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="">
|
||||||
|
<div>
|
||||||
|
<Breadcrumbs items={breadcrumb}/>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col m-4 w-300 ">
|
||||||
|
<GroupEdit anlage={currentAnlage} groups={groups} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import { api_groups } from "@/actions/rk2/api-groups";
|
||||||
|
import { api_anlage_getSelected } from "@/actions/rk/api-anlage";
|
||||||
|
import { GroupViewList } from "@/components/rk2/groups/groupViewList";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import Link from "next/link";
|
||||||
|
import Breadcrumbs from "@/components/ui/navigation/breadcrumbs";
|
||||||
|
|
||||||
|
|
||||||
|
export default async function PageGroups() {
|
||||||
|
const currentAnlage= await api_anlage_getSelected();
|
||||||
|
const groups = await api_groups();
|
||||||
|
|
||||||
|
const breadcrumb = [{ label: "RK", href: "/" },{ label: "Anlage", href: "/rk2" },{ label: "Groups" }]
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="">
|
||||||
|
<div>
|
||||||
|
<Breadcrumbs items={breadcrumb}/>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col m-4 w-300 ">
|
||||||
|
<GroupViewList anlage={currentAnlage} groups={groups} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import { api_anlage_getSelected } from "@/actions/rk/api-anlage";
|
||||||
|
import { Anlage } from "@/types/rk";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
children: React.ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function AnlageLayout({ children }: Props) {
|
||||||
|
const router = useRouter();
|
||||||
|
const [anlage,setAnlage] = useState<Anlage>()
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
const loadAnlage = async ()=>{
|
||||||
|
const currentAnlage = await api_anlage_getSelected();
|
||||||
|
setAnlage(()=>currentAnlage);
|
||||||
|
}
|
||||||
|
loadAnlage();
|
||||||
|
},[])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex h-screen flex-col overflow-hidden">
|
||||||
|
|
||||||
|
<header className="flex h-16 items-center border-b bg-blue-600 text-white px-6 ">
|
||||||
|
<h1 className="text-xl font-semibold ">
|
||||||
|
{`RK -${anlage?.anlageNr} ${anlage?.name}`}
|
||||||
|
</h1>
|
||||||
|
</header>
|
||||||
|
<div className="flex min-h-0 flex-1">
|
||||||
|
<aside className="w-64 border-r bg-gray-50 p-4">
|
||||||
|
<nav className="flex flex-col gap-2">
|
||||||
|
<h2 className="mb-4 font-semibold">Anlage</h2>
|
||||||
|
|
||||||
|
<ul className="space-y-2">
|
||||||
|
<li>
|
||||||
|
<a href="/rk2/groups">Groups</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="/rk2/units">Units</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
{/* Content */}
|
||||||
|
<main className="min-w-0 flex-1 overflow-y-auto p-6">
|
||||||
|
{children}
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import { api_units } from "@/actions/rk2/api-units";
|
||||||
|
|
||||||
|
import { api_anlage_getSelected } from "@/actions/rk/api-anlage";
|
||||||
|
|
||||||
|
|
||||||
|
import Link from "next/link";
|
||||||
|
import { List, ListItem, ListItemAction } from "@/components/ui/list";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import Breadcrumbs from "@/components/ui/navigation/breadcrumbs";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export default async function PageUnits() {
|
||||||
|
|
||||||
|
const currentAnlage = await api_anlage_getSelected();
|
||||||
|
const units = await api_units();
|
||||||
|
const breadcrumb = [{ label: "RK", href: "/" },{ label: "Anlage" }]
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{/* Main-Nav */}
|
||||||
|
<Breadcrumbs items={breadcrumb}/>
|
||||||
|
|
||||||
|
<div className="flex flex-col m-4 w-170 ">
|
||||||
|
|
||||||
|
<List variant={"transparent"} >
|
||||||
|
{units.map((unit) => (
|
||||||
|
<ListItem hover={true} key={unit.id}>
|
||||||
|
<div className="w-50">
|
||||||
|
{unit.name}
|
||||||
|
</div>
|
||||||
|
<div className="w-20">
|
||||||
|
{unit.type}
|
||||||
|
</div>
|
||||||
|
<div className="w-40">
|
||||||
|
{unit.components?.map((comp) => <div key={comp.id}><div>{comp.name}</div></div>)}
|
||||||
|
</div>
|
||||||
|
<ListItemAction>
|
||||||
|
<Button variant={"secondary"} size={"xs"} >
|
||||||
|
<Link href={`/rk2/units/edit/${unit.id}`}>Auswahl</Link>
|
||||||
|
</Button>
|
||||||
|
</ListItemAction>
|
||||||
|
</ListItem>
|
||||||
|
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import { api_anlage_getSelected } from "@/actions/rk/api-anlage";
|
||||||
|
import { api_component_byId } from "@/actions/rk2/api-component";
|
||||||
|
import { componentTypeDefinitions } from "@/actions/rk2/api-compTypes";
|
||||||
|
import { SignalForm } from "@/components/rk2/signals/signalForm";
|
||||||
|
import { Card, CardContent, CardHeader } from "@/components/ui/card";
|
||||||
|
import { Link } from "lucide-react";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
params: Promise<{
|
||||||
|
componentId: string;
|
||||||
|
}>;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export default async function PageSignalsEdit({ params }: Props) {
|
||||||
|
|
||||||
|
const { componentId } = await params;
|
||||||
|
const resultComponentOfId = await api_component_byId(componentId);
|
||||||
|
const currentAnlage= await api_anlage_getSelected();
|
||||||
|
const componentTypes = componentTypeDefinitions;
|
||||||
|
|
||||||
|
if(!resultComponentOfId) return <div>Keine Daten</div>
|
||||||
|
return (
|
||||||
|
<div className="">
|
||||||
|
<Link href={Sites.main.url}>{Sites.main.name}</Link>
|
||||||
|
<Link href={Sites.procon.url}>{Sites.procon.name}</Link>
|
||||||
|
<div className="flex flex-col m-4 w-300 ">
|
||||||
|
|
||||||
|
<SignalForm componente={resultComponentOfId.data.component} ></SignalForm>
|
||||||
|
|
||||||
|
{true &&
|
||||||
|
<Card positons={"start"}>
|
||||||
|
<CardHeader variant={"danger"} >Debug</CardHeader>
|
||||||
|
<CardContent className="ps-8">
|
||||||
|
{componentId}
|
||||||
|
<pre>{JSON.stringify(resultComponentOfId, null, 2)}</pre>
|
||||||
|
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import { api_units_byId } from "@/actions/rk2/api-units";
|
||||||
|
|
||||||
|
import { api_anlage_getSelected } from "@/actions/rk/api-anlage";
|
||||||
|
import { UnitCreateForm } from "@/components/rk2/units/unit_createForm";
|
||||||
|
|
||||||
|
import Link from "next/link";
|
||||||
|
import { UnitEdit } from "@/components/rk2/units/unitEdit";
|
||||||
|
import { api_groups } from "@/actions/rk2/api-groups";
|
||||||
|
import { componentDefaults, componentTypeDefinitions } from "@/actions/rk2/api-compTypes";
|
||||||
|
import Breadcrumbs from "@/components/ui/navigation/breadcrumbs";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
params: Promise<{
|
||||||
|
id: string;
|
||||||
|
}>;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export default async function PageUnitsEdit({ params }: Props) {
|
||||||
|
|
||||||
|
const { id } = await params;
|
||||||
|
const resultFindUnitById = await api_units_byId(id);
|
||||||
|
const currentAnlage= await api_anlage_getSelected();
|
||||||
|
const groups = await api_groups();
|
||||||
|
const componentTypes = componentTypeDefinitions;
|
||||||
|
const cd = componentDefaults;
|
||||||
|
if(!resultFindUnitById.success) return <div>Unit nicht gefunden {resultFindUnitById.errors}</div>
|
||||||
|
|
||||||
|
const breadcrumb = [{ label: "RK", href: "/" },{ label: "Anlage", href: "/rk2" },{ label: "Units",href: "/rk2/units" },{ label: "Ändern" },{ label: resultFindUnitById.data.name }]
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="">
|
||||||
|
<div>
|
||||||
|
<Breadcrumbs items={breadcrumb}/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col m-4 w-300 ">
|
||||||
|
|
||||||
|
<UnitEdit anlage={currentAnlage} groups={groups} selectedUnit={resultFindUnitById.data} componentTypes={componentTypes} componentDefaults={cd}></UnitEdit>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import { api_groups } from "@/actions/rk2/api-groups";
|
||||||
|
import { api_anlage_getSelected } from "@/actions/rk/api-anlage";
|
||||||
|
import { UnitEdit } from "@/components/rk2/units/unitEdit";
|
||||||
|
|
||||||
|
import Link from "next/link";
|
||||||
|
import { componentDefaults, componentTypeDefinitions } from "@/actions/rk2/api-compTypes";
|
||||||
|
import Breadcrumbs from "@/components/ui/navigation/breadcrumbs";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export default async function PageUnitsEditNew() {
|
||||||
|
const currentAnlage = await api_anlage_getSelected();
|
||||||
|
const groups = await api_groups();
|
||||||
|
const componentTypes = componentTypeDefinitions;
|
||||||
|
const cd = componentDefaults;
|
||||||
|
|
||||||
|
const breadcrumb = [{ label: "RK", href: "/" },{ label: "Anlage", href: "/rk2" },{ label: "Units" },{ label: "Neu" }]
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="">
|
||||||
|
<div>
|
||||||
|
<Breadcrumbs items={breadcrumb}/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col m-4 w-300 ">
|
||||||
|
<UnitEdit anlage={currentAnlage} groups={groups} componentTypes={componentTypes} componentDefaults={cd}></UnitEdit>
|
||||||
|
{/*
|
||||||
|
<UnitCreateForm anlage={currentAnlage}></UnitCreateForm>
|
||||||
|
*/}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import { api_units } from "@/actions/rk2/api-units";
|
||||||
|
import { api_anlage_getSelected } from "@/actions/rk/api-anlage";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { List, ListHeader, ListHeaderItem, ListItem, ListItemAction, ListItemContent, ListItemDescription, ListItemTitle } from "@/components/ui/list";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import Breadcrumbs from "@/components/ui/navigation/breadcrumbs";
|
||||||
|
import { Card, CardContent, CardHeader } from "@/components/ui/card";
|
||||||
|
import { GroupPath } from "@/components/rk2/groups/groupPath";
|
||||||
|
import { api_groups } from "@/actions/rk2/api-groups";
|
||||||
|
import { AusgabeUnitInfo } from "@/components/rk2/ausgabe/ausgabeUnitInfo";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export default async function PageUnits() {
|
||||||
|
|
||||||
|
const units = await api_units();
|
||||||
|
const groups = await api_groups();
|
||||||
|
const breadcrumb = [{ label: "RK", href: "/" }, { label: "Anlage", href: "/rk2" }, { label: "Units" }]
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{/* Main-Nav */}
|
||||||
|
<div>
|
||||||
|
<Breadcrumbs items={breadcrumb} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Card className="flex flex-col m-4 w-170 ">
|
||||||
|
<CardHeader>Units</CardHeader>
|
||||||
|
|
||||||
|
<Button size={"xs"} className="w-30 mt-2 ms-2 mb-2">
|
||||||
|
<Link href={Sites.rk2.units.new.url}>{Sites.rk2.units.new.name}</Link>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
|
||||||
|
<List variant={"transparent"} >
|
||||||
|
<ListHeader>
|
||||||
|
<ListHeaderItem className="w-50">Gruppe</ListHeaderItem>
|
||||||
|
<ListHeaderItem className="w-50">Unit</ListHeaderItem>
|
||||||
|
<ListHeaderItem>Typ</ListHeaderItem>
|
||||||
|
</ListHeader>
|
||||||
|
{units.map((unit) => (
|
||||||
|
<ListItem hover={true} key={unit.id}>
|
||||||
|
<ListItemContent >
|
||||||
|
<ListItemTitle className="flex">
|
||||||
|
<div className="w-50">
|
||||||
|
<GroupPath groups={groups} groupId={unit.groupId} />
|
||||||
|
</div>
|
||||||
|
<div className="w-50">
|
||||||
|
{unit.prefix}_{unit.bmk}_{unit.name}{unit.postfix ? "_"+unit.postfix:""}
|
||||||
|
</div>
|
||||||
|
<div className="w-20">
|
||||||
|
{unit.type}
|
||||||
|
</div>
|
||||||
|
</ListItemTitle>
|
||||||
|
<ListItemDescription className="ps-50 pt-1 flex gap-2">
|
||||||
|
{unit.components?.map((comp) => <div key={comp.id}>
|
||||||
|
{comp.prefix && comp.prefix}
|
||||||
|
{comp.name}
|
||||||
|
{comp.postfix && comp.postfix}
|
||||||
|
{comp.index && comp.index>0 ? comp.index:""}
|
||||||
|
</div>)}
|
||||||
|
</ListItemDescription>
|
||||||
|
</ListItemContent>
|
||||||
|
<ListItemAction>
|
||||||
|
<Button variant={"secondary"} size={"xs"} >
|
||||||
|
<Link href={`/rk2/units/edit/${unit.id}`}>Auswahl</Link>
|
||||||
|
</Button>
|
||||||
|
</ListItemAction>
|
||||||
|
</ListItem>
|
||||||
|
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
</Card >
|
||||||
|
<Card>
|
||||||
|
<CardHeader>Ausgabe</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<AusgabeUnitInfo units={units} groups={groups} />
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,142 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { DndContext, closestCenter, DragOverlay, useDroppable } from "@dnd-kit/core";
|
||||||
|
import {
|
||||||
|
arrayMove,
|
||||||
|
SortableContext,
|
||||||
|
useSortable,
|
||||||
|
verticalListSortingStrategy,
|
||||||
|
|
||||||
|
} from "@dnd-kit/sortable";
|
||||||
|
import { CSS } from "@dnd-kit/utilities";
|
||||||
|
import { useState } from "react";
|
||||||
|
import type { DragEndEvent, DragStartEvent } from "@dnd-kit/core";
|
||||||
|
import { SortableItem } from "@/components/test_dnd";
|
||||||
|
import { DroppableContainer } from "@/components/ui/droppableContainer";
|
||||||
|
|
||||||
|
interface TestItem {
|
||||||
|
id: string,
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
const [left, setLeft] = useState<TestItem[]>([{ id: "1", name: "Apfel" }, { id: "2", name: "Banane" }]);
|
||||||
|
const [right, setRight] = useState<TestItem[]>([{ id: "3", name: "Traube" }]);
|
||||||
|
|
||||||
|
const [activeItem, setActiveItem] = useState<TestItem | null>(null);
|
||||||
|
|
||||||
|
function findContainer(id: string) {
|
||||||
|
if (left.find((item) => item.id === id)) return "left";
|
||||||
|
if (right.find((item) => item.id === id)) return "right";
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDragStart(event: DragStartEvent) {
|
||||||
|
const { active } = event;
|
||||||
|
|
||||||
|
const item =
|
||||||
|
left.find((i) => i.id === active.id) ||
|
||||||
|
right.find((i) => i.id === active.id);
|
||||||
|
|
||||||
|
if (item) setActiveItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDragEnd(event: DragEndEvent) {
|
||||||
|
|
||||||
|
const { active, over } = event;
|
||||||
|
setActiveItem(null);
|
||||||
|
if (!over) return;
|
||||||
|
|
||||||
|
const overId = over.id;
|
||||||
|
|
||||||
|
const activeContainer = findContainer(active.id as string);
|
||||||
|
|
||||||
|
const overContainer =
|
||||||
|
overId === "left" || overId === "right"
|
||||||
|
? overId
|
||||||
|
: findContainer(overId as string);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (!activeContainer || !overContainer) return;
|
||||||
|
|
||||||
|
// 🔁 Innerhalb gleicher Liste sortieren
|
||||||
|
if (activeContainer === overContainer) {
|
||||||
|
if (activeContainer === "left") {
|
||||||
|
const oldIndex = left.findIndex((i) => i.id === active.id);
|
||||||
|
const newIndex = left.findIndex((i) => i.id === over.id);
|
||||||
|
|
||||||
|
setLeft(arrayMove(left, oldIndex, newIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activeContainer === "right") {
|
||||||
|
const oldIndex = right.findIndex((i) => i.id === active.id);
|
||||||
|
const newIndex = right.findIndex((i) => i.id === over.id);
|
||||||
|
|
||||||
|
setRight(arrayMove(right, oldIndex, newIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (activeContainer === "left") {
|
||||||
|
const item = left.find((i) => i.id === active.id);
|
||||||
|
if (!item) return;
|
||||||
|
|
||||||
|
setLeft(left.filter((i) => i.id !== active.id));
|
||||||
|
setRight([...right, item]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activeContainer === "right") {
|
||||||
|
const item = right.find((i) => i.id === active.id);
|
||||||
|
if (!item) return;
|
||||||
|
|
||||||
|
setRight(right.filter((i) => i.id !== active.id));
|
||||||
|
setLeft([...left, item]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ padding: 40 }}>
|
||||||
|
<DndContext collisionDetection={closestCenter} onDragStart={handleDragStart} onDragEnd={handleDragEnd}>
|
||||||
|
<div className="flex gap-10 border-1">
|
||||||
|
<DroppableContainer id="left">
|
||||||
|
<SortableContext items={left.map(i => i.id)} strategy={verticalListSortingStrategy}>
|
||||||
|
<div className="border-1 p-4">
|
||||||
|
<h3>Links</h3>
|
||||||
|
{left.map((item) => (
|
||||||
|
<SortableItem key={item.id} item={item} ><div>Test</div></SortableItem>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</SortableContext>
|
||||||
|
</DroppableContainer>
|
||||||
|
|
||||||
|
<DroppableContainer id="right">
|
||||||
|
<SortableContext items={right.map(i => i.id)} strategy={verticalListSortingStrategy}>
|
||||||
|
<div className="border-1 p-4">
|
||||||
|
<h3>Rechts</h3>
|
||||||
|
{right.map((item) => (
|
||||||
|
<SortableItem key={item.id} item={item} ><div>Test</div></SortableItem>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</SortableContext>
|
||||||
|
</DroppableContainer>
|
||||||
|
</div>
|
||||||
|
{/* DRAG OVERLAY */}
|
||||||
|
<DragOverlay>
|
||||||
|
{activeItem ? (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
padding: 12,
|
||||||
|
border: "1px solid black",
|
||||||
|
background: "lightyellow",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{activeItem.id} {activeItem.name}
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
</DragOverlay>
|
||||||
|
</DndContext>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { uploadFile } from "@/actions/rk/api-file-uplaod";
|
||||||
|
|
||||||
|
export default function UploadPage() {
|
||||||
|
return (
|
||||||
|
<form action={uploadFile}>
|
||||||
|
<input type="file" name="file" />
|
||||||
|
<button type="submit">Upload</button>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import { drawGetSvg } from "@/actions/rk/api-draw";
|
||||||
|
import { api_VisuElementsAll } from "@/actions/rk/api-visuElements";
|
||||||
|
import VisuCreatePlatform from "@/components/visu/create/visuCreatePlatform";
|
||||||
|
import VisuContent from "@/components/visu/visuContent";
|
||||||
|
|
||||||
|
export default async function PageVisu() {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="">
|
||||||
|
<VisuCreatePlatform />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
import { api_ElementsGet } from "@/actions/rk/api-element";
|
||||||
|
import { api_VisuElementsAll } from "@/actions/rk/api-visuElements";
|
||||||
|
import VisuElementsList from "@/components/visu/visuElements/visuElementsList";
|
||||||
|
|
||||||
|
|
||||||
|
export default async function PageVisuElemente() {
|
||||||
|
|
||||||
|
const visuElements = await api_VisuElementsAll();
|
||||||
|
const elements = await api_ElementsGet();
|
||||||
|
|
||||||
|
if(!visuElements) {
|
||||||
|
return <div>Loading...</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="">
|
||||||
|
<VisuElementsList visuElements={visuElements} elements={elements}></VisuElementsList>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import { api_ElementsGet } from "@/actions/rk/api-element";
|
||||||
|
import { api_GroupAll } from "@/actions/rk/api-groups";
|
||||||
|
import { api_VisuElementsAll } from "@/actions/rk/api-visuElements";
|
||||||
|
import VisuAddGroups from "@/components/visu/visuAddGroups";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
|
||||||
|
export default async function PageGroups() {
|
||||||
|
const groups = await api_GroupAll();
|
||||||
|
const elements = await api_ElementsGet();
|
||||||
|
const visuElements = await api_VisuElementsAll();
|
||||||
|
|
||||||
|
if(!groups || !visuElements) return <div>Loading...</div>
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="">
|
||||||
|
<Link href={Sites.main.url}>{Sites.main.name}</Link>
|
||||||
|
<div>
|
||||||
|
<VisuAddGroups groups={groups} elements={elements} visuElements={visuElements}></VisuAddGroups>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { VisuElementsProvider } from "@/_context/visu/VisuElementsProvider";
|
||||||
|
import { drawGetSvg } from "@/actions/rk/api-draw";
|
||||||
|
import { api_VisuElementsAll } from "@/actions/rk/api-visuElements";
|
||||||
|
import VisuContent from "@/components/visu/visuContent";
|
||||||
|
|
||||||
|
export default async function PageVisu() {
|
||||||
|
|
||||||
|
const visuElements = await api_VisuElementsAll();
|
||||||
|
console.log('reander')
|
||||||
|
|
||||||
|
if(!visuElements) {
|
||||||
|
console.log('reload!!!')
|
||||||
|
return <div>Loading...</div>
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className="">
|
||||||
|
<VisuElementsProvider initialValues={visuElements}>
|
||||||
|
<VisuContent />
|
||||||
|
</VisuElementsProvider>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import { VisuElementsProvider } from "@/_context/visu/VisuElementsProvider";
|
||||||
|
import { api_drawData } from "@/actions/draw/api-draw";
|
||||||
|
import { drawGetSvg } from "@/actions/rk/api-draw";
|
||||||
|
import { api_VisuElementsAll } from "@/actions/rk/api-visuElements";
|
||||||
|
import { Card, CardContent, CardHeader } from "@/components/ui/card";
|
||||||
|
import { SvgShow } from "@/components/visu/draw/svgShow";
|
||||||
|
import VisuContent from "@/components/visu/visuContent";
|
||||||
|
|
||||||
|
export default async function PageShowDraw() {
|
||||||
|
|
||||||
|
const data = await api_drawData();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="bg-gray-200">
|
||||||
|
<svg
|
||||||
|
width="180%"
|
||||||
|
height="180%"
|
||||||
|
viewBox={`${0} ${0} ${1820} ${1120}`}
|
||||||
|
>
|
||||||
|
<rect x1={1} y1={0} width={1750} height={1500} fill="#fee0fe" stroke="#000" strokeWidth={1} />
|
||||||
|
|
||||||
|
<SvgShow svg={data.svg} />
|
||||||
|
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
{true &&
|
||||||
|
<Card positons={"start"}>
|
||||||
|
<CardHeader variant={"danger"} >Debug</CardHeader>
|
||||||
|
<CardContent className="ps-8">
|
||||||
|
<pre>{JSON.stringify(data, null, 2)}</pre>
|
||||||
|
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
+16
-17
@@ -3,32 +3,31 @@ import { Geist, Geist_Mono } from "next/font/google";
|
|||||||
import "./globals.css";
|
import "./globals.css";
|
||||||
|
|
||||||
const geistSans = Geist({
|
const geistSans = Geist({
|
||||||
variable: "--font-geist-sans",
|
variable: "--font-geist-sans",
|
||||||
subsets: ["latin"],
|
subsets: ["latin"],
|
||||||
});
|
});
|
||||||
|
|
||||||
const geistMono = Geist_Mono({
|
const geistMono = Geist_Mono({
|
||||||
variable: "--font-geist-mono",
|
variable: "--font-geist-mono",
|
||||||
subsets: ["latin"],
|
subsets: ["latin"],
|
||||||
});
|
});
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "Create Next App",
|
title: "Create Next App",
|
||||||
description: "Generated by create next app",
|
description: "Generated by create next app",
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function RootLayout({
|
export default function RootLayout({
|
||||||
children,
|
children,
|
||||||
}: Readonly<{
|
}: Readonly<{
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}>) {
|
}>) {
|
||||||
return (
|
return (
|
||||||
<html lang="en">
|
<html lang="de">
|
||||||
<body
|
<body className={`${geistSans.variable} ${geistMono.variable} antialiased`} >
|
||||||
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
|
|
||||||
>
|
{children}
|
||||||
{children}
|
</body>
|
||||||
</body>
|
</html>
|
||||||
</html>
|
);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
+31
-63
@@ -1,65 +1,33 @@
|
|||||||
import Image from "next/image";
|
import { Sites } from "@/_config/sites";
|
||||||
|
|
||||||
export default function Home() {
|
import Image from "next/image";
|
||||||
return (
|
import Link from "next/link";
|
||||||
<div className="flex min-h-screen items-center justify-center bg-zinc-50 font-sans dark:bg-black">
|
|
||||||
<main className="flex min-h-screen w-full max-w-3xl flex-col items-center justify-between py-32 px-16 bg-white dark:bg-black sm:items-start">
|
export default async function Home() {
|
||||||
<Image
|
|
||||||
className="dark:invert"
|
return (
|
||||||
src="/next.svg"
|
<div className="flex min-h-screen bg-zinc-50 font-sans dark:bg-black">
|
||||||
alt="Next.js logo"
|
|
||||||
width={100}
|
<div className="flex flex-col m-4">
|
||||||
height={20}
|
<Link href={Sites.anlagen.url}>{Sites.anlagen.name}</Link>
|
||||||
priority
|
<Link href={Sites.groups.url}>{Sites.groups.name}</Link>
|
||||||
/>
|
<Link href={Sites.elements.url}>{Sites.elements.name}</Link>
|
||||||
<div className="flex flex-col items-center gap-6 text-center sm:items-start sm:text-left">
|
<Link href={Sites.peripheries.url}>{Sites.peripheries.name}</Link>
|
||||||
<h1 className="max-w-xs text-3xl font-semibold leading-10 tracking-tight text-black dark:text-zinc-50">
|
<Link href={Sites.visu.url}>{Sites.visu.name}</Link>
|
||||||
To get started, edit the page.tsx file.
|
<Link href={Sites.visu.create.url}>{Sites.visu.create.name}</Link>
|
||||||
</h1>
|
<Link href={Sites.visu.selectGroups.url}>{Sites.visu.selectGroups.name}</Link>
|
||||||
<p className="max-w-md text-lg leading-8 text-zinc-600 dark:text-zinc-400">
|
<Link href={Sites.visu.elements.url}>{Sites.visu.elements.name}</Link>
|
||||||
Looking for a starting point or more instructions? Head over to{" "}
|
<Link href={Sites.logNote.url}>{Sites.logNote.name}</Link>
|
||||||
<a
|
|
||||||
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
<Link href={Sites.logNote.url}>{Sites.logNote.name}</Link>
|
||||||
className="font-medium text-zinc-950 dark:text-zinc-50"
|
|
||||||
>
|
</div>
|
||||||
Templates
|
|
||||||
</a>{" "}
|
<div className="flex flex-col m-4">
|
||||||
or the{" "}
|
|
||||||
<a
|
<Link href={Sites.rk2.url}>{Sites.rk2.name}</Link>
|
||||||
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
|
||||||
className="font-medium text-zinc-950 dark:text-zinc-50"
|
</div>
|
||||||
>
|
</div>
|
||||||
Learning
|
);
|
||||||
</a>{" "}
|
|
||||||
center.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-col gap-4 text-base font-medium sm:flex-row">
|
|
||||||
<a
|
|
||||||
className="flex h-12 w-full items-center justify-center gap-2 rounded-full bg-foreground px-5 text-background transition-colors hover:bg-[#383838] dark:hover:bg-[#ccc] md:w-[158px]"
|
|
||||||
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
className="dark:invert"
|
|
||||||
src="/vercel.svg"
|
|
||||||
alt="Vercel logomark"
|
|
||||||
width={16}
|
|
||||||
height={16}
|
|
||||||
/>
|
|
||||||
Deploy Now
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
className="flex h-12 w-full items-center justify-center rounded-full border border-solid border-black/[.08] px-5 transition-colors hover:border-transparent hover:bg-black/[.04] dark:border-white/[.145] dark:hover:bg-[#1a1a1a] md:w-[158px]"
|
|
||||||
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
Documentation
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import { ProConView, ProConXamlData } from "@/types/procon"
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import VisualisierungPositionen from "./visualiserungPositionen";
|
||||||
|
import { api_ProconViews_UpdateXAML } from "@/actions/procon/api-procon-views";
|
||||||
|
import { useVisuAgg } from "@/hooks/procon/useVisuAgg";
|
||||||
|
import SvgView from "./svg/SvgView";
|
||||||
|
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
visuElements: ProConView[]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default function Visualisierungen({ visuElements }: Props) {
|
||||||
|
const [selectedElement, setSelectedElement] = useState<ProConView | undefined>();
|
||||||
|
const [selectedView, setSelectedView] = useState<ProConXamlData | undefined>();
|
||||||
|
|
||||||
|
const { elements, viewNames, selectedViewElement, onSelectViewElement, graphics } = useVisuAgg({ data: visuElements });
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setSelectedElement(undefined);
|
||||||
|
setSelectedView(undefined);
|
||||||
|
}, [visuElements])
|
||||||
|
|
||||||
|
|
||||||
|
const headers = ['Symbol', "PosX", "PosY", "Höhe", "Breite", "Ebene", "Auswahl"]
|
||||||
|
|
||||||
|
const handlerSaveXaml = () => {
|
||||||
|
if (!selectedView) return;
|
||||||
|
api_ProconViews_UpdateXAML(selectedView.id, selectedView.xaml)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className="flex gap-8">
|
||||||
|
<section>
|
||||||
|
<div>
|
||||||
|
XAML-Views
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-1 w-50 ">
|
||||||
|
{viewNames.map((v) => (
|
||||||
|
<div
|
||||||
|
className="border-1 rounded p-1 bg-gray-100"
|
||||||
|
key={v.index}
|
||||||
|
onClick={() => onSelectViewElement(v.index)}
|
||||||
|
>
|
||||||
|
{v.name}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<div>
|
||||||
|
{selectedViewElement?.viewType}
|
||||||
|
<div className="flex gap-4">
|
||||||
|
<div>X</div>
|
||||||
|
<div>{selectedViewElement?.posX}</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{graphics.map((g) => (<div>{g.viewType}-{g.viewIndex}-{g.state}</div>))}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{graphics.map((g) => <SvgView svg={g.svg} />)
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{ graphics[0] &&
|
||||||
|
<textarea className="w-300 h-100" value={(graphics[0].xaml)} />
|
||||||
|
}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<div className="grid grid-cols-[200px_50px_50px_50px_50px_50px_400px] gap-4">
|
||||||
|
{headers.map((name) => <div key={name}>{name}</div>)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{elements.map((element) => (
|
||||||
|
<div className="grid grid-cols-[200px_50px_50px_50px_50px_50px_400px] gap-4" key={element.id}>
|
||||||
|
<div>{element.viewType}{element.viewType == 'pfeil' && element.viewIndex}</div>
|
||||||
|
<VisualisierungPositionen id={element.id} koordinaten={{ ...element }}></VisualisierungPositionen>
|
||||||
|
<div>{element.views.length > 0 && <button onClick={() => setSelectedElement(() => element)}>x</button>}</div>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
<div className="mt-8">
|
||||||
|
{selectedElement && <div>
|
||||||
|
<div className="font-bold p-4">View {selectedElement.viewType}{selectedElement.viewType == "pfeil" && selectedElement.viewIndex}</div>
|
||||||
|
<div className="flex gap-4 p-4">
|
||||||
|
{selectedElement.views.map((view) => <div onClick={() => setSelectedView(view)} key={view.id}>{view.state}</div>)}
|
||||||
|
</div>
|
||||||
|
</div>}
|
||||||
|
</div>
|
||||||
|
{selectedViewElement?.viewType}
|
||||||
|
{selectedViewElement && selectedViewElement.views &&
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<textarea className="w-300 h-100" value={atob(selectedViewElement.views[0].xaml)} onChange={(e) => setSelectedView((old) => ({ ...old!, xaml: btoa(e.target.value) }))} />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<button onClick={() => handlerSaveXaml()}>Save</button>
|
||||||
|
<button onClick={() => setSelectedView((old) => undefined)}>cancel</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import Modal from "../ui/Modal";
|
||||||
|
interface Props {
|
||||||
|
xamlBase64Data: string
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default function AggregateXamlData({ xamlBase64Data }: Props) {
|
||||||
|
const [showDetails, setShowDetails] = useState(false);
|
||||||
|
const [text, setText] = useState('');
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setText(atob(xamlBase64Data))
|
||||||
|
}, [xamlBase64Data])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section>
|
||||||
|
<button onClick={() => setShowDetails(!showDetails)}>
|
||||||
|
{showDetails ? "Weniger Details" : "Mehr Details"}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{showDetails && (
|
||||||
|
<Modal onClose={()=>setShowDetails(false)}>
|
||||||
|
<div className="w-400 h-200">
|
||||||
|
<textarea className="w-full h-full" name="xaml" id="xaml" value={text} onChange={(e) => setText(e.target.value)}></textarea>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
)}
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import Modal from "../ui/Modal";
|
||||||
|
import { InputNumber } from "../ui/InputNumber";
|
||||||
|
import { api_ProconVisualisierungen_Update } from "@/actions/procon/api-procon-visualisierungen";
|
||||||
|
import { ProConView } from "@/types/procon";
|
||||||
|
|
||||||
|
interface Positionen{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
data:ProConView
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default function EditXaml({ data }: Props) {
|
||||||
|
const [showDetails, setShowDetails] = useState(false);
|
||||||
|
const [text, setText] = useState('');
|
||||||
|
|
||||||
|
const handleChange = (name:string,value:number)=>{
|
||||||
|
console.log('Submit','name',name,' value',value);
|
||||||
|
let data :Partial<ProConView> = {}
|
||||||
|
if(name==='posX') data['posX'] = value;
|
||||||
|
if(name==='posY') data['posY'] = value;
|
||||||
|
if(name==='height') data['height'] = value;
|
||||||
|
if(name==='width') data['width'] = value;
|
||||||
|
if(name==='zIndex') data['zIndex'] = value;
|
||||||
|
|
||||||
|
|
||||||
|
//api_ProconVisualisierungen_Update(id,data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{data.views.map((view)=><div>{view.state}</div>)}
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
<div>{element.posX}</div>
|
||||||
|
<div>{element.posY}</div>
|
||||||
|
<div>{element.height}</div>
|
||||||
|
<div>{element.width}</div>
|
||||||
|
<div>{element.zIndex}</div>
|
||||||
|
*/
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
svg: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function SvgView({ svg }: Props) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: svg,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
Whitespace-only changes.
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,59 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import Modal from "../ui/Modal";
|
||||||
|
import { InputNumber } from "../ui/InputNumber";
|
||||||
|
import { api_ProconVisualisierungen_Update } from "@/actions/procon/api-procon-visualisierungen";
|
||||||
|
import { ProConView } from "@/types/procon";
|
||||||
|
|
||||||
|
interface Positionen{
|
||||||
|
posX:number,
|
||||||
|
posY:number,
|
||||||
|
height:number,
|
||||||
|
width:number,
|
||||||
|
zIndex:number
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
id:number,
|
||||||
|
koordinaten: Positionen
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default function VisualisierungPositionen({ id,koordinaten }: Props) {
|
||||||
|
const [showDetails, setShowDetails] = useState(false);
|
||||||
|
const [text, setText] = useState('');
|
||||||
|
|
||||||
|
const handleChange = (name:string,value:number)=>{
|
||||||
|
console.log('Submit','name',name,' value',value);
|
||||||
|
let data :Partial<ProConView> = {}
|
||||||
|
if(name==='posX') data['posX'] = value;
|
||||||
|
if(name==='posY') data['posY'] = value;
|
||||||
|
if(name==='height') data['height'] = value;
|
||||||
|
if(name==='width') data['width'] = value;
|
||||||
|
if(name==='zIndex') data['zIndex'] = value;
|
||||||
|
|
||||||
|
|
||||||
|
api_ProconVisualisierungen_Update(id,data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
|
||||||
|
<InputNumber name="posX" inValue={koordinaten.posX} onChanged={handleChange} />
|
||||||
|
<InputNumber name="posY" inValue={koordinaten.posY} onChanged={handleChange} />
|
||||||
|
<InputNumber name="height" inValue={koordinaten.height} onChanged={handleChange} />
|
||||||
|
<InputNumber name="width" inValue={koordinaten.width} onChanged={handleChange} />
|
||||||
|
<InputNumber name="zIndex" inValue={koordinaten.zIndex} onChanged={handleChange} />
|
||||||
|
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
<div>{element.posX}</div>
|
||||||
|
<div>{element.posY}</div>
|
||||||
|
<div>{element.height}</div>
|
||||||
|
<div>{element.width}</div>
|
||||||
|
<div>{element.zIndex}</div>
|
||||||
|
*/
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
"use client"
|
||||||
|
import { api_anlage_setSelected } from "@/actions/rk/api-anlage";
|
||||||
|
import { Anlage } from "@/types/rk";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
data: Anlage,
|
||||||
|
isSelected: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function AnlageColumn({ data, isSelected }: Props) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return <div style={{ backgroundColor: isSelected ? "#00ff00" : "#ffffff" }}
|
||||||
|
onClick={() => api_anlage_setSelected(data.id)}>
|
||||||
|
<div>
|
||||||
|
{data.id}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{data.anlageNr}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{data.name}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import { Anlage, Element, ExcelProCon, Group } from "@/types/rk";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { ElementEdit } from "./elementEdit";
|
||||||
|
import ElementViewItem from "./elementsViewItem";
|
||||||
|
import ElementViewListHeader from "./elementsViewListHeader";
|
||||||
|
import ElementSelectExcelList from "./elementsSelectExcelList";
|
||||||
|
import { ElementEditRow } from "./elementEditRow";
|
||||||
|
import { useElements } from "@/hooks/useElements";
|
||||||
|
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
analge:Anlage,
|
||||||
|
elements: Element[],
|
||||||
|
groups: Group[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ElementCreateView({ analge,elements:initElements, groups }: Props) {
|
||||||
|
|
||||||
|
const { elements, selectedElement, filterExcelListe, setFilterExcelListe, setSelectedItem } = useElements({ elements: initElements });
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="grid grid-cols-[1200_300]">
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<ElementSelectExcelList onSelect={(liste) => setFilterExcelListe(liste)}></ElementSelectExcelList>
|
||||||
|
|
||||||
|
<ElementEditRow anlage={analge} groups={groups}></ElementEditRow>
|
||||||
|
{filterExcelListe}
|
||||||
|
|
||||||
|
<div className="m-4 p-4">
|
||||||
|
<ElementViewListHeader></ElementViewListHeader>
|
||||||
|
<div className="h-180 overflow-y-scroll border">
|
||||||
|
{elements.map((item) =>
|
||||||
|
|
||||||
|
<ElementViewItem key={item.id} element={item} onSelect={setSelectedItem}></ElementViewItem>
|
||||||
|
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,141 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useEffect, useState } from "react"
|
||||||
|
import { useForm } from "react-hook-form"
|
||||||
|
import { InputTextR } from "@/components/ui/inputTextR";
|
||||||
|
import { Element, ElementCreate, emptyElement, Group } from "@/types/rk";
|
||||||
|
|
||||||
|
import { api_elementDelete, elementCreate, elementUpdate } from "@/actions/rk/api-element";
|
||||||
|
import { SelectR } from "@/components/ui/selectR";
|
||||||
|
|
||||||
|
|
||||||
|
interface Params {
|
||||||
|
groups: Group[]
|
||||||
|
initData?: Element
|
||||||
|
debug?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ElementEdit = ({ initData, groups, debug }: Params) => {
|
||||||
|
|
||||||
|
const { control, register, handleSubmit, formState: { errors }, watch, getFieldState, reset } = useForm<ElementCreate>({ defaultValues: emptyElement, })
|
||||||
|
|
||||||
|
|
||||||
|
const [modeUpdate, setModeUpdate] = useState(false);
|
||||||
|
const [selGroup, setSelGroup] = useState<string | undefined>();
|
||||||
|
|
||||||
|
const [id, setId] = useState<string | undefined>();
|
||||||
|
const [error, setError] = useState<string | undefined>();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (initData) {
|
||||||
|
const { id, group, ...rest } = initData;
|
||||||
|
setId(id);
|
||||||
|
setModeUpdate(true);
|
||||||
|
if (initData.group) setSelGroup(() => initData.group.id);
|
||||||
|
reset({ ...rest, groupId: group ? group.id : undefined })
|
||||||
|
}
|
||||||
|
}, [initData]);
|
||||||
|
|
||||||
|
const onSubmit = async (data: ElementCreate) => {
|
||||||
|
setError(undefined);
|
||||||
|
//const { name, isConsumable, description } = data;
|
||||||
|
if (modeUpdate) {
|
||||||
|
if (id) {
|
||||||
|
elementUpdate(id, data);
|
||||||
|
} else {
|
||||||
|
setError('Etwas ist falsch, keine ID');
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
elementCreate(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handlerDelete = async () => {
|
||||||
|
if (id) api_elementDelete(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
const excelListe = [{ id: "keine", value: "" },
|
||||||
|
{ id: "Aggregate", value: "Aggregate" },
|
||||||
|
{ id: "Sensoren", value: "Sensoren" },
|
||||||
|
{ id: "Analogwerte", value: "Analogwerte" },
|
||||||
|
{ id: "AnlagenVisu", value: "AnlagenVisualisierung" },
|
||||||
|
]
|
||||||
|
|
||||||
|
const options = watch("options")
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="w-120 flex flex-col p-4 pt-10 ps-10" >
|
||||||
|
<div className="border-1 p-4">
|
||||||
|
<form onSubmit={handleSubmit(onSubmit)} className="max-w-md mx-auto">
|
||||||
|
<div>
|
||||||
|
|
||||||
|
{initData && initData.group &&
|
||||||
|
<div>
|
||||||
|
{initData?.group.nr}_{initData?.group.name}
|
||||||
|
</div>}
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<SelectR label="Gruppe" options={groups.map((g) => ({ id: g.id, value: g.nr + '_' + g.name }))} {...register("groupId")} ></SelectR>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="grid grid-cols-[60px_1fr] gap-2">
|
||||||
|
<InputTextR label="Nr" {...register("excelNr", { required: "Pflichtfeld" })} error={errors.excelNr?.message} />
|
||||||
|
<InputTextR label="Name" {...register("name", { required: "Pflichtfeld" })} error={errors.name?.message} />
|
||||||
|
</div>
|
||||||
|
<InputTextR label="Prefix" {...register("prefix", { required: false })} error={errors.prefix?.message} />
|
||||||
|
<InputTextR label="funcTxt" {...register("funcTxt", { required: false })} error={errors.funcTxt?.message} />
|
||||||
|
<InputTextR label="Type" {...register("type", { required: "Pflichtfeld" })} error={errors.type?.message} />
|
||||||
|
<SelectR label="Excel Liste" options={excelListe.map((e) => ({ id: e.id, value: e.value }))} {...register("excelListe")} ></SelectR>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{error && <div>{error}</div>}
|
||||||
|
{errors.name && <div>{errors.name.message}</div>}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="p-2 mt-4 ">
|
||||||
|
<div className="font-semibold">Optionen</div>
|
||||||
|
<div className="border-1 rounded border-gray-200 p-4 ">
|
||||||
|
{options &&
|
||||||
|
Object.entries(options).map(([key, value]) => (
|
||||||
|
<div key={key} className="grid grid-cols-[100px_200px] pt-1">
|
||||||
|
|
||||||
|
<label className="font-semibold">{key}:</label>
|
||||||
|
|
||||||
|
{typeof value === "boolean" ? (
|
||||||
|
<div className="flex flex-start ">
|
||||||
|
<input
|
||||||
|
className=""
|
||||||
|
type="checkbox"
|
||||||
|
{...register(`options.${key}` as const)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
) : (
|
||||||
|
<div className="">
|
||||||
|
<InputTextR {...register(`options.${key}` as const)} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
</div>))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex gap-4">
|
||||||
|
<button type="submit" className="bg-blue-500 text-white p-2 rounded mt-2 hover:bg-blue-600">Speichern</button>
|
||||||
|
{id && <button className="bg-red-500 text-white p-2 rounded mt-2 hover:bg-blue-600" onClick={() => handlerDelete()}>Löschen</button>}
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div >
|
||||||
|
|
||||||
|
{debug &&
|
||||||
|
<div>
|
||||||
|
<div>ID: {id}</div>
|
||||||
|
<pre>{JSON.stringify(watch(), null, 2)}</pre>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div >
|
||||||
|
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useEffect, useState } from "react"
|
||||||
|
import { useForm } from "react-hook-form"
|
||||||
|
import { InputTextR } from "@/components/ui/inputTextR";
|
||||||
|
import { Anlage, Element, ElementCreate, emptyElement, Group } from "@/types/rk";
|
||||||
|
|
||||||
|
import { api_elementDelete, elementCreate, elementUpdate } from "@/actions/rk/api-element";
|
||||||
|
import { SelectR } from "@/components/ui/selectR";
|
||||||
|
import { useElement } from "@/hooks/useElement";
|
||||||
|
import { Sites } from "@/_config/sites";
|
||||||
|
import Toast from "@/components/ui/Toast";
|
||||||
|
|
||||||
|
|
||||||
|
interface Params {
|
||||||
|
anlage: Anlage,
|
||||||
|
groups: Group[]
|
||||||
|
elementIntial?: Element
|
||||||
|
debug?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ElementEditRow = ({ anlage, elementIntial, groups, debug }: Params) => {
|
||||||
|
|
||||||
|
const { control, register, handleSubmit, formState: { errors }, watch, setFocus, reset } = useForm<ElementCreate>({ defaultValues: emptyElement, })
|
||||||
|
const { proConExcelLists } = useElement({ element: elementIntial })
|
||||||
|
const [selGroup, setSelGroup] = useState<string | undefined>();
|
||||||
|
const [toast, setToast] = useState<string | null>(null);
|
||||||
|
|
||||||
|
|
||||||
|
const [error, setError] = useState<string | undefined>();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (elementIntial) {
|
||||||
|
const { id, group, ...rest } = elementIntial;
|
||||||
|
|
||||||
|
if (elementIntial.group) setSelGroup(() => elementIntial.group.id);
|
||||||
|
reset({ ...rest, groupId: group ? group.id : undefined })
|
||||||
|
} else {
|
||||||
|
reset({ ...emptyElement, anlageId: anlage.id })
|
||||||
|
}
|
||||||
|
}, [elementIntial]);
|
||||||
|
|
||||||
|
const onSubmit = async (data: ElementCreate) => {
|
||||||
|
setError(undefined);
|
||||||
|
//await elementCreate(data);
|
||||||
|
setToast("Erfolgreich gespeichert!");
|
||||||
|
setFocus('excelNr')
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const options = watch("options")
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col p-4 pt-10 ps-10" >
|
||||||
|
|
||||||
|
<div className="relative inline-block">
|
||||||
|
{toast && (
|
||||||
|
<Toast
|
||||||
|
message={toast}
|
||||||
|
onClose={() => setToast(null)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<form onSubmit={handleSubmit(onSubmit)} className="">
|
||||||
|
<div className="flex gap-4 border-1 border-gray-200 rounded-sm p-4 shadow-md">
|
||||||
|
|
||||||
|
<div className="grid grid-cols-[60px_1fr] gap-2">
|
||||||
|
<InputTextR label="Nr" {...register("excelNr", { required: "Pflichtfeld" })} error={errors.excelNr?.message} />
|
||||||
|
<InputTextR label="Name" {...register("name", { required: "Pflichtfeld" })} error={errors.name?.message} />
|
||||||
|
</div>
|
||||||
|
<InputTextR label="Prefix" {...register("prefix", { required: false })} error={errors.prefix?.message} />
|
||||||
|
<InputTextR label="funcTxt" {...register("funcTxt", { required: false })} error={errors.funcTxt?.message} />
|
||||||
|
<InputTextR label="Type" {...register("type", { required: "Pflichtfeld" })} error={errors.type?.message} />
|
||||||
|
<SelectR label="Excel Liste" options={proConExcelLists} {...register("excelListe")} ></SelectR>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{error && <div>{error}</div>}
|
||||||
|
{errors.name && <div>{errors.name.message}</div>}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div className="flex gap-4">
|
||||||
|
<button type="submit" className="bg-blue-500 text-white p-2 rounded mt-2 hover:bg-blue-600">Speichern</button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div >
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{true &&
|
||||||
|
<div>
|
||||||
|
<pre>{JSON.stringify(watch(), null, 2)}</pre>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div >
|
||||||
|
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import { Element, Group } from "@/types/rk";
|
||||||
|
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
elements: Element[],
|
||||||
|
onSelect?: (element:Element)=>void
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ElementSelect({ elements,onSelect }: Props) {
|
||||||
|
|
||||||
|
const handleSelect = (element:Element)=>{
|
||||||
|
if(onSelect) onSelect(element);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className="">
|
||||||
|
<div className="flex flex-col m-4 pt-4 overflow-y-scroll border h-150">
|
||||||
|
{elements.map((el) => (
|
||||||
|
|
||||||
|
<div className="flex hover:bg-sky-100 h-8 items-center" onClick={()=>handleSelect(el)} key={el.id}>
|
||||||
|
<div className="ps-4 ">{`${el.group ? el.group.nr:'noGroup'}${el.prefix ? el.prefix:""} ${el.name}`}</div>
|
||||||
|
</div>))}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import { ExcelProCon } from "@/types/rk";
|
||||||
|
import MonButton from "@/components/ui/MonBotton";
|
||||||
|
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
|
||||||
|
onSelect:(excelListitem:ExcelProCon)=> void
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ElementSelectExcelList({ onSelect }: Props) {
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex gap-4 p-4">
|
||||||
|
{Object.values(ExcelProCon).map((item) => (
|
||||||
|
<MonButton key={item} onClick={()=>onSelect(item)}>
|
||||||
|
{item}
|
||||||
|
</MonButton>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import { Element, ExcelProCon, Group } from "@/types/rk";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { ElementEdit } from "./elementEdit";
|
||||||
|
import ElementViewItem from "./elementsViewItem";
|
||||||
|
import ElementViewListHeader from "./elementsViewListHeader";
|
||||||
|
import ElementSelectExcelList from "./elementsSelectExcelList";
|
||||||
|
import { useElements } from "@/hooks/useElements";
|
||||||
|
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
elements: Element[],
|
||||||
|
groups: Group[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ElementView({ elements: initElements, groups }: Props) {
|
||||||
|
|
||||||
|
const { elements, selectedElement, filterExcelListe, setFilterExcelListe, setSelectedItem } = useElements({ elements: initElements });
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="grid grid-cols-[1200_300]">
|
||||||
|
<div>
|
||||||
|
<ElementSelectExcelList onSelect={(liste) => setFilterExcelListe(liste)}></ElementSelectExcelList>
|
||||||
|
{filterExcelListe}
|
||||||
|
|
||||||
|
<div className="m-4 p-4">
|
||||||
|
<ElementViewListHeader></ElementViewListHeader>
|
||||||
|
<div className="h-180 overflow-y-scroll border">
|
||||||
|
{elements.map((item) =>
|
||||||
|
|
||||||
|
<ElementViewItem key={item.id} element={item} onSelect={setSelectedItem}></ElementViewItem>
|
||||||
|
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{selectedElement &&
|
||||||
|
<div>
|
||||||
|
<ElementEdit initData={selectedElement} debug={true} groups={groups}></ElementEdit>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import { Element, ExcelProCon, Group } from "@/types/rk";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { ElementEdit } from "./elementEdit";
|
||||||
|
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
element: Element,
|
||||||
|
onSelect: (element: Element) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ElementViewItem({ element, onSelect }: Props) {
|
||||||
|
|
||||||
|
|
||||||
|
const cols = [180, 80, 200, 300, 300, 150];
|
||||||
|
|
||||||
|
const style = { gridTemplateColumns: cols.map(c => `${c}px`).join(" ") }
|
||||||
|
|
||||||
|
return (
|
||||||
|
|
||||||
|
<div className="grid grid-cols-[1200_300]" style={style} onClick={() => onSelect(element)}>
|
||||||
|
|
||||||
|
<div>{element.excelListe}</div>
|
||||||
|
<div>{element.excelNr}</div>
|
||||||
|
{element.group ? <div>{element.group.nr} {element.group.name}</div> : <div>-</div>}
|
||||||
|
<div>{element.name}</div>
|
||||||
|
|
||||||
|
{/* Type */}
|
||||||
|
{element.group ? <div>
|
||||||
|
G_{element.group.nr}
|
||||||
|
{element.prefix != undefined && element.prefix !== "" && "_" + element.prefix}
|
||||||
|
_{element.group.name}
|
||||||
|
|
||||||
|
{element.funcTxt != undefined && element.funcTxt !== "" && "_" + element.funcTxt}
|
||||||
|
</div> : <div>n.v.</div>}
|
||||||
|
{<div>{element.type}</div>}
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import { Element, ExcelProCon, Group } from "@/types/rk";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { ElementEdit } from "./elementEdit";
|
||||||
|
import ElementViewItem from "./elementsViewItem";
|
||||||
|
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ElementViewListHeader({ }: Props) {
|
||||||
|
|
||||||
|
|
||||||
|
const cols = [180, 80, 200, 300, 300, 150];
|
||||||
|
const style = { gridTemplateColumns: cols.map(c => `${c}px`).join(" ") };
|
||||||
|
|
||||||
|
const headers = [
|
||||||
|
{ id: 0, name: "Excel Liste" },
|
||||||
|
{ id: 1, name: "Excel Nr" },
|
||||||
|
{ id: 2, name: "Gruppe" },
|
||||||
|
{ id: 3, name: "Element" },
|
||||||
|
{ id: 4, name: "ProConName" },
|
||||||
|
{ id: 5, name: "Typ" },
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
|
||||||
|
<div className={`grid font-bold `} style={style}>
|
||||||
|
{headers.map((col) => <div key={col.id}>{col.name}</div>)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import { Group } from "@/types/rk";
|
||||||
|
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
groups: Group[],
|
||||||
|
onSelect?: (id:Group)=>void
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function GroupSelect({ groups,onSelect }: Props) {
|
||||||
|
|
||||||
|
const handleSelect = (id:Group)=>{
|
||||||
|
if(onSelect) onSelect(id);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className="">
|
||||||
|
<div className="flex flex-col m-4 pt-4 overflow-y-scroll border h-150">
|
||||||
|
{groups.map((group) => (
|
||||||
|
|
||||||
|
<div className="flex hover:bg-sky-100 h-8 items-center" onClick={()=>handleSelect(group)} key={group.id}>
|
||||||
|
<div className="ps-4 ">{`${group.nr} ${group.name}`}</div>
|
||||||
|
</div>))}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import { Group } from "@/types/rk";
|
||||||
|
import GroupSelect from "./groupSelect";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import GroupViewItem from "./group_ViewItem";
|
||||||
|
import GroupFilter from "./group_Filter";
|
||||||
|
import { GroupEdit } from "./group_Edit";
|
||||||
|
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
groups: Group[],
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function GroupView({ groups }: Props) {
|
||||||
|
|
||||||
|
const [selectedItem, setSelectedItem] = useState<Group | undefined>();
|
||||||
|
const [groupFilterd, setGroupFilterd] = useState<Group[]>([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setGroupFilterd([...groups]);
|
||||||
|
if(selectedItem){
|
||||||
|
const updatedGroup = groups.find((g)=>g.id==selectedItem.id);
|
||||||
|
if(updatedGroup) setSelectedItem(()=>updatedGroup);
|
||||||
|
|
||||||
|
}
|
||||||
|
}, [groups])
|
||||||
|
|
||||||
|
const handlerOnChangeFilter = (groups: Group[]) => {
|
||||||
|
setGroupFilterd([...groups]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSelect = (item: Group) => {
|
||||||
|
console.log(item);
|
||||||
|
setSelectedItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className="m-4 p-4 border-1 border-gray-100 w-256">
|
||||||
|
<GroupFilter groups={groups} onChange={handlerOnChangeFilter}></GroupFilter>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div className="m-4 grid grid-cols-[300_2fr]">
|
||||||
|
{/** Spalte 1 Auswahl Gruppe */}
|
||||||
|
<div>
|
||||||
|
<GroupSelect onSelect={handleSelect} groups={groupFilterd}></GroupSelect>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/** Spalte 2 Anzeige Gruppe details */}
|
||||||
|
<div className="flex flex-col w-256 h-10">
|
||||||
|
{selectedItem && <div >
|
||||||
|
<div>edit</div>
|
||||||
|
<GroupViewItem group={selectedItem} ></GroupViewItem>
|
||||||
|
{<GroupEdit debug={true} initData={selectedItem} ></GroupEdit>}
|
||||||
|
</div>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useEffect, useState } from "react"
|
||||||
|
import { useForm } from "react-hook-form"
|
||||||
|
import { InputTextR } from "@/components/ui/inputTextR";
|
||||||
|
import { Anlage, emptyGroup, Group, GroupCreate } from "@/types/rk";
|
||||||
|
import { groupCreate, groupUpdate } from "@/actions/rk/api-groups";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
interface Params {
|
||||||
|
anlage:Anlage
|
||||||
|
initData?: Group
|
||||||
|
debug?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export const GroupEdit = ({anlage, initData, debug }: Params) => {
|
||||||
|
|
||||||
|
const { control, register, handleSubmit, formState: { errors }, watch, getFieldState, reset } = useForm<GroupCreate>({ defaultValues: emptyGroup, })
|
||||||
|
|
||||||
|
|
||||||
|
const [modeUpdate, setModeUpdate] = useState(false);
|
||||||
|
const [id, setId] = useState<string | undefined>();
|
||||||
|
const [error, setError] = useState<string | undefined>();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (initData) {
|
||||||
|
const { id, ...rest } = initData;
|
||||||
|
setId(id);
|
||||||
|
setModeUpdate(true);
|
||||||
|
reset({ ...rest })
|
||||||
|
}else{
|
||||||
|
reset({ ...emptyGroup,anlageId:anlage.id })
|
||||||
|
|
||||||
|
}
|
||||||
|
}, [initData]);
|
||||||
|
|
||||||
|
const onSubmit = async (data: GroupCreate) => {
|
||||||
|
setError(undefined);
|
||||||
|
//const { name, isConsumable, description } = data;
|
||||||
|
if (modeUpdate) {
|
||||||
|
if (id) {
|
||||||
|
groupUpdate(id, data);
|
||||||
|
} else {
|
||||||
|
setError('Etwas ist falsch, keine ID');
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
console.log('create',data)
|
||||||
|
groupCreate(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const options = watch("options")
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="w-120 flex flex-col p-4 pt-10 ps-10" >
|
||||||
|
<div className="border-1 p-4">
|
||||||
|
<form onSubmit={handleSubmit(onSubmit)} className="max-w-md mx-auto">
|
||||||
|
<div className="grid grid-cols-[60px_1fr] gap-2">
|
||||||
|
<InputTextR label="Nr" {...register("nr", { required: "Pflichtfeld" })} error={errors.nr?.message} />
|
||||||
|
<InputTextR label="Name" {...register("name", { required: "Pflichtfeld" })} error={errors.name?.message} />
|
||||||
|
</div>
|
||||||
|
<InputTextR label="Anzeige Name" {...register("displayName", {})} error={errors.displayName?.message} />
|
||||||
|
<InputTextR label="Info" {...register("info", { required: "Pflichtfeld" })} error={errors.info?.message} />
|
||||||
|
<InputTextR label="Ort" {...register("ort", { required: "Pflichtfeld" })} error={errors.ort?.message} />
|
||||||
|
<InputTextR label="Type" {...register("type", { required: "Pflichtfeld" })} error={errors.type?.message} />
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{error && <div>{error}</div>}
|
||||||
|
{errors.name && <div>{errors.name.message}</div>}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="p-2 mt-4 ">
|
||||||
|
<div className="font-semibold">Optionen</div>
|
||||||
|
<div className="border-1 rounded border-gray-200 p-4 ">
|
||||||
|
{options &&
|
||||||
|
Object.entries(options).map(([key, value]) => (
|
||||||
|
<div key={key} className="grid grid-cols-[100px_200px] pt-1">
|
||||||
|
|
||||||
|
<label className="font-semibold">{key}:</label>
|
||||||
|
|
||||||
|
{typeof value === "boolean" ? (
|
||||||
|
<div className="flex flex-start ">
|
||||||
|
<input
|
||||||
|
className=""
|
||||||
|
type="checkbox"
|
||||||
|
{...register(`options.${key}` as const)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
) : (
|
||||||
|
<div className="">
|
||||||
|
<InputTextR {...register(`options.${key}` as const)} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
</div>))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button type="submit" className="bg-blue-500 text-white p-2 rounded mt-2 hover:bg-blue-600">Speichern</button>
|
||||||
|
</form>
|
||||||
|
</div >
|
||||||
|
|
||||||
|
{debug &&
|
||||||
|
<div>
|
||||||
|
<div>{watch("name")}</div>
|
||||||
|
<pre>touched:{getFieldState("displayName").isTouched ? 'true' : 'false'}</pre>
|
||||||
|
<pre>{JSON.stringify(watch(), null, 2)}</pre>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div >
|
||||||
|
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
<div className="mt-4 mb-4 p-2 border-1 border-gray-200 relative ">
|
||||||
|
<div className="absolute -top-2 left-2 bg-white ps-1 pe-1 text-xs">Optionen</div>
|
||||||
|
<InputCheckboxR label="Konsumierbar" {...register("isConsumable")} error={errors.isConsumable?.message} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
*/
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import { Group } from "@/types/rk";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
groups: Group[],
|
||||||
|
onChange: (filterdGroups:Group[])=>void
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function GroupFilter({ groups,onChange }: Props) {
|
||||||
|
|
||||||
|
const [txt,setText] = useState('');
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
const filterd = groups.filter((group)=>{
|
||||||
|
let found = false;
|
||||||
|
if(group.name.includes(txt)) found = true;
|
||||||
|
if(group.nr.includes(txt)) found = true;
|
||||||
|
return found
|
||||||
|
})
|
||||||
|
onChange(filterd);
|
||||||
|
},[txt,groups])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="">
|
||||||
|
<div className="text-sm font-semibold">Suche</div>
|
||||||
|
<input onChange={(e)=>setText(e.target.value)} value={txt} className="w-96 border rounded p-2 border-gray-300" />
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import { Group } from "@/types/rk";
|
||||||
|
import GroupListItem from "./group_List_Item";
|
||||||
|
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
groups: Group[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function GroupList({ groups }: Props) {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="m-16 ms-32 w-256 bg-gray-0 border-t-1 border-gray-100 shadow-xl">
|
||||||
|
<div className="flex flex-col m-4 gap-2">
|
||||||
|
<div className="grid grid-cols-[200px_200px_250px_1fr] border-b-1 border-gray-800 ps-4 pb-1 pt-1 text-lg font-bold" >
|
||||||
|
<div>ID</div>
|
||||||
|
<div>Name</div>
|
||||||
|
<div>Optionen</div>
|
||||||
|
<div>Aggregate</div>
|
||||||
|
</div>
|
||||||
|
{groups.map((group) => (
|
||||||
|
|
||||||
|
|
||||||
|
<div className="grid grid-cols-[200px_200px_250px_1fr] border-b-1 min-h-16 border-gray-200 ps-4 pb-4 pt-2" key={group.id}>
|
||||||
|
<GroupListItem item={group}></GroupListItem>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import { Group } from "@/types/rk";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
item: Group
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function GroupListItem({ item }: Props) {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div>
|
||||||
|
{item.nr}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{item.name}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{item.options &&
|
||||||
|
Object.entries(item.options).map(([key, value]) => (
|
||||||
|
<div key={key} className="grid grid-cols-2 gap-8">
|
||||||
|
<div >{key}</div>
|
||||||
|
<div>
|
||||||
|
{typeof value === "boolean" ? (value ? "Ja" : "Nein") : value}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="">
|
||||||
|
{item.elements && <div>
|
||||||
|
{item.elements.map((element) => (
|
||||||
|
<div key={element.id} className="grid grid-cols-2 gap-8">
|
||||||
|
{false && element.prefix && <div>
|
||||||
|
{element.prefix}
|
||||||
|
</div>}
|
||||||
|
{element.name}
|
||||||
|
<div>
|
||||||
|
{element.excelNr}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>))}
|
||||||
|
</div>}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import { Group, Peripherie, PeripherieFilterOptionen } from "@/types/rk";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import PeripherieListView from "../peripherie/peripherieListView";
|
||||||
|
import { PeripherieFindApi } from "@/actions/rk/api-peripherie";
|
||||||
|
import { api_GroupAll, api_groupDelete } from "@/actions/rk/api-groups";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
group: Group
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function GroupViewItem({ group }: Props) {
|
||||||
|
|
||||||
|
const [showEA_Group, setShowEA_Group] = useState(false);
|
||||||
|
const [showEA_Element, setShowEA_Element] = useState(false);
|
||||||
|
const [showEA_Diff, setShowEA_Diff] = useState(false);
|
||||||
|
const [peripheries, setPeripheries] = useState<Peripherie[]>([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setPeripheries([]);
|
||||||
|
setShowEA_Group(false);
|
||||||
|
setShowEA_Element(false);
|
||||||
|
setShowEA_Diff(false);
|
||||||
|
|
||||||
|
}, [group])
|
||||||
|
|
||||||
|
const handlerShow_Group = () => {
|
||||||
|
const newMode = !showEA_Group;
|
||||||
|
setShowEA_Group(newMode)
|
||||||
|
if (newMode) {
|
||||||
|
let filter: PeripherieFilterOptionen = {
|
||||||
|
groupId: group.id
|
||||||
|
}
|
||||||
|
PeripherieFindApi(filter).then(setPeripheries);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
setPeripheries([])
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
const handlerShow_Element = () => {
|
||||||
|
setShowEA_Element((pre) => !pre)
|
||||||
|
//if (filterElementId) filter['elementId'] = filterElementId;
|
||||||
|
if (showEA_Group) {
|
||||||
|
let filter: PeripherieFilterOptionen = {
|
||||||
|
// elementId: group..id
|
||||||
|
};
|
||||||
|
|
||||||
|
// PeripherieFindApi(filter).then(setPeripheries);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
const handlerShow_Diff = () => {
|
||||||
|
setShowEA_Diff((pre) => !pre)
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlerDelete = () => {
|
||||||
|
if(group.id) api_groupDelete(group.id);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="ms-2">
|
||||||
|
<div className="flex gap-2 text-lg font-semibold bg-gray-200 ps-2">
|
||||||
|
<div>Gruppe :</div>
|
||||||
|
<div>{group.nr}</div>
|
||||||
|
<div>{group.name}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<div>Anzeige Name :{group.displayName}</div>
|
||||||
|
<div>Info: {group.info}</div>
|
||||||
|
<div>Ort: {group.ort}</div>
|
||||||
|
<div>Type {group.type}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-2 ps-2">
|
||||||
|
<div className="text-lg font-semibold">Eigenschaften</div>
|
||||||
|
{group.options &&
|
||||||
|
Object.entries(group.options).map(([key, value]) => (
|
||||||
|
<div key={key} className="grid grid-cols-2 gap-8">
|
||||||
|
<div >{key}</div>
|
||||||
|
<div>
|
||||||
|
{typeof value === "boolean" ? (value ? "Ja" : "Nein") : value}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-2 ps-2">
|
||||||
|
<div className="text-lg font-semibold">Elemente</div>
|
||||||
|
|
||||||
|
{group.elements && <div>
|
||||||
|
{group.elements.map((element) => (
|
||||||
|
<div key={element.id} className="grid grid-cols-2 gap-8">
|
||||||
|
{false && element.prefix &&
|
||||||
|
<div> {element.prefix}</div>
|
||||||
|
}
|
||||||
|
<div>{element.name}</div>
|
||||||
|
<div>{element.excelNr}</div>
|
||||||
|
|
||||||
|
</div>))}
|
||||||
|
</div>}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-8">
|
||||||
|
<button className="bg-gray-300 rounded-xl p-2 hover:bg-gray-500 me-2" onClick={() => handlerShow_Group()}>Show EA Group</button>
|
||||||
|
<button className="bg-gray-300 rounded-xl p-2 hover:bg-gray-500 me-2" onClick={() => handlerShow_Element()}>Show EA Elements</button>
|
||||||
|
<button className="bg-red-300 rounded-xl p-2 hover:bg-gray-500 me-2" onClick={() => handlerDelete()}>Löschen</button>
|
||||||
|
|
||||||
|
<button className="bg-gray-300 rounded-xl p-2 hover:bg-gray-500 me-2">Show EA Diffrences to Excel</button>
|
||||||
|
</div>
|
||||||
|
{showEA_Group && <div>
|
||||||
|
Ein-Ausgänge
|
||||||
|
</div>}
|
||||||
|
{showEA_Group && <div className="border-1">
|
||||||
|
|
||||||
|
</div>}
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useEffect, useState } from "react"
|
||||||
|
import { useFieldArray, useForm } from "react-hook-form"
|
||||||
|
import { InputTextR } from "@/components/ui/inputTextR";
|
||||||
|
import { InputCheckboxR } from "@/components/ui/inputCheckboxR";
|
||||||
|
import { Anlage, emptyGroup, Group, GroupCreate } from "@/types/rk";
|
||||||
|
import { groupCreate, groupUpdate } from "@/actions/rk/api-groups";
|
||||||
|
import { api_anlage_getSelected } from "@/actions/rk/api-anlage";
|
||||||
|
import { useFocusManager } from "@/components/ui/editable/useFocusManager";
|
||||||
|
|
||||||
|
|
||||||
|
interface Params {
|
||||||
|
anlage:Anlage
|
||||||
|
defaultGroup?: Group
|
||||||
|
debug?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export const GroupBulkEdit = ({anlage, defaultGroup, debug }: Params) => {
|
||||||
|
|
||||||
|
const { control, register, handleSubmit, formState: { errors }, watch, getFieldState, reset } = useForm<GroupCreate>({ defaultValues: emptyGroup, })
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const [error, setError] = useState<string | undefined>();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if(defaultGroup){
|
||||||
|
const {id,elements,options,...defaults} = defaultGroup;
|
||||||
|
reset({ ...emptyGroup,...defaults })
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const onSubmit = async (data: GroupCreate) => {
|
||||||
|
setError(undefined);
|
||||||
|
groupCreate(data);
|
||||||
|
|
||||||
|
}
|
||||||
|
const options = watch("options")
|
||||||
|
|
||||||
|
const focus = useFocusManager();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="w-120 flex flex-col p-4 pt-10 ps-10" >
|
||||||
|
|
||||||
|
<div className="border-1 p-4">
|
||||||
|
<form onSubmit={handleSubmit(onSubmit)} className="max-w-md mx-auto">
|
||||||
|
<div className="grid grid-cols-[60px_1fr] gap-2">
|
||||||
|
<InputTextR label="Nr" {...register("nr", { required: "Pflichtfeld" })} error={errors.nr?.message} />
|
||||||
|
<InputTextR label="Name" {...register("name", { required: "Pflichtfeld" })} error={errors.name?.message} />
|
||||||
|
</div>
|
||||||
|
<InputTextR label="Anzeige Name" {...register("displayName", {})} error={errors.displayName?.message} />
|
||||||
|
<InputTextR label="Info" {...register("info", { required: "Pflichtfeld" })} error={errors.info?.message} />
|
||||||
|
<InputTextR label="Ort" {...register("ort", { required: "Pflichtfeld" })} error={errors.ort?.message} />
|
||||||
|
<InputTextR label="Type" {...register("type", { required: "Pflichtfeld" })} error={errors.type?.message} />
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{error && <div>{error}</div>}
|
||||||
|
{errors.name && <div>{errors.name.message}</div>}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="p-2 mt-4 ">
|
||||||
|
<div className="font-semibold">Optionen</div>
|
||||||
|
<div className="border-1 rounded border-gray-200 p-4 ">
|
||||||
|
{options &&
|
||||||
|
Object.entries(options).map(([key, value]) => (
|
||||||
|
<div key={key} className="grid grid-cols-[100px_200px] pt-1">
|
||||||
|
|
||||||
|
<label className="font-semibold">{key}:</label>
|
||||||
|
|
||||||
|
{typeof value === "boolean" ? (
|
||||||
|
<div className="flex flex-start ">
|
||||||
|
<input
|
||||||
|
className=""
|
||||||
|
type="checkbox"
|
||||||
|
{...register(`options.${key}` as const)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
) : (
|
||||||
|
<div className="">
|
||||||
|
<InputTextR {...register(`options.${key}` as const)} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
</div>))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button type="submit" className="bg-blue-500 text-white p-2 rounded mt-2 hover:bg-blue-600">Speichern</button>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</div >
|
||||||
|
|
||||||
|
{debug &&
|
||||||
|
<div>
|
||||||
|
<div>{watch("name")}</div>
|
||||||
|
<pre>touched:{getFieldState("displayName").isTouched ? 'true' : 'false'}</pre>
|
||||||
|
<pre>{JSON.stringify(watch(), null, 2)}</pre>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div >
|
||||||
|
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
<div className="mt-4 mb-4 p-2 border-1 border-gray-200 relative ">
|
||||||
|
<div className="absolute -top-2 left-2 bg-white ps-1 pe-1 text-xs">Optionen</div>
|
||||||
|
<InputCheckboxR label="Konsumierbar" {...register("isConsumable")} error={errors.isConsumable?.message} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
*/
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import { useEditableList } from "@/components/ui/editable-list/useEditableList";
|
||||||
|
import { Group } from "@/types/rk";
|
||||||
|
import { useRef } from "react";
|
||||||
|
import { GroupEditRow } from "./group_edit_row";
|
||||||
|
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
data: Group[],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export const GroupEditList = ({ data }: Props) => {
|
||||||
|
|
||||||
|
|
||||||
|
const listRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
const list = useEditableList({
|
||||||
|
ref: listRef, data: data, onSave: async (group) => {
|
||||||
|
|
||||||
|
//await anlageApiUpdate(anlage.id, { anlageNr: anlage.anlageNr, name: anlage.name });
|
||||||
|
console.log(group)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col w-400 p-4 border-1 border-gray-200 focus:outline-none focus:ring-1 focus:ring-sky-100 rounded focus:border-1 "
|
||||||
|
ref={listRef}
|
||||||
|
tabIndex={0}
|
||||||
|
onKeyDown={list.onKeyDown}
|
||||||
|
>
|
||||||
|
|
||||||
|
|
||||||
|
{data.map((a, index) => (
|
||||||
|
|
||||||
|
<GroupEditRow
|
||||||
|
key={a.id}
|
||||||
|
data={a}
|
||||||
|
options={{ col1_w: 250, col2_w: 350,col3_w: 350, col: true }}
|
||||||
|
selected={list.isItemSelected(index)}
|
||||||
|
editing={list.isItemEditing(index)}
|
||||||
|
onClick={() => list.select(index)}
|
||||||
|
onSave={list.save}
|
||||||
|
onCancel={list.cancelEdit}
|
||||||
|
/>
|
||||||
|
|
||||||
|
))}
|
||||||
|
</div>)
|
||||||
|
}
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
import { EditableRow } from "@/components/ui/editable/EditableRow";
|
||||||
|
import { NumberCell } from "@/components/ui/editable/NumberCell";
|
||||||
|
import { TextCell } from "@/components/ui/editable/TextCell";
|
||||||
|
import { useFocusManager } from "@/components/ui/editable/useFocusManager";
|
||||||
|
import { emptyGroup, Group } from "@/types/rk";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
data: Group,
|
||||||
|
|
||||||
|
editing: boolean,
|
||||||
|
selected: boolean,
|
||||||
|
onSave: (value: Group) => void;
|
||||||
|
onCancel: () => void;
|
||||||
|
onClick: () => void;
|
||||||
|
options?: {
|
||||||
|
col1_w?: number
|
||||||
|
col2_w?: number,
|
||||||
|
col3_w?: number,
|
||||||
|
col4_w?: number,
|
||||||
|
col5_w?: number,
|
||||||
|
col6_w?: number,
|
||||||
|
col7_w?: number,
|
||||||
|
full?: boolean,
|
||||||
|
col?: boolean,
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const GroupEditRow = ({ data, selected, editing, options, onSave, onCancel }: Props) => {
|
||||||
|
const [id, setId] = useState('');
|
||||||
|
const [editData, setEditData] = useState(emptyGroup);
|
||||||
|
|
||||||
|
const focus = useFocusManager();
|
||||||
|
|
||||||
|
const col1w = options?.col1_w ? options?.col1_w : 100
|
||||||
|
const col2w = options?.col2_w ? options?.col2_w : 100
|
||||||
|
const col3w = options?.col3_w ? options?.col3_w : 100
|
||||||
|
const col4w = options?.col4_w ? options?.col4_w : 100
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const { id, ...anlageData } = data;
|
||||||
|
setEditData(() => ({ ...anlageData }));
|
||||||
|
setId(() => id);
|
||||||
|
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (editing) {
|
||||||
|
focus.focusFirst();
|
||||||
|
}
|
||||||
|
}, [editing]);
|
||||||
|
|
||||||
|
|
||||||
|
const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {
|
||||||
|
|
||||||
|
switch (e.key) {
|
||||||
|
|
||||||
|
case "Enter":
|
||||||
|
e.preventDefault();
|
||||||
|
onSave({ ...data, ...editData })
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Escape":
|
||||||
|
e.preventDefault();
|
||||||
|
onCancel();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Tab":
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if (e.shiftKey) focus.focusPrevious(e.currentTarget);
|
||||||
|
else focus.focusNext(e.currentTarget);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<EditableRow selected={selected} columns={`${col1w}px ${col2w}px ${col3w}px ${col4w}px`}>
|
||||||
|
|
||||||
|
<NumberCell
|
||||||
|
ref={focus.register(0)}
|
||||||
|
editing={editing}
|
||||||
|
value={editData.nr.toString()}
|
||||||
|
onChange={(value) => setEditData((o) => ({ ...o, nr: value }))}
|
||||||
|
onKey={handleKeyDown}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextCell
|
||||||
|
ref={focus.register(1)}
|
||||||
|
editing={editing}
|
||||||
|
value={editData.name}
|
||||||
|
onChange={(value) => setEditData((o) => ({ ...o, name: value }))}
|
||||||
|
onKey={handleKeyDown}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextCell
|
||||||
|
ref={focus.register(2)}
|
||||||
|
editing={editing}
|
||||||
|
value={editData.funcTxt ? editData.funcTxt : '' }
|
||||||
|
onChange={(value) => setEditData((o) => ({ ...o, funcTxt: value }))}
|
||||||
|
onKey={handleKeyDown}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextCell
|
||||||
|
ref={focus.register(3)}
|
||||||
|
editing={editing}
|
||||||
|
value={editData.info ? editData.info : '' }
|
||||||
|
onChange={(value) => setEditData((o) => ({ ...o, info: value }))}
|
||||||
|
onKey={handleKeyDown}
|
||||||
|
/>
|
||||||
|
|
||||||
|
</EditableRow>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import { LogNote } from "@/types/rk";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import LogNoteListItem from "./logNoteListItem";
|
||||||
|
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
notes: LogNote[],
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function LogNoteList({ notes }: Props) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{notes.map((item)=><LogNoteListItem note={item} key={item.id}></LogNoteListItem>)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import { LogNote } from "@/types/rk";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
note: LogNote,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function LogNoteListItem({ note }: Props) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="m-4 grid grid-cols-[300_2fr]">
|
||||||
|
{/** Spalte 1 Topic */}
|
||||||
|
<div>
|
||||||
|
{note.topic}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{note.status}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import { LogNote } from "@/types/rk";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import LogNoteList from "./logNoteList";
|
||||||
|
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
notes: LogNote[],
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function LogNoteView({ notes }: Props) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="m-4 p-4 border-1 border-gray-100 w-256">
|
||||||
|
<LogNoteList notes={notes}></LogNoteList>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import { Group, GroupSubElement, Peripherie, PeripherieFilterOptionen, PeripherieUpdate } from "@/types/rk";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { api_peripherieUpdate, PeripherieFindApi } from "@/actions/rk/api-peripherie";
|
||||||
|
import { useStringInput } from "@/hooks/useStringInput";
|
||||||
|
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
peripheries: Peripherie
|
||||||
|
groups: Group[]
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function PeripherieListInput({ peripheries, groups }: Props) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const [filteredGroups, setFilteredGroups] = useState<Group[]>([]);
|
||||||
|
|
||||||
|
const nameInput = useStringInput({ value: peripheries.name, fallback: "", onCommit: (value) => api_peripherieUpdate(peripheries.id, { name: value }) });
|
||||||
|
const functionTxtInput = useStringInput({ value: peripheries.functionTxt, fallback: "", onCommit: (value) => api_peripherieUpdate(peripheries.id, { functionTxt: value }) });
|
||||||
|
const textInput = useStringInput({ value: peripheries.text, fallback: "", onCommit: (value) => api_peripherieUpdate(peripheries.id, { text: value }) });
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setFilteredGroups(groups);
|
||||||
|
}, [groups])
|
||||||
|
|
||||||
|
const handleChangeGroup = (id: string, value: string) => {
|
||||||
|
api_peripherieUpdate(id, { groupId: value })
|
||||||
|
console.log(id, { groupId: value });
|
||||||
|
}
|
||||||
|
//if(peripheries.excelData?.functionText === peripheries.text) return < ></>
|
||||||
|
return (
|
||||||
|
|
||||||
|
|
||||||
|
<div className="grid grid-cols-[300px_250px_250px_350px_200px_600px_10px_600px]">
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<select onChange={(e) => handleChangeGroup(peripheries.id, e.target.value)} value={peripheries.group?.id}>
|
||||||
|
{
|
||||||
|
filteredGroups.map((group) => <option key={group.id} value={group.id} >{group.nr}_{group.name}</option>)
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{peripheries.element?.name}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input type="text" {...nameInput} name="name" />
|
||||||
|
</div>
|
||||||
|
<div className="border-1 flex w-full">
|
||||||
|
<input type="text" {...functionTxtInput} name="functionTxt" />
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{peripheries.adrType}{peripheries.adrByte}.{peripheries.adrBit}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="border-1 flex">
|
||||||
|
<input type="text" {...textInput} name="text" className="w-full" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="bg-gray-100"></div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{peripheries.excelData?.functionText}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import { Element, Group, GroupSubElement, Peripherie, PeripherieFilterOptionen } from "@/types/rk";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { api_peripherieUpdate, PeripherieFindApi } from "@/actions/rk/api-peripherie";
|
||||||
|
import PeripherieListInput from "./peripherieListInput";
|
||||||
|
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
peripheries:Peripherie[]
|
||||||
|
groups:Group[]
|
||||||
|
elemente:Element[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function PeripherieListView({peripheries, groups }: Props) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const [filteredGroups,setFilteredGroups] = useState<Group[]>([]);
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
setFilteredGroups(groups);
|
||||||
|
},[groups])
|
||||||
|
|
||||||
|
const handleChangeGroup = (id:string,value:string)=>{
|
||||||
|
api_peripherieUpdate(id,{groupId:value})
|
||||||
|
console.log(id,{groupId:value});
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
|
||||||
|
{peripheries.map((p) => (<div key={p.id} className="grid grid-cols-[100px_150px_100px_150px_100px_200px_200px_250px_250px_200px_400px]">
|
||||||
|
<PeripherieListInput peripheries={p} groups={groups} key={p.id} />
|
||||||
|
|
||||||
|
|
||||||
|
</div>))}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { Anlage } from "@/types/rk";
|
||||||
|
import Modal from "@/components/ui/Modal";
|
||||||
|
import { GroupResponse } from "@/types/anlagen/groups";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { useGroups } from "@/hooks/rk2/useGroups";
|
||||||
|
import { UnitResponse } from "@/types/anlagen/units";
|
||||||
|
import { useUnit } from "@/hooks/rk2/useUnit";
|
||||||
|
import { ComponentResponse } from "@/types/anlagen/components";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
interface Params {
|
||||||
|
anlage?: Anlage,
|
||||||
|
groups: GroupResponse[],
|
||||||
|
units: UnitResponse[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const AusgabeUnitInfo = ({ anlage, groups, units }: Params) => {
|
||||||
|
|
||||||
|
const {getPathToRoot} = useGroups({groups})
|
||||||
|
|
||||||
|
const getUnitInfo = (unit:UnitResponse) =>{
|
||||||
|
let groupId = unit.groupId;
|
||||||
|
|
||||||
|
let uGroupPath = getPathToRoot(groupId);
|
||||||
|
|
||||||
|
let unitName = [unit.prefix,unit.bmk,unit.name]
|
||||||
|
if(unit.postfix) unitName.push(unit.postfix)
|
||||||
|
|
||||||
|
let typ = unit.type;
|
||||||
|
|
||||||
|
//--- Components
|
||||||
|
let txt = "";
|
||||||
|
txt = uGroupPath.map((g)=>g.name).join('\t')+'\t';
|
||||||
|
txt += "\t" + unitName.join('_')+'\t';
|
||||||
|
//txt += "\tTyp:" + typ+'\n';
|
||||||
|
|
||||||
|
//txt += "\t\tKomponenten:"+'\n'
|
||||||
|
unit.components.forEach((comp)=>{
|
||||||
|
let cName:string[] = []
|
||||||
|
comp.prefix && cName.push(comp.prefix);
|
||||||
|
comp.name && cName.push(comp.name + (comp.index ? comp.index.toString():""));
|
||||||
|
//comp.index && cName.push();
|
||||||
|
comp.postfix && cName.push(comp.postfix);
|
||||||
|
//,comp.name,comp.index,comp.postfix
|
||||||
|
|
||||||
|
txt += '\t' + cName.join('_')+''
|
||||||
|
})
|
||||||
|
|
||||||
|
return txt;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const getComponentData = (comp:ComponentResponse) =>{
|
||||||
|
const name = [comp.prefix, comp.name,comp.index, comp.postfix]
|
||||||
|
}
|
||||||
|
|
||||||
|
const getText = ()=>{
|
||||||
|
let txt = ""
|
||||||
|
|
||||||
|
units.forEach((u)=> txt += getUnitInfo(u)+`\n`)
|
||||||
|
return txt;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<textarea className="w-full h-100" value={getText()} />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div >
|
||||||
|
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
Loaded 100 of 199 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user