feat: add new page and migration scripts for access rules and collections
- Introduced new page component for library topics with type checks. - Added migration scripts to update access rules for various collections including badges, curriculum versions, and themes. - Implemented PocketBase integration for managing collection access rules dynamically. - Ensured proper type validation for page props and metadata generation functions.
This commit is contained in:
@@ -66,6 +66,11 @@
|
||||
"static/chunks/main-app.js",
|
||||
"static/chunks/app/app/profile/page.js"
|
||||
],
|
||||
"/app/library/[topicId]/page": [
|
||||
"static/chunks/webpack.js",
|
||||
"static/chunks/main-app.js",
|
||||
"static/chunks/app/app/library/[topicId]/page.js"
|
||||
],
|
||||
"/_not-found/page": [
|
||||
"static/chunks/webpack.js",
|
||||
"static/chunks/main-app.js",
|
||||
|
||||
BIN
app/frontend/.next/cache/webpack/client-development/10.pack.gz
vendored
Normal file
BIN
app/frontend/.next/cache/webpack/client-development/10.pack.gz
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
app/frontend/.next/cache/webpack/client-development/7.pack.gz
vendored
Normal file
BIN
app/frontend/.next/cache/webpack/client-development/7.pack.gz
vendored
Normal file
Binary file not shown.
BIN
app/frontend/.next/cache/webpack/client-development/8.pack.gz
vendored
Normal file
BIN
app/frontend/.next/cache/webpack/client-development/8.pack.gz
vendored
Normal file
Binary file not shown.
BIN
app/frontend/.next/cache/webpack/client-development/9.pack.gz
vendored
Normal file
BIN
app/frontend/.next/cache/webpack/client-development/9.pack.gz
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
app/frontend/.next/cache/webpack/server-development/7.pack.gz
vendored
Normal file
BIN
app/frontend/.next/cache/webpack/server-development/7.pack.gz
vendored
Normal file
Binary file not shown.
BIN
app/frontend/.next/cache/webpack/server-development/8.pack.gz
vendored
Normal file
BIN
app/frontend/.next/cache/webpack/server-development/8.pack.gz
vendored
Normal file
Binary file not shown.
BIN
app/frontend/.next/cache/webpack/server-development/9.pack.gz
vendored
Normal file
BIN
app/frontend/.next/cache/webpack/server-development/9.pack.gz
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -2,9 +2,9 @@
|
||||
"/_not-found/page": "app/_not-found/page.js",
|
||||
"/auth/page": "app/auth/page.js",
|
||||
"/page": "app/page.js",
|
||||
"/app/session/page": "app/app/session/page.js",
|
||||
"/admin/page": "app/admin/page.js",
|
||||
"/app/profile/page": "app/app/profile/page.js",
|
||||
"/app/library/page": "app/app/library/page.js",
|
||||
"/admin/documents/page": "app/admin/documents/page.js"
|
||||
"/admin/documents/page": "app/admin/documents/page.js",
|
||||
"/app/session/page": "app/app/session/page.js",
|
||||
"/app/library/[topicId]/page": "app/app/library/[topicId]/page.js",
|
||||
"/app/page": "app/app/page.js"
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
420
app/frontend/.next/server/app/app/library/[topicId]/page.js
Normal file
420
app/frontend/.next/server/app/app/library/[topicId]/page.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -125,7 +125,7 @@
|
||||
/******/
|
||||
/******/ /* webpack/runtime/getFullHash */
|
||||
/******/ (() => {
|
||||
/******/ __webpack_require__.h = () => ("51e1c2914ed1ba13")
|
||||
/******/ __webpack_require__.h = () => ("5fc192207423a534")
|
||||
/******/ })();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/hasOwnProperty shorthand */
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -25,7 +25,7 @@ eval(__webpack_require__.ts("Promise.resolve(/*! import() eager */).then(__webpa
|
||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
eval(__webpack_require__.ts("__webpack_require__.r(__webpack_exports__);\n/* harmony default export */ __webpack_exports__[\"default\"] = (\"b88116e9ef0b\");\nif (true) { module.hot.accept() }\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKGFwcC1wYWdlcy1icm93c2VyKS8uL3NyYy9hcHAvZ2xvYmFscy5jc3MiLCJtYXBwaW5ncyI6IjtBQUFBLCtEQUFlLGNBQWM7QUFDN0IsSUFBSSxJQUFVLElBQUksaUJBQWlCIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vX05fRS8uL3NyYy9hcHAvZ2xvYmFscy5jc3M/ZjYwMSJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCBcImI4ODExNmU5ZWYwYlwiXG5pZiAobW9kdWxlLmhvdCkgeyBtb2R1bGUuaG90LmFjY2VwdCgpIH1cbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///(app-pages-browser)/./src/app/globals.css\n"));
|
||||
eval(__webpack_require__.ts("__webpack_require__.r(__webpack_exports__);\n/* harmony default export */ __webpack_exports__[\"default\"] = (\"faba7d6da641\");\nif (true) { module.hot.accept() }\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKGFwcC1wYWdlcy1icm93c2VyKS8uL3NyYy9hcHAvZ2xvYmFscy5jc3MiLCJtYXBwaW5ncyI6IjtBQUFBLCtEQUFlLGNBQWM7QUFDN0IsSUFBSSxJQUFVLElBQUksaUJBQWlCIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vX05fRS8uL3NyYy9hcHAvZ2xvYmFscy5jc3M/ZjYwMSJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCBcImZhYmE3ZDZkYTY0MVwiXG5pZiAobW9kdWxlLmhvdCkgeyBtb2R1bGUuaG90LmFjY2VwdCgpIH1cbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///(app-pages-browser)/./src/app/globals.css\n"));
|
||||
|
||||
/***/ }),
|
||||
|
||||
|
||||
@@ -192,7 +192,7 @@
|
||||
/******/
|
||||
/******/ /* webpack/runtime/getFullHash */
|
||||
/******/ !function() {
|
||||
/******/ __webpack_require__.h = function() { return "f0b0b64480e0ded4"; }
|
||||
/******/ __webpack_require__.h = function() { return "a7ccb1bd8466330b"; }
|
||||
/******/ }();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/global */
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
{"c":["app/layout","webpack"],"r":[],"m":[]}
|
||||
@@ -0,0 +1 @@
|
||||
{"c":["app/layout","webpack"],"r":[],"m":[]}
|
||||
@@ -0,0 +1 @@
|
||||
{"c":["app/layout","app/admin/documents/page","webpack"],"r":[],"m":[]}
|
||||
@@ -0,0 +1 @@
|
||||
{"c":["webpack"],"r":["app/_not-found/page"],"m":["(app-pages-browser)/./node_modules/next/dist/build/webpack/loaders/next-client-pages-loader.js?absolutePagePath=C%3A%5CUsers%5CRaymondVerhoef%5CGitea%5Clearning-platform%5Capp%5Cfrontend%5Cnode_modules%5Cnext%5Cdist%5Cclient%5Ccomponents%5Cnot-found-error.js&page=%2F_not-found%2Fpage!","(app-pages-browser)/./node_modules/next/dist/client/components/not-found-error.js"]}
|
||||
@@ -0,0 +1 @@
|
||||
{"c":["app/layout","webpack"],"r":[],"m":[]}
|
||||
@@ -0,0 +1 @@
|
||||
{"c":["app/layout","webpack"],"r":[],"m":[]}
|
||||
@@ -0,0 +1 @@
|
||||
{"c":["webpack"],"r":[],"m":[]}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,22 @@
|
||||
"use strict";
|
||||
/*
|
||||
* ATTENTION: An "eval-source-map" devtool has been used.
|
||||
* This devtool is neither made for production nor for readable output files.
|
||||
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
|
||||
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
||||
* or disable the default devtool with "devtool: false".
|
||||
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
||||
*/
|
||||
self["webpackHotUpdate_N_E"]("app/layout",{
|
||||
|
||||
/***/ "(app-pages-browser)/./src/app/globals.css":
|
||||
/*!*****************************!*\
|
||||
!*** ./src/app/globals.css ***!
|
||||
\*****************************/
|
||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
eval(__webpack_require__.ts("__webpack_require__.r(__webpack_exports__);\n/* harmony default export */ __webpack_exports__[\"default\"] = (\"faba7d6da641\");\nif (true) { module.hot.accept() }\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKGFwcC1wYWdlcy1icm93c2VyKS8uL3NyYy9hcHAvZ2xvYmFscy5jc3MiLCJtYXBwaW5ncyI6IjtBQUFBLCtEQUFlLGNBQWM7QUFDN0IsSUFBSSxJQUFVLElBQUksaUJBQWlCIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vX05fRS8uL3NyYy9hcHAvZ2xvYmFscy5jc3M/ZjYwMSJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCBcImZhYmE3ZDZkYTY0MVwiXG5pZiAobW9kdWxlLmhvdCkgeyBtb2R1bGUuaG90LmFjY2VwdCgpIH1cbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///(app-pages-browser)/./src/app/globals.css\n"));
|
||||
|
||||
/***/ })
|
||||
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
"use strict";
|
||||
/*
|
||||
* ATTENTION: An "eval-source-map" devtool has been used.
|
||||
* This devtool is neither made for production nor for readable output files.
|
||||
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
|
||||
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
||||
* or disable the default devtool with "devtool: false".
|
||||
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
||||
*/
|
||||
self["webpackHotUpdate_N_E"]("app/layout",{
|
||||
|
||||
/***/ "(app-pages-browser)/./src/app/globals.css":
|
||||
/*!*****************************!*\
|
||||
!*** ./src/app/globals.css ***!
|
||||
\*****************************/
|
||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
eval(__webpack_require__.ts("__webpack_require__.r(__webpack_exports__);\n/* harmony default export */ __webpack_exports__[\"default\"] = (\"4d1be2fbc1d5\");\nif (true) { module.hot.accept() }\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKGFwcC1wYWdlcy1icm93c2VyKS8uL3NyYy9hcHAvZ2xvYmFscy5jc3MiLCJtYXBwaW5ncyI6IjtBQUFBLCtEQUFlLGNBQWM7QUFDN0IsSUFBSSxJQUFVLElBQUksaUJBQWlCIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vX05fRS8uL3NyYy9hcHAvZ2xvYmFscy5jc3M/ZjYwMSJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCBcIjRkMWJlMmZiYzFkNVwiXG5pZiAobW9kdWxlLmhvdCkgeyBtb2R1bGUuaG90LmFjY2VwdCgpIH1cbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///(app-pages-browser)/./src/app/globals.css\n"));
|
||||
|
||||
/***/ })
|
||||
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
"use strict";
|
||||
/*
|
||||
* ATTENTION: An "eval-source-map" devtool has been used.
|
||||
* This devtool is neither made for production nor for readable output files.
|
||||
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
|
||||
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
||||
* or disable the default devtool with "devtool: false".
|
||||
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
||||
*/
|
||||
self["webpackHotUpdate_N_E"]("app/layout",{
|
||||
|
||||
/***/ "(app-pages-browser)/./src/app/globals.css":
|
||||
/*!*****************************!*\
|
||||
!*** ./src/app/globals.css ***!
|
||||
\*****************************/
|
||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
eval(__webpack_require__.ts("__webpack_require__.r(__webpack_exports__);\n/* harmony default export */ __webpack_exports__[\"default\"] = (\"823f19c267ee\");\nif (true) { module.hot.accept() }\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKGFwcC1wYWdlcy1icm93c2VyKS8uL3NyYy9hcHAvZ2xvYmFscy5jc3MiLCJtYXBwaW5ncyI6IjtBQUFBLCtEQUFlLGNBQWM7QUFDN0IsSUFBSSxJQUFVLElBQUksaUJBQWlCIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vX05fRS8uL3NyYy9hcHAvZ2xvYmFscy5jc3M/ZjYwMSJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCBcIjgyM2YxOWMyNjdlZVwiXG5pZiAobW9kdWxlLmhvdCkgeyBtb2R1bGUuaG90LmFjY2VwdCgpIH1cbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///(app-pages-browser)/./src/app/globals.css\n"));
|
||||
|
||||
/***/ })
|
||||
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
"use strict";
|
||||
/*
|
||||
* ATTENTION: An "eval-source-map" devtool has been used.
|
||||
* This devtool is neither made for production nor for readable output files.
|
||||
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
|
||||
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
||||
* or disable the default devtool with "devtool: false".
|
||||
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
||||
*/
|
||||
self["webpackHotUpdate_N_E"]("app/layout",{
|
||||
|
||||
/***/ "(app-pages-browser)/./src/app/globals.css":
|
||||
/*!*****************************!*\
|
||||
!*** ./src/app/globals.css ***!
|
||||
\*****************************/
|
||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
eval(__webpack_require__.ts("__webpack_require__.r(__webpack_exports__);\n/* harmony default export */ __webpack_exports__[\"default\"] = (\"25d949e1ff47\");\nif (true) { module.hot.accept() }\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKGFwcC1wYWdlcy1icm93c2VyKS8uL3NyYy9hcHAvZ2xvYmFscy5jc3MiLCJtYXBwaW5ncyI6IjtBQUFBLCtEQUFlLGNBQWM7QUFDN0IsSUFBSSxJQUFVLElBQUksaUJBQWlCIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vX05fRS8uL3NyYy9hcHAvZ2xvYmFscy5jc3M/ZjYwMSJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCBcIjI1ZDk0OWUxZmY0N1wiXG5pZiAobW9kdWxlLmhvdCkgeyBtb2R1bGUuaG90LmFjY2VwdCgpIH1cbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///(app-pages-browser)/./src/app/globals.css\n"));
|
||||
|
||||
/***/ })
|
||||
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
"use strict";
|
||||
/*
|
||||
* ATTENTION: An "eval-source-map" devtool has been used.
|
||||
* This devtool is neither made for production nor for readable output files.
|
||||
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
|
||||
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
||||
* or disable the default devtool with "devtool: false".
|
||||
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
||||
*/
|
||||
self["webpackHotUpdate_N_E"]("app/layout",{
|
||||
|
||||
/***/ "(app-pages-browser)/./src/app/globals.css":
|
||||
/*!*****************************!*\
|
||||
!*** ./src/app/globals.css ***!
|
||||
\*****************************/
|
||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
eval(__webpack_require__.ts("__webpack_require__.r(__webpack_exports__);\n/* harmony default export */ __webpack_exports__[\"default\"] = (\"39ba7864e079\");\nif (true) { module.hot.accept() }\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKGFwcC1wYWdlcy1icm93c2VyKS8uL3NyYy9hcHAvZ2xvYmFscy5jc3MiLCJtYXBwaW5ncyI6IjtBQUFBLCtEQUFlLGNBQWM7QUFDN0IsSUFBSSxJQUFVLElBQUksaUJBQWlCIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vX05fRS8uL3NyYy9hcHAvZ2xvYmFscy5jc3M/ZjYwMSJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCBcIjM5YmE3ODY0ZTA3OVwiXG5pZiAobW9kdWxlLmhvdCkgeyBtb2R1bGUuaG90LmFjY2VwdCgpIH1cbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///(app-pages-browser)/./src/app/globals.css\n"));
|
||||
|
||||
/***/ })
|
||||
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
"use strict";
|
||||
/*
|
||||
* ATTENTION: An "eval-source-map" devtool has been used.
|
||||
* This devtool is neither made for production nor for readable output files.
|
||||
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
|
||||
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
||||
* or disable the default devtool with "devtool: false".
|
||||
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
||||
*/
|
||||
self["webpackHotUpdate_N_E"]("app/layout",{
|
||||
|
||||
/***/ "(app-pages-browser)/./src/app/globals.css":
|
||||
/*!*****************************!*\
|
||||
!*** ./src/app/globals.css ***!
|
||||
\*****************************/
|
||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
eval(__webpack_require__.ts("__webpack_require__.r(__webpack_exports__);\n/* harmony default export */ __webpack_exports__[\"default\"] = (\"a49431f69319\");\nif (true) { module.hot.accept() }\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKGFwcC1wYWdlcy1icm93c2VyKS8uL3NyYy9hcHAvZ2xvYmFscy5jc3MiLCJtYXBwaW5ncyI6IjtBQUFBLCtEQUFlLGNBQWM7QUFDN0IsSUFBSSxJQUFVLElBQUksaUJBQWlCIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vX05fRS8uL3NyYy9hcHAvZ2xvYmFscy5jc3M/ZjYwMSJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCBcImE0OTQzMWY2OTMxOVwiXG5pZiAobW9kdWxlLmhvdCkgeyBtb2R1bGUuaG90LmFjY2VwdCgpIH1cbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///(app-pages-browser)/./src/app/globals.css\n"));
|
||||
|
||||
/***/ })
|
||||
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
"use strict";
|
||||
/*
|
||||
* ATTENTION: An "eval-source-map" devtool has been used.
|
||||
* This devtool is neither made for production nor for readable output files.
|
||||
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
|
||||
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
||||
* or disable the default devtool with "devtool: false".
|
||||
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
||||
*/
|
||||
self["webpackHotUpdate_N_E"]("app/layout",{
|
||||
|
||||
/***/ "(app-pages-browser)/./src/app/globals.css":
|
||||
/*!*****************************!*\
|
||||
!*** ./src/app/globals.css ***!
|
||||
\*****************************/
|
||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
eval(__webpack_require__.ts("__webpack_require__.r(__webpack_exports__);\n/* harmony default export */ __webpack_exports__[\"default\"] = (\"f963c24539ed\");\nif (true) { module.hot.accept() }\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKGFwcC1wYWdlcy1icm93c2VyKS8uL3NyYy9hcHAvZ2xvYmFscy5jc3MiLCJtYXBwaW5ncyI6IjtBQUFBLCtEQUFlLGNBQWM7QUFDN0IsSUFBSSxJQUFVLElBQUksaUJBQWlCIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vX05fRS8uL3NyYy9hcHAvZ2xvYmFscy5jc3M/ZjYwMSJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCBcImY5NjNjMjQ1MzllZFwiXG5pZiAobW9kdWxlLmhvdCkgeyBtb2R1bGUuaG90LmFjY2VwdCgpIH1cbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///(app-pages-browser)/./src/app/globals.css\n"));
|
||||
|
||||
/***/ })
|
||||
|
||||
});
|
||||
@@ -0,0 +1 @@
|
||||
{"c":["app/layout","webpack"],"r":[],"m":[]}
|
||||
@@ -0,0 +1 @@
|
||||
{"c":["app/layout","app/admin/knowledge/page","webpack"],"r":[],"m":[]}
|
||||
@@ -0,0 +1 @@
|
||||
{"c":["app/admin/documents/page","app/admin/knowledge/page","app/admin/curriculum/page","app/app/session/page","app/app/profile/page","webpack"],"r":["app/_not-found/page"],"m":["(app-pages-browser)/./node_modules/next/dist/build/webpack/loaders/next-client-pages-loader.js?absolutePagePath=C%3A%5CUsers%5CRaymondVerhoef%5CGitea%5Clearning-platform%5Capp%5Cfrontend%5Cnode_modules%5Cnext%5Cdist%5Cclient%5Ccomponents%5Cnot-found-error.js&page=%2F_not-found%2Fpage!","(app-pages-browser)/./node_modules/next/dist/client/components/not-found-error.js"]}
|
||||
@@ -0,0 +1 @@
|
||||
{"c":["webpack"],"r":[],"m":[]}
|
||||
@@ -0,0 +1,18 @@
|
||||
"use strict";
|
||||
/*
|
||||
* ATTENTION: An "eval-source-map" devtool has been used.
|
||||
* This devtool is neither made for production nor for readable output files.
|
||||
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
|
||||
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
||||
* or disable the default devtool with "devtool: false".
|
||||
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
||||
*/
|
||||
self["webpackHotUpdate_N_E"]("webpack",{},
|
||||
/******/ function(__webpack_require__) { // webpackRuntimeModules
|
||||
/******/ /* webpack/runtime/getFullHash */
|
||||
/******/ !function() {
|
||||
/******/ __webpack_require__.h = function() { return "a7ccb1bd8466330b"; }
|
||||
/******/ }();
|
||||
/******/
|
||||
/******/ }
|
||||
);
|
||||
@@ -0,0 +1,18 @@
|
||||
"use strict";
|
||||
/*
|
||||
* ATTENTION: An "eval-source-map" devtool has been used.
|
||||
* This devtool is neither made for production nor for readable output files.
|
||||
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
|
||||
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
||||
* or disable the default devtool with "devtool: false".
|
||||
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
||||
*/
|
||||
self["webpackHotUpdate_N_E"]("webpack",{},
|
||||
/******/ function(__webpack_require__) { // webpackRuntimeModules
|
||||
/******/ /* webpack/runtime/getFullHash */
|
||||
/******/ !function() {
|
||||
/******/ __webpack_require__.h = function() { return "2eb37301afdeda1e"; }
|
||||
/******/ }();
|
||||
/******/
|
||||
/******/ }
|
||||
);
|
||||
@@ -0,0 +1,18 @@
|
||||
"use strict";
|
||||
/*
|
||||
* ATTENTION: An "eval-source-map" devtool has been used.
|
||||
* This devtool is neither made for production nor for readable output files.
|
||||
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
|
||||
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
||||
* or disable the default devtool with "devtool: false".
|
||||
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
||||
*/
|
||||
self["webpackHotUpdate_N_E"]("webpack",{},
|
||||
/******/ function(__webpack_require__) { // webpackRuntimeModules
|
||||
/******/ /* webpack/runtime/getFullHash */
|
||||
/******/ !function() {
|
||||
/******/ __webpack_require__.h = function() { return "ff5e88d2dcebc726"; }
|
||||
/******/ }();
|
||||
/******/
|
||||
/******/ }
|
||||
);
|
||||
@@ -0,0 +1,18 @@
|
||||
"use strict";
|
||||
/*
|
||||
* ATTENTION: An "eval-source-map" devtool has been used.
|
||||
* This devtool is neither made for production nor for readable output files.
|
||||
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
|
||||
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
||||
* or disable the default devtool with "devtool: false".
|
||||
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
||||
*/
|
||||
self["webpackHotUpdate_N_E"]("webpack",{},
|
||||
/******/ function(__webpack_require__) { // webpackRuntimeModules
|
||||
/******/ /* webpack/runtime/getFullHash */
|
||||
/******/ !function() {
|
||||
/******/ __webpack_require__.h = function() { return "e803e77acd202a08"; }
|
||||
/******/ }();
|
||||
/******/
|
||||
/******/ }
|
||||
);
|
||||
@@ -0,0 +1,18 @@
|
||||
"use strict";
|
||||
/*
|
||||
* ATTENTION: An "eval-source-map" devtool has been used.
|
||||
* This devtool is neither made for production nor for readable output files.
|
||||
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
|
||||
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
||||
* or disable the default devtool with "devtool: false".
|
||||
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
||||
*/
|
||||
self["webpackHotUpdate_N_E"]("webpack",{},
|
||||
/******/ function(__webpack_require__) { // webpackRuntimeModules
|
||||
/******/ /* webpack/runtime/getFullHash */
|
||||
/******/ !function() {
|
||||
/******/ __webpack_require__.h = function() { return "b156fa60016c21cf"; }
|
||||
/******/ }();
|
||||
/******/
|
||||
/******/ }
|
||||
);
|
||||
@@ -0,0 +1,18 @@
|
||||
"use strict";
|
||||
/*
|
||||
* ATTENTION: An "eval-source-map" devtool has been used.
|
||||
* This devtool is neither made for production nor for readable output files.
|
||||
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
|
||||
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
||||
* or disable the default devtool with "devtool: false".
|
||||
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
||||
*/
|
||||
self["webpackHotUpdate_N_E"]("webpack",{},
|
||||
/******/ function(__webpack_require__) { // webpackRuntimeModules
|
||||
/******/ /* webpack/runtime/getFullHash */
|
||||
/******/ !function() {
|
||||
/******/ __webpack_require__.h = function() { return "4907ba520745328f"; }
|
||||
/******/ }();
|
||||
/******/
|
||||
/******/ }
|
||||
);
|
||||
@@ -0,0 +1,18 @@
|
||||
"use strict";
|
||||
/*
|
||||
* ATTENTION: An "eval-source-map" devtool has been used.
|
||||
* This devtool is neither made for production nor for readable output files.
|
||||
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
|
||||
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
||||
* or disable the default devtool with "devtool: false".
|
||||
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
||||
*/
|
||||
self["webpackHotUpdate_N_E"]("webpack",{},
|
||||
/******/ function(__webpack_require__) { // webpackRuntimeModules
|
||||
/******/ /* webpack/runtime/getFullHash */
|
||||
/******/ !function() {
|
||||
/******/ __webpack_require__.h = function() { return "5c4f3d7b80335c82"; }
|
||||
/******/ }();
|
||||
/******/
|
||||
/******/ }
|
||||
);
|
||||
@@ -0,0 +1,18 @@
|
||||
"use strict";
|
||||
/*
|
||||
* ATTENTION: An "eval-source-map" devtool has been used.
|
||||
* This devtool is neither made for production nor for readable output files.
|
||||
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
|
||||
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
||||
* or disable the default devtool with "devtool: false".
|
||||
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
||||
*/
|
||||
self["webpackHotUpdate_N_E"]("webpack",{},
|
||||
/******/ function(__webpack_require__) { // webpackRuntimeModules
|
||||
/******/ /* webpack/runtime/getFullHash */
|
||||
/******/ !function() {
|
||||
/******/ __webpack_require__.h = function() { return "14b62dbaa8275210"; }
|
||||
/******/ }();
|
||||
/******/
|
||||
/******/ }
|
||||
);
|
||||
@@ -0,0 +1,18 @@
|
||||
"use strict";
|
||||
/*
|
||||
* ATTENTION: An "eval-source-map" devtool has been used.
|
||||
* This devtool is neither made for production nor for readable output files.
|
||||
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
|
||||
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
||||
* or disable the default devtool with "devtool: false".
|
||||
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
||||
*/
|
||||
self["webpackHotUpdate_N_E"]("webpack",{},
|
||||
/******/ function(__webpack_require__) { // webpackRuntimeModules
|
||||
/******/ /* webpack/runtime/getFullHash */
|
||||
/******/ !function() {
|
||||
/******/ __webpack_require__.h = function() { return "994e7beecd42381b"; }
|
||||
/******/ }();
|
||||
/******/
|
||||
/******/ }
|
||||
);
|
||||
@@ -0,0 +1,18 @@
|
||||
"use strict";
|
||||
/*
|
||||
* ATTENTION: An "eval-source-map" devtool has been used.
|
||||
* This devtool is neither made for production nor for readable output files.
|
||||
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
|
||||
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
||||
* or disable the default devtool with "devtool: false".
|
||||
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
||||
*/
|
||||
self["webpackHotUpdate_N_E"]("webpack",{},
|
||||
/******/ function(__webpack_require__) { // webpackRuntimeModules
|
||||
/******/ /* webpack/runtime/getFullHash */
|
||||
/******/ !function() {
|
||||
/******/ __webpack_require__.h = function() { return "28206c700b782558"; }
|
||||
/******/ }();
|
||||
/******/
|
||||
/******/ }
|
||||
);
|
||||
@@ -0,0 +1,18 @@
|
||||
"use strict";
|
||||
/*
|
||||
* ATTENTION: An "eval-source-map" devtool has been used.
|
||||
* This devtool is neither made for production nor for readable output files.
|
||||
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
|
||||
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
||||
* or disable the default devtool with "devtool: false".
|
||||
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
||||
*/
|
||||
self["webpackHotUpdate_N_E"]("webpack",{},
|
||||
/******/ function(__webpack_require__) { // webpackRuntimeModules
|
||||
/******/ /* webpack/runtime/getFullHash */
|
||||
/******/ !function() {
|
||||
/******/ __webpack_require__.h = function() { return "402d7af51f69ed0f"; }
|
||||
/******/ }();
|
||||
/******/
|
||||
/******/ }
|
||||
);
|
||||
79
app/frontend/.next/types/app/app/library/[topicId]/page.ts
Normal file
79
app/frontend/.next/types/app/app/library/[topicId]/page.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
// File: C:\Users\RaymondVerhoef\Gitea\learning-platform\app\frontend\src\app\app\library\[topicId]\page.tsx
|
||||
import * as entry from '../../../../../../src/app/app/library/[topicId]/page.js'
|
||||
import type { ResolvingMetadata, ResolvingViewport } from 'next/dist/lib/metadata/types/metadata-interface.js'
|
||||
|
||||
type TEntry = typeof import('../../../../../../src/app/app/library/[topicId]/page.js')
|
||||
|
||||
// Check that the entry is a valid entry
|
||||
checkFields<Diff<{
|
||||
default: Function
|
||||
config?: {}
|
||||
generateStaticParams?: Function
|
||||
revalidate?: RevalidateRange<TEntry> | false
|
||||
dynamic?: 'auto' | 'force-dynamic' | 'error' | 'force-static'
|
||||
dynamicParams?: boolean
|
||||
fetchCache?: 'auto' | 'force-no-store' | 'only-no-store' | 'default-no-store' | 'default-cache' | 'only-cache' | 'force-cache'
|
||||
preferredRegion?: 'auto' | 'global' | 'home' | string | string[]
|
||||
runtime?: 'nodejs' | 'experimental-edge' | 'edge'
|
||||
maxDuration?: number
|
||||
|
||||
metadata?: any
|
||||
generateMetadata?: Function
|
||||
viewport?: any
|
||||
generateViewport?: Function
|
||||
|
||||
}, TEntry, ''>>()
|
||||
|
||||
// Check the prop type of the entry function
|
||||
checkFields<Diff<PageProps, FirstArg<TEntry['default']>, 'default'>>()
|
||||
|
||||
// Check the arguments and return type of the generateMetadata function
|
||||
if ('generateMetadata' in entry) {
|
||||
checkFields<Diff<PageProps, FirstArg<MaybeField<TEntry, 'generateMetadata'>>, 'generateMetadata'>>()
|
||||
checkFields<Diff<ResolvingMetadata, SecondArg<MaybeField<TEntry, 'generateMetadata'>>, 'generateMetadata'>>()
|
||||
}
|
||||
|
||||
// Check the arguments and return type of the generateViewport function
|
||||
if ('generateViewport' in entry) {
|
||||
checkFields<Diff<PageProps, FirstArg<MaybeField<TEntry, 'generateViewport'>>, 'generateViewport'>>()
|
||||
checkFields<Diff<ResolvingViewport, SecondArg<MaybeField<TEntry, 'generateViewport'>>, 'generateViewport'>>()
|
||||
}
|
||||
|
||||
// Check the arguments and return type of the generateStaticParams function
|
||||
if ('generateStaticParams' in entry) {
|
||||
checkFields<Diff<{ params: PageParams }, FirstArg<MaybeField<TEntry, 'generateStaticParams'>>, 'generateStaticParams'>>()
|
||||
checkFields<Diff<{ __tag__: 'generateStaticParams', __return_type__: any[] | Promise<any[]> }, { __tag__: 'generateStaticParams', __return_type__: ReturnType<MaybeField<TEntry, 'generateStaticParams'>> }>>()
|
||||
}
|
||||
|
||||
type PageParams = any
|
||||
export interface PageProps {
|
||||
params?: any
|
||||
searchParams?: any
|
||||
}
|
||||
export interface LayoutProps {
|
||||
children?: React.ReactNode
|
||||
|
||||
params?: any
|
||||
}
|
||||
|
||||
// =============
|
||||
// Utility types
|
||||
type RevalidateRange<T> = T extends { revalidate: any } ? NonNegative<T['revalidate']> : never
|
||||
|
||||
// If T is unknown or any, it will be an empty {} type. Otherwise, it will be the same as Omit<T, keyof Base>.
|
||||
type OmitWithTag<T, K extends keyof any, _M> = Omit<T, K>
|
||||
type Diff<Base, T extends Base, Message extends string = ''> = 0 extends (1 & T) ? {} : OmitWithTag<T, keyof Base, Message>
|
||||
|
||||
type FirstArg<T extends Function> = T extends (...args: [infer T, any]) => any ? unknown extends T ? any : T : never
|
||||
type SecondArg<T extends Function> = T extends (...args: [any, infer T]) => any ? unknown extends T ? any : T : never
|
||||
type MaybeField<T, K extends string> = T extends { [k in K]: infer G } ? G extends Function ? G : never : never
|
||||
|
||||
|
||||
|
||||
function checkFields<_ extends { [k in keyof any]: never }>() {}
|
||||
|
||||
// https://github.com/sindresorhus/type-fest
|
||||
type Numeric = number | bigint
|
||||
type Zero = 0 | 0n
|
||||
type Negative<T extends Numeric> = T extends Zero ? never : `${T}` extends `-${string}` ? T : never
|
||||
type NonNegative<T extends Numeric> = T extends Zero ? T : Negative<T> extends never ? T : '__invalid_negative_number__'
|
||||
@@ -3,6 +3,7 @@ import React, { useEffect, useState } from 'react'
|
||||
import { useParams } from 'next/navigation'
|
||||
import Link from 'next/link'
|
||||
import { pb } from '@/lib/pocketbase'
|
||||
import { postGenerateAll } from '@/lib/services'
|
||||
import { TopicEditCard } from '@/components/admin/TopicEditCard'
|
||||
import { Button } from '@/components/ui/Button'
|
||||
import { StatusBadge } from '@/components/ui/StatusBadge'
|
||||
@@ -17,6 +18,7 @@ export default function ThemeDetailPage() {
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
const [publishingAll, setPublishingAll] = useState(false)
|
||||
const [approveToast, setApproveToast] = useState<string | null>(null)
|
||||
|
||||
async function load() {
|
||||
setLoading(true)
|
||||
@@ -43,17 +45,24 @@ export default function ThemeDetailPage() {
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [themeId])
|
||||
|
||||
async function handlePublishAll() {
|
||||
async function handleApproveBatch() {
|
||||
setPublishingAll(true)
|
||||
setApproveToast(null)
|
||||
try {
|
||||
// Publish all draft topics
|
||||
await Promise.all(
|
||||
topics
|
||||
.filter((t) => t.status === 'draft')
|
||||
.map((t) => pb.collection('topics').update(t.id, { status: 'published' })),
|
||||
)
|
||||
// Publish the theme
|
||||
await pb.collection('themes').update(themeId, { status: 'published' })
|
||||
// Trigger generation
|
||||
const { queued } = await postGenerateAll(themeId)
|
||||
setApproveToast(`Approved. Generation queued for ${queued} micro-learnings.`)
|
||||
void load()
|
||||
} catch {
|
||||
// refresh anyway
|
||||
} catch (err) {
|
||||
setApproveToast(err instanceof Error ? err.message : 'Approval failed')
|
||||
void load()
|
||||
} finally {
|
||||
setPublishingAll(false)
|
||||
@@ -134,16 +143,21 @@ export default function ThemeDetailPage() {
|
||||
<span style={{ fontSize: 'var(--t-body)', color: 'var(--fg-muted)' }}>
|
||||
{publishedCount} published · {draftCount} draft
|
||||
</span>
|
||||
{draftCount > 0 && (
|
||||
{theme.status !== 'published' && (
|
||||
<Button
|
||||
variant="primary"
|
||||
size="sm"
|
||||
onClick={() => void handlePublishAll()}
|
||||
onClick={() => void handleApproveBatch()}
|
||||
loading={publishingAll}
|
||||
>
|
||||
Publish all drafts ({draftCount})
|
||||
Approve batch{draftCount > 0 ? ` (${draftCount} draft${draftCount !== 1 ? 's' : ''})` : ''}
|
||||
</Button>
|
||||
)}
|
||||
{approveToast && (
|
||||
<span style={{ fontSize: 'var(--t-small)', color: 'var(--teal)', fontWeight: 500 }}>
|
||||
{approveToast}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Topics list */}
|
||||
|
||||
@@ -38,19 +38,26 @@ export function DocumentUpload({ onSuccess }: DocumentUploadProps) {
|
||||
|
||||
try {
|
||||
// Create record in PocketBase
|
||||
const format = ext.slice(1) as 'pdf' | 'md' | 'txt'
|
||||
const fd = new FormData()
|
||||
fd.append('file', file)
|
||||
fd.append('filename', file.name)
|
||||
fd.append('format', ext.slice(1) as 'pdf' | 'md' | 'txt')
|
||||
fd.append('format', format)
|
||||
fd.append('status', 'processing')
|
||||
|
||||
const doc = await pb.collection('source_documents').create<{ id: string }>(fd)
|
||||
const doc = await pb.collection('source_documents').create<{ id: string; file: string }>(fd)
|
||||
|
||||
// Build PocketBase file download URL
|
||||
const pbUrl = process.env.NEXT_PUBLIC_POCKETBASE_URL ?? 'http://localhost:8090'
|
||||
const fileUrl = `${pbUrl}/api/files/source_documents/${doc.id}/${doc.file}`
|
||||
|
||||
// Kick off ingestion
|
||||
const ingestFd = new FormData()
|
||||
ingestFd.append('documentId', doc.id)
|
||||
|
||||
const { jobId: jId } = await postIngest(ingestFd)
|
||||
const { jobId: jId } = await postIngest({
|
||||
documentId: doc.id,
|
||||
filename: file.name,
|
||||
format,
|
||||
fileUrl,
|
||||
})
|
||||
setJobId(jId)
|
||||
} catch (err) {
|
||||
setUploadError(err instanceof Error ? err.message : 'Upload failed')
|
||||
|
||||
@@ -4,6 +4,7 @@ import Link from 'next/link'
|
||||
import type { Theme } from '@/types'
|
||||
import { StatusBadge } from '@/components/ui/StatusBadge'
|
||||
import { Button } from '@/components/ui/Button'
|
||||
import { pb } from '@/lib/pocketbase'
|
||||
import { postGenerateAll } from '@/lib/services'
|
||||
|
||||
interface ThemeCardProps {
|
||||
@@ -12,24 +13,57 @@ interface ThemeCardProps {
|
||||
}
|
||||
|
||||
export function ThemeCard({ theme, onUpdate }: ThemeCardProps) {
|
||||
const [generating, setGenerating] = useState(false)
|
||||
const [approving, setApproving] = useState(false)
|
||||
const [rejecting, setRejecting] = useState(false)
|
||||
const [toast, setToast] = useState<string | null>(null)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
const [queued, setQueued] = useState<number | null>(null)
|
||||
|
||||
async function handleGenerate() {
|
||||
setGenerating(true)
|
||||
async function handleApprove() {
|
||||
setApproving(true)
|
||||
setError(null)
|
||||
setToast(null)
|
||||
try {
|
||||
const { queued: q } = await postGenerateAll(theme.id)
|
||||
setQueued(q)
|
||||
// 1. Fetch all topics in this theme
|
||||
const topics = await pb.collection('topics').getFullList<{ id: string }>({
|
||||
filter: `theme="${theme.id}"`,
|
||||
fields: 'id',
|
||||
})
|
||||
|
||||
// 2. Publish all topics
|
||||
await Promise.all(
|
||||
topics.map((t) => pb.collection('topics').update(t.id, { status: 'published' }))
|
||||
)
|
||||
|
||||
// 3. Publish the theme
|
||||
await pb.collection('themes').update(theme.id, { status: 'published' })
|
||||
|
||||
// 4. Trigger generation service
|
||||
const { queued } = await postGenerateAll(theme.id)
|
||||
setToast(`Generation queued for ${queued} micro-learnings`)
|
||||
onUpdate()
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'Generation failed')
|
||||
setError(err instanceof Error ? err.message : 'Approval failed')
|
||||
} finally {
|
||||
setGenerating(false)
|
||||
setApproving(false)
|
||||
}
|
||||
}
|
||||
|
||||
async function handleReject() {
|
||||
setRejecting(true)
|
||||
setError(null)
|
||||
try {
|
||||
await pb.collection('themes').update(theme.id, { status: 'rejected' })
|
||||
onUpdate()
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'Rejection failed')
|
||||
} finally {
|
||||
setRejecting(false)
|
||||
}
|
||||
}
|
||||
|
||||
const isPublished = theme.status === 'published'
|
||||
const isRejected = theme.status === 'rejected'
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
@@ -40,28 +74,15 @@ export function ThemeCard({ theme, onUpdate }: ThemeCardProps) {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: 'var(--s-3)',
|
||||
opacity: isRejected ? 0.6 : 1,
|
||||
}}
|
||||
>
|
||||
<div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 'var(--s-3)' }}>
|
||||
<div style={{ flex: 1, minWidth: 0 }}>
|
||||
<h3
|
||||
style={{
|
||||
margin: '0 0 var(--s-1)',
|
||||
fontSize: 'var(--t-body)',
|
||||
fontWeight: 700,
|
||||
color: 'var(--fg)',
|
||||
}}
|
||||
>
|
||||
<h3 style={{ margin: '0 0 var(--s-1)', fontSize: 'var(--t-body)', fontWeight: 700, color: 'var(--fg)' }}>
|
||||
{theme.title}
|
||||
</h3>
|
||||
<p
|
||||
style={{
|
||||
margin: 0,
|
||||
fontSize: 'var(--t-small)',
|
||||
color: 'var(--fg-muted)',
|
||||
lineHeight: 1.5,
|
||||
}}
|
||||
>
|
||||
<p style={{ margin: 0, fontSize: 'var(--t-small)', color: 'var(--fg-muted)', lineHeight: 1.5 }}>
|
||||
{theme.description}
|
||||
</p>
|
||||
</div>
|
||||
@@ -80,49 +101,34 @@ export function ThemeCard({ theme, onUpdate }: ThemeCardProps) {
|
||||
{theme.source_documents.length} source doc{theme.source_documents.length !== 1 ? 's' : ''}
|
||||
</div>
|
||||
|
||||
{queued !== null && (
|
||||
<div
|
||||
style={{
|
||||
background: 'var(--success)',
|
||||
color: 'var(--teal-900)',
|
||||
borderRadius: 'var(--r-sm)',
|
||||
padding: 'var(--s-2) var(--s-3)',
|
||||
fontSize: 'var(--t-small)',
|
||||
fontWeight: 500,
|
||||
}}
|
||||
>
|
||||
{queued} micro-learnings queued for generation
|
||||
{toast && (
|
||||
<div style={{ background: 'var(--success)', color: 'var(--teal-900)', borderRadius: 'var(--r-sm)', padding: 'var(--s-2) var(--s-3)', fontSize: 'var(--t-small)', fontWeight: 500 }}>
|
||||
{toast}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{error && (
|
||||
<div
|
||||
style={{
|
||||
background: '#f8d7da',
|
||||
color: '#c0392b',
|
||||
borderRadius: 'var(--r-sm)',
|
||||
padding: 'var(--s-2) var(--s-3)',
|
||||
fontSize: 'var(--t-small)',
|
||||
}}
|
||||
>
|
||||
<div style={{ background: '#f8d7da', color: '#c0392b', borderRadius: 'var(--r-sm)', padding: 'var(--s-2) var(--s-3)', fontSize: 'var(--t-small)' }}>
|
||||
{error}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div style={{ display: 'flex', gap: 'var(--s-2)', flexWrap: 'wrap' }}>
|
||||
{!isRejected && (
|
||||
<Link href={`/admin/knowledge/${theme.id}`} style={{ textDecoration: 'none' }}>
|
||||
<Button variant="secondary" size="sm">
|
||||
View topics
|
||||
</Button>
|
||||
<Button variant="secondary" size="sm">Edit topics</Button>
|
||||
</Link>
|
||||
<Button
|
||||
variant="primary"
|
||||
size="sm"
|
||||
onClick={() => void handleGenerate()}
|
||||
loading={generating}
|
||||
>
|
||||
Generate micro-learnings
|
||||
)}
|
||||
{!isPublished && !isRejected && (
|
||||
<>
|
||||
<Button variant="primary" size="sm" onClick={() => void handleApprove()} loading={approving}>
|
||||
Approve batch
|
||||
</Button>
|
||||
<Button variant="danger" size="sm" onClick={() => void handleReject()} loading={rejecting}>
|
||||
Reject
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -19,16 +19,22 @@ async function handleResponse<T>(res: Response): Promise<T> {
|
||||
return res.json() as Promise<T>
|
||||
}
|
||||
|
||||
export async function postIngest(formData: FormData): Promise<{ jobId: string }> {
|
||||
export async function postIngest(payload: {
|
||||
documentId: string
|
||||
filename: string
|
||||
format: 'pdf' | 'md' | 'txt'
|
||||
fileUrl: string
|
||||
}): Promise<{ jobId: string }> {
|
||||
const res = await fetch(`${INGESTION_URL}/ingest`, {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
return handleResponse<{ jobId: string }>(res)
|
||||
}
|
||||
|
||||
export async function getIngestionStatus(jobId: string): Promise<IngestionJobStatus> {
|
||||
const res = await fetch(`${INGESTION_URL}/ingest/${encodeURIComponent(jobId)}/status`)
|
||||
const res = await fetch(`${INGESTION_URL}/ingest/status/${encodeURIComponent(jobId)}`)
|
||||
return handleResponse<IngestionJobStatus>(res)
|
||||
}
|
||||
|
||||
|
||||
24
app/pb_migrations/1779567108_updated_badges.js
Normal file
24
app/pb_migrations/1779567108_updated_badges.js
Normal file
@@ -0,0 +1,24 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((db) => {
|
||||
const dao = new Dao(db)
|
||||
const collection = dao.findCollectionByNameOrId("5gl7qj7aky6wjl9")
|
||||
|
||||
collection.listRule = "@request.auth.id != \"\""
|
||||
collection.viewRule = "@request.auth.id != \"\""
|
||||
collection.createRule = "@request.auth.role = \"admin\""
|
||||
collection.updateRule = "@request.auth.role = \"admin\""
|
||||
collection.deleteRule = "@request.auth.role = \"admin\""
|
||||
|
||||
return dao.saveCollection(collection)
|
||||
}, (db) => {
|
||||
const dao = new Dao(db)
|
||||
const collection = dao.findCollectionByNameOrId("5gl7qj7aky6wjl9")
|
||||
|
||||
collection.listRule = null
|
||||
collection.viewRule = null
|
||||
collection.createRule = null
|
||||
collection.updateRule = null
|
||||
collection.deleteRule = null
|
||||
|
||||
return dao.saveCollection(collection)
|
||||
})
|
||||
24
app/pb_migrations/1779567108_updated_curriculum_versions.js
Normal file
24
app/pb_migrations/1779567108_updated_curriculum_versions.js
Normal file
@@ -0,0 +1,24 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((db) => {
|
||||
const dao = new Dao(db)
|
||||
const collection = dao.findCollectionByNameOrId("1cbepol4z1jxb20")
|
||||
|
||||
collection.listRule = "@request.auth.id != \"\""
|
||||
collection.viewRule = "@request.auth.id != \"\""
|
||||
collection.createRule = "@request.auth.role = \"admin\""
|
||||
collection.updateRule = "@request.auth.role = \"admin\""
|
||||
collection.deleteRule = "@request.auth.role = \"admin\""
|
||||
|
||||
return dao.saveCollection(collection)
|
||||
}, (db) => {
|
||||
const dao = new Dao(db)
|
||||
const collection = dao.findCollectionByNameOrId("1cbepol4z1jxb20")
|
||||
|
||||
collection.listRule = null
|
||||
collection.viewRule = null
|
||||
collection.createRule = null
|
||||
collection.updateRule = null
|
||||
collection.deleteRule = null
|
||||
|
||||
return dao.saveCollection(collection)
|
||||
})
|
||||
24
app/pb_migrations/1779567108_updated_curriculum_weeks.js
Normal file
24
app/pb_migrations/1779567108_updated_curriculum_weeks.js
Normal file
@@ -0,0 +1,24 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((db) => {
|
||||
const dao = new Dao(db)
|
||||
const collection = dao.findCollectionByNameOrId("9ivwlfc584lp63w")
|
||||
|
||||
collection.listRule = "@request.auth.id != \"\""
|
||||
collection.viewRule = "@request.auth.id != \"\""
|
||||
collection.createRule = "@request.auth.role = \"admin\""
|
||||
collection.updateRule = "@request.auth.role = \"admin\""
|
||||
collection.deleteRule = "@request.auth.role = \"admin\""
|
||||
|
||||
return dao.saveCollection(collection)
|
||||
}, (db) => {
|
||||
const dao = new Dao(db)
|
||||
const collection = dao.findCollectionByNameOrId("9ivwlfc584lp63w")
|
||||
|
||||
collection.listRule = null
|
||||
collection.viewRule = null
|
||||
collection.createRule = null
|
||||
collection.updateRule = null
|
||||
collection.deleteRule = null
|
||||
|
||||
return dao.saveCollection(collection)
|
||||
})
|
||||
24
app/pb_migrations/1779567108_updated_employee_badges.js
Normal file
24
app/pb_migrations/1779567108_updated_employee_badges.js
Normal file
@@ -0,0 +1,24 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((db) => {
|
||||
const dao = new Dao(db)
|
||||
const collection = dao.findCollectionByNameOrId("52xqp11w4t0y68u")
|
||||
|
||||
collection.listRule = "@request.auth.id != \"\""
|
||||
collection.viewRule = "@request.auth.id != \"\""
|
||||
collection.createRule = "@request.auth.role = \"admin\""
|
||||
collection.updateRule = "@request.auth.role = \"admin\""
|
||||
collection.deleteRule = "@request.auth.role = \"admin\""
|
||||
|
||||
return dao.saveCollection(collection)
|
||||
}, (db) => {
|
||||
const dao = new Dao(db)
|
||||
const collection = dao.findCollectionByNameOrId("52xqp11w4t0y68u")
|
||||
|
||||
collection.listRule = null
|
||||
collection.viewRule = null
|
||||
collection.createRule = null
|
||||
collection.updateRule = null
|
||||
collection.deleteRule = null
|
||||
|
||||
return dao.saveCollection(collection)
|
||||
})
|
||||
@@ -0,0 +1,24 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((db) => {
|
||||
const dao = new Dao(db)
|
||||
const collection = dao.findCollectionByNameOrId("516qnoxsmeomkte")
|
||||
|
||||
collection.listRule = "@request.auth.id != \"\""
|
||||
collection.viewRule = "@request.auth.id != \"\""
|
||||
collection.createRule = "@request.auth.id != \"\""
|
||||
collection.updateRule = "@request.auth.id = user"
|
||||
collection.deleteRule = "@request.auth.role = \"admin\""
|
||||
|
||||
return dao.saveCollection(collection)
|
||||
}, (db) => {
|
||||
const dao = new Dao(db)
|
||||
const collection = dao.findCollectionByNameOrId("516qnoxsmeomkte")
|
||||
|
||||
collection.listRule = null
|
||||
collection.viewRule = null
|
||||
collection.createRule = null
|
||||
collection.updateRule = null
|
||||
collection.deleteRule = null
|
||||
|
||||
return dao.saveCollection(collection)
|
||||
})
|
||||
@@ -0,0 +1,24 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((db) => {
|
||||
const dao = new Dao(db)
|
||||
const collection = dao.findCollectionByNameOrId("o9gcrudod9g510u")
|
||||
|
||||
collection.listRule = "@request.auth.id != \"\""
|
||||
collection.viewRule = "@request.auth.id != \"\""
|
||||
collection.createRule = "@request.auth.role = \"admin\""
|
||||
collection.updateRule = "@request.auth.role = \"admin\""
|
||||
collection.deleteRule = "@request.auth.role = \"admin\""
|
||||
|
||||
return dao.saveCollection(collection)
|
||||
}, (db) => {
|
||||
const dao = new Dao(db)
|
||||
const collection = dao.findCollectionByNameOrId("o9gcrudod9g510u")
|
||||
|
||||
collection.listRule = null
|
||||
collection.viewRule = null
|
||||
collection.createRule = null
|
||||
collection.updateRule = null
|
||||
collection.deleteRule = null
|
||||
|
||||
return dao.saveCollection(collection)
|
||||
})
|
||||
24
app/pb_migrations/1779567108_updated_micro_learnings.js
Normal file
24
app/pb_migrations/1779567108_updated_micro_learnings.js
Normal file
@@ -0,0 +1,24 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((db) => {
|
||||
const dao = new Dao(db)
|
||||
const collection = dao.findCollectionByNameOrId("li75ivkr87g3r94")
|
||||
|
||||
collection.listRule = "@request.auth.id != \"\""
|
||||
collection.viewRule = "@request.auth.id != \"\""
|
||||
collection.createRule = "@request.auth.role = \"admin\""
|
||||
collection.updateRule = "@request.auth.role = \"admin\""
|
||||
collection.deleteRule = "@request.auth.role = \"admin\""
|
||||
|
||||
return dao.saveCollection(collection)
|
||||
}, (db) => {
|
||||
const dao = new Dao(db)
|
||||
const collection = dao.findCollectionByNameOrId("li75ivkr87g3r94")
|
||||
|
||||
collection.listRule = null
|
||||
collection.viewRule = null
|
||||
collection.createRule = null
|
||||
collection.updateRule = null
|
||||
collection.deleteRule = null
|
||||
|
||||
return dao.saveCollection(collection)
|
||||
})
|
||||
24
app/pb_migrations/1779567108_updated_milestone_cards.js
Normal file
24
app/pb_migrations/1779567108_updated_milestone_cards.js
Normal file
@@ -0,0 +1,24 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((db) => {
|
||||
const dao = new Dao(db)
|
||||
const collection = dao.findCollectionByNameOrId("ilkfmv9xibmekna")
|
||||
|
||||
collection.listRule = "@request.auth.id != \"\""
|
||||
collection.viewRule = "@request.auth.id != \"\""
|
||||
collection.createRule = "@request.auth.role = \"admin\""
|
||||
collection.updateRule = "@request.auth.role = \"admin\""
|
||||
collection.deleteRule = "@request.auth.role = \"admin\""
|
||||
|
||||
return dao.saveCollection(collection)
|
||||
}, (db) => {
|
||||
const dao = new Dao(db)
|
||||
const collection = dao.findCollectionByNameOrId("ilkfmv9xibmekna")
|
||||
|
||||
collection.listRule = null
|
||||
collection.viewRule = null
|
||||
collection.createRule = null
|
||||
collection.updateRule = null
|
||||
collection.deleteRule = null
|
||||
|
||||
return dao.saveCollection(collection)
|
||||
})
|
||||
24
app/pb_migrations/1779567108_updated_session_completions.js
Normal file
24
app/pb_migrations/1779567108_updated_session_completions.js
Normal file
@@ -0,0 +1,24 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((db) => {
|
||||
const dao = new Dao(db)
|
||||
const collection = dao.findCollectionByNameOrId("57kc85afcdkjlje")
|
||||
|
||||
collection.listRule = "@request.auth.id != \"\""
|
||||
collection.viewRule = "@request.auth.id != \"\""
|
||||
collection.createRule = "@request.auth.id != \"\""
|
||||
collection.updateRule = ""
|
||||
collection.deleteRule = ""
|
||||
|
||||
return dao.saveCollection(collection)
|
||||
}, (db) => {
|
||||
const dao = new Dao(db)
|
||||
const collection = dao.findCollectionByNameOrId("57kc85afcdkjlje")
|
||||
|
||||
collection.listRule = null
|
||||
collection.viewRule = null
|
||||
collection.createRule = null
|
||||
collection.updateRule = null
|
||||
collection.deleteRule = null
|
||||
|
||||
return dao.saveCollection(collection)
|
||||
})
|
||||
24
app/pb_migrations/1779567108_updated_source_documents.js
Normal file
24
app/pb_migrations/1779567108_updated_source_documents.js
Normal file
@@ -0,0 +1,24 @@
|
||||
/// <reference path="../pb_data/types.d.ts" />
|
||||
migrate((db) => {
|
||||
const dao = new Dao(db)
|
||||
const collection = dao.findCollectionByNameOrId("0lr0nf3rzh5tdq3")
|
||||
|
||||
collection.listRule = "@request.auth.role = \"admin\""
|
||||
collection.viewRule = "@request.auth.role = \"admin\""
|
||||
collection.createRule = "@request.auth.role = \"admin\""
|
||||
collection.updateRule = "@request.auth.role = \"admin\""
|
||||
collection.deleteRule = "@request.auth.role = \"admin\""
|
||||
|
||||
return dao.saveCollection(collection)
|
||||
}, (db) => {
|
||||
const dao = new Dao(db)
|
||||
const collection = dao.findCollectionByNameOrId("0lr0nf3rzh5tdq3")
|
||||
|
||||
collection.listRule = null
|
||||
collection.viewRule = null
|
||||
collection.createRule = null
|
||||
collection.updateRule = null
|
||||
collection.deleteRule = null
|
||||
|
||||
return dao.saveCollection(collection)
|
||||
})
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user