diff --git a/package-lock.json b/package-lock.json index f01b90c7ec..a901e64956 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,7 +22,8 @@ "date-fns-tz": "3.1.3", "express": "4.19.2", "js-cookie": "^3.0.5", - "lodash": "^4.17.21", + "json-bigint": "1.0.0", + "lodash": "4.17.21", "pinia": "2.1.7", "tiny-emitter": "2.1.0", "vue": "^3.3.9", @@ -1031,9 +1032,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.0.tgz", - "integrity": "sha512-Eeao7ewDq79jVEsrtWIj5RNqB8p2knlm9fhR6uJ2gqP7UfbLrTrxevudVrEPDM7Wkpn/HpRC2QfazH7MXLz3vQ==", + "version": "4.34.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.2.tgz", + "integrity": "sha512-6Fyg9yQbwJR+ykVdT9sid1oc2ewejS6h4wzQltmJfSW53N60G/ah9pngXGANdy9/aaE/TcUFpWosdm7JXS1WTQ==", "cpu": [ "arm" ], @@ -1043,9 +1044,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.0.tgz", - "integrity": "sha512-yVh0Kf1f0Fq4tWNf6mWcbQBCLDpDrDEl88lzPgKhrgTcDrTtlmun92ywEF9dCjmYO3EFiSuJeeo9cYRxl2FswA==", + "version": "4.34.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.2.tgz", + "integrity": "sha512-K5GfWe+vtQ3kyEbihrimM38UgX57UqHp+oME7X/EX9Im6suwZfa7Hsr8AtzbJvukTpwMGs+4s29YMSO3rwWtsw==", "cpu": [ "arm64" ], @@ -1055,9 +1056,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.0.tgz", - "integrity": "sha512-gCs0ErAZ9s0Osejpc3qahTsqIPUDjSKIyxK/0BGKvL+Tn0n3Kwvj8BrCv7Y5sR1Ypz1K2qz9Ny0VvkVyoXBVUQ==", + "version": "4.34.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.2.tgz", + "integrity": "sha512-PSN58XG/V/tzqDb9kDGutUruycgylMlUE59f40ny6QIRNsTEIZsrNQTJKUN2keMMSmlzgunMFqyaGLmly39sug==", "cpu": [ "arm64" ], @@ -1067,9 +1068,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.0.tgz", - "integrity": "sha512-aIB5Anc8hngk15t3GUkiO4pv42ykXHfmpXGS+CzM9CTyiWyT8HIS5ygRAy7KcFb/wiw4Br+vh1byqcHRTfq2tQ==", + "version": "4.34.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.2.tgz", + "integrity": "sha512-gQhK788rQJm9pzmXyfBB84VHViDERhAhzGafw+E5mUpnGKuxZGkMVDa3wgDFKT6ukLC5V7QTifzsUKdNVxp5qQ==", "cpu": [ "x64" ], @@ -1079,9 +1080,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.0.tgz", - "integrity": "sha512-kpdsUdMlVJMRMaOf/tIvxk8TQdzHhY47imwmASOuMajg/GXpw8GKNd8LNwIHE5Yd1onehNpcUB9jHY6wgw9nHQ==", + "version": "4.34.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.2.tgz", + "integrity": "sha512-eiaHgQwGPpxLC3+zTAcdKl4VsBl3r0AiJOd1Um/ArEzAjN/dbPK1nROHrVkdnoE6p7Svvn04w3f/jEZSTVHunA==", "cpu": [ "arm64" ], @@ -1091,9 +1092,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.0.tgz", - "integrity": "sha512-D0RDyHygOBCQiqookcPevrvgEarN0CttBecG4chOeIYCNtlKHmf5oi5kAVpXV7qs0Xh/WO2RnxeicZPtT50V0g==", + "version": "4.34.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.2.tgz", + "integrity": "sha512-lhdiwQ+jf8pewYOTG4bag0Qd68Jn1v2gO1i0mTuiD+Qkt5vNfHVK/jrT7uVvycV8ZchlzXp5HDVmhpzjC6mh0g==", "cpu": [ "x64" ], @@ -1103,9 +1104,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.0.tgz", - "integrity": "sha512-mCIw8j5LPDXmCOW8mfMZwT6F/Kza03EnSr4wGYEswrEfjTfVsFOxvgYfuRMxTuUF/XmRb9WSMD5GhCWDe2iNrg==", + "version": "4.34.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.2.tgz", + "integrity": "sha512-lfqTpWjSvbgQP1vqGTXdv+/kxIznKXZlI109WkIFPbud41bjigjNmOAAKoazmRGx+k9e3rtIdbq2pQZPV1pMig==", "cpu": [ "arm" ], @@ -1115,9 +1116,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.0.tgz", - "integrity": "sha512-AwwldAu4aCJPob7zmjuDUMvvuatgs8B/QiVB0KwkUarAcPB3W+ToOT+18TQwY4z09Al7G0BvCcmLRop5zBLTag==", + "version": "4.34.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.2.tgz", + "integrity": "sha512-RGjqULqIurqqv+NJTyuPgdZhka8ImMLB32YwUle2BPTDqDoXNgwFjdjQC59FbSk08z0IqlRJjrJ0AvDQ5W5lpw==", "cpu": [ "arm" ], @@ -1127,9 +1128,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.0.tgz", - "integrity": "sha512-e7kDUGVP+xw05pV65ZKb0zulRploU3gTu6qH1qL58PrULDGxULIS0OSDQJLH7WiFnpd3ZKUU4VM3u/Z7Zw+e7Q==", + "version": "4.34.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.2.tgz", + "integrity": "sha512-ZvkPiheyXtXlFqHpsdgscx+tZ7hoR59vOettvArinEspq5fxSDSgfF+L5wqqJ9R4t+n53nyn0sKxeXlik7AY9Q==", "cpu": [ "arm64" ], @@ -1139,9 +1140,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.0.tgz", - "integrity": "sha512-SXYJw3zpwHgaBqTXeAZ31qfW/v50wq4HhNVvKFhRr5MnptRX2Af4KebLWR1wpxGJtLgfS2hEPuALRIY3LPAAcA==", + "version": "4.34.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.2.tgz", + "integrity": "sha512-UlFk+E46TZEoxD9ufLKDBzfSG7Ki03fo6hsNRRRHF+KuvNZ5vd1RRVQm8YZlGsjcJG8R252XFK0xNPay+4WV7w==", "cpu": [ "arm64" ], @@ -1151,9 +1152,9 @@ ] }, "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.0.tgz", - "integrity": "sha512-e5XiCinINCI4RdyU3sFyBH4zzz7LiQRvHqDtRe9Dt8o/8hTBaYpdPimayF00eY2qy5j4PaaWK0azRgUench6WQ==", + "version": "4.34.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.2.tgz", + "integrity": "sha512-hJhfsD9ykx59jZuuoQgYT1GEcNNi3RCoEmbo5OGfG8RlHOiVS7iVNev9rhLKh7UBYq409f4uEw0cclTXx8nh8Q==", "cpu": [ "loong64" ], @@ -1163,9 +1164,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.0.tgz", - "integrity": "sha512-3SWN3e0bAsm9ToprLFBSro8nJe6YN+5xmB11N4FfNf92wvLye/+Rh5JGQtKOpwLKt6e61R1RBc9g+luLJsc23A==", + "version": "4.34.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.2.tgz", + "integrity": "sha512-g/O5IpgtrQqPegvqopvmdCF9vneLE7eqYfdPWW8yjPS8f63DNam3U4ARL1PNNB64XHZDHKpvO2Giftf43puB8Q==", "cpu": [ "ppc64" ], @@ -1175,9 +1176,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.0.tgz", - "integrity": "sha512-B1Oqt3GLh7qmhvfnc2WQla4NuHlcxAD5LyueUi5WtMc76ZWY+6qDtQYqnxARx9r+7mDGfamD+8kTJO0pKUJeJA==", + "version": "4.34.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.2.tgz", + "integrity": "sha512-bSQijDC96M6PuooOuXHpvXUYiIwsnDmqGU8+br2U7iPoykNi9JtMUpN7K6xml29e0evK0/g0D1qbAUzWZFHY5Q==", "cpu": [ "riscv64" ], @@ -1187,9 +1188,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.0.tgz", - "integrity": "sha512-UfUCo0h/uj48Jq2lnhX0AOhZPSTAq3Eostas+XZ+GGk22pI+Op1Y6cxQ1JkUuKYu2iU+mXj1QjPrZm9nNWV9rg==", + "version": "4.34.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.2.tgz", + "integrity": "sha512-49TtdeVAsdRuiUHXPrFVucaP4SivazetGUVH8CIxVsNsaPHV4PFkpLmH9LeqU/R4Nbgky9lzX5Xe1NrzLyraVA==", "cpu": [ "s390x" ], @@ -1199,9 +1200,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.0.tgz", - "integrity": "sha512-chZLTUIPbgcpm+Z7ALmomXW8Zh+wE2icrG+K6nt/HenPLmtwCajhQC5flNSk1Xy5EDMt/QAOz2MhzfOfJOLSiA==", + "version": "4.34.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.2.tgz", + "integrity": "sha512-j+jFdfOycLIQ7FWKka9Zd3qvsIyugg5LeZuHF6kFlXo6MSOc6R1w37YUVy8VpAKd81LMWGi5g9J25P09M0SSIw==", "cpu": [ "x64" ], @@ -1211,9 +1212,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.0.tgz", - "integrity": "sha512-jo0UolK70O28BifvEsFD/8r25shFezl0aUk2t0VJzREWHkq19e+pcLu4kX5HiVXNz5qqkD+aAq04Ct8rkxgbyQ==", + "version": "4.34.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.2.tgz", + "integrity": "sha512-aDPHyM/D2SpXfSNCVWCxyHmOqN9qb7SWkY1+vaXqMNMXslZYnwh9V/UCudl6psyG0v6Ukj7pXanIpfZwCOEMUg==", "cpu": [ "x64" ], @@ -1223,9 +1224,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.0.tgz", - "integrity": "sha512-Vmg0NhAap2S54JojJchiu5An54qa6t/oKT7LmDaWggpIcaiL8WcWHEN6OQrfTdL6mQ2GFyH7j2T5/3YPEDOOGA==", + "version": "4.34.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.2.tgz", + "integrity": "sha512-LQRkCyUBnAo7r8dbEdtNU08EKLCJMgAk2oP5H3R7BnUlKLqgR3dUjrLBVirmc1RK6U6qhtDw29Dimeer8d5hzQ==", "cpu": [ "arm64" ], @@ -1235,9 +1236,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.0.tgz", - "integrity": "sha512-CV2aqhDDOsABKHKhNcs1SZFryffQf8vK2XrxP6lxC99ELZAdvsDgPklIBfd65R8R+qvOm1SmLaZ/Fdq961+m7A==", + "version": "4.34.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.2.tgz", + "integrity": "sha512-wt8OhpQUi6JuPFkm1wbVi1BByeag87LDFzeKSXzIdGcX4bMLqORTtKxLoCbV57BHYNSUSOKlSL4BYYUghainYA==", "cpu": [ "ia32" ], @@ -1247,9 +1248,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.0.tgz", - "integrity": "sha512-g2ASy1QwHP88y5KWvblUolJz9rN+i4ZOsYzkEwcNfaNooxNUXG+ON6F5xFo0NIItpHqxcdAyls05VXpBnludGw==", + "version": "4.34.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.2.tgz", + "integrity": "sha512-rUrqINax0TvrPBXrFKg0YbQx18NpPN3NNrgmaao9xRNbTwek7lOXObhx8tQy8gelmQ/gLaGy1WptpU2eKJZImg==", "cpu": [ "x64" ], @@ -1329,9 +1330,9 @@ "peer": true }, "node_modules/@types/node": { - "version": "22.13.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.0.tgz", - "integrity": "sha512-ClIbNe36lawluuvq3+YYhnIN2CELi+6q8NpnM7PYp4hBn/TatfboPgVSm2rwKRfnV2M+Ty9GWDFI64KEe+kysA==", + "version": "22.13.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz", + "integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==", "devOptional": true, "dependencies": { "undici-types": "~6.20.0" @@ -2160,6 +2161,14 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/bignumber.js": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", + "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", + "engines": { + "node": "*" + } + }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -2364,9 +2373,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001696", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001696.tgz", - "integrity": "sha512-pDCPkvzfa39ehJtJ+OwGT/2yvT2SbjfHhiIW2LWOAcMQ7BzwxT/XuyUp4OTOd0XFWA6BKw0JalnBHgSi5DGJBQ==", + "version": "1.0.30001697", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001697.tgz", + "integrity": "sha512-GwNPlWJin8E+d7Gxq96jxM6w0w+VFeyyXRsjU58emtkYqnbwHqXm5uT2uCmO0RQE9htWknOP4xtBlLmM/gWxvQ==", "dev": true, "funding": [ { @@ -2828,9 +2837,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.5.90", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.90.tgz", - "integrity": "sha512-C3PN4aydfW91Natdyd449Kw+BzhLmof6tzy5W1pFC5SpQxVXT+oyiyOG9AgYYSN9OdA/ik3YkCrpwqI8ug5Tug==", + "version": "1.5.92", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.92.tgz", + "integrity": "sha512-BeHgmNobs05N1HMmMZ7YIuHfYBGlq/UmvlsTgg+fsbFs9xVMj+xJHFg19GN04+9Q+r8Xnh9LXqaYIyEWElnNgQ==", "dev": true, "peer": true }, @@ -2849,9 +2858,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.18.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.0.tgz", - "integrity": "sha512-0/r0MySGYG8YqlayBZ6MuCfECmHFdJ5qyPh8s8wa5Hnm6SaFLSK1VYCbj+NKp090Nm1caZhD+QTnmxO7esYGyQ==", + "version": "5.18.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz", + "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==", "dev": true, "peer": true, "dependencies": { @@ -4103,6 +4112,14 @@ } } }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -4503,9 +4520,9 @@ "dev": true }, "node_modules/object-inspect": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", - "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "engines": { "node": ">= 0.4" }, @@ -5112,9 +5129,9 @@ } }, "node_modules/rollup": { - "version": "4.34.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.0.tgz", - "integrity": "sha512-+4C/cgJ9w6sudisA0nZz0+O7lTP9a3CzNLsoDwaRumM8QHwghUsu6tqHXiTmNUp/rqNiM14++7dkzHDyCRs0Jg==", + "version": "4.34.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.2.tgz", + "integrity": "sha512-sBDUoxZEaqLu9QeNalL8v3jw6WjPku4wfZGyTU7l7m1oC+rpRihXc/n/H+4148ZkGz5Xli8CHMns//fFGKvpIQ==", "dependencies": { "@types/estree": "1.0.6" }, @@ -5126,25 +5143,25 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.34.0", - "@rollup/rollup-android-arm64": "4.34.0", - "@rollup/rollup-darwin-arm64": "4.34.0", - "@rollup/rollup-darwin-x64": "4.34.0", - "@rollup/rollup-freebsd-arm64": "4.34.0", - "@rollup/rollup-freebsd-x64": "4.34.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.34.0", - "@rollup/rollup-linux-arm-musleabihf": "4.34.0", - "@rollup/rollup-linux-arm64-gnu": "4.34.0", - "@rollup/rollup-linux-arm64-musl": "4.34.0", - "@rollup/rollup-linux-loongarch64-gnu": "4.34.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.34.0", - "@rollup/rollup-linux-riscv64-gnu": "4.34.0", - "@rollup/rollup-linux-s390x-gnu": "4.34.0", - "@rollup/rollup-linux-x64-gnu": "4.34.0", - "@rollup/rollup-linux-x64-musl": "4.34.0", - "@rollup/rollup-win32-arm64-msvc": "4.34.0", - "@rollup/rollup-win32-ia32-msvc": "4.34.0", - "@rollup/rollup-win32-x64-msvc": "4.34.0", + "@rollup/rollup-android-arm-eabi": "4.34.2", + "@rollup/rollup-android-arm64": "4.34.2", + "@rollup/rollup-darwin-arm64": "4.34.2", + "@rollup/rollup-darwin-x64": "4.34.2", + "@rollup/rollup-freebsd-arm64": "4.34.2", + "@rollup/rollup-freebsd-x64": "4.34.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.34.2", + "@rollup/rollup-linux-arm-musleabihf": "4.34.2", + "@rollup/rollup-linux-arm64-gnu": "4.34.2", + "@rollup/rollup-linux-arm64-musl": "4.34.2", + "@rollup/rollup-linux-loongarch64-gnu": "4.34.2", + "@rollup/rollup-linux-powerpc64le-gnu": "4.34.2", + "@rollup/rollup-linux-riscv64-gnu": "4.34.2", + "@rollup/rollup-linux-s390x-gnu": "4.34.2", + "@rollup/rollup-linux-x64-gnu": "4.34.2", + "@rollup/rollup-linux-x64-musl": "4.34.2", + "@rollup/rollup-win32-arm64-msvc": "4.34.2", + "@rollup/rollup-win32-ia32-msvc": "4.34.2", + "@rollup/rollup-win32-x64-msvc": "4.34.2", "fsevents": "~2.3.2" } }, @@ -5287,9 +5304,9 @@ } }, "node_modules/semver": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.0.tgz", - "integrity": "sha512-DrfFnPzblFmNrIZzg5RzHegbiRWg7KMR7btwi2yjHwx06zsUbO5g613sVwEV7FTwmzJu+Io0lJe2GJ3LxqpvBQ==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "dev": true, "bin": { "semver": "bin/semver.js" diff --git a/package.json b/package.json index 50b81b5281..dc6a0f6cee 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,8 @@ "date-fns-tz": "3.1.3", "express": "4.19.2", "js-cookie": "^3.0.5", - "lodash": "^4.17.21", + "json-bigint": "1.0.0", + "lodash": "4.17.21", "pinia": "2.1.7", "tiny-emitter": "2.1.0", "vue": "^3.3.9", diff --git a/src/assets/styles/bmc/custom/_tables.scss b/src/assets/styles/bmc/custom/_tables.scss index fb055dd60a..b984c22706 100644 --- a/src/assets/styles/bmc/custom/_tables.scss +++ b/src/assets/styles/bmc/custom/_tables.scss @@ -152,6 +152,10 @@ background-color: theme-color-dark($light); } } + + caption { + color: $gray-600; + } } .b-table-sticky-header td { diff --git a/src/components/AppHeader/AppHeader.vue b/src/components/AppHeader/AppHeader.vue index e38cd95664..3ac37faf79 100644 --- a/src/components/AppHeader/AppHeader.vue +++ b/src/components/AppHeader/AppHeader.vue @@ -157,7 +157,7 @@ getEvents(); const assetTag = computed(() => globalStore.assetTag); const isNavTagPresent = computed( - () => assetTag.value || globalStore.modelType || globalStore.serialNumber, + () => assetTag.value || globalStore.modelType || globalStore.serialNumber ); const modelType = computed(() => globalStore.modelType); const serialNumber = computed(() => globalStore.serialNumber); diff --git a/src/layouts/AppLayout.vue b/src/layouts/AppLayout.vue index 48eb07ca87..a4494d53bd 100644 --- a/src/layouts/AppLayout.vue +++ b/src/layouts/AppLayout.vue @@ -22,7 +22,9 @@ import AppHeader from '@/components/AppHeader/AppHeader.vue'; import { ref, watch, onMounted } from 'vue'; import { useRoute } from 'vue-router'; import eventBus from '@/eventBus'; +import { GlobalStore } from '@/store'; +const globalStore = GlobalStore(); // const { setFocus } = useJumpLinkComposable(); const routerKey = ref(0); const route = useRoute(); @@ -33,7 +35,7 @@ onMounted(() => { }); watch( - () => route, + () => route // () => { // nextTick(() => { // setFocus(focusTarget.value); @@ -41,6 +43,7 @@ watch( // }, ); const refreshPage = async () => { + globalStore.getSystemInfo(); console.log('Refresh called'); routerKey.value += 1; }; diff --git a/src/locales/en-US.json b/src/locales/en-US.json index 4819eeca10..29a0ae4c0b 100644 --- a/src/locales/en-US.json +++ b/src/locales/en-US.json @@ -1778,7 +1778,7 @@ "invalidVlanTagId": "VLAN ID must be in range %{min} to %{max}", "invalidIsciTargetPort": "The port value should be a positive integer between %{min} and %{max}", "chapNameRequired": "CHAP name is required when CHAP secret is specified", - "chapSecretRequired": "CHAP secret is required when CHAP secret is specified", + "chapSecretRequired": "CHAP secret is required when CHAP name is specified", "invalidFieldLength": "%{field} should not exceed %{max} characters", "invalidChapSecretLength": "CHAP secret length must be between %{min} and %{max} characters" } diff --git a/src/main.js b/src/main.js index 1a6e68a6ed..2f8520c7e7 100644 --- a/src/main.js +++ b/src/main.js @@ -3,7 +3,7 @@ import { createPinia } from 'pinia'; import App from './App.vue'; import router from './router'; import { createBootstrap } from 'bootstrap-vue-next'; -import { GlobalStore } from './store'; +import { GlobalStore, AuthenticationStore } from './store'; import { format } from 'date-fns-tz'; // Add the necessary CSSs // import 'bootstrap/dist/css/bootstrap.css'; @@ -11,6 +11,9 @@ import 'bootstrap-vue-next/dist/bootstrap-vue-next.css'; import i18n from './i18n'; import ArrowRight16 from '@carbon/icons-vue/es/arrow--right/16'; +import WebSocketPlugin, { + initWebSocket, +} from '@/store/plugins/WebSocketPlugin.js'; const pinia = createPinia(); const app = createApp(App); @@ -20,7 +23,12 @@ app.component('IconArrowRight', ArrowRight16); app.use(createBootstrap({ components: true, directives: true })); // Change this line app.use(i18n); +pinia.use(WebSocketPlugin); + const globalStore = GlobalStore(); +const authenticationStore = AuthenticationStore(); + +if (authenticationStore.isLoggedIn) initWebSocket(); app.config.globalProperties.$filters = { shortTimeZone(value) { diff --git a/src/router/routes.js b/src/router/routes.js index ea7e437e63..5da6310093 100644 --- a/src/router/routes.js +++ b/src/router/routes.js @@ -31,6 +31,7 @@ import HostConsole from '@/views/Operations/HostConsole'; import HostConsoleConsole from '@/views/Operations/HostConsole/HostConsoleConsole.vue'; import CapacityOnDemand from '../views/ResourceManagement/CapacityOnDemand/CapacityOnDemand.vue'; import DeconfigurationRecords from '../views/Logs/DeconfigurationRecords/DeconfigurationRecords.vue'; +import ServerPowerOperations from '@/views/Operations/ServerPowerOperations'; const roles = { administrator: 'Administrator', @@ -83,6 +84,14 @@ export const routes = [ exclusiveToRoles: [roles.administrator], }, }, + { + path: '/operations/server-power-operations', + name: 'server-power-operations', + component: ServerPowerOperations, + meta: { + title: i18n.global.t('appPageTitle.serverPowerOperations'), + }, + }, { path: '/hardware-status/sensors', name: 'sensors', @@ -189,14 +198,14 @@ export const routes = [ title: i18n.global.t('appPageTitle.hostConsole'), }, }, - { + { path: '/logs/deconfiguration-records', name: 'deconfiguration-records', component: DeconfigurationRecords, meta: { title: i18n.global.t('appPageTitle.deconfigurationRecords'), - }, - }, + }, + }, { path: '/settings/power-restore-policy', name: 'power-restore-policy', diff --git a/src/store/index.js b/src/store/index.js index fbe106dbcb..6b4b196205 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -31,6 +31,7 @@ import UserManagementStore from './modules/SecurityAndAccess/UserManagementStore import PcieTopologyStore from './modules/HardwareStatus/PcieTopologyStore.js'; import HardwareDeconfigurationStore from './modules/Settings/HardwareDeconfigurationStore'; import DeconfigurationRecordsStore from './modules/Logs/DeconfigurationRecordsStore.js'; +import NetworkSettingsStore from './modules/Operations/NetworkSettingsStore.js'; // ... (export use other stores) export { EventLogStore, @@ -64,5 +65,6 @@ export { UserManagementStore, PcieTopologyStore, HardwareDeconfigurationStore, - DeconfigurationRecordsStore + DeconfigurationRecordsStore, + NetworkSettingsStore, }; diff --git a/src/store/modules/Authentication/AuthenticationStore.js b/src/store/modules/Authentication/AuthenticationStore.js index c4cea36581..3ae95f816a 100644 --- a/src/store/modules/Authentication/AuthenticationStore.js +++ b/src/store/modules/Authentication/AuthenticationStore.js @@ -6,6 +6,7 @@ import { useCookies } from 'vue3-cookies'; import Cookies from 'js-cookie'; const { cookies } = useCookies(); // const router = useRouter(); + export const AuthenticationStore = defineStore('authentication', { state: () => ({ consoleWindow: null, @@ -51,7 +52,6 @@ export const AuthenticationStore = defineStore('authentication', { .then((response) => { this.authSuccess(); this.$state.authError = false; - this.xsrfCookie = response.data.token; }) .catch((error) => { this.$state.authError = true; @@ -82,7 +82,6 @@ export const AuthenticationStore = defineStore('authentication', { console.log(error); this.logoutRemove(); }); - }, getUserInfo(username) { return api @@ -96,14 +95,13 @@ export const AuthenticationStore = defineStore('authentication', { .then((response) => { this.$state.bmcTime = response.data.DateTime; const cookie = Cookies.get('XSRF-TOKEN'); - console.log('cookie', cookie); }) .catch((error) => console.log(error)); }, resetStoreState() { - this.$state.authError = false; - this.$state.xsrfCookie = cookies.get('XSRF-TOKEN'); - this.$state.isAuthenticatedCookie = cookies.get('IsAuthenticated'); + this.authError = false; + this.xsrfCookie = cookies.get('XSRF-TOKEN'); + this.isAuthenticatedCookie = cookies.get('IsAuthenticated'); }, }, }); diff --git a/src/store/modules/GlobalStore.js b/src/store/modules/GlobalStore.js index 37a7961e80..158220e1b9 100644 --- a/src/store/modules/GlobalStore.js +++ b/src/store/modules/GlobalStore.js @@ -39,14 +39,16 @@ export const GlobalStore = defineStore('global', { serialNumber: null, safeMode: null, serverStatus: 'unreachable', + postCodeValue: null, languagePreference: localStorage.getItem('storedLanguage') || 'en-US', isUtcDisplay: localStorage.getItem('storedUtcDisplay') ? JSON.parse(localStorage.getItem('storedUtcDisplay')) : true, username: localStorage.getItem('storedUsername'), - isAuthorized: true, - userPrivilege: null, currentUser: JSON.parse(localStorage.getItem('storedCurrentUser')), + isAuthorized: true, + hmcManaged: localStorage.getItem('storedHmcManagedValue') || null, + isServiceLoginEnabled: false, }), getters: { bootProgressGetter: (state) => state.bootProgress, @@ -57,14 +59,31 @@ export const GlobalStore = defineStore('global', { state.bootProgress === 'OSBootStarted' || state.bootProgress === 'OSRunning', isOSRunningGetter: (state) => state.bootProgress === 'OSRunning', + assetTagGetter: (state) => state.assetTag, + modelTypeGetter: (state) => state.modelType, + serialNumberGetter: (state) => state.serialNumber, getIsUtcDisplay: (state) => state.isUtcDisplay, safeModeGetter: (state) => state.safeMode, + postCodeValueGetter: (state) => state.postCodeValue, + bmcTimeGetter: (state) => state.bmcTime, + acfInstalledGetter: (state) => state.acfInstalled, + expirationDateGetter: (state) => state.expirationDate, + languagePreferenceGetter: (state) => state.languagePreference, + isUtcDisplayGetter: (state) => state.isUtcDisplay, serverStatusGetter: (state) => state.serverStatus, + usernameGetter: (state) => state.username, + hmcManagedGetter: (state) => state.hmcManaged, currentUserGetter: (state) => state.currentUser, isServiceUser: (state) => state.currentUser?.RoleId === 'OemIBMServiceAgent' || !state.currentUser, isReadOnlyUserGetter: (state) => state.currentUser?.RoleId === 'ReadOnly' || !state.currentUser, + isAdminUser: (state) => + state.currentUser?.RoleId === 'Administrator' || !state.currentUser, + isReadOnlyUser: (state) => + state.currentUser?.RoleId === 'ReadOnly' || !state.currentUser, + isAuthorizedGetter: (state) => state.isAuthorized, + isServiceLoginEnabledGetter: (state) => state.isServiceLoginEnabled, }, actions: { async getBmcTime() { @@ -77,8 +96,58 @@ export const GlobalStore = defineStore('global', { }) .catch((error) => console.log(error)); }, - setCurrentUser (currentUsr) { - this.currentUser = currentUsr + async getServiceLogin() { + return await api + .get('/redfish/v1/AccountService/Accounts/service') + .then((response) => { + this.acfInstalled = response.data.Oem.IBM.ACF.ACFInstalled; + this.expirationDate = response.data.Oem.IBM.ACF.ExpirationDate; + this.isServiceLoginEnabled = response.data.Enabled; + }) + .catch((error) => console.log(error)); + }, + getCurrentUser(username = localStorage.getItem('storedUsername')) { + if (localStorage.getItem('storedCurrentUser')) return; + return api + .get(`/redfish/v1/AccountService/Accounts/${username}`) + .then(({ data }) => { + this.currentUser = data; + localStorage.setItem( + 'storedCurrentUser', + JSON.stringify(this.currentUser) + ); + }) + .catch((error) => { + console.log(error); + this.getAccountService(); + }); + }, + getAccountService() { + return api + .get('/redfish/v1/AccountService') + .then((response) => { + if (response.data?.LDAP?.RemoteRoleMapping?.length > 0) { + return Promise.resolve(); + } + }) + .catch(() => { + return Promise.reject(); + }); + }, + async getHmcManaged() { + return await api + .get( + '/redfish/v1/Registries/BiosAttributeRegistry/BiosAttributeRegistry' + ) + .then(({ data: { RegistryEntries } }) => { + const hmcMananged = RegistryEntries.Attributes.filter( + (Attribute) => Attribute.AttributeName == 'pvm_hmc_managed' + ); + let hmcManangedValue = hmcMananged[0].CurrentValue; + this.hmcManaged = hmcManangedValue; + localStorage.setItem('storedHmcManagedValue', hmcManangedValue); + }) + .catch((error) => console.log(error)); }, getSystemInfo() { api @@ -110,43 +179,13 @@ export const GlobalStore = defineStore('global', { } else { this.serverStatus = serverStateMapper(PowerState); } - }, + } ) .catch((error) => { console.log(error); return Promise.reject(); }); }, - getCurrentUser( - username = localStorage.getItem('storedUsername') - ) { - if (localStorage.getItem('storedCurrentUser')) return; - return api - .get(`/redfish/v1/AccountService/Accounts/${username}`) - .then(({ data }) => { - this.setCurrentUser(data) - localStorage.setItem( - 'storedCurrentUser', - JSON.stringify(this.currentUser) - ); - }) - .catch((error) => { - console.log(error); - return this.getAccountService(); - }); - }, - getAccountService() { - return api - .get('/redfish/v1/AccountService') - .then((response) => { - if (response.data?.LDAP?.RemoteRoleMapping?.length > 0) { - return Promise.resolve(); - } - }) - .catch(() => { - return Promise.reject(); - }); - }, async getBootProgress() { api .get('/redfish/v1/Systems/system') @@ -165,9 +204,6 @@ export const GlobalStore = defineStore('global', { this.isAuthorized = true; }, 100); }, - setUtcTime(state, isUtcDisplay) { - state.isUtcDisplay = isUtcDisplay; - }, async getCurrentTask(task) { return await api.get(task).then(({ data }) => { return data; diff --git a/src/store/modules/Operations/BootSettingsStore.js b/src/store/modules/Operations/BootSettingsStore.js index eee97df306..cd9922b900 100644 --- a/src/store/modules/Operations/BootSettingsStore.js +++ b/src/store/modules/Operations/BootSettingsStore.js @@ -69,19 +69,19 @@ export const BootSettingsStore = defineStore('bootSettings', { return await api.all(promises).then( api.spread((...responses) => { let message = i18n.global.t( - 'pageServerPowerOperations.toast.successSaveSettings', + 'pageServerPowerOperations.toast.successSaveSettings' ); responses.forEach((response) => { if (response instanceof Error) { throw new Error( i18n.global.t( - 'pageServerPowerOperations.toast.errorSaveSettings', - ), + 'pageServerPowerOperations.toast.errorSaveSettings' + ) ); } }); return message; - }), + }) ); }, async fetchBiosAttributes() { @@ -108,7 +108,7 @@ export const BootSettingsStore = defineStore('bootSettings', { // Action not tested. Remove this comment once the action is tested and verified. return await api .get( - '/redfish/v1/Registries/BiosAttributeRegistry/BiosAttributeRegistry', + '/redfish/v1/Registries/BiosAttributeRegistry/BiosAttributeRegistry' ) .then( ({ @@ -117,22 +117,22 @@ export const BootSettingsStore = defineStore('bootSettings', { }, }) => { let linuxPercentObj = Attributes.find( - (itm) => itm.AttributeName === 'pvm_linux_kvm_percentage', + (itm) => itm.AttributeName === 'pvm_linux_kvm_percentage' ); let linuxPercentCurrentObj = Attributes.find( - (itm) => itm.AttributeName === 'pvm_linux_kvm_percentage_current', + (itm) => itm.AttributeName === 'pvm_linux_kvm_percentage_current' ); let linuxValue = linuxPercentObj?.CurrentValue / 10; let ibmi_load_source = Attributes.find( - (itm) => itm.AttributeName === 'pvm_ibmi_load_source', + (itm) => itm.AttributeName === 'pvm_ibmi_load_source' ); let ibmi_load_source_value = ibmi_load_source?.CurrentValue; let ibmi_alt_load_source = Attributes.find( - (itm) => itm.AttributeName === 'pvm_ibmi_alt_load_source', + (itm) => itm.AttributeName === 'pvm_ibmi_alt_load_source' ); let ibmi_alt_load_source_value = ibmi_alt_load_source?.CurrentValue; let ibmi_console = Attributes.find( - (itm) => itm.AttributeName === 'pvm_ibmi_console', + (itm) => itm.AttributeName === 'pvm_ibmi_console' ); let ibmi_console_value = ibmi_console?.CurrentValue; let linuxPercentCurrentValue = @@ -180,16 +180,16 @@ export const BootSettingsStore = defineStore('bootSettings', { 'pvm_linux_kvm_memory', ].indexOf(attributeObj.AttributeName) >= 0 ? i18n.global.t( - `pageServerPowerOperations.biosSettings.attributeValues.${attributeObj.AttributeName}.${item.ValueName}`, + `pageServerPowerOperations.biosSettings.attributeValues.${attributeObj.AttributeName}.${item.ValueName}` ) : item.ValueName, }; - }, + } ), }; }, {}); this.attributeValues = filteredAttributeValues; - }, + } ) .catch((error) => console.log(error)); }, @@ -207,7 +207,7 @@ export const BootSettingsStore = defineStore('bootSettings', { pcieSlot?.Location?.PartLocation?.ServiceLabel ) { locationCodes.push( - pcieSlot?.Location?.PartLocation?.ServiceLabel, + pcieSlot?.Location?.PartLocation?.ServiceLabel ); } }); @@ -239,14 +239,14 @@ export const BootSettingsStore = defineStore('bootSettings', { ResetType: 'On', }) .then(() => { - return i18n.global.tc( - 'pageServerPowerOperations.toast.successSaveSettings', + return i18n.global.t( + 'pageServerPowerOperations.toast.successSaveSettings' ); }) .catch((error) => { console.log(error); throw new Error( - i18n.global.tc('pageServerPowerOperations.toast.errorSaveSettings'), + i18n.global.t('pageServerPowerOperations.toast.errorSaveSettings') ); }); }, diff --git a/src/store/modules/Operations/ControlStore.js b/src/store/modules/Operations/ControlStore.js index 190ca1dfe8..ae8ad67825 100644 --- a/src/store/modules/Operations/ControlStore.js +++ b/src/store/modules/Operations/ControlStore.js @@ -8,6 +8,7 @@ export const ControlStore = defineStore('control', { isOperationInProgress: false, lastPowerOperationTime: null, lastBmcRebootTime: null, + displayInfoToast: false, }), getters: { getIsOperationInProgress: (state) => state.isOperationInProgress, @@ -24,7 +25,6 @@ export const ControlStore = defineStore('control', { * @returns {Promise} */ async checkForServerStatus(serverStatus) { - // Action not tested. Remove this comment once the action is tested and verified. const global = GlobalStore(); return new Promise((resolve) => { const timer = setTimeout(() => { @@ -42,12 +42,11 @@ export const ControlStore = defineStore('control', { clearTimeout(timer); } }, - { detached: true }, + { detached: true } ); }); }, async fetchLastPowerOperationTime() { - // Action not tested. Remove this comment once the action is tested and verified. return await api .get('/redfish/v1/Systems/system') .then((response) => { @@ -78,57 +77,61 @@ export const ControlStore = defineStore('control', { .catch((error) => { console.log(error); throw new Error( - i18n.global.t('pageRebootBmc.toast.errorRebootStart'), + i18n.global.t('pageRebootBmc.toast.errorRebootStart') ); }); }, - async serverPowerOn() { - // Action not tested. Remove this comment once the action is tested and verified. - const data = { ResetType: 'On' }; - this.serverPowerChange(data); - await this.checkForServerStatus('on'); + async powerOps(value) { + await this.checkForServerStatus(value); this.isOperationInProgress = false; this.fetchLastPowerOperationTime(); }, + async serverPowerOn() { + const value = 'on'; + const data = { ResetType: 'On' }; + const displayInfo = await this.serverPowerChange(data); + this.powerOps(value); + return Promise.resolve(displayInfo); + }, async serverSoftReboot() { - // Action not tested. Remove this comment once the action is tested and verified. + const value = 'on'; const data = { ResetType: 'GracefulRestart' }; - this.serverPowerChange(data); - await this.checkForServerStatus('on'); - this.isOperationInProgress = false; - this.fetchLastPowerOperationTime(); + const displayInfo = await this.serverPowerChange(data); + this.powerOps(value); + return Promise.resolve(displayInfo); }, async serverHardReboot() { - // Action not tested. Remove this comment once the action is tested and verified. + const value = 'on'; const data = { ResetType: 'ForceRestart' }; - this.serverPowerChange(data); - await this.checkForServerStatus('on'); - this.isOperationInProgress = false; - this.fetchLastPowerOperationTime(); + const displayInfo = await this.serverPowerChange(data); + this.powerOps(value); + return Promise.resolve(displayInfo); }, async serverSoftPowerOff() { - // Action not tested. Remove this comment once the action is tested and verified. + const value = 'off'; const data = { ResetType: 'GracefulShutdown' }; - this.serverPowerChange(data); - await this.checkForServerStatus('off'); - this.isOperationInProgress = false; - this.fetchLastPowerOperationTime(); + const displayInfo = await this.serverPowerChange(data); + this.powerOps(value); + return Promise.resolve(displayInfo); }, async serverHardPowerOff() { - // Action not tested. Remove this comment once the action is tested and verified. + const value = 'off'; const data = { ResetType: 'ForceOff' }; - this.serverPowerChange(data); - await this.checkForServerStatus('off'); - this.isOperationInProgress = false; - this.fetchLastPowerOperationTime(); + const displayInfo = await this.serverPowerChange(data); + this.powerOps(value); + return Promise.resolve(displayInfo); }, serverPowerChange(data) { - // Action not tested. Remove this comment once the action is tested and verified. this.isOperationInProgress = true; - api + return api .post('/redfish/v1/Systems/system/Actions/ComputerSystem.Reset', data) + .then(() => { + this.displayInfoToast = true; + return this.displayInfoToast; + }) .catch((error) => { console.log(error); + this.displayInfoToast = false; this.isOperationInProgress = false; }); }, diff --git a/src/store/modules/Operations/NetworkSettingsStore.js b/src/store/modules/Operations/NetworkSettingsStore.js index df393082a9..584ef4a99a 100644 --- a/src/store/modules/Operations/NetworkSettingsStore.js +++ b/src/store/modules/Operations/NetworkSettingsStore.js @@ -1,9 +1,9 @@ import api from '@/store/api'; import i18n from '@/i18n'; +import { defineStore } from 'pinia'; -const NetworkSettingsStore = { - namespaced: true, - state: { +export const NetworkSettingsStore = defineStore('networkSettings', { + state: () => ({ biosAttributes: null, requiredAttributes: [ 'pvm_ibmi_network_install_type', @@ -24,35 +24,21 @@ const NetworkSettingsStore = { targetNameMaxLength: null, targetPortUpperBound: null, vlanTagIdUpperBound: null, - }, + }), getters: { - biosAttributes: (state) => state.biosAttributes, - nfsImageDirMaxLength: (state) => state.nfsImageDirMaxLength, - initiatorNameMaxLength: (state) => state.initiatorNameMaxLength, - targetNameMaxLength: (state) => state.targetNameMaxLength, - targetPortUpperBound: (state) => state.targetPortUpperBound, - vlanTagIdUpperBound: (state) => state.vlanTagIdUpperBound, - }, - mutations: { - setBiosAttributes: (state, biosAttributes) => - (state.biosAttributes = biosAttributes), - setNfsImageDirMaxLength: (state, nfsImageDirMaxLength) => - (state.nfsImageDirMaxLength = nfsImageDirMaxLength), - setInitiatorNameMaxLength: (state, initiatorNameMaxLength) => - (state.initiatorNameMaxLength = initiatorNameMaxLength), - setTargetNameMaxLength: (state, targetNameMaxLength) => - (state.targetNameMaxLength = targetNameMaxLength), - setTargetPortUpperBound: (state, targetPortUpperBound) => - (state.targetPortUpperBound = targetPortUpperBound), - setVlanTagIdUpperBound: (state, vlanTagIdUpperBound) => - (state.vlanTagIdUpperBound = vlanTagIdUpperBound), + biosAttributesGetter: (state) => state.biosAttributes, + nfsImageDirMaxLengthGetter: (state) => state.nfsImageDirMaxLength, + initiatorNameMaxLengthGetter: (state) => state.initiatorNameMaxLength, + targetNameMaxLengthGetter: (state) => state.targetNameMaxLength, + targetPortUpperBoundGetter: (state) => state.targetPortUpperBound, + vlanTagIdUpperBoundGetter: (state) => state.vlanTagIdUpperBound, }, actions: { - async getBiosAttributes({ commit, state }) { + async getBiosAttributes() { return await api .get('/redfish/v1/Systems/system/Bios') .then(({ data: { Attributes } }) => { - const filteredAttributes = state.requiredAttributes + const filteredAttributes = this.requiredAttributes .filter((key) => Object.keys(Attributes).includes(key)) .reduce((obj, key) => { return { @@ -60,7 +46,7 @@ const NetworkSettingsStore = { [key]: Attributes[key], }; }, {}); - commit('setBiosAttributes', filteredAttributes); + this.biosAttributes = filteredAttributes; }) .catch((error) => { console.log(error); @@ -73,60 +59,60 @@ const NetworkSettingsStore = { return await api .patch('/redfish/v1/Systems/system/Bios/Settings', setDModeObj) .then(() => { - return i18n.t( - 'pageServerPowerOperations.modal.networkSettings.toast.successUpdateDMode', + return i18n.global.t( + 'pageServerPowerOperations.modal.networkSettings.toast.successUpdateDMode' ); }) .catch((error) => { console.log(error); throw new Error( - i18n.t( - 'pageServerPowerOperations.modal.networkSettings.toast.errorUpdateDMode', - ), + i18n.global.t( + 'pageServerPowerOperations.modal.networkSettings.toast.errorUpdateDMode' + ) ); }); }, - async restoreDefault({ dispatch }) { + async restoreDefault() { const restoreDefaultObj = { Attributes: { pvm_ibmi_iscsi_initiator_name: '' }, }; return await api .patch('/redfish/v1/Systems/system/Bios/Settings', restoreDefaultObj) .then(() => { - dispatch('getBiosAttributes'); - return i18n.t( - 'pageServerPowerOperations.modal.networkSettings.toast.successRestoreDefault', + this.getBiosAttributes(); + return i18n.global.t( + 'pageServerPowerOperations.modal.networkSettings.toast.successRestoreDefault' ); }) .catch((error) => { console.log(error); throw new Error( - i18n.t( - 'pageServerPowerOperations.modal.networkSettings.toast.errorRestoreDefault', - ), + i18n.global.t( + 'pageServerPowerOperations.modal.networkSettings.toast.errorRestoreDefault' + ) ); }); }, - async saveBiosSettings(_, { form }) { + async saveBiosSettings({ form }) { return await api .patch('/redfish/v1/Systems/system/Bios/Settings', { Attributes: form, }) .then(() => { - return i18n.t( - 'pageServerPowerOperations.modal.networkSettings.toast.successSavedSetting', + return i18n.global.t( + 'pageServerPowerOperations.modal.networkSettings.toast.successSavedSetting' ); }) .catch((error) => { console.log(error); throw new Error( - i18n.t( - 'pageServerPowerOperations.modal.networkSettings.toast.errorSavedSettings', - ), + i18n.global.t( + 'pageServerPowerOperations.modal.networkSettings.toast.errorSavedSettings' + ) ); }); }, - async updateChapData(_, { chapData }) { + async updateChapData({ chapData }) { return await api .patch('/redfish/v1/Systems/system', { Oem: { @@ -139,61 +125,61 @@ const NetworkSettingsStore = { }, }) .then(() => { - return i18n.t( - 'pageServerPowerOperations.modal.networkSettings.toast.successSavedSetting', + return i18n.global.t( + 'pageServerPowerOperations.modal.networkSettings.toast.successSavedSetting' ); }) .catch((error) => { console.log('error', error); throw new Error( - i18n.t( - 'pageServerPowerOperations.modal.networkSettings.toast.errorSavedSettings', - ), + i18n.global.t( + 'pageServerPowerOperations.modal.networkSettings.toast.errorSavedSettings' + ) ); }); }, - async getPropertyLimits({ commit }) { + async getPropertyLimits() { return await api .get( - '/redfish/v1/Registries/BiosAttributeRegistry/BiosAttributeRegistry', + '/redfish/v1/Registries/BiosAttributeRegistry/BiosAttributeRegistry' ) .then(({ data: { RegistryEntries } }) => { const nfsImageDir = RegistryEntries.Attributes.filter( (Attribute) => - Attribute.AttributeName == 'pvm_ibmi_nfs_image_directory', + Attribute.AttributeName == 'pvm_ibmi_nfs_image_directory' ); const nfsImageDirMaxLength = nfsImageDir[0].MaxLength; - commit('setNfsImageDirMaxLength', nfsImageDirMaxLength); + this.nfsImageDirMaxLength = nfsImageDirMaxLength; const initiatorName = RegistryEntries.Attributes.filter( (Attribute) => - Attribute.AttributeName == 'pvm_ibmi_iscsi_initiator_name', + Attribute.AttributeName == 'pvm_ibmi_iscsi_initiator_name' ); const initiatorNameMaxLength = initiatorName[0].MaxLength; - commit('setInitiatorNameMaxLength', initiatorNameMaxLength); + this.initiatorNameMaxLength = initiatorNameMaxLength; const targetName = RegistryEntries.Attributes.filter( (Attribute) => - Attribute.AttributeName == 'pvm_ibmi_iscsi_target_name', + Attribute.AttributeName == 'pvm_ibmi_iscsi_target_name' ); const targetNameMaxLength = targetName[0].MaxLength; - commit('setTargetNameMaxLength', targetNameMaxLength); + this.targetNameMaxLength = targetNameMaxLength; const targetPort = RegistryEntries.Attributes.filter( (Attribute) => - Attribute.AttributeName == 'pvm_ibmi_iscsi_target_port', + Attribute.AttributeName == 'pvm_ibmi_iscsi_target_port' ); const targetPortUpperBound = targetPort[0].UpperBound; - commit('setTargetPortUpperBound', targetPortUpperBound); + this.targetPortUpperBound = targetPortUpperBound; const vlanTagId = RegistryEntries.Attributes.filter( - (Attribute) => Attribute.AttributeName == 'pvm_ibmi_vlan_tag_id', + (Attribute) => Attribute.AttributeName == 'pvm_ibmi_vlan_tag_id' ); const vlanTagIdUpperBound = vlanTagId[0].UpperBound; - commit('setVlanTagIdUpperBound', vlanTagIdUpperBound); + this.vlanTagIdUpperBound = vlanTagIdUpperBound; }); }, }, -}; +}); export default NetworkSettingsStore; diff --git a/src/store/modules/Settings/NetworkStore.js b/src/store/modules/Settings/NetworkStore.js index ab29604835..6d6813f8b2 100644 --- a/src/store/modules/Settings/NetworkStore.js +++ b/src/store/modules/Settings/NetworkStore.js @@ -2,53 +2,71 @@ import api from '@/store/api'; import i18n from '@/i18n'; import { defineStore } from 'pinia'; +import { find } from 'lodash'; export const NetworkStore = defineStore('network', { state: () => ({ - dchpEnabledState: false, - ipv6DchpEnabledState: false, + dhcpEnabledState: false, + ipv6DhcpEnabledState: false, ipv6AutoConfigEnabled: false, - ethernetData: [], - firstInterfaceId: '', //used for setting global DHCP settings - globalNetworkSettings: [], + networkSettings: [], selectedInterfaceId: '', // which tab is selected - selectedInterfaceIndex: 0, - isTableBusy: false, // which tab is selected + selectedInterfaceIndex: 0, // which tab is selected + isTableBusy: false, }), getters: { - getEthernetDatathernetData: (state) => state.ethernetData, - getFirstInterfaceId: (state) => state.firstInterfaceId, - getGlobalNetworkSettings: (state) => state.globalNetworkSettings, - getIsTableBusy: (state) => state.isTableBusy, - getSelectedInterfaceIdIndex: (state) => state.selectedInterfaceId, - getSelectedInterfaceData: (state) => state.ethernetData, - getSelectedInterfaceId: (state) => state.selectedInterfaceId, - getSelectedInterfaceIndex: (state) => state.selectedInterfaceIndex, + dhcpEnabledStateGetter: (state) => state.dhcpEnabledState, + ipv6DhcpEnabledStateGetter: (state) => state.ipv6DhcpEnabledState, + ipv6AutoConfigEnabledGetter: (state) => state.ipv6AutoConfigEnabled, + networkSettingsGetter: (state) => state.networkSettings, + selectedInterfaceIdGetter: (state) => state.selectedInterfaceId, + selectedInterfaceIndexGetter: (state) => state.selectedInterfaceIndex, + isTableBusyGetter: (state) => state.isTableBusy, }, actions: { - async setGlobalNetworkSettings(data) { - this.globalNetworkSettings = data.map(({ data }) => { + setNetworkSettings: (data) => { + this.networkSettings = data.map(({ data }) => { const { DHCPv4, + DHCPv6, HostName, + Id, IPv4Addresses, IPv4StaticAddresses, - LinkStatus, + IPv6StaticAddresses, + IPv6Addresses, + IPv6DefaultGateway, + IPv6StaticDefaultGateways, MACAddress, + StaticNameServers, + StatelessAddressAutoConfig, } = data; return { defaultGateway: IPv4StaticAddresses[0]?.Gateway, //First static gateway is the default gateway dhcpAddress: IPv4Addresses.filter( - (ipv4) => ipv4.AddressOrigin === 'DHCP', + (ipv4) => ipv4.AddressOrigin === 'DHCP' ), dhcpEnabled: DHCPv4.DHCPEnabled, hostname: HostName, + id: Id, + ipv4: IPv4Addresses, macAddress: MACAddress, - linkStatus: LinkStatus, staticAddress: IPv4StaticAddresses[0]?.Address, // Display first static address on overview page + staticIpv4Addresses: IPv4StaticAddresses, + staticNameServers: StaticNameServers, useDnsEnabled: DHCPv4.UseDNSServers, useDomainNameEnabled: DHCPv4.UseDomainName, useNtpEnabled: DHCPv4.UseNTPServers, + staticIpv6Addresses: IPv6StaticAddresses ?? [], + ipv6: IPv6Addresses ?? [], + ipv6DefaultGateway: IPv6DefaultGateway ?? '', + ipv6OperatingMode: DHCPv6?.OperatingMode ?? '', + ipv6StaticDefaultGateways: IPv6StaticDefaultGateways ?? [], + ipv6UseDnsEnabled: DHCPv6?.UseDNSServers ?? false, + ipv6UseDomainNameEnabled: DHCPv6?.UseDomainName ?? false, + ipv6UseNtpEnabled: DHCPv6?.UseNTPServers ?? false, + ipv6AutoConfigEnabled: + StatelessAddressAutoConfig?.IPv6AutoConfigEnabled ?? false, }; }); }, @@ -57,141 +75,222 @@ export const NetworkStore = defineStore('network', { .get('/redfish/v1/Managers/bmc/EthernetInterfaces') .then((response) => response.data.Members.map( - (ethernetInterface) => ethernetInterface['@odata.id'], - ), + (ethernetInterface) => ethernetInterface['@odata.id'] + ) ) .then((ethernetInterfaceIds) => api.all( ethernetInterfaceIds.map((ethernetInterface) => - api.get(ethernetInterface), - ), - ), + api.get(ethernetInterface) + ) + ) ) .then((ethernetInterfaces) => { const ethernetData = ethernetInterfaces.map( - (ethernetInterface) => ethernetInterface.data, + (ethernetInterface) => ethernetInterface.data ); - const firstInterfaceId = ethernetData[0].Id; - this.ethernetData = ethernetData; - this.firstInterfaceId = firstInterfaceId; - this.selectedInterfaceId = firstInterfaceId; - this.setGlobalNetworkSettings(ethernetInterfaces); + this.setNetworkSettings(ethernetInterfaces); + let currentInterfaceIndex = 0; + if (this.selectedInterfaceIndex) { + currentInterfaceIndex = this.selectedInterfaceIndex; + } + this.selectedInterfaceId = ethernetData[currentInterfaceIndex].Id; }) .catch((error) => { console.log('Network Data:', error); }); }, - async saveDhcpEnabledState(dhcpState) { + async getEthernetDataAfterDelay() { + this.isTableBusy = true; + setTimeout(() => { + this.getEthernetData(); + }, 10000); + setTimeout(() => { + this.isTableBusy = false; + }, 15000); + }, + async saveDomainNameState(domainState) { + this.domainState = domainState; const data = { DHCPv4: { - DHCPEnabled: dhcpState, + UseDomainName: domainState, }, }; return api .patch( `/redfish/v1/Managers/bmc/EthernetInterfaces/${this.selectedInterfaceId}`, - data, + data ) .then(this.getEthernetData()) .then(() => { return i18n.global.t('pageNetwork.toast.successSaveNetworkSettings', { - setting: i18n.global.t('pageNetwork.dhcp'), + setting: i18n.global.t('pageNetwork.domainName'), }); }) .catch((error) => { console.log(error); + this.domainState = !domainState; throw new Error( i18n.global.t('pageNetwork.toast.errorSaveNetworkSettings', { - setting: i18n.global.t('pageNetwork.dhcp'), - }), + setting: i18n.global.t('pageNetwork.domainName'), + }) ); }); }, - async saveDomainNameState(domainState) { - this.domainState = domainState; + async saveDnsState(dnsState) { + this.dnsState = dnsState; const data = { DHCPv4: { - UseDomainName: domainState, + UseDNSServers: dnsState, }, }; - // Saving to the first interface automatically updates DHCPv4 and DHCPv6 - // on all interfaces return api .patch( - `/redfish/v1/Managers/bmc/EthernetInterfaces/${this.firstInterfaceId}`, - data, + `/redfish/v1/Managers/bmc/EthernetInterfaces/${this.selectedInterfaceId}`, + data ) + .then(this.getEthernetData()) .then(() => { return i18n.global.t('pageNetwork.toast.successSaveNetworkSettings', { - setting: i18n.global.t('pageNetwork.domainName'), + setting: i18n.global.t('pageNetwork.dns'), }); }) .catch((error) => { console.log(error); - this.domainState = !domainState; + this.dnsState = !dnsState; throw new Error( i18n.global.t('pageNetwork.toast.errorSaveNetworkSettings', { - setting: i18n.global.t('pageNetwork.domainName'), - }), + setting: i18n.global.t('pageNetwork.dns'), + }) ); }); }, - async saveDnsState(dnsState) { - this.dnsState = dnsState; + async saveNtpState(ntpState) { + this.ntpState = ntpState; const data = { DHCPv4: { - UseDNSServers: dnsState, + UseNTPServers: ntpState, }, }; - // Saving to the first interface automatically updates DHCPv4 and DHCPv6 - // on all interfaces return api .patch( - `/redfish/v1/Managers/bmc/EthernetInterfaces/${this.firstInterfaceId}`, - data, + `/redfish/v1/Managers/bmc/EthernetInterfaces/${this.selectedInterfaceId}`, + data ) + .then(this.getEthernetData()) .then(() => { return i18n.global.t('pageNetwork.toast.successSaveNetworkSettings', { - setting: i18n.global.t('pageNetwork.dns'), + setting: i18n.global.t('pageNetwork.ntp'), }); }) .catch((error) => { console.log(error); - this.dnsState = !dnsState; + this.ntpState = !ntpState; throw new Error( i18n.global.t('pageNetwork.toast.errorSaveNetworkSettings', { - setting: i18n.global.t('pageNetwork.dns'), - }), + setting: i18n.global.t('pageNetwork.ntp'), + }) ); }); }, - async saveNtpState(ntpState) { - this.ntpState = ntpState; + async saveDhcpEnabledState(dhcpState) { + this.dhcpEnabledState = dhcpState; const data = { DHCPv4: { - UseNTPServers: ntpState, + DHCPEnabled: dhcpState, + }, + }; + return api + .patch( + `/redfish/v1/Managers/bmc/EthernetInterfaces/${this.selectedInterfaceId}`, + data + ) + .then(() => { + // Getting Ethernet data here so that the toggle gets updated + this.getEthernetData(); + // Getting Ethernet data here so that the IPv4 table gets updated + this.getEthernetDataAfterDelay(); + }) + .then(() => { + return i18n.global.t('pageNetwork.toast.successSaveNetworkSettings', { + setting: i18n.global.t('pageNetwork.dhcp'), + }); + }) + .catch((error) => { + console.log(error); + this.dhcpEnabledState = !dhcpState; + throw new Error( + i18n.global.t('pageNetwork.toast.errorSaveNetworkSettings', { + setting: i18n.global.t('pageNetwork.dhcp'), + }) + ); + }); + }, + async saveIpv6DhcpEnabledState(dhcpState) { + const updatedDhcpState = dhcpState ? 'Enabled' : 'Disabled'; + this.ipv6DhcpEnabledState = updatedDhcpState; + const data = { + DHCPv6: { + OperatingMode: updatedDhcpState, }, }; - // Saving to the first interface automatically updates DHCPv4 and DHCPv6 - // on all interfaces return api .patch( - `/redfish/v1/Managers/bmc/EthernetInterfaces/${this.firstInterfaceId}`, - data, + `/redfish/v1/Managers/bmc/EthernetInterfaces/${this.selectedInterfaceId}`, + data ) + .then(() => { + // Getting Ethernet data here so that the toggle gets updated + this.getEthernetData(); + // Getting Ethernet data here so that the IPv6 table gets updated + this.getEthernetDataAfterDelay(); + }) .then(() => { return i18n.global.t('pageNetwork.toast.successSaveNetworkSettings', { - setting: i18n.global.t('pageNetwork.ntp'), + setting: i18n.global.t('pageNetwork.dhcp'), }); }) .catch((error) => { console.log(error); - this.ntpState = !ntpState; + this.ipv6DhcpEnabledState = !dhcpState; throw new Error( i18n.global.t('pageNetwork.toast.errorSaveNetworkSettings', { - setting: i18n.global.t('pageNetwork.ntp'), - }), + setting: i18n.global.t('pageNetwork.dhcp'), + }) + ); + }); + }, + async saveIpv6AutoConfigState(ipv6AutoConfigState) { + this.ipv6AutoConfigEnabled = ipv6AutoConfigState; + const data = { + StatelessAddressAutoConfig: { + IPv6AutoConfigEnabled: ipv6AutoConfigState, + }, + }; + return api + .patch( + `/redfish/v1/Managers/bmc/EthernetInterfaces/${this.selectedInterfaceId}`, + data + ) + .then(() => { + // Getting Ethernet data here so that the toggle gets updated + this.getEthernetData(); + // Getting Ethernet data here so that the IPv6 table gets updated + this.getEthernetDataAfterDelay(); + }) + .then(() => { + return i18n.global.t('pageNetwork.toast.successSaveNetworkSettings', { + setting: i18n.global.t('pageNetwork.ipv6AutoConfig'), + }); + }) + .catch((error) => { + console.log(error); + this.ipv6AutoConfigEnabled = !ipv6AutoConfigState; + throw new Error( + i18n.global.t('pageNetwork.toast.errorSaveNetworkSettings', { + setting: i18n.global.t('pageNetwork.ipv6AutoConfig'), + }) ); }); }, @@ -201,26 +300,31 @@ export const NetworkStore = defineStore('network', { async setSelectedTabId(tabId) { this.selectedInterfaceId = tabId; }, - async saveIpv4Address(ipv4Form) { - const originalAddresses = this.ethernetData[ - this.selectedInterfaceIndex - ].IPv4StaticAddresses.map((ipv4) => { - const { Address, SubnetMask, Gateway } = ipv4; - return { - Address, - SubnetMask, - Gateway, - }; + async updateIpv4Address(newIpv4Address) { + const originalAddresses = + this.networkSettings[this.selectedInterfaceIndex].staticIpv4Addresses; + const updatedIpv4 = originalAddresses.map((item) => { + const address = item.Address; + if (find(newIpv4Address, { Address: address })) { + return null; // if address matches then delete address to "edit" + } else { + return {}; // if address doesn't match then skip address, no change + } }); - const newAddress = [ipv4Form]; + const filteredAddress = newIpv4Address.filter( + (item) => item.Subnet !== '' + ); + const updatedIpv4Array = { + IPv4StaticAddresses: [...updatedIpv4, ...filteredAddress], + }; return api .patch( `/redfish/v1/Managers/bmc/EthernetInterfaces/${this.selectedInterfaceId}`, - { - IPv4StaticAddresses: originalAddresses.concat(newAddress), - }, + updatedIpv4Array ) - .then(this.getEthernetData()) + .then(() => { + this.getEthernetDataAfterDelay(); + }) .then(() => { return i18n.global.t('pageNetwork.toast.successSaveNetworkSettings', { setting: i18n.global.t('pageNetwork.ipv4'), @@ -231,40 +335,199 @@ export const NetworkStore = defineStore('network', { throw new Error( i18n.global.t('pageNetwork.toast.errorSaveNetworkSettings', { setting: i18n.global.t('pageNetwork.ipv4'), - }), + }) ); }); }, - async editIpv4Address(ipv4TableData) { + async updateIpv6Address(newIpv6Address) { + const originalAddresses = + this.networkSettings[this.selectedInterfaceIndex].staticIpv6Addresses; + const updatedIpv6 = originalAddresses.map((item) => { + const address = item.Address; + if (find(newIpv6Address, { Address: address })) { + return null; // if address matches then delete address to "edit" + } else { + return {}; // if address doesn't match then skip address, no change + } + }); + const filteredAddress = newIpv6Address.filter( + (item) => item.PrefixLength !== 0 + ); + const updatedIpv6Array = { + IPv6StaticAddresses: [...updatedIpv6, ...filteredAddress], + }; return api .patch( `/redfish/v1/Managers/bmc/EthernetInterfaces/${this.selectedInterfaceId}`, - { - IPv4StaticAddresses: ipv4TableData, - }, + updatedIpv6Array ) - .then(this.getEthernetData()) + .then(() => { + this.getEthernetDataAfterDelay(); + }) + .then(() => { + return i18n.globalt('pageNetwork.toast.successSaveNetworkSettings', { + setting: i18n.global.t('pageNetwork.ipv6'), + }); + }) + .catch((error) => { + console.log(error); + throw new Error( + i18n.global.t('pageNetwork.toast.errorSaveNetworkSettings', { + setting: i18n.global.t('pageNetwork.ipv6'), + }) + ); + }); + }, + async updateIpv6StaticDefaultGatewayAddress( + newIpv6StaticDefaultGatewayAddress + ) { + const originalAddresses = + this.networkSettings[this.selectedInterfaceIndex] + .ipv6StaticDefaultGateways; + const updatedIpv6 = originalAddresses.map((item) => { + const address = item.Address; + if (find(newIpv6StaticDefaultGatewayAddress, { Address: address })) { + return null; // if address matches then delete address to "edit" + } else { + return {}; // if address doesn't match then skip address, no change + } + }); + const filteredAddress = newIpv6StaticDefaultGatewayAddress.filter( + (item) => item.PrefixLength !== 0 + ); + const updatedIpv6Array = { + IPv6StaticDefaultGateways: [...updatedIpv6, ...filteredAddress], + }; + return api + .patch( + `/redfish/v1/Managers/bmc/EthernetInterfaces/${this.selectedInterfaceId}`, + updatedIpv6Array + ) + .then(() => { + this.getEthernetDataAfterDelay(); + }) .then(() => { return i18n.global.t('pageNetwork.toast.successSaveNetworkSettings', { - setting: i18n.global.t('pageNetwork.ipv4'), + setting: i18n.global.t('pageNetwork.ipv6StaticDefaultGateway'), }); }) .catch((error) => { console.log(error); throw new Error( i18n.global.t('pageNetwork.toast.errorSaveNetworkSettings', { - setting: i18n.global.t('pageNetwork.ipv4'), - }), + setting: i18n.global.t('pageNetwork.ipv6StaticDefaultGateway'), + }) ); }); }, - async saveSettings(interfaceSettingsForm) { + async deleteIpv4Address(updatedIpv4Array) { + const originalAddressArray = + this.networkSettings[this.selectedInterfaceIndex].staticIpv4Addresses; + const newIpv4Array = originalAddressArray.map((item) => { + const address = item.Address; + if (find(updatedIpv4Array, { Address: address })) { + return {}; //return addresses that match the updated array + } else { + return null; // delete address that do not match updated array + } + }); + return api .patch( `/redfish/v1/Managers/bmc/EthernetInterfaces/${this.selectedInterfaceId}`, - interfaceSettingsForm, + { IPv4StaticAddresses: newIpv4Array } + ) + .then(() => { + // Getting Ethernet data here so that the address is deleted immediately + this.getEthernetData(); + // Getting Ethernet data here so that the IPv4 table gets updated + this.getEthernetDataAfterDelay(); + }) + .then(() => { + return i18n.global.t('pageNetwork.toast.successDeletingIpv4Server'); + }) + .catch((error) => { + console.log(error); + throw new Error( + i18n.global.t('pageNetwork.toast.errorDeletingIpv4Server') + ); + }); + }, + async deleteIpv6Address(updatedIpv6Array) { + const originalAddressArray = + this.networkSettings[this.selectedInterfaceIndex].staticIpv6Addresses; + const newIpv6Array = originalAddressArray.map((item) => { + const address = item.Address; + if (find(updatedIpv6Array, { Address: address })) { + return {}; //return addresses that match the updated array + } else { + return null; // delete address that do not match updated array + } + }); + return api + .patch( + `/redfish/v1/Managers/bmc/EthernetInterfaces/${this.selectedInterfaceId}`, + { IPv6StaticAddresses: newIpv6Array } + ) + .then(() => { + // Getting Ethernet data here so that the address is deleted immediately + this.getEthernetData(); + // Getting Ethernet data here so that the IPv6 table gets updated + this.getEthernetDataAfterDelay(); + }) + .then(() => { + return i18n.global.t('pageNetwork.toast.successDeletingIpv6Server'); + }) + .catch((error) => { + console.log(error); + throw new Error( + i18n.global.t('pageNetwork.toast.errorDeletingIpv6Server') + ); + }); + }, + async deleteIpv6StaticDefaultGatewayAddress(updatedIpv6Array) { + const originalAddressArray = + this.networkSettings[this.selectedInterfaceIndex] + .ipv6StaticDefaultGateways; + const newIpv6Array = originalAddressArray.map((item) => { + const address = item.Address; + if (find(updatedIpv6Array, { Address: address })) { + return {}; //return addresses that match the updated array + } else { + return null; // delete address that do not match updated array + } + }); + return api + .patch( + `/redfish/v1/Managers/bmc/EthernetInterfaces/${this.selectedInterfaceId}`, + { IPv6StaticDefaultGateways: newIpv6Array } + ) + .then(() => { + // Getting Ethernet data here so that the address is deleted immediately + this.getEthernetData(); + // Getting Ethernet data here so that the table gets updated + this.getEthernetDataAfterDelay(); + }) + .then(() => { + return i18n.global.t( + 'pageNetwork.toast.successDeletingIpv6StaticDefaultGateway' + ); + }) + .catch((error) => { + console.log(error); + throw new Error( + i18n.global.t( + 'pageNetwork.toast.errorDeletingIpv6StaticDefaultGateway' + ) + ); + }); + }, + async saveHostname(hostname) { + return api + .patch( + `/redfish/v1/Managers/bmc/EthernetInterfaces/${this.selectedInterfaceId}`, + hostname ) - .then(this.getEthernetData()) .then(() => { return i18n.global.t('pageNetwork.toast.successSaveNetworkSettings', { setting: i18n.global.t('pageNetwork.network'), @@ -275,34 +538,28 @@ export const NetworkStore = defineStore('network', { throw new Error( i18n.global.t('pageNetwork.toast.errorSaveNetworkSettings', { setting: i18n.global.t('pageNetwork.network'), - }), + }) ); }); }, async saveDnsAddress(dnsForm) { const newAddress = dnsForm; const originalAddresses = - this.ethernetData[this.selectedInterfaceIndex].StaticNameServers; + this.networkSettings[this.selectedInterfaceIndex].staticNameServers; const newDnsArray = originalAddresses.concat(newAddress); return api .patch( `/redfish/v1/Managers/bmc/EthernetInterfaces/${this.selectedInterfaceId}`, - { - StaticNameServers: newDnsArray, - }, + { StaticNameServers: newDnsArray } ) .then(this.getEthernetData()) .then(() => { - return i18n.global.t('pageNetwork.toast.successSaveNetworkSettings', { - setting: i18n.global.t('pageNetwork.dns'), - }); + return i18n.global.t('pageNetwork.toast.successAddingDnsServer'); }) .catch((error) => { console.log(error); throw new Error( - i18n.global.t('pageNetwork.toast.errorSaveNetworkSettings', { - setting: i18n.global.t('pageNetwork.dns'), - }), + i18n.global.t('pageNetwork.toast.errorAddingDnsServer') ); }); }, @@ -310,22 +567,16 @@ export const NetworkStore = defineStore('network', { return api .patch( `/redfish/v1/Managers/bmc/EthernetInterfaces/${this.selectedInterfaceId}`, - { - StaticNameServers: dnsTableData, - }, + { StaticNameServers: dnsTableData } ) .then(this.getEthernetData()) .then(() => { - return i18n.global.t('pageNetwork.toast.successSaveNetworkSettings', { - setting: i18n.global.t('pageNetwork.dns'), - }); + return i18n.global.t('pageNetwork.toast.successDeletingDnsServer'); }) .catch((error) => { console.log(error); throw new Error( - i18n.global.t('pageNetwork.toast.errorSaveNetworkSettings', { - setting: i18n.global.t('pageNetwork.dns'), - }), + i18n.global.t('pageNetwork.toast.errorDeletingDnsServer') ); }); }, diff --git a/src/store/plugins/WebSocketPlugin.js b/src/store/plugins/WebSocketPlugin.js index f50e8608dc..e7699d6d3b 100644 --- a/src/store/plugins/WebSocketPlugin.js +++ b/src/store/plugins/WebSocketPlugin.js @@ -1,3 +1,5 @@ +import JSONbig from 'json-bigint'; +import { AuthenticationStore, GlobalStore, EventLogStore } from '@/store'; /** * WebSocketPlugin will allow us to get new data from the server * without having to poll for changes on the frontend. @@ -7,73 +9,81 @@ * * https://github.com/openbmc/docs/blob/b41aff0fabe137cdb0cfff584b5fe4a41c0c8e77/rest-api.md#event-subscription-protocol */ -const WebSocketPlugin = (store) => { - let ws; - const data = { - paths: [ - '/xyz/openbmc_project/state/host0', - '/xyz/openbmc_project/logging', - '/xyz/openbmc_project/state/boot/raw0', - ], - interfaces: [ - 'xyz.openbmc_project.State.Host', - 'xyz.openbmc_project.Logging.Entry', - 'xyz.openbmc_project.State.Boot.Raw', - ], - }; - const initWebSocket = () => { - const socketDisabled = - process.env.VUE_APP_SUBSCRIBE_SOCKET_DISABLED === 'true' ? true : false; - if (socketDisabled) return; - const token = store.getters['authentication/token']; - var host = - window.location.origin.replace('https://', '') + window.location.pathname; - host = host.replace(/\/$/, ''); - ws = new WebSocket(`wss://${host}/subscribe`, [token]); - ws.onopen = () => { - ws.send(JSON.stringify(data)); - }; - ws.onerror = (event) => { - console.error(event); - }; - ws.onmessage = (event) => { - var JSONbig = require('json-bigint'); - var data = JSONbig.parse(event.data); - const eventInterface = data.interface; - const path = data.path; - if (eventInterface === 'xyz.openbmc_project.State.Boot.Raw') { - if (path === '/xyz/openbmc_project/state/boot/raw0') { - const { properties: { Value } = {} } = data; - if (Value) { - if (Array.isArray(Value) && Value.length) { - var finalValue = Value[0].c.join(''); - } - store.commit('global/setPostCodeValue', finalValue); +let ws; +const data = { + paths: [ + '/xyz/openbmc_project/state/host0', + '/xyz/openbmc_project/logging', + '/xyz/openbmc_project/state/boot/raw0', + ], + interfaces: [ + 'xyz.openbmc_project.State.Host', + 'xyz.openbmc_project.Logging.Entry', + 'xyz.openbmc_project.State.Boot.Raw', + ], +}; + +export const initWebSocket = () => { + const globalStore = GlobalStore(); + const authenticationStore = AuthenticationStore(); + const eventLogStore = EventLogStore(); + + const socketDisabled = + import.meta.env.VITE_APP_SUBSCRIBE_SOCKET_DISABLED === 'true' + ? true + : false; + + if (socketDisabled) return; + + const token = authenticationStore.token; + + var host = window.location.origin.replace('https://', ''); + host = host.replace(/\/$/, ''); + ws = new WebSocket(`wss://${host}/subscribe`, [token]); + ws.onopen = () => { + ws.send(JSON.stringify(data)); + }; + ws.onerror = (event) => { + console.error(event); + }; + ws.onmessage = (event) => { + var data = JSONbig.parse(event.data); + const eventInterface = data.interface; + const path = data.path; + if (eventInterface === 'xyz.openbmc_project.State.Boot.Raw') { + if (path === '/xyz/openbmc_project/state/boot/raw0') { + const { properties: { Value } = {} } = data; + if (Value) { + if (Array.isArray(Value) && Value.length) { + var finalValue = Value[0].c.join(''); } + globalStore.postCodeValue = finalValue; } } - if (eventInterface === 'xyz.openbmc_project.State.Host') { - const { properties: { CurrentHostState } = {} } = data; - if (CurrentHostState) { - store.commit('global/setServerStatus', CurrentHostState); - } - } else if (path === '/xyz/openbmc_project/logging') { - store.dispatch('eventLog/getEventLogData'); + } + if (eventInterface === 'xyz.openbmc_project.State.Host') { + const { properties: { CurrentHostState } = {} } = data; + if (CurrentHostState) { + globalStore.serverStatus = CurrentHostState; } - }; + } else if (path === '/xyz/openbmc_project/logging') { + eventLogStore.getEventLogData(); + } }; +}; - store.subscribe(({ type }) => { - if (type === 'authentication/authSuccess') { - initWebSocket(); - } - if (type === 'authentication/logout') { - if (ws) ws.close(); - } +function WebSocketPlugin({ store }) { + store.$onAction(({ name, _, after }) => { + after(() => { + if (name === 'authSuccess') { + initWebSocket(); + } + if (name === 'logout') { + if (ws) ws.close(); + } + }); }); - - if (store.getters['authentication/isLoggedIn']) initWebSocket(); -}; +} export default WebSocketPlugin; diff --git a/src/views/Operations/ServerPowerOperations/BiosSettings.vue b/src/views/Operations/ServerPowerOperations/BiosSettings.vue index 7f20c2f30a..68dab4df7c 100644 --- a/src/views/Operations/ServerPowerOperations/BiosSettings.vue +++ b/src/views/Operations/ServerPowerOperations/BiosSettings.vue @@ -1,8 +1,8 @@ - - - + + - - - + - - - + + + + + + {{ $t('pageServerPowerOperations.biosSettings.powerSettingDescription') }} - - - + + {{ $t('pageServerPowerOperations.biosSettings.serverFirmware') }} - - + - - + - - + - - + {{ $t( - 'pageServerPowerOperations.biosSettings.pvm_ibmi_load_source', + 'pageServerPowerOperations.biosSettings.pvm_ibmi_load_source' ) }} ({{ $t('pageServerPowerOperations.biosSettings.nonHMCManaged') }}) - - + {{ $t( - 'pageServerPowerOperations.biosSettings.pvm_ibmi_alt_load_source', + 'pageServerPowerOperations.biosSettings.pvm_ibmi_alt_load_source' ) }} ({{ $t('pageServerPowerOperations.biosSettings.nonHMCManaged') }}) - - + - - + {{ $t( - 'pageServerPowerOperations.biosSettings.pvm_linux_kvm_memory', + 'pageServerPowerOperations.biosSettings.pvm_linux_kvm_memory' ) }} ({{ $t('pageServerPowerOperations.biosSettings.nonHMCManaged') }}) - - + {{ $t( - 'pageServerPowerOperations.biosSettings.pvm_linux_kvm_percentage', + 'pageServerPowerOperations.biosSettings.pvm_linux_kvm_percentage' ) }} ({{ $t('pageServerPowerOperations.biosSettings.nonHMCManaged') }}) - - - - + + + + - - diff --git a/src/views/Operations/ServerPowerOperations/BootSettings.vue b/src/views/Operations/ServerPowerOperations/BootSettings.vue index 4bfd49db8d..d4c0c55fca 100644 --- a/src/views/Operations/ServerPowerOperations/BootSettings.vue +++ b/src/views/Operations/ServerPowerOperations/BootSettings.vue @@ -1,5 +1,5 @@ - diff --git a/src/views/Operations/ServerPowerOperations/NetworkSettingsModal.vue b/src/views/Operations/ServerPowerOperations/NetworkSettingsModal.vue index 8ce5e5e5ac..bc001b0a82 100644 --- a/src/views/Operations/ServerPowerOperations/NetworkSettingsModal.vue +++ b/src/views/Operations/ServerPowerOperations/NetworkSettingsModal.vue @@ -1,7 +1,7 @@ - diff --git a/src/views/Operations/ServerPowerOperations/ServerPowerOperations.vue b/src/views/Operations/ServerPowerOperations/ServerPowerOperations.vue index 3acd1bc28c..4657360c1d 100644 --- a/src/views/Operations/ServerPowerOperations/ServerPowerOperations.vue +++ b/src/views/Operations/ServerPowerOperations/ServerPowerOperations.vue @@ -1,444 +1,518 @@ - diff --git a/src/views/Overview/OverviewNetwork.vue b/src/views/Overview/OverviewNetwork.vue index 7b1bf79171..c3934012bc 100644 --- a/src/views/Overview/OverviewNetwork.vue +++ b/src/views/Overview/OverviewNetwork.vue @@ -38,7 +38,7 @@ dataFormatterGlobal.dataFormatter( network.dhcpAddress.length !== 0 ? network.dhcpAddress[0].Address - : null, + : null ) }} @@ -60,6 +60,7 @@ const dataFormatterGlobal = useDataFormatterGlobal(); const networkStore = NetworkStore(); networkStore.getEthernetData(); const network = computed(() => { - return networkStore.globalNetworkSettings[0]; + // Commenting this line out. Will be implemented once overview page is completed + // return networkStore.globalNetworkSettings[0]; }); diff --git a/vite.config.js b/vite.config.js index 16dfa3e44e..657965c2e1 100644 --- a/vite.config.js +++ b/vite.config.js @@ -58,7 +58,7 @@ export default defineConfig({ // locale messages resource pre-compile option include: resolve( dirname(fileURLToPath(import.meta.url)), - './path/to/src/locales/**', + './path/to/src/locales/**' ), }), ], @@ -98,7 +98,7 @@ export default defineConfig({ const setCookieHeader = proxyRes.headers['set-cookie']; if (setCookieHeader) { proxyRes.headers['set-cookie'] = setCookieHeader.map( - (cookie) => cookie + '; Path=/', + (cookie) => cookie + '; Path=/' ); } // Remove the 'strict-transport-security' header @@ -148,7 +148,7 @@ export default defineConfig({ // eslint-disable-next-line no-undef new CompressionPlugin({ deleteOriginalAssets: true, - }), + }) ); }