From 017b2e5a8ccf229b723f01a66568ae26b00ef778 Mon Sep 17 00:00:00 2001 From: Tropicananass Date: Mon, 12 May 2025 18:02:33 +0200 Subject: [PATCH] vue frontend --- RpiLedBars/frontend/webapp/jsconfig.json | 5 + RpiLedBars/frontend/webapp/package-lock.json | 214 +++++++++-- RpiLedBars/frontend/webapp/package.json | 5 +- RpiLedBars/frontend/webapp/public/index.html | 36 +- RpiLedBars/frontend/webapp/src/App.vue | 350 ++++-------------- .../webapp/src/components/AutoMode.vue | 67 ++++ .../webapp/src/components/ModeSelect copy.vue | 34 -- .../webapp/src/components/ModeSelect.vue | 34 -- .../webapp/src/components/Reconnect.vue | 33 -- .../webapp/src/components/WSConnection.vue | 61 +++ .../webapp/src/components/patterns/Pulse.vue | 34 ++ .../webapp/src/components/patterns/Strobe.vue | 29 ++ .../webapp/src/components/patterns/Travel.vue | 53 +++ .../webapp/src/components/ui/CheckBox.vue | 27 ++ .../src/components/ui/ColorAndModulation.vue | 71 ++++ .../webapp/src/components/ui/ColorPicker.vue | 58 +++ .../webapp/src/components/ui/Radio.vue | 58 --- .../webapp/src/components/ui/RadioButton.vue | 29 ++ .../src/components/ui/RadioButtonGroup.vue | 44 +++ .../webapp/src/components/ui/RangeSlider.vue | 41 ++ RpiLedBars/frontend/webapp/src/main.js | 82 +++- RpiLedBars/frontend/webapp/src/store.js | 100 +++++ RpiLedBars/frontend/webapp/src/storews.js | 64 ++++ RpiLedBars/frontend/webapp/src/websocket.js | 46 +++ RpiLedBars/frontend/workspace.code-workspace | 14 + 25 files changed, 1099 insertions(+), 490 deletions(-) create mode 100644 RpiLedBars/frontend/webapp/jsconfig.json create mode 100644 RpiLedBars/frontend/webapp/src/components/AutoMode.vue delete mode 100644 RpiLedBars/frontend/webapp/src/components/ModeSelect copy.vue delete mode 100644 RpiLedBars/frontend/webapp/src/components/ModeSelect.vue delete mode 100644 RpiLedBars/frontend/webapp/src/components/Reconnect.vue create mode 100644 RpiLedBars/frontend/webapp/src/components/WSConnection.vue create mode 100644 RpiLedBars/frontend/webapp/src/components/patterns/Pulse.vue create mode 100644 RpiLedBars/frontend/webapp/src/components/patterns/Strobe.vue create mode 100644 RpiLedBars/frontend/webapp/src/components/patterns/Travel.vue create mode 100644 RpiLedBars/frontend/webapp/src/components/ui/CheckBox.vue create mode 100644 RpiLedBars/frontend/webapp/src/components/ui/ColorAndModulation.vue create mode 100644 RpiLedBars/frontend/webapp/src/components/ui/ColorPicker.vue delete mode 100644 RpiLedBars/frontend/webapp/src/components/ui/Radio.vue create mode 100644 RpiLedBars/frontend/webapp/src/components/ui/RadioButton.vue create mode 100644 RpiLedBars/frontend/webapp/src/components/ui/RadioButtonGroup.vue create mode 100644 RpiLedBars/frontend/webapp/src/components/ui/RangeSlider.vue create mode 100644 RpiLedBars/frontend/webapp/src/store.js create mode 100644 RpiLedBars/frontend/webapp/src/storews.js create mode 100644 RpiLedBars/frontend/webapp/src/websocket.js create mode 100644 RpiLedBars/frontend/workspace.code-workspace diff --git a/RpiLedBars/frontend/webapp/jsconfig.json b/RpiLedBars/frontend/webapp/jsconfig.json new file mode 100644 index 0000000..9a58b73 --- /dev/null +++ b/RpiLedBars/frontend/webapp/jsconfig.json @@ -0,0 +1,5 @@ +{ + "include": [ + "./src/**/*" + ] +} \ No newline at end of file diff --git a/RpiLedBars/frontend/webapp/package-lock.json b/RpiLedBars/frontend/webapp/package-lock.json index 3db3875..41b3b6a 100644 --- a/RpiLedBars/frontend/webapp/package-lock.json +++ b/RpiLedBars/frontend/webapp/package-lock.json @@ -8,9 +8,12 @@ "name": "webapp", "version": "0.1.0", "dependencies": { + "@jaames/iro": "^5.5.2", "bootstrap": "^5.1.2", "core-js": "^3.6.5", - "vue": "^3.0.0" + "vue": "^3.0.0", + "vue-native-websocket-vue3": "^3.1.4", + "vuex": "^4.0.2" }, "devDependencies": { "@vue/cli-plugin-babel": "~4.5.0", @@ -1669,6 +1672,20 @@ "webpack": "^4.0.0" } }, + "node_modules/@irojs/iro-core": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@irojs/iro-core/-/iro-core-1.2.1.tgz", + "integrity": "sha512-p2OvsBSSmidsDsTSkID6jEyXDF7lcyxPrkh3qBzasBZFpjkYd6kZ3yMWai3MlAaQ3F7li/Et7rSJVV09Fpei+A==" + }, + "node_modules/@jaames/iro": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/@jaames/iro/-/iro-5.5.2.tgz", + "integrity": "sha512-Fbi5U4Vdkw6UsF+R3oMlPONqkvUDMkwzh+mX718gQsDFt3+1r1jvGsrfCbedmXAAy0WsjDHOrefK0BkDk99TQg==", + "dependencies": { + "@irojs/iro-core": "^1.2.1", + "preact": "^10.0.0" + } + }, "node_modules/@mrmlnc/readdir-enhanced": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", @@ -2495,6 +2512,11 @@ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", "dev": true }, + "node_modules/@vue/devtools-api": { + "version": "6.0.0-beta.19", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.0.0-beta.19.tgz", + "integrity": "sha512-ObzQhgkoVeoyKv+e8+tB/jQBL2smtk/NmC9OmFK8UqdDpoOdv/Kf9pyDWL+IFyM7qLD2C75rszJujvGSPSpGlw==" + }, "node_modules/@vue/preload-webpack-plugin": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@vue/preload-webpack-plugin/-/preload-webpack-plugin-1.1.2.tgz", @@ -3269,8 +3291,7 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/base": { "version": "0.11.2", @@ -3480,7 +3501,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -4508,8 +4528,7 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "node_modules/concat-stream": { "version": "1.6.2", @@ -7031,8 +7050,7 @@ "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "node_modules/fsevents": { "version": "2.3.2", @@ -7142,7 +7160,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -7959,7 +7976,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -7968,8 +7984,7 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/inquirer": { "version": "7.3.3", @@ -9328,7 +9343,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -9941,7 +9955,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "dependencies": { "wrappy": "1" } @@ -10319,7 +10332,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -11155,6 +11167,15 @@ "node": ">=0.10.0" } }, + "node_modules/preact": { + "version": "10.5.15", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.5.15.tgz", + "integrity": "sha512-5chK29n6QcJc3m1lVrKQSQ+V7K1Gb8HeQY6FViQ5AxCAEGu3DaHffWNDkC9+miZgsLvbvU9rxbV1qinGHMHzqA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, "node_modules/prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -14199,6 +14220,60 @@ "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=", "dev": true }, + "node_modules/vue-native-websocket-vue3": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/vue-native-websocket-vue3/-/vue-native-websocket-vue3-3.1.4.tgz", + "integrity": "sha512-Dqq+LaoV1ZgWhPGIEBKBIXMc+n+7Bh6BkAgnRrf3iV6NSOA7q42dQNOEPbJCzmn/L779ck56RT1UtoCZfIwq/w==", + "dependencies": { + "file-entry-cache": "^6.0.1" + }, + "peerDependencies": { + "core-js": "^3.6.5", + "vue": "^3.0.0" + } + }, + "node_modules/vue-native-websocket-vue3/node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/vue-native-websocket-vue3/node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/vue-native-websocket-vue3/node_modules/flatted": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.2.tgz", + "integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==" + }, + "node_modules/vue-native-websocket-vue3/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/vue-style-loader": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.3.tgz", @@ -14221,6 +14296,17 @@ "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==", "dev": true }, + "node_modules/vuex": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vuex/-/vuex-4.0.2.tgz", + "integrity": "sha512-M6r8uxELjZIK8kTKDGgZTYX/ahzblnzC4isU1tpmEuOIIKmV+TRdc+H4s8ds2NuZ7wpUTdGRzJRtoj+lI+pc0Q==", + "dependencies": { + "@vue/devtools-api": "^6.0.0-beta.11" + }, + "peerDependencies": { + "vue": "^3.0.2" + } + }, "node_modules/watchpack": { "version": "1.7.5", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", @@ -15134,8 +15220,7 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "node_modules/write": { "version": "1.0.3", @@ -16550,6 +16635,20 @@ "postcss": "^7.0.0" } }, + "@irojs/iro-core": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@irojs/iro-core/-/iro-core-1.2.1.tgz", + "integrity": "sha512-p2OvsBSSmidsDsTSkID6jEyXDF7lcyxPrkh3qBzasBZFpjkYd6kZ3yMWai3MlAaQ3F7li/Et7rSJVV09Fpei+A==" + }, + "@jaames/iro": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/@jaames/iro/-/iro-5.5.2.tgz", + "integrity": "sha512-Fbi5U4Vdkw6UsF+R3oMlPONqkvUDMkwzh+mX718gQsDFt3+1r1jvGsrfCbedmXAAy0WsjDHOrefK0BkDk99TQg==", + "requires": { + "@irojs/iro-core": "^1.2.1", + "preact": "^10.0.0" + } + }, "@mrmlnc/readdir-enhanced": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", @@ -17251,6 +17350,11 @@ } } }, + "@vue/devtools-api": { + "version": "6.0.0-beta.19", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.0.0-beta.19.tgz", + "integrity": "sha512-ObzQhgkoVeoyKv+e8+tB/jQBL2smtk/NmC9OmFK8UqdDpoOdv/Kf9pyDWL+IFyM7qLD2C75rszJujvGSPSpGlw==" + }, "@vue/preload-webpack-plugin": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@vue/preload-webpack-plugin/-/preload-webpack-plugin-1.1.2.tgz", @@ -17891,8 +17995,7 @@ "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "base": { "version": "0.11.2", @@ -18067,7 +18170,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -18912,8 +19014,7 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "concat-stream": { "version": "1.6.2", @@ -20921,8 +21022,7 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { "version": "2.3.2", @@ -21004,7 +21104,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -21632,7 +21731,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -21641,8 +21739,7 @@ "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "inquirer": { "version": "7.3.3", @@ -22701,7 +22798,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -23198,7 +23294,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "requires": { "wrappy": "1" } @@ -23504,8 +23599,7 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-is-inside": { "version": "1.0.2", @@ -24223,6 +24317,11 @@ "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==", "dev": true }, + "preact": { + "version": "10.5.15", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.5.15.tgz", + "integrity": "sha512-5chK29n6QcJc3m1lVrKQSQ+V7K1Gb8HeQY6FViQ5AxCAEGu3DaHffWNDkC9+miZgsLvbvU9rxbV1qinGHMHzqA==" + }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -26741,6 +26840,46 @@ } } }, + "vue-native-websocket-vue3": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/vue-native-websocket-vue3/-/vue-native-websocket-vue3-3.1.4.tgz", + "integrity": "sha512-Dqq+LaoV1ZgWhPGIEBKBIXMc+n+7Bh6BkAgnRrf3iV6NSOA7q42dQNOEPbJCzmn/L779ck56RT1UtoCZfIwq/w==", + "requires": { + "file-entry-cache": "^6.0.1" + }, + "dependencies": { + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "requires": { + "flat-cache": "^3.0.4" + } + }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.2.tgz", + "integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==" + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "requires": { + "glob": "^7.1.3" + } + } + } + }, "vue-style-loader": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.3.tgz", @@ -26765,6 +26904,14 @@ "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==", "dev": true }, + "vuex": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vuex/-/vuex-4.0.2.tgz", + "integrity": "sha512-M6r8uxELjZIK8kTKDGgZTYX/ahzblnzC4isU1tpmEuOIIKmV+TRdc+H4s8ds2NuZ7wpUTdGRzJRtoj+lI+pc0Q==", + "requires": { + "@vue/devtools-api": "^6.0.0-beta.11" + } + }, "watchpack": { "version": "1.7.5", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", @@ -27494,8 +27641,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "write": { "version": "1.0.3", diff --git a/RpiLedBars/frontend/webapp/package.json b/RpiLedBars/frontend/webapp/package.json index 1f81bf5..287d52c 100644 --- a/RpiLedBars/frontend/webapp/package.json +++ b/RpiLedBars/frontend/webapp/package.json @@ -8,9 +8,12 @@ "lint": "vue-cli-service lint" }, "dependencies": { + "@jaames/iro": "^5.5.2", "bootstrap": "^5.1.2", "core-js": "^3.6.5", - "vue": "^3.0.0" + "vue": "^3.0.0", + "vue-native-websocket-vue3": "^3.1.4", + "vuex": "^4.0.2" }, "devDependencies": { "@vue/cli-plugin-babel": "~4.5.0", diff --git a/RpiLedBars/frontend/webapp/public/index.html b/RpiLedBars/frontend/webapp/public/index.html index 3e5a139..556d598 100644 --- a/RpiLedBars/frontend/webapp/public/index.html +++ b/RpiLedBars/frontend/webapp/public/index.html @@ -1,17 +1,23 @@ - - - - - - <%= htmlWebpackPlugin.options.title %> - - - -
- - - + + + + + + + + <%= htmlWebpackPlugin.options.title %> + + + + + +
+ + + + \ No newline at end of file diff --git a/RpiLedBars/frontend/webapp/src/App.vue b/RpiLedBars/frontend/webapp/src/App.vue index 901e3b3..382dd07 100644 --- a/RpiLedBars/frontend/webapp/src/App.vue +++ b/RpiLedBars/frontend/webapp/src/App.vue @@ -1,295 +1,85 @@ - + diff --git a/RpiLedBars/frontend/webapp/src/components/AutoMode.vue b/RpiLedBars/frontend/webapp/src/components/AutoMode.vue new file mode 100644 index 0000000..fb8dcf1 --- /dev/null +++ b/RpiLedBars/frontend/webapp/src/components/AutoMode.vue @@ -0,0 +1,67 @@ + + + + \ No newline at end of file diff --git a/RpiLedBars/frontend/webapp/src/components/ModeSelect copy.vue b/RpiLedBars/frontend/webapp/src/components/ModeSelect copy.vue deleted file mode 100644 index 628788e..0000000 --- a/RpiLedBars/frontend/webapp/src/components/ModeSelect copy.vue +++ /dev/null @@ -1,34 +0,0 @@ - - - - - diff --git a/RpiLedBars/frontend/webapp/src/components/ModeSelect.vue b/RpiLedBars/frontend/webapp/src/components/ModeSelect.vue deleted file mode 100644 index 8879d91..0000000 --- a/RpiLedBars/frontend/webapp/src/components/ModeSelect.vue +++ /dev/null @@ -1,34 +0,0 @@ - - - - - diff --git a/RpiLedBars/frontend/webapp/src/components/Reconnect.vue b/RpiLedBars/frontend/webapp/src/components/Reconnect.vue deleted file mode 100644 index d66bc2f..0000000 --- a/RpiLedBars/frontend/webapp/src/components/Reconnect.vue +++ /dev/null @@ -1,33 +0,0 @@ - - - - - diff --git a/RpiLedBars/frontend/webapp/src/components/WSConnection.vue b/RpiLedBars/frontend/webapp/src/components/WSConnection.vue new file mode 100644 index 0000000..6c8839e --- /dev/null +++ b/RpiLedBars/frontend/webapp/src/components/WSConnection.vue @@ -0,0 +1,61 @@ + + + + + diff --git a/RpiLedBars/frontend/webapp/src/components/patterns/Pulse.vue b/RpiLedBars/frontend/webapp/src/components/patterns/Pulse.vue new file mode 100644 index 0000000..c216940 --- /dev/null +++ b/RpiLedBars/frontend/webapp/src/components/patterns/Pulse.vue @@ -0,0 +1,34 @@ + + + + \ No newline at end of file diff --git a/RpiLedBars/frontend/webapp/src/components/patterns/Strobe.vue b/RpiLedBars/frontend/webapp/src/components/patterns/Strobe.vue new file mode 100644 index 0000000..c31fbdb --- /dev/null +++ b/RpiLedBars/frontend/webapp/src/components/patterns/Strobe.vue @@ -0,0 +1,29 @@ + + + + \ No newline at end of file diff --git a/RpiLedBars/frontend/webapp/src/components/patterns/Travel.vue b/RpiLedBars/frontend/webapp/src/components/patterns/Travel.vue new file mode 100644 index 0000000..f21ed28 --- /dev/null +++ b/RpiLedBars/frontend/webapp/src/components/patterns/Travel.vue @@ -0,0 +1,53 @@ + + + + \ No newline at end of file diff --git a/RpiLedBars/frontend/webapp/src/components/ui/CheckBox.vue b/RpiLedBars/frontend/webapp/src/components/ui/CheckBox.vue new file mode 100644 index 0000000..c451054 --- /dev/null +++ b/RpiLedBars/frontend/webapp/src/components/ui/CheckBox.vue @@ -0,0 +1,27 @@ + + + diff --git a/RpiLedBars/frontend/webapp/src/components/ui/ColorAndModulation.vue b/RpiLedBars/frontend/webapp/src/components/ui/ColorAndModulation.vue new file mode 100644 index 0000000..36405c0 --- /dev/null +++ b/RpiLedBars/frontend/webapp/src/components/ui/ColorAndModulation.vue @@ -0,0 +1,71 @@ + + + \ No newline at end of file diff --git a/RpiLedBars/frontend/webapp/src/components/ui/ColorPicker.vue b/RpiLedBars/frontend/webapp/src/components/ui/ColorPicker.vue new file mode 100644 index 0000000..9b4f6ea --- /dev/null +++ b/RpiLedBars/frontend/webapp/src/components/ui/ColorPicker.vue @@ -0,0 +1,58 @@ + + + + + \ No newline at end of file diff --git a/RpiLedBars/frontend/webapp/src/components/ui/Radio.vue b/RpiLedBars/frontend/webapp/src/components/ui/Radio.vue deleted file mode 100644 index 879051a..0000000 --- a/RpiLedBars/frontend/webapp/src/components/ui/Radio.vue +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - diff --git a/RpiLedBars/frontend/webapp/src/components/ui/RadioButton.vue b/RpiLedBars/frontend/webapp/src/components/ui/RadioButton.vue new file mode 100644 index 0000000..15c0f30 --- /dev/null +++ b/RpiLedBars/frontend/webapp/src/components/ui/RadioButton.vue @@ -0,0 +1,29 @@ + + + diff --git a/RpiLedBars/frontend/webapp/src/components/ui/RadioButtonGroup.vue b/RpiLedBars/frontend/webapp/src/components/ui/RadioButtonGroup.vue new file mode 100644 index 0000000..1fcdee7 --- /dev/null +++ b/RpiLedBars/frontend/webapp/src/components/ui/RadioButtonGroup.vue @@ -0,0 +1,44 @@ + + + diff --git a/RpiLedBars/frontend/webapp/src/components/ui/RangeSlider.vue b/RpiLedBars/frontend/webapp/src/components/ui/RangeSlider.vue new file mode 100644 index 0000000..773ddc9 --- /dev/null +++ b/RpiLedBars/frontend/webapp/src/components/ui/RangeSlider.vue @@ -0,0 +1,41 @@ + + + diff --git a/RpiLedBars/frontend/webapp/src/main.js b/RpiLedBars/frontend/webapp/src/main.js index c98d72b..bd78ef9 100644 --- a/RpiLedBars/frontend/webapp/src/main.js +++ b/RpiLedBars/frontend/webapp/src/main.js @@ -1,6 +1,86 @@ import { createApp } from 'vue' import App from './App.vue' +// import store from './store' +// import store from './storews' + +// import VueNativeSock from "vue-native-websocket-vue3"; import "bootstrap/dist/css/bootstrap.min.css" import "bootstrap" +// import { createStore } from "vuex"; -createApp(App).mount('#app') \ No newline at end of file + +const app = createApp(App) + +// const store = createStore({ +// state: { +// socket: { +// // Connection Status +// isConnected: false, +// // Message content +// message: "", +// // Reconnect error +// reconnectError: false, +// // Heartbeat message sending time +// heartBeatInterval: 50000, +// // Heartbeat timer +// heartBeatTimer: 0 +// } +// }, +// mutations: { +// // Connection open +// SOCKET_ONOPEN(state, event) { +// console.log(event); +// app.config.globalProperties.$socket = event.currentTarget; +// state.socket.isConnected = true; +// // When the connection is successful, start sending heartbeat messages regularly to avoid being disconnected by the server +// // state.socket.heartBeatTimer = setInterval(() => { +// // const message = "Heartbeat message"; +// // state.socket.isConnected && +// // app.config.globalProperties.$socket.sendObj({ +// // code: 200, +// // msg: message +// // }); +// // }, state.socket.heartBeatInterval); +// }, +// // Connection closed +// SOCKET_ONCLOSE(state, event) { +// state.socket.isConnected = false; +// // Stop the heartbeat message when the connection is closed +// clearInterval(state.socket.heartBeatTimer); +// state.socket.heartBeatTimer = 0; +// console.log("The line is disconnected: " + new Date()); +// console.log(event); +// }, +// // An error occurred +// SOCKET_ONERROR(state, event) { +// console.error(state, event); +// }, +// // Receive the message sent by the server +// SOCKET_ONMESSAGE(state, message) { +// state.socket.message = message; +// }, +// // Auto reconnect +// SOCKET_RECONNECT(state, count) { +// console.info("消息系统重连中...", state, count); +// }, +// // Reconnect error +// SOCKET_RECONNECT_ERROR(state) { +// state.socket.reconnectError = true; +// } +// }, +// modules: {} +// }) + +// app.use(store) + +// app.use(VueNativeSock, "ws://192.168.4.1:8080", { +// store: store +// }, { +// reconnection: true, // (Boolean) whether to reconnect automatically (false) +// reconnectionAttempts: 90, // (Number) number of reconnection attempts before giving up (Infinity), +// reconnectionDelay: 10, // (Number) how long to initially wait before attempting a new (1000) +// }); + +app.mount('#app') + +export default app \ No newline at end of file diff --git a/RpiLedBars/frontend/webapp/src/store.js b/RpiLedBars/frontend/webapp/src/store.js new file mode 100644 index 0000000..dbab6d4 --- /dev/null +++ b/RpiLedBars/frontend/webapp/src/store.js @@ -0,0 +1,100 @@ +// import Vue from 'vue' +// import Vuex from 'vuex' +import { createStore } from "vuex"; + +// Vue.use(Vuex) + +// root state object. +// each Vuex instance is just a single state tree. +const state = { + count: 0, + webSocket: WebSocket +} + + + +// mutations are operations that actually mutate the state. +// each mutation handler gets the entire state tree as the +// first argument, followed by additional payload arguments. +// mutations must be synchronous and can be recorded by plugins +// for debugging purposes. +const mutations = { + increment(state) { + state.count++ + }, + decrement(state) { + state.count-- + }, + reconnect() { + state.webSocket = new WebSocket("ws://tropicananass.ovh:8080"); + + state.webSocket.onopen = function (event) { + console.log(`[open] ws: Connection established: ${event.code}`); + }; + + state.webSocket.onmessage = function (event) { + console.log(`[message] ws: Data received from server: ${event.data}`); + let message = event.data.split(":"); + let command = message[0]; + let payload = message[1]; + console.log(command + ", " + payload); + switch (command) { + case 'm': + document.getElementById("mode-input").elements["mode-selection"][payload].checked = true; + break; + + default: + break; + } + }; + + state.webSocket.webSocketonclose = function (event) { + if (event.wasClean) { + console.log(`[close] ws: Connection closed cleanly, code=${event.code} reason=${event.reason}`); + } else { + console.log('[close] ws: Connection died'); + } + }; + + state.webSocket.onerror = function (error) { + console.log(`[error] ws: ${error.message}`); + }; + } +} + +// actions are functions that cause side effects and can involve +// asynchronous operations. +const actions = { + increment: ({ commit }) => commit('increment'), + decrement: ({ commit }) => commit('decrement'), + incrementIfOdd({ commit, state }) { + if ((state.count + 1) % 2 === 0) { + commit('increment') + } + }, + incrementAsync({ commit }) { + return new Promise((resolve) => { + setTimeout(() => { + commit('increment') + resolve() + }, 1000) + }) + } +} + +// getters are functions. +const getters = { + evenOrOdd: state => state.count % 2 === 0 ? 'even' : 'odd', + isConnected: state => state.webSocket.readyState == WebSocket.OPEN +} + +// A Vuex instance is created by combining the state, mutations, actions, +// and getters. +const store = createStore({ + state, + getters, + actions, + mutations +}) + +export default store \ No newline at end of file diff --git a/RpiLedBars/frontend/webapp/src/storews.js b/RpiLedBars/frontend/webapp/src/storews.js new file mode 100644 index 0000000..3729f9f --- /dev/null +++ b/RpiLedBars/frontend/webapp/src/storews.js @@ -0,0 +1,64 @@ +import { createStore } from "vuex"; +// import app from "main.js"; +import { getCurrentInstance } from 'vue' + +export default createStore({ + state: { + socket: { + // Connection Status + isConnected: false, + // Message content + message: "", + // Reconnect error + reconnectError: false, + // Heartbeat message sending time + heartBeatInterval: 50000, + // Heartbeat timer + heartBeatTimer: 0 + } + }, + mutations: { + // Connection open + SOCKET_ONOPEN(state, event) { + console.log(event); + const app = getCurrentInstance() + app.config.globalProperties.$socket = event.currentTarget; + state.socket.isConnected = true; + // When the connection is successful, start sending heartbeat messages regularly to avoid being disconnected by the server + // state.socket.heartBeatTimer = setInterval(() => { + // const message = "Heartbeat message"; + // state.socket.isConnected && + // app.config.globalProperties.$socket.sendObj({ + // code: 200, + // msg: message + // }); + // }, state.socket.heartBeatInterval); + }, + // Connection closed + SOCKET_ONCLOSE(state, event) { + state.socket.isConnected = false; + // Stop the heartbeat message when the connection is closed + clearInterval(state.socket.heartBeatTimer); + state.socket.heartBeatTimer = 0; + console.log("The line is disconnected: " + new Date()); + console.log(event); + }, + // An error occurred + SOCKET_ONERROR(state, event) { + console.error(state, event); + }, + // Receive the message sent by the server + SOCKET_ONMESSAGE(state, message) { + state.socket.message = message; + }, + // Auto reconnect + SOCKET_RECONNECT(state, count) { + console.info("消息系统重连中...", state, count); + }, + // Reconnect error + SOCKET_RECONNECT_ERROR(state) { + state.socket.reconnectError = true; + } + }, + modules: {} +}); \ No newline at end of file diff --git a/RpiLedBars/frontend/webapp/src/websocket.js b/RpiLedBars/frontend/webapp/src/websocket.js new file mode 100644 index 0000000..47cba6a --- /dev/null +++ b/RpiLedBars/frontend/webapp/src/websocket.js @@ -0,0 +1,46 @@ +const reconnect = function (options) { + console.log("connecting") + options.webSocket = new WebSocket("ws://192.168.4.1:8080"); + options.webSocket.onopen = function (event) { + options.isConnected = true; + console.log(`[open] ws: Connection established: ${event.code}`); + }; + options.webSocket.onmessage = function (event) { + console.log(`[message] ws: Data received from server: ${event.data}`); + }; + options.webSocket.onclose = function (event) { + if (event.wasClean) { + console.log( + `[close] ws: Connection closed cleanly, code=${event.code} reason=${event.reason}` + ); + } else { + console.log("[close] ws: Connection died"); + } + options.isConnected = false; + }; + options.webSocket.onerror = function (error) { + console.log(`[error] ws: ${error.message}`); + }; +} + +// const isConnected = function () { +// if (this.webSocket != null) { +// console.log(this.webSocket.readyState) +// return this.webSocket.readyState == WebSocket.OPEN +// } +// return false +// } + +import { ref } from "vue" + +// plugins/i18n.js +export default { + install: (app, options) => { + let webSocket = null; + app.config.globalProperties.webSocket = webSocket + app.config.globalProperties.reconnect = () => reconnect(options) + + app.provide('ws', options) + app.provide('isConnected', ref(options.isConnected)) + } +} diff --git a/RpiLedBars/frontend/workspace.code-workspace b/RpiLedBars/frontend/workspace.code-workspace new file mode 100644 index 0000000..95b7975 --- /dev/null +++ b/RpiLedBars/frontend/workspace.code-workspace @@ -0,0 +1,14 @@ +{ + "folders": [ + { + "path": "webapp" + }, + { + "path": "vuex" + }, + { + "path": "web" + } + ], + "settings": {} +} \ No newline at end of file