diff --git a/package-lock.json b/package-lock.json
index 801b5141..5ebd1426 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17,7 +17,7 @@
"@patternfly/react-table": "^6.0.0",
"axios": "^1.7.7",
"js-yaml": "^4.1.0",
- "next": "^14.2.15",
+ "next": "^15.0.2",
"next-auth": "^4.24.10",
"node-fetch": "^3.3.2",
"react": "18.3.1",
@@ -341,6 +341,15 @@
"kuler": "^2.0.0"
}
},
+ "node_modules/@emnapi/runtime": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.3.1.tgz",
+ "integrity": "sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
"node_modules/@eslint-community/eslint-utils": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
@@ -560,6 +569,348 @@
"dev": true,
"license": "BSD-3-Clause"
},
+ "node_modules/@img/sharp-darwin-arm64": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz",
+ "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-darwin-arm64": "1.0.4"
+ }
+ },
+ "node_modules/@img/sharp-darwin-x64": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz",
+ "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-darwin-x64": "1.0.4"
+ }
+ },
+ "node_modules/@img/sharp-libvips-darwin-arm64": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz",
+ "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-darwin-x64": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz",
+ "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-arm": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz",
+ "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==",
+ "cpu": [
+ "arm"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-arm64": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz",
+ "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-s390x": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz",
+ "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==",
+ "cpu": [
+ "s390x"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-x64": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz",
+ "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linuxmusl-arm64": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz",
+ "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linuxmusl-x64": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz",
+ "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-linux-arm": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz",
+ "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==",
+ "cpu": [
+ "arm"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-arm": "1.0.5"
+ }
+ },
+ "node_modules/@img/sharp-linux-arm64": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz",
+ "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-arm64": "1.0.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-s390x": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz",
+ "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==",
+ "cpu": [
+ "s390x"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-s390x": "1.0.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-x64": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz",
+ "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-x64": "1.0.4"
+ }
+ },
+ "node_modules/@img/sharp-linuxmusl-arm64": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz",
+ "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linuxmusl-arm64": "1.0.4"
+ }
+ },
+ "node_modules/@img/sharp-linuxmusl-x64": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz",
+ "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linuxmusl-x64": "1.0.4"
+ }
+ },
+ "node_modules/@img/sharp-wasm32": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz",
+ "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==",
+ "cpu": [
+ "wasm32"
+ ],
+ "optional": true,
+ "dependencies": {
+ "@emnapi/runtime": "^1.2.0"
+ },
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-win32-ia32": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz",
+ "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-win32-x64": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz",
+ "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
@@ -676,9 +1027,9 @@
}
},
"node_modules/@next/swc-darwin-arm64": {
- "version": "14.2.15",
- "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.15.tgz",
- "integrity": "sha512-Rvh7KU9hOUBnZ9TJ28n2Oa7dD9cvDBKua9IKx7cfQQ0GoYUwg9ig31O2oMwH3wm+pE3IkAQ67ZobPfEgurPZIA==",
+ "version": "15.0.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.0.2.tgz",
+ "integrity": "sha512-GK+8w88z+AFlmt+ondytZo2xpwlfAR8U6CRwXancHImh6EdGfHMIrTSCcx5sOSBei00GyLVL0ioo1JLKTfprgg==",
"cpu": [
"arm64"
],
@@ -691,9 +1042,9 @@
}
},
"node_modules/@next/swc-darwin-x64": {
- "version": "14.2.15",
- "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.15.tgz",
- "integrity": "sha512-5TGyjFcf8ampZP3e+FyCax5zFVHi+Oe7sZyaKOngsqyaNEpOgkKB3sqmymkZfowy3ufGA/tUgDPPxpQx931lHg==",
+ "version": "15.0.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.0.2.tgz",
+ "integrity": "sha512-KUpBVxIbjzFiUZhiLIpJiBoelqzQtVZbdNNsehhUn36e2YzKHphnK8eTUW1s/4aPy5kH/UTid8IuVbaOpedhpw==",
"cpu": [
"x64"
],
@@ -706,9 +1057,9 @@
}
},
"node_modules/@next/swc-linux-arm64-gnu": {
- "version": "14.2.15",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.15.tgz",
- "integrity": "sha512-3Bwv4oc08ONiQ3FiOLKT72Q+ndEMyLNsc/D3qnLMbtUYTQAmkx9E/JRu0DBpHxNddBmNT5hxz1mYBphJ3mfrrw==",
+ "version": "15.0.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.0.2.tgz",
+ "integrity": "sha512-9J7TPEcHNAZvwxXRzOtiUvwtTD+fmuY0l7RErf8Yyc7kMpE47MIQakl+3jecmkhOoIyi/Rp+ddq7j4wG6JDskQ==",
"cpu": [
"arm64"
],
@@ -721,9 +1072,9 @@
}
},
"node_modules/@next/swc-linux-arm64-musl": {
- "version": "14.2.15",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.15.tgz",
- "integrity": "sha512-k5xf/tg1FBv/M4CMd8S+JL3uV9BnnRmoe7F+GWC3DxkTCD9aewFRH1s5rJ1zkzDa+Do4zyN8qD0N8c84Hu96FQ==",
+ "version": "15.0.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.0.2.tgz",
+ "integrity": "sha512-BjH4ZSzJIoTTZRh6rG+a/Ry4SW0HlizcPorqNBixBWc3wtQtj4Sn9FnRZe22QqrPnzoaW0ctvSz4FaH4eGKMww==",
"cpu": [
"arm64"
],
@@ -736,9 +1087,9 @@
}
},
"node_modules/@next/swc-linux-x64-gnu": {
- "version": "14.2.15",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.15.tgz",
- "integrity": "sha512-kE6q38hbrRbKEkkVn62reLXhThLRh6/TvgSP56GkFNhU22TbIrQDEMrO7j0IcQHcew2wfykq8lZyHFabz0oBrA==",
+ "version": "15.0.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.0.2.tgz",
+ "integrity": "sha512-i3U2TcHgo26sIhcwX/Rshz6avM6nizrZPvrDVDY1bXcLH1ndjbO8zuC7RoHp0NSK7wjJMPYzm7NYL1ksSKFreA==",
"cpu": [
"x64"
],
@@ -751,9 +1102,9 @@
}
},
"node_modules/@next/swc-linux-x64-musl": {
- "version": "14.2.15",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.15.tgz",
- "integrity": "sha512-PZ5YE9ouy/IdO7QVJeIcyLn/Rc4ml9M2G4y3kCM9MNf1YKvFY4heg3pVa/jQbMro+tP6yc4G2o9LjAz1zxD7tQ==",
+ "version": "15.0.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.0.2.tgz",
+ "integrity": "sha512-AMfZfSVOIR8fa+TXlAooByEF4OB00wqnms1sJ1v+iu8ivwvtPvnkwdzzFMpsK5jA2S9oNeeQ04egIWVb4QWmtQ==",
"cpu": [
"x64"
],
@@ -766,9 +1117,9 @@
}
},
"node_modules/@next/swc-win32-arm64-msvc": {
- "version": "14.2.15",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.15.tgz",
- "integrity": "sha512-2raR16703kBvYEQD9HNLyb0/394yfqzmIeyp2nDzcPV4yPjqNUG3ohX6jX00WryXz6s1FXpVhsCo3i+g4RUX+g==",
+ "version": "15.0.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.0.2.tgz",
+ "integrity": "sha512-JkXysDT0/hEY47O+Hvs8PbZAeiCQVxKfGtr4GUpNAhlG2E0Mkjibuo8ryGD29Qb5a3IOnKYNoZlh/MyKd2Nbww==",
"cpu": [
"arm64"
],
@@ -780,25 +1131,10 @@
"node": ">= 10"
}
},
- "node_modules/@next/swc-win32-ia32-msvc": {
- "version": "14.2.15",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.15.tgz",
- "integrity": "sha512-fyTE8cklgkyR1p03kJa5zXEaZ9El+kDNM5A+66+8evQS5e/6v0Gk28LqA0Jet8gKSOyP+OTm/tJHzMlGdQerdQ==",
- "cpu": [
- "ia32"
- ],
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
"node_modules/@next/swc-win32-x64-msvc": {
- "version": "14.2.15",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.15.tgz",
- "integrity": "sha512-SzqGbsLsP9OwKNUG9nekShTwhj6JSB9ZLMWQ8g1gG6hdE5gQLncbnbymrwy2yVmH9nikSLYRYxYMFu78Ggp7/g==",
+ "version": "15.0.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.0.2.tgz",
+ "integrity": "sha512-foaUL0NqJY/dX0Pi/UcZm5zsmSk5MtP/gxx3xOPyREkMFN+CTjctPfu3QaqrQHinaKdPnMWPJDKt4VjDfTBe/Q==",
"cpu": [
"x64"
],
@@ -1070,16 +1406,13 @@
"node_modules/@swc/counter": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
- "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==",
- "license": "Apache-2.0"
+ "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ=="
},
"node_modules/@swc/helpers": {
- "version": "0.5.5",
- "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz",
- "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==",
- "license": "Apache-2.0",
+ "version": "0.5.13",
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.13.tgz",
+ "integrity": "sha512-UoKGxQ3r5kYI9dALKJapMmuK+1zWM/H17Z1+iwnNmzcJRnfFuevZs375TA5rW31pu4BS4NoSy1fRsexDXfWn5w==",
"dependencies": {
- "@swc/counter": "^0.1.3",
"tslib": "^2.4.0"
}
},
@@ -1839,8 +2172,7 @@
"node_modules/client-only": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
- "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
- "license": "MIT"
+ "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
},
"node_modules/color": {
"version": "3.2.1",
@@ -2116,6 +2448,15 @@
"node": ">=0.4.0"
}
},
+ "node_modules/detect-libc": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
+ "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
+ "optional": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/dir-glob": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
@@ -3731,6 +4072,7 @@
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "dev": true,
"license": "ISC"
},
"node_modules/graphemer": {
@@ -4686,40 +5028,41 @@
"license": "MIT"
},
"node_modules/next": {
- "version": "14.2.15",
- "resolved": "https://registry.npmjs.org/next/-/next-14.2.15.tgz",
- "integrity": "sha512-h9ctmOokpoDphRvMGnwOJAedT6zKhwqyZML9mDtspgf4Rh3Pn7UTYKqePNoDvhsWBAO5GoPNYshnAUGIazVGmw==",
+ "version": "15.0.2",
+ "resolved": "https://registry.npmjs.org/next/-/next-15.0.2.tgz",
+ "integrity": "sha512-rxIWHcAu4gGSDmwsELXacqAPUk+j8dV/A9cDF5fsiCMpkBDYkO2AEaL1dfD+nNmDiU6QMCFN8Q30VEKapT9UHQ==",
"dependencies": {
- "@next/env": "14.2.15",
- "@swc/helpers": "0.5.5",
+ "@next/env": "15.0.2",
+ "@swc/counter": "0.1.3",
+ "@swc/helpers": "0.5.13",
"busboy": "1.6.0",
"caniuse-lite": "^1.0.30001579",
- "graceful-fs": "^4.2.11",
"postcss": "8.4.31",
- "styled-jsx": "5.1.1"
+ "styled-jsx": "5.1.6"
},
"bin": {
"next": "dist/bin/next"
},
"engines": {
- "node": ">=18.17.0"
+ "node": ">=18.18.0"
},
"optionalDependencies": {
- "@next/swc-darwin-arm64": "14.2.15",
- "@next/swc-darwin-x64": "14.2.15",
- "@next/swc-linux-arm64-gnu": "14.2.15",
- "@next/swc-linux-arm64-musl": "14.2.15",
- "@next/swc-linux-x64-gnu": "14.2.15",
- "@next/swc-linux-x64-musl": "14.2.15",
- "@next/swc-win32-arm64-msvc": "14.2.15",
- "@next/swc-win32-ia32-msvc": "14.2.15",
- "@next/swc-win32-x64-msvc": "14.2.15"
+ "@next/swc-darwin-arm64": "15.0.2",
+ "@next/swc-darwin-x64": "15.0.2",
+ "@next/swc-linux-arm64-gnu": "15.0.2",
+ "@next/swc-linux-arm64-musl": "15.0.2",
+ "@next/swc-linux-x64-gnu": "15.0.2",
+ "@next/swc-linux-x64-musl": "15.0.2",
+ "@next/swc-win32-arm64-msvc": "15.0.2",
+ "@next/swc-win32-x64-msvc": "15.0.2",
+ "sharp": "^0.33.5"
},
"peerDependencies": {
"@opentelemetry/api": "^1.1.0",
"@playwright/test": "^1.41.2",
- "react": "^18.2.0",
- "react-dom": "^18.2.0",
+ "babel-plugin-react-compiler": "*",
+ "react": "^18.2.0 || 19.0.0-rc-02c0e824-20241028",
+ "react-dom": "^18.2.0 || 19.0.0-rc-02c0e824-20241028",
"sass": "^1.3.0"
},
"peerDependenciesMeta": {
@@ -4729,6 +5072,9 @@
"@playwright/test": {
"optional": true
},
+ "babel-plugin-react-compiler": {
+ "optional": true
+ },
"sass": {
"optional": true
}
@@ -4774,11 +5120,6 @@
"uuid": "dist/bin/uuid"
}
},
- "node_modules/next/node_modules/@next/env": {
- "version": "14.2.15",
- "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.15.tgz",
- "integrity": "sha512-S1qaj25Wru2dUpcIZMjxeMVSwkt8BK4dmWHHiBuRstcIyOsMapqT4A4jSB6onvqeygkSSmOkyny9VVx8JIGamQ=="
- },
"node_modules/next/node_modules/postcss": {
"version": "8.4.31",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
@@ -5750,6 +6091,88 @@
"node": ">= 0.4"
}
},
+ "node_modules/sharp": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz",
+ "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==",
+ "hasInstallScript": true,
+ "optional": true,
+ "dependencies": {
+ "color": "^4.2.3",
+ "detect-libc": "^2.0.3",
+ "semver": "^7.6.3"
+ },
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-darwin-arm64": "0.33.5",
+ "@img/sharp-darwin-x64": "0.33.5",
+ "@img/sharp-libvips-darwin-arm64": "1.0.4",
+ "@img/sharp-libvips-darwin-x64": "1.0.4",
+ "@img/sharp-libvips-linux-arm": "1.0.5",
+ "@img/sharp-libvips-linux-arm64": "1.0.4",
+ "@img/sharp-libvips-linux-s390x": "1.0.4",
+ "@img/sharp-libvips-linux-x64": "1.0.4",
+ "@img/sharp-libvips-linuxmusl-arm64": "1.0.4",
+ "@img/sharp-libvips-linuxmusl-x64": "1.0.4",
+ "@img/sharp-linux-arm": "0.33.5",
+ "@img/sharp-linux-arm64": "0.33.5",
+ "@img/sharp-linux-s390x": "0.33.5",
+ "@img/sharp-linux-x64": "0.33.5",
+ "@img/sharp-linuxmusl-arm64": "0.33.5",
+ "@img/sharp-linuxmusl-x64": "0.33.5",
+ "@img/sharp-wasm32": "0.33.5",
+ "@img/sharp-win32-ia32": "0.33.5",
+ "@img/sharp-win32-x64": "0.33.5"
+ }
+ },
+ "node_modules/sharp/node_modules/color": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
+ "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
+ "optional": true,
+ "dependencies": {
+ "color-convert": "^2.0.1",
+ "color-string": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=12.5.0"
+ }
+ },
+ "node_modules/sharp/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "optional": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/sharp/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "optional": true
+ },
+ "node_modules/sharp/node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "optional": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -6083,10 +6506,9 @@
}
},
"node_modules/styled-jsx": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz",
- "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==",
- "license": "MIT",
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz",
+ "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==",
"dependencies": {
"client-only": "0.0.1"
},
@@ -6094,7 +6516,7 @@
"node": ">= 12.0.0"
},
"peerDependencies": {
- "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0"
+ "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0"
},
"peerDependenciesMeta": {
"@babel/core": {
diff --git a/package.json b/package.json
index d0e7c798..1f60f2fd 100644
--- a/package.json
+++ b/package.json
@@ -25,7 +25,7 @@
"@patternfly/react-table": "^6.0.0",
"axios": "^1.7.7",
"js-yaml": "^4.1.0",
- "next": "^14.2.15",
+ "next": "^15.0.2",
"next-auth": "^4.24.10",
"node-fetch": "^3.3.2",
"react": "18.3.1",
diff --git a/public/default-avatar.png b/public/default-avatar.png
new file mode 100644
index 00000000..b87ded01
Binary files /dev/null and b/public/default-avatar.png differ
diff --git a/public/default-avatar.svg b/public/default-avatar.svg
new file mode 100644
index 00000000..73726f9b
--- /dev/null
+++ b/public/default-avatar.svg
@@ -0,0 +1,18 @@
+
+
+
diff --git a/src/app/edit-submission/knowledge/[id]/page.tsx b/src/app/edit-submission/knowledge/[id]/page.tsx
index 50e5f678..55b25ce4 100644
--- a/src/app/edit-submission/knowledge/[id]/page.tsx
+++ b/src/app/edit-submission/knowledge/[id]/page.tsx
@@ -1,179 +1,19 @@
// src/app/edit-submission/knowledge/[id]/page.tsx
-'use client';
-
import * as React from 'react';
-import { useSession } from 'next-auth/react';
-import { AppLayout } from '../../../../components/AppLayout';
-import { AttributionData, PullRequestFile, KnowledgeYamlData } from '@/types';
-import { KnowledgeSchemaVersion } from '@/types/const';
-import { fetchPullRequest, fetchFileContent, fetchPullRequestFiles } from '../../../../utils/github';
-import yaml from 'js-yaml';
-import axios from 'axios';
-import KnowledgeForm, { KnowledgeEditFormData, KnowledgeFormData, QuestionAndAnswerPair, SeedExample } from '@/components/Contribute/Knowledge';
-import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants';
-import { useEffect, useState } from 'react';
-import { Modal, ModalVariant } from '@patternfly/react-core/dist/esm/components/Modal/Modal';
-import { useRouter } from 'next/navigation';
-
-const EditKnowledgePage: React.FunctionComponent<{ params: { id: string } }> = ({ params }) => {
- const { data: session } = useSession();
- const [isLoading, setIsLoading] = useState(true);
- const [loadingMsg, setLoadingMsg] = useState('');
- const [knowledgeEditFormData, setKnowledgeEditFormData] = useState();
- const prNumber = parseInt(params.id, 10);
- const router = useRouter();
-
- useEffect(() => {
- setLoadingMsg('Fetching knowledge data from PR : ' + prNumber);
- const fetchPRData = async () => {
- if (session?.accessToken) {
- try {
- const prData = await fetchPullRequest(session.accessToken, prNumber);
-
- // Create KnowledgeFormData from existing form.
- const knowledgeExistingFormData: KnowledgeFormData = {
- email: '',
- name: '',
- submissionSummary: '',
- domain: '',
- documentOutline: '',
- filePath: '',
- seedExamples: [],
- knowledgeDocumentRepositoryUrl: '',
- knowledgeDocumentCommit: '',
- documentName: '',
- titleWork: '',
- linkWork: '',
- revision: '',
- licenseWork: '',
- creators: ''
- };
-
- const knowledgeEditFormData: KnowledgeEditFormData = {
- isEditForm: true,
- knowledgeVersion: KnowledgeSchemaVersion,
- branchName: '',
- knowledgeFormData: knowledgeExistingFormData,
- pullRequestNumber: prNumber,
- yamlFile: { filename: '' },
- attributionFile: { filename: '' }
- };
-
- knowledgeExistingFormData.submissionSummary = prData.title;
- knowledgeEditFormData.branchName = prData.head.ref; // Store the branch name from the pull request
-
- const prFiles: PullRequestFile[] = await fetchPullRequestFiles(session.accessToken, prNumber);
-
- const foundYamlFile = prFiles.find((file: PullRequestFile) => file.filename.endsWith('.yaml'));
- if (!foundYamlFile) {
- throw new Error('No YAML file found in the pull request.');
- }
- knowledgeEditFormData.yamlFile = foundYamlFile;
-
- const yamlContent = await fetchFileContent(session.accessToken, foundYamlFile.filename, prData.head.sha);
- const yamlData: KnowledgeYamlData = yaml.load(yamlContent) as KnowledgeYamlData;
- console.log('Parsed YAML data:', yamlData);
+import { AppLayout } from '@/components/AppLayout';
+import EditKnowledge from '@/components/Contribute/EditKnowledge/EditKnowledge';
- // Populate the form fields with YAML data
- knowledgeExistingFormData.documentOutline = yamlData.document_outline;
- knowledgeExistingFormData.domain = yamlData.domain;
- knowledgeExistingFormData.knowledgeDocumentRepositoryUrl = yamlData.document.repo;
- knowledgeExistingFormData.knowledgeDocumentCommit = yamlData.document.commit;
- knowledgeExistingFormData.documentName = yamlData.document.patterns.join(', ');
-
- const seedExamples: SeedExample[] = [];
- yamlData.seed_examples.forEach((seed, index) => {
- // iterate through questions_and_answers and create a new object for each
- const example: SeedExample = {
- immutable: index < 5 ? true : false,
- isExpanded: true,
- context: seed.context,
- isContextValid: ValidatedOptions.success,
- questionAndAnswers: []
- };
-
- const qnaExamples: QuestionAndAnswerPair[] = seed.questions_and_answers.map((qa, index) => {
- const qna: QuestionAndAnswerPair = {
- question: qa.question,
- answer: qa.answer,
- immutable: index < 3 ? true : false,
- isQuestionValid: ValidatedOptions.success,
- isAnswerValid: ValidatedOptions.success
- };
- return qna;
- });
- example.questionAndAnswers = qnaExamples;
- seedExamples.push(example);
- });
- knowledgeExistingFormData.seedExamples = seedExamples;
-
- // Set the file path from the current YAML file (remove the root folder name from the path)
- const currentFilePath = foundYamlFile.filename.split('/').slice(1, -1).join('/');
- knowledgeEditFormData.knowledgeFormData.filePath = currentFilePath + '/';
-
- // Fetch and parse attribution file if it exists
- const foundAttributionFile = prFiles.find((file: PullRequestFile) => file.filename.includes('attribution'));
- if (foundAttributionFile) {
- const attributionContent = await fetchFileContent(session.accessToken, foundAttributionFile.filename, prData.head.sha);
- const attributionData = parseAttributionContent(attributionContent);
- console.log('Parsed attribution data:', attributionData);
-
- knowledgeEditFormData.attributionFile = foundAttributionFile;
- // Populate the form fields with attribution data
- knowledgeExistingFormData.titleWork = attributionData.title_of_work;
- knowledgeExistingFormData.linkWork = attributionData.link_to_work ? attributionData.link_to_work : '';
- knowledgeExistingFormData.revision = attributionData.revision ? attributionData.revision : '';
- knowledgeExistingFormData.licenseWork = attributionData.license_of_the_work;
- knowledgeExistingFormData.creators = attributionData.creator_names;
- }
- setKnowledgeEditFormData(knowledgeEditFormData);
- setIsLoading(false);
- } catch (error) {
- if (axios.isAxiosError(error)) {
- console.error('Error fetching pull request data:', error.response ? error.response.data : error.message);
- setLoadingMsg('Error fetching knowledge data from PR : ' + prNumber) + '. Please try again.';
- } else if (error instanceof Error) {
- console.error('Error fetching pull request data:', error.message);
- setLoadingMsg('Error fetching knowledge data from PR : ' + prNumber + ' [' + error.message + ']') + '. Please try again.';
- }
- }
- }
- };
- fetchPRData();
- }, [session, prNumber]);
-
- const parseAttributionContent = (content: string): AttributionData => {
- const lines = content.split('\n');
- const attributionData: { [key: string]: string } = {};
- lines.forEach((line) => {
- const [key, ...value] = line.split(':');
- if (key && value) {
- // Remove spaces in the attribution field for parsing
- const normalizedKey = key.trim().toLowerCase().replace(/\s+/g, '_');
- attributionData[normalizedKey] = value.join(':').trim();
- }
- });
- return attributionData as unknown as AttributionData;
- };
-
- const handleOnClose = () => {
- router.push('/dashboard');
- setIsLoading(false);
- };
+type PageProps = {
+ params: Promise<{ id: string }>;
+};
- if (isLoading) {
- return (
-
- handleOnClose()}>
- {loadingMsg}
-
-
- );
- }
+const EditKnowledgePage = async ({ params }: PageProps) => {
+ const resolvedParams = await params;
+ const prNumber = parseInt(resolvedParams.id, 10);
return (
-
+
);
};
diff --git a/src/app/edit-submission/skill/[id]/page.tsx b/src/app/edit-submission/skill/[id]/page.tsx
index 9feae61c..735436fa 100644
--- a/src/app/edit-submission/skill/[id]/page.tsx
+++ b/src/app/edit-submission/skill/[id]/page.tsx
@@ -1,158 +1,19 @@
-// src/app/edit-submission/knowledge/[id]/page.tsx
-'use client';
-
+// src/app/edit-submission/skill/[id]/page.tsx
import * as React from 'react';
-import { useSession } from 'next-auth/react';
-import { AppLayout } from '../../../../components/AppLayout';
-import { AttributionData, PullRequestFile, SkillYamlData } from '@/types';
-import { SkillSchemaVersion } from '@/types/const';
-import { fetchPullRequest, fetchFileContent, fetchPullRequestFiles } from '../../../../utils/github';
-import yaml from 'js-yaml';
-import axios from 'axios';
-import SkillForm, { SkillEditFormData, SkillFormData, SeedExample } from '@/components/Contribute/Skill';
-import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants';
-import { useEffect, useState } from 'react';
-import { Modal, ModalVariant } from '@patternfly/react-core/dist/esm/components/Modal/Modal';
-import { useRouter } from 'next/navigation';
-
-const EditSkillPage: React.FunctionComponent<{ params: { id: string } }> = ({ params }) => {
- const { data: session } = useSession();
- const [isLoading, setIsLoading] = useState(true);
- const [loadingMsg, setLoadingMsg] = useState('');
- const [skillEditFormData, setSkillEditFormData] = useState();
- const prNumber = parseInt(params.id, 10);
- const router = useRouter();
-
- useEffect(() => {
- setLoadingMsg('Fetching skill data from PR : ' + prNumber);
- const fetchPRData = async () => {
- if (session?.accessToken) {
- try {
- const prData = await fetchPullRequest(session.accessToken, prNumber);
-
- // Create SkillFormData from existing form.
- const skillExistingFormData: SkillFormData = {
- email: '',
- name: '',
- submissionSummary: '',
- documentOutline: '',
- filePath: '',
- seedExamples: [],
- titleWork: '',
- licenseWork: '',
- creators: ''
- };
-
- const skillEditFormData: SkillEditFormData = {
- isEditForm: true,
- skillVersion: SkillSchemaVersion,
- branchName: '',
- skillFormData: skillExistingFormData,
- pullRequestNumber: prNumber,
- yamlFile: { filename: '' },
- attributionFile: { filename: '' }
- };
-
- skillExistingFormData.submissionSummary = prData.title;
- skillEditFormData.branchName = prData.head.ref; // Store the branch name from the pull request
-
- const prFiles: PullRequestFile[] = await fetchPullRequestFiles(session.accessToken, prNumber);
-
- const foundYamlFile = prFiles.find((file: PullRequestFile) => file.filename.endsWith('.yaml'));
- if (!foundYamlFile) {
- throw new Error('No YAML file found in the pull request.');
- }
- skillEditFormData.yamlFile = foundYamlFile;
+import { AppLayout } from '@/components/AppLayout';
+import EditSkill from '@/components/Contribute/EditSkill/EditSkill';
- const yamlContent = await fetchFileContent(session.accessToken, foundYamlFile.filename, prData.head.sha);
- const yamlData: SkillYamlData = yaml.load(yamlContent) as SkillYamlData;
- console.log('Parsed YAML data:', yamlData);
-
- // Populate the form fields with YAML data
- skillExistingFormData.documentOutline = yamlData.task_description;
-
- const seedExamples: SeedExample[] = [];
- yamlData.seed_examples.forEach((seed, index) => {
- // iterate through seed examples and create a new object for each
- const example: SeedExample = {
- immutable: index < 5 ? true : false,
- isExpanded: true,
- context: seed.context ? seed.context : '',
- isContextValid: ValidatedOptions.success,
- question: seed.question,
- isQuestionValid: ValidatedOptions.success,
- answer: seed.answer,
- isAnswerValid: ValidatedOptions.success
- };
- seedExamples.push(example);
- });
- skillExistingFormData.seedExamples = seedExamples;
-
- // Set the file path from the current YAML file (Note: skills root directory starts from the repo root)
- const currentFilePath = foundYamlFile.filename.split('/').slice(1, -1).join('/');
- skillEditFormData.skillFormData.filePath = currentFilePath + '/';
-
- // Fetch and parse attribution file if it exists
- const foundAttributionFile = prFiles.find((file: PullRequestFile) => file.filename.includes('attribution'));
- if (foundAttributionFile) {
- const attributionContent = await fetchFileContent(session.accessToken, foundAttributionFile.filename, prData.head.sha);
- const attributionData = parseAttributionContent(attributionContent);
- console.log('Parsed attribution data:', attributionData);
-
- skillEditFormData.attributionFile = foundAttributionFile;
- // Populate the form fields with attribution data
- skillExistingFormData.titleWork = attributionData.title_of_work;
- skillExistingFormData.licenseWork = attributionData.license_of_the_work;
- skillExistingFormData.creators = attributionData.creator_names;
- }
- setSkillEditFormData(skillEditFormData);
- setIsLoading(false);
- } catch (error) {
- if (axios.isAxiosError(error)) {
- console.error('Error fetching pull request data:', error.response ? error.response.data : error.message);
- setLoadingMsg('Error fetching skills data from PR : ' + prNumber) + '. Please try again.';
- } else if (error instanceof Error) {
- console.error('Error fetching pull request data:', error.message);
- setLoadingMsg('Error fetching skills data from PR : ' + prNumber + ' [' + error.message + ']') + '. Please try again.';
- }
- }
- }
- };
- fetchPRData();
- }, [session, prNumber]);
-
- const parseAttributionContent = (content: string): AttributionData => {
- const lines = content.split('\n');
- const attributionData: { [key: string]: string } = {};
- lines.forEach((line) => {
- const [key, ...value] = line.split(':');
- if (key && value) {
- // Remove spaces in the attribution field for parsing
- const normalizedKey = key.trim().toLowerCase().replace(/\s+/g, '_');
- attributionData[normalizedKey] = value.join(':').trim();
- }
- });
- return attributionData as unknown as AttributionData;
- };
-
- const handleOnClose = () => {
- router.push('/dashboard');
- setIsLoading(false);
- };
+type PageProps = {
+ params: Promise<{ id: string }>;
+};
- if (isLoading) {
- return (
-
- handleOnClose()}>
- {loadingMsg}
-
-
- );
- }
+const EditSkillPage = async ({ params }: PageProps) => {
+ const resolvedParams = await params;
+ const prNumber = parseInt(resolvedParams.id, 10);
return (
-
+
);
};
diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx
index 36af9001..fe59a690 100644
--- a/src/app/login/page.tsx
+++ b/src/app/login/page.tsx
@@ -14,17 +14,13 @@ const Login: React.FunctionComponent = () => {
const [password, setPassword] = useState('');
const [isValidPassword, setIsValidPassword] = useState(true);
const [isRememberMeChecked, setIsRememberMeChecked] = useState(false);
- const [isProd, setIsProd] = useState(true);
+ const [isProd, setIsProd] = useState(null); // Use null for initial load state
React.useEffect(() => {
const chooseLoginPage = async () => {
const res = await fetch('/api/envConfig');
const envConfig = await res.json();
- if (envConfig.DEPLOYMENT_TYPE === 'dev') {
- setIsProd(false);
- } else {
- setIsProd(true);
- }
+ setIsProd(envConfig.DEPLOYMENT_TYPE !== 'dev');
};
chooseLoginPage();
}, []);
@@ -103,12 +99,15 @@ const Login: React.FunctionComponent = () => {
/>
);
+ if (isProd === null) return null; // Render nothing until environment is loaded
+
if (isProd) {
return ;
}
return (
= ({ prNumber }) => {
+ const { data: session } = useSession();
+ const [isLoading, setIsLoading] = useState(true);
+ const [loadingMsg, setLoadingMsg] = useState('');
+ const [knowledgeEditFormData, setKnowledgeEditFormData] = useState();
+ const router = useRouter();
+
+ useEffect(() => {
+ setLoadingMsg('Fetching knowledge data from PR : ' + prNumber);
+ const fetchPRData = async () => {
+ if (session?.accessToken) {
+ try {
+ const prData = await fetchPullRequest(session.accessToken, prNumber);
+
+ // Create KnowledgeFormData from existing form.
+ const knowledgeExistingFormData: KnowledgeFormData = {
+ email: '',
+ name: '',
+ submissionSummary: '',
+ domain: '',
+ documentOutline: '',
+ filePath: '',
+ seedExamples: [],
+ knowledgeDocumentRepositoryUrl: '',
+ knowledgeDocumentCommit: '',
+ documentName: '',
+ titleWork: '',
+ linkWork: '',
+ revision: '',
+ licenseWork: '',
+ creators: ''
+ };
+
+ const knowledgeEditFormData: KnowledgeEditFormData = {
+ isEditForm: true,
+ knowledgeVersion: KnowledgeSchemaVersion,
+ branchName: '',
+ knowledgeFormData: knowledgeExistingFormData,
+ pullRequestNumber: prNumber,
+ yamlFile: { filename: '' },
+ attributionFile: { filename: '' }
+ };
+
+ knowledgeExistingFormData.submissionSummary = prData.title;
+ knowledgeEditFormData.branchName = prData.head.ref; // Store the branch name from the pull request
+
+ const prFiles: PullRequestFile[] = await fetchPullRequestFiles(session.accessToken, prNumber);
+
+ const foundYamlFile = prFiles.find((file: PullRequestFile) => file.filename.endsWith('.yaml'));
+ if (!foundYamlFile) {
+ throw new Error('No YAML file found in the pull request.');
+ }
+ knowledgeEditFormData.yamlFile = foundYamlFile;
+
+ const yamlContent = await fetchFileContent(session.accessToken, foundYamlFile.filename, prData.head.sha);
+ const yamlData: KnowledgeYamlData = yaml.load(yamlContent) as KnowledgeYamlData;
+ console.log('Parsed YAML data:', yamlData);
+
+ // Populate the form fields with YAML data
+ knowledgeExistingFormData.documentOutline = yamlData.document_outline;
+ knowledgeExistingFormData.domain = yamlData.domain;
+ knowledgeExistingFormData.knowledgeDocumentRepositoryUrl = yamlData.document.repo;
+ knowledgeExistingFormData.knowledgeDocumentCommit = yamlData.document.commit;
+ knowledgeExistingFormData.documentName = yamlData.document.patterns.join(', ');
+
+ const seedExamples: SeedExample[] = [];
+ yamlData.seed_examples.forEach((seed, index) => {
+ // iterate through questions_and_answers and create a new object for each
+ const example: SeedExample = {
+ immutable: index < 5 ? true : false,
+ isExpanded: true,
+ context: seed.context,
+ isContextValid: ValidatedOptions.success,
+ questionAndAnswers: []
+ };
+
+ const qnaExamples: QuestionAndAnswerPair[] = seed.questions_and_answers.map((qa, index) => {
+ const qna: QuestionAndAnswerPair = {
+ question: qa.question,
+ answer: qa.answer,
+ immutable: index < 3 ? true : false,
+ isQuestionValid: ValidatedOptions.success,
+ isAnswerValid: ValidatedOptions.success
+ };
+ return qna;
+ });
+ example.questionAndAnswers = qnaExamples;
+ seedExamples.push(example);
+ });
+ knowledgeExistingFormData.seedExamples = seedExamples;
+
+ // Set the file path from the current YAML file (remove the root folder name from the path)
+ const currentFilePath = foundYamlFile.filename.split('/').slice(1, -1).join('/');
+ knowledgeEditFormData.knowledgeFormData.filePath = currentFilePath + '/';
+
+ // Fetch and parse attribution file if it exists
+ const foundAttributionFile = prFiles.find((file: PullRequestFile) => file.filename.includes('attribution'));
+ if (foundAttributionFile) {
+ const attributionContent = await fetchFileContent(session.accessToken, foundAttributionFile.filename, prData.head.sha);
+ const attributionData = parseAttributionContent(attributionContent);
+ console.log('Parsed attribution data:', attributionData);
+
+ knowledgeEditFormData.attributionFile = foundAttributionFile;
+ // Populate the form fields with attribution data
+ knowledgeExistingFormData.titleWork = attributionData.title_of_work;
+ knowledgeExistingFormData.linkWork = attributionData.link_to_work ? attributionData.link_to_work : '';
+ knowledgeExistingFormData.revision = attributionData.revision ? attributionData.revision : '';
+ knowledgeExistingFormData.licenseWork = attributionData.license_of_the_work;
+ knowledgeExistingFormData.creators = attributionData.creator_names;
+ }
+ setKnowledgeEditFormData(knowledgeEditFormData);
+ setIsLoading(false);
+ } catch (error) {
+ if (axios.isAxiosError(error)) {
+ console.error('Error fetching pull request data:', error.response ? error.response.data : error.message);
+ setLoadingMsg('Error fetching knowledge data from PR : ' + prNumber) + '. Please try again.';
+ } else if (error instanceof Error) {
+ console.error('Error fetching pull request data:', error.message);
+ setLoadingMsg('Error fetching knowledge data from PR : ' + prNumber + ' [' + error.message + ']') + '. Please try again.';
+ }
+ }
+ }
+ };
+ fetchPRData();
+ }, [session, prNumber]);
+
+ const parseAttributionContent = (content: string): AttributionData => {
+ const lines = content.split('\n');
+ const attributionData: { [key: string]: string } = {};
+ lines.forEach((line) => {
+ const [key, ...value] = line.split(':');
+ if (key && value) {
+ // Remove spaces in the attribution field for parsing
+ const normalizedKey = key.trim().toLowerCase().replace(/\s+/g, '_');
+ attributionData[normalizedKey] = value.join(':').trim();
+ }
+ });
+ return attributionData as unknown as AttributionData;
+ };
+
+ const handleOnClose = () => {
+ router.push('/dashboard');
+ setIsLoading(false);
+ };
+
+ if (isLoading) {
+ return (
+ //
+ handleOnClose()}>
+ {loadingMsg}
+
+ //
+ );
+ }
+
+ return (
+ //
+
+ //
+ );
+};
+
+export default EditKnowledge;
diff --git a/src/components/Contribute/EditSkill/EditSkill.tsx b/src/components/Contribute/EditSkill/EditSkill.tsx
new file mode 100644
index 00000000..d09cd9c8
--- /dev/null
+++ b/src/components/Contribute/EditSkill/EditSkill.tsx
@@ -0,0 +1,153 @@
+// src/app/edit-submission/skill/[id]/EditSkillClientComponent.tsx
+'use client';
+
+import * as React from 'react';
+import { useSession } from 'next-auth/react';
+import { useEffect, useState } from 'react';
+import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants';
+import { Modal, ModalVariant } from '@patternfly/react-core/dist/esm/components/Modal/Modal';
+import { useRouter } from 'next/navigation';
+import SkillForm, { SkillEditFormData, SkillFormData, SeedExample } from '@/components/Contribute/Skill';
+import { fetchPullRequest, fetchFileContent, fetchPullRequestFiles } from '@/utils/github';
+import yaml from 'js-yaml';
+import axios from 'axios';
+import { SkillYamlData, AttributionData, PullRequestFile } from '@/types';
+import { SkillSchemaVersion } from '@/types/const';
+
+interface EditSkillClientComponentProps {
+ prNumber: number;
+}
+
+const EditSkill: React.FC = ({ prNumber }) => {
+ const { data: session } = useSession();
+ const [isLoading, setIsLoading] = useState(true);
+ const [loadingMsg, setLoadingMsg] = useState('');
+ const [skillEditFormData, setSkillEditFormData] = useState();
+ const router = useRouter();
+
+ useEffect(() => {
+ const fetchPRData = async () => {
+ setLoadingMsg('Fetching skill data from PR: ' + prNumber);
+ if (session?.accessToken) {
+ try {
+ const prData = await fetchPullRequest(session.accessToken, prNumber);
+
+ const skillExistingFormData: SkillFormData = {
+ email: '',
+ name: '',
+ submissionSummary: '',
+ documentOutline: '',
+ filePath: '',
+ seedExamples: [],
+ titleWork: '',
+ licenseWork: '',
+ creators: ''
+ };
+
+ const skillEditFormData: SkillEditFormData = {
+ isEditForm: true,
+ skillVersion: SkillSchemaVersion,
+ branchName: '',
+ skillFormData: skillExistingFormData,
+ pullRequestNumber: prNumber,
+ yamlFile: { filename: '' },
+ attributionFile: { filename: '' }
+ };
+
+ skillExistingFormData.submissionSummary = prData.title;
+ skillEditFormData.branchName = prData.head.ref; // Store the branch name from the pull request
+
+ const prFiles: PullRequestFile[] = await fetchPullRequestFiles(session.accessToken, prNumber);
+
+ const foundYamlFile = prFiles.find((file: PullRequestFile) => file.filename.endsWith('.yaml'));
+ if (!foundYamlFile) {
+ throw new Error('No YAML file found in the pull request.');
+ }
+ skillEditFormData.yamlFile = foundYamlFile;
+
+ const yamlContent = await fetchFileContent(session.accessToken, foundYamlFile.filename, prData.head.sha);
+ const yamlData: SkillYamlData = yaml.load(yamlContent) as SkillYamlData;
+ console.log('Parsed YAML data:', yamlData);
+
+ // Populate the form fields with YAML data
+ skillExistingFormData.documentOutline = yamlData.task_description;
+
+ const seedExamples: SeedExample[] = [];
+ yamlData.seed_examples.forEach((seed, index) => {
+ const example: SeedExample = {
+ immutable: index < 5 ? true : false,
+ isExpanded: true,
+ context: seed.context || '',
+ isContextValid: ValidatedOptions.success,
+ question: seed.question,
+ isQuestionValid: ValidatedOptions.success,
+ answer: seed.answer,
+ isAnswerValid: ValidatedOptions.success
+ };
+ seedExamples.push(example);
+ });
+ skillExistingFormData.seedExamples = seedExamples;
+
+ // Set the file path from the current YAML file
+ const currentFilePath = foundYamlFile.filename.split('/').slice(1, -1).join('/');
+ skillEditFormData.skillFormData.filePath = currentFilePath + '/';
+
+ // Fetch and parse attribution file if it exists
+ const foundAttributionFile = prFiles.find((file: PullRequestFile) => file.filename.includes('attribution'));
+ if (foundAttributionFile) {
+ const attributionContent = await fetchFileContent(session.accessToken, foundAttributionFile.filename, prData.head.sha);
+ const attributionData = parseAttributionContent(attributionContent);
+ console.log('Parsed attribution data:', attributionData);
+
+ skillEditFormData.attributionFile = foundAttributionFile;
+ // Populate the form fields with attribution data
+ skillExistingFormData.titleWork = attributionData.title_of_work;
+ skillExistingFormData.licenseWork = attributionData.license_of_the_work;
+ skillExistingFormData.creators = attributionData.creator_names;
+ }
+ setSkillEditFormData(skillEditFormData);
+ setIsLoading(false);
+ } catch (error) {
+ if (axios.isAxiosError(error)) {
+ console.error('Error fetching pull request data:', error.response ? error.response.data : error.message);
+ setLoadingMsg('Error fetching skills data from PR: ' + prNumber + '. Please try again.');
+ } else if (error instanceof Error) {
+ console.error('Error fetching pull request data:', error.message);
+ setLoadingMsg('Error fetching skills data from PR: ' + prNumber + ' [' + error.message + ']. Please try again.');
+ }
+ }
+ }
+ };
+ fetchPRData();
+ }, [session, prNumber]);
+
+ const parseAttributionContent = (content: string): AttributionData => {
+ const lines = content.split('\n');
+ const attributionData: { [key: string]: string } = {};
+ lines.forEach((line) => {
+ const [key, ...value] = line.split(':');
+ if (key && value) {
+ const normalizedKey = key.trim().toLowerCase().replace(/\s+/g, '_');
+ attributionData[normalizedKey] = value.join(':').trim();
+ }
+ });
+ return attributionData as unknown as AttributionData;
+ };
+
+ const handleOnClose = () => {
+ router.push('/dashboard');
+ setIsLoading(false);
+ };
+
+ if (isLoading) {
+ return (
+
+ {loadingMsg}
+
+ );
+ }
+
+ return ;
+};
+
+export default EditSkill;
diff --git a/src/components/Contribute/Knowledge/ViewDropdown/ViewDropdown.tsx b/src/components/Contribute/Knowledge/ViewDropdown/ViewDropdown.tsx
index 8dd1d0af..bd1280bc 100644
--- a/src/components/Contribute/Knowledge/ViewDropdown/ViewDropdown.tsx
+++ b/src/components/Contribute/Knowledge/ViewDropdown/ViewDropdown.tsx
@@ -85,10 +85,10 @@ export const ViewDropdown: React.FunctionComponent = ({ knowledgeFormData
shouldFocusToggleOnSelect
>
-
+
YAML Content
-
+
Attribution Content
diff --git a/src/components/Contribute/Knowledge/knowledge.css b/src/components/Contribute/Knowledge/knowledge.css
index 48a2273d..9f65e32c 100644
--- a/src/components/Contribute/Knowledge/knowledge.css
+++ b/src/components/Contribute/Knowledge/knowledge.css
@@ -23,7 +23,7 @@
border-color: #45a049;
}
-.spinner-container{
+.spinner-container {
display: flex;
justify-content: center;
align-items: center;
diff --git a/src/components/Contribute/Skill/ViewDropdown/ViewDropdown.tsx b/src/components/Contribute/Skill/ViewDropdown/ViewDropdown.tsx
index 29c81e07..14af20e5 100644
--- a/src/components/Contribute/Skill/ViewDropdown/ViewDropdown.tsx
+++ b/src/components/Contribute/Skill/ViewDropdown/ViewDropdown.tsx
@@ -76,10 +76,10 @@ export const ViewDropdown: React.FunctionComponent = ({ skillFormData, gi
shouldFocusToggleOnSelect
>
-
+
YAML Content
-
+
Attribution Content
diff --git a/src/components/PathService/PathService.tsx b/src/components/PathService/PathService.tsx
index 7e265d9a..47d04df0 100644
--- a/src/components/PathService/PathService.tsx
+++ b/src/components/PathService/PathService.tsx
@@ -1,4 +1,4 @@
-// components/PathService.tsx
+// /src/components/PathService.tsx
import React, { useState, useEffect, useRef } from 'react';
import { SearchInput } from '@patternfly/react-core/dist/dynamic/components/SearchInput';
import { List } from '@patternfly/react-core/dist/dynamic/components/List';
@@ -44,7 +44,7 @@ const PathService: React.FC = ({ reset, rootPath, path, handle
});
if (!response.ok) {
- throw new Error('Failed to get tree for subpath ( ' + subpath + ' ) from server.');
+ console.warn('Failed to get path service tree for subpath ( ' + subpath + ' ) from server.');
}
const result = await response.json();
@@ -55,7 +55,7 @@ const PathService: React.FC = ({ reset, rootPath, path, handle
}
setItems(result.data.map((item: string) => item.valueOf()));
} catch (error) {
- console.error('Error fetching data:', error);
+ console.warn('Error fetching path service data:', error);
setItems([]);
}
};
diff --git a/src/components/UserMenu/UserMenu.tsx b/src/components/UserMenu/UserMenu.tsx
index 8fe4e551..7defe55f 100644
--- a/src/components/UserMenu/UserMenu.tsx
+++ b/src/components/UserMenu/UserMenu.tsx
@@ -17,10 +17,10 @@ const UserMenu: React.FC = () => {
useEffect(() => {
if (session?.user?.name === 'Admin') {
setUserName(session?.user?.name);
- setUserImage('https://www.patternfly.org/images/668560cd.svg');
+ setUserImage('/default-avatar.png');
} else {
setUserName(session?.user?.name ?? '');
- setUserImage(session?.user?.image ?? '');
+ setUserImage(session?.user?.image || '');
}
}, [session?.user?.name, session?.user?.image]);
@@ -40,9 +40,7 @@ const UserMenu: React.FC = () => {
toggle={(toggleRef: React.Ref) => (
-
-
-
+ {userImage ? : }
{userName}