From d16785e957f950e06c25982cf7b9c0668c9a84e4 Mon Sep 17 00:00:00 2001 From: Henrik Nygren Date: Wed, 6 Sep 2023 10:51:28 +0300 Subject: [PATCH 01/38] Add shared module v2 --- shared-module-v2/Readme.md | 13 + shared-module-v2/file.ts | 0 shared-module-v2/file.ts2 | 0 shared-module-v2/package-lock.json | 1307 ++++++++++++++ shared-module-v2/package.json | 17 + .../packages/create-exercise-service/index.ts | 58 + .../create-exercise-service/package-lock.json | 1562 +++++++++++++++++ .../create-exercise-service/package.json | 18 + shared-module-v2/sync.ts | 21 + 9 files changed, 2996 insertions(+) create mode 100644 shared-module-v2/Readme.md create mode 100644 shared-module-v2/file.ts create mode 100644 shared-module-v2/file.ts2 create mode 100644 shared-module-v2/package-lock.json create mode 100644 shared-module-v2/package.json create mode 100644 shared-module-v2/packages/create-exercise-service/index.ts create mode 100644 shared-module-v2/packages/create-exercise-service/package-lock.json create mode 100644 shared-module-v2/packages/create-exercise-service/package.json create mode 100644 shared-module-v2/sync.ts diff --git a/shared-module-v2/Readme.md b/shared-module-v2/Readme.md new file mode 100644 index 000000000000..9aaee6288c6d --- /dev/null +++ b/shared-module-v2/Readme.md @@ -0,0 +1,13 @@ +# Shared module + +This project consists of multiple programs that sometimes need to share code. The shared code is placed in shared module. Also, some programs are not a part of this repository, but they still need access to some parts of the shared module. Due to different programs needing access to slighty different kinds of code, the shared module has been split into multiple packages. The packages needed by external programs are published to NPM. + +The programs in the repository will use direct copies of the packages instead of the NPM packages. This is done to make it easier to develop the shared module and the programs at the same time. This is accomplished with a program synchronizes hard links of the shared modules into the programs `src` directory. The reason why we do this way is this method works well with the build and bundle our applications. + +To ensure that the syncing is up-to-date, you can use the following command on the root of the repository: + +```bash +bin/shared-module-sync-watch +``` + +See `sync.ts` for implementation details. diff --git a/shared-module-v2/file.ts b/shared-module-v2/file.ts new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/shared-module-v2/file.ts2 b/shared-module-v2/file.ts2 new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/shared-module-v2/package-lock.json b/shared-module-v2/package-lock.json new file mode 100644 index 000000000000..950f9ee0b622 --- /dev/null +++ b/shared-module-v2/package-lock.json @@ -0,0 +1,1307 @@ +{ + "name": "secret-project-shared-module", + "version": "0.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "secret-project-shared-module", + "version": "0.0.0", + "dependencies": { + "@parcel/watcher": "^2.3.0" + }, + "devDependencies": { + "tsx": "^3.12.8" + } + }, + "node_modules/@esbuild-kit/cjs-loader": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@esbuild-kit/cjs-loader/-/cjs-loader-2.4.2.tgz", + "integrity": "sha512-BDXFbYOJzT/NBEtp71cvsrGPwGAMGRB/349rwKuoxNSiKjPraNNnlK6MIIabViCjqZugu6j+xeMDlEkWdHHJSg==", + "dev": true, + "dependencies": { + "@esbuild-kit/core-utils": "^3.0.0", + "get-tsconfig": "^4.4.0" + } + }, + "node_modules/@esbuild-kit/core-utils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@esbuild-kit/core-utils/-/core-utils-3.2.2.tgz", + "integrity": "sha512-Ub6LaRaAgF80dTSzUdXpFLM1pVDdmEVB9qb5iAzSpyDlX/mfJTFGOnZ516O05p5uWWteNviMKi4PAyEuRxI5gA==", + "dev": true, + "dependencies": { + "esbuild": "~0.18.20", + "source-map-support": "^0.5.21" + } + }, + "node_modules/@esbuild-kit/esm-loader": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@esbuild-kit/esm-loader/-/esm-loader-2.5.5.tgz", + "integrity": "sha512-Qwfvj/qoPbClxCRNuac1Du01r9gvNOT+pMYtJDapfB1eoGN1YlJ1BixLyL9WVENRx5RXgNLdfYdx/CuswlGhMw==", + "dev": true, + "dependencies": { + "@esbuild-kit/core-utils": "^3.0.0", + "get-tsconfig": "^4.4.0" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", + "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", + "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", + "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", + "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", + "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", + "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", + "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", + "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", + "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", + "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", + "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", + "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", + "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", + "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", + "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", + "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", + "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", + "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", + "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", + "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", + "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", + "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@parcel/watcher": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.3.0.tgz", + "integrity": "sha512-pW7QaFiL11O0BphO+bq3MgqeX/INAk9jgBldVDYjlQPO4VddoZnF22TcF9onMhnLVHuNqBJeRf+Fj7eezi/+rQ==", + "hasInstallScript": true, + "dependencies": { + "detect-libc": "^1.0.3", + "is-glob": "^4.0.3", + "micromatch": "^4.0.5", + "node-addon-api": "^7.0.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.3.0", + "@parcel/watcher-darwin-arm64": "2.3.0", + "@parcel/watcher-darwin-x64": "2.3.0", + "@parcel/watcher-freebsd-x64": "2.3.0", + "@parcel/watcher-linux-arm-glibc": "2.3.0", + "@parcel/watcher-linux-arm64-glibc": "2.3.0", + "@parcel/watcher-linux-arm64-musl": "2.3.0", + "@parcel/watcher-linux-x64-glibc": "2.3.0", + "@parcel/watcher-linux-x64-musl": "2.3.0", + "@parcel/watcher-win32-arm64": "2.3.0", + "@parcel/watcher-win32-ia32": "2.3.0", + "@parcel/watcher-win32-x64": "2.3.0" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.3.0.tgz", + "integrity": "sha512-f4o9eA3dgk0XRT3XhB0UWpWpLnKgrh1IwNJKJ7UJek7eTYccQ8LR7XUWFKqw6aEq5KUNlCcGvSzKqSX/vtWVVA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.3.0.tgz", + "integrity": "sha512-mKY+oijI4ahBMc/GygVGvEdOq0L4DxhYgwQqYAz/7yPzuGi79oXrZG52WdpGA1wLBPrYb0T8uBaGFo7I6rvSKw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.3.0.tgz", + "integrity": "sha512-20oBj8LcEOnLE3mgpy6zuOq8AplPu9NcSSSfyVKgfOhNAc4eF4ob3ldj0xWjGGbOF7Dcy1Tvm6ytvgdjlfUeow==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.3.0.tgz", + "integrity": "sha512-7LftKlaHunueAEiojhCn+Ef2CTXWsLgTl4hq0pkhkTBFI3ssj2bJXmH2L67mKpiAD5dz66JYk4zS66qzdnIOgw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.3.0.tgz", + "integrity": "sha512-1apPw5cD2xBv1XIHPUlq0cO6iAaEUQ3BcY0ysSyD9Kuyw4MoWm1DV+W9mneWI+1g6OeP6dhikiFE6BlU+AToTQ==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.3.0.tgz", + "integrity": "sha512-mQ0gBSQEiq1k/MMkgcSB0Ic47UORZBmWoAWlMrTW6nbAGoLZP+h7AtUM7H3oDu34TBFFvjy4JCGP43JlylkTQA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.3.0.tgz", + "integrity": "sha512-LXZAExpepJew0Gp8ZkJ+xDZaTQjLHv48h0p0Vw2VMFQ8A+RKrAvpFuPVCVwKJCr5SE+zvaG+Etg56qXvTDIedw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.3.0.tgz", + "integrity": "sha512-P7Wo91lKSeSgMTtG7CnBS6WrA5otr1K7shhSjKHNePVmfBHDoAOHYRXgUmhiNfbcGk0uMCHVcdbfxtuiZCHVow==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.3.0.tgz", + "integrity": "sha512-+kiRE1JIq8QdxzwoYY+wzBs9YbJ34guBweTK8nlzLKimn5EQ2b2FSC+tAOpq302BuIMjyuUGvBiUhEcLIGMQ5g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.3.0.tgz", + "integrity": "sha512-35gXCnaz1AqIXpG42evcoP2+sNL62gZTMZne3IackM+6QlfMcJLy3DrjuL6Iks7Czpd3j4xRBzez3ADCj1l7Aw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.3.0.tgz", + "integrity": "sha512-FJS/IBQHhRpZ6PiCjFt1UAcPr0YmCLHRbTc00IBTrelEjlmmgIVLeOx4MSXzx2HFEy5Jo5YdhGpxCuqCyDJ5ow==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.3.0.tgz", + "integrity": "sha512-dLx+0XRdMnVI62kU3wbXvbIRhLck4aE28bIGKbRGS7BJNt54IIj9+c/Dkqb+7DJEbHUZAX1bwaoM8PqVlHJmCA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esbuild": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", + "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.18.20", + "@esbuild/android-arm64": "0.18.20", + "@esbuild/android-x64": "0.18.20", + "@esbuild/darwin-arm64": "0.18.20", + "@esbuild/darwin-x64": "0.18.20", + "@esbuild/freebsd-arm64": "0.18.20", + "@esbuild/freebsd-x64": "0.18.20", + "@esbuild/linux-arm": "0.18.20", + "@esbuild/linux-arm64": "0.18.20", + "@esbuild/linux-ia32": "0.18.20", + "@esbuild/linux-loong64": "0.18.20", + "@esbuild/linux-mips64el": "0.18.20", + "@esbuild/linux-ppc64": "0.18.20", + "@esbuild/linux-riscv64": "0.18.20", + "@esbuild/linux-s390x": "0.18.20", + "@esbuild/linux-x64": "0.18.20", + "@esbuild/netbsd-x64": "0.18.20", + "@esbuild/openbsd-x64": "0.18.20", + "@esbuild/sunos-x64": "0.18.20", + "@esbuild/win32-arm64": "0.18.20", + "@esbuild/win32-ia32": "0.18.20", + "@esbuild/win32-x64": "0.18.20" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-tsconfig": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.0.tgz", + "integrity": "sha512-pmjiZ7xtB8URYm74PlGJozDNyhvsVLUcpBa8DZBG3bWHwaHa9bPiRpiSfovw+fjhwONSCWKRyk+JQHEGZmMrzw==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/node-addon-api": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.0.0.tgz", + "integrity": "sha512-vgbBJTS4m5/KkE16t5Ly0WW9hz46swAstv0hYYwMtbG7AznRhNyfLRe8HZAiWIpcHzoO7HxhLuBQj9rJ/Ho0ZA==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tsx": { + "version": "3.12.8", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-3.12.8.tgz", + "integrity": "sha512-Lt9KYaRGF023tlLInPj8rgHwsZU8qWLBj4iRXNWxTfjIkU7canGL806AqKear1j722plHuiYNcL2ZCo6uS9UJA==", + "dev": true, + "dependencies": { + "@esbuild-kit/cjs-loader": "^2.4.2", + "@esbuild-kit/core-utils": "^3.2.2", + "@esbuild-kit/esm-loader": "^2.5.5" + }, + "bin": { + "tsx": "dist/cli.js" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + } + }, + "dependencies": { + "@esbuild-kit/cjs-loader": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@esbuild-kit/cjs-loader/-/cjs-loader-2.4.2.tgz", + "integrity": "sha512-BDXFbYOJzT/NBEtp71cvsrGPwGAMGRB/349rwKuoxNSiKjPraNNnlK6MIIabViCjqZugu6j+xeMDlEkWdHHJSg==", + "dev": true, + "requires": { + "@esbuild-kit/core-utils": "^3.0.0", + "get-tsconfig": "^4.4.0" + } + }, + "@esbuild-kit/core-utils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@esbuild-kit/core-utils/-/core-utils-3.2.2.tgz", + "integrity": "sha512-Ub6LaRaAgF80dTSzUdXpFLM1pVDdmEVB9qb5iAzSpyDlX/mfJTFGOnZ516O05p5uWWteNviMKi4PAyEuRxI5gA==", + "dev": true, + "requires": { + "esbuild": "~0.18.20", + "source-map-support": "^0.5.21" + } + }, + "@esbuild-kit/esm-loader": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@esbuild-kit/esm-loader/-/esm-loader-2.5.5.tgz", + "integrity": "sha512-Qwfvj/qoPbClxCRNuac1Du01r9gvNOT+pMYtJDapfB1eoGN1YlJ1BixLyL9WVENRx5RXgNLdfYdx/CuswlGhMw==", + "dev": true, + "requires": { + "@esbuild-kit/core-utils": "^3.0.0", + "get-tsconfig": "^4.4.0" + } + }, + "@esbuild/android-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", + "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", + "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", + "dev": true, + "optional": true + }, + "@esbuild/android-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", + "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", + "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", + "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", + "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", + "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", + "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", + "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", + "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", + "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-mips64el": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", + "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ppc64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", + "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-riscv64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", + "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", + "dev": true, + "optional": true + }, + "@esbuild/linux-s390x": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", + "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", + "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", + "dev": true, + "optional": true + }, + "@esbuild/netbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", + "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", + "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", + "dev": true, + "optional": true + }, + "@esbuild/sunos-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", + "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", + "dev": true, + "optional": true + }, + "@esbuild/win32-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", + "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", + "dev": true, + "optional": true + }, + "@esbuild/win32-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", + "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", + "dev": true, + "optional": true + }, + "@esbuild/win32-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", + "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", + "dev": true, + "optional": true + }, + "@parcel/watcher": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.3.0.tgz", + "integrity": "sha512-pW7QaFiL11O0BphO+bq3MgqeX/INAk9jgBldVDYjlQPO4VddoZnF22TcF9onMhnLVHuNqBJeRf+Fj7eezi/+rQ==", + "requires": { + "@parcel/watcher-android-arm64": "2.3.0", + "@parcel/watcher-darwin-arm64": "2.3.0", + "@parcel/watcher-darwin-x64": "2.3.0", + "@parcel/watcher-freebsd-x64": "2.3.0", + "@parcel/watcher-linux-arm-glibc": "2.3.0", + "@parcel/watcher-linux-arm64-glibc": "2.3.0", + "@parcel/watcher-linux-arm64-musl": "2.3.0", + "@parcel/watcher-linux-x64-glibc": "2.3.0", + "@parcel/watcher-linux-x64-musl": "2.3.0", + "@parcel/watcher-win32-arm64": "2.3.0", + "@parcel/watcher-win32-ia32": "2.3.0", + "@parcel/watcher-win32-x64": "2.3.0", + "detect-libc": "^1.0.3", + "is-glob": "^4.0.3", + "micromatch": "^4.0.5", + "node-addon-api": "^7.0.0" + } + }, + "@parcel/watcher-android-arm64": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.3.0.tgz", + "integrity": "sha512-f4o9eA3dgk0XRT3XhB0UWpWpLnKgrh1IwNJKJ7UJek7eTYccQ8LR7XUWFKqw6aEq5KUNlCcGvSzKqSX/vtWVVA==", + "optional": true + }, + "@parcel/watcher-darwin-arm64": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.3.0.tgz", + "integrity": "sha512-mKY+oijI4ahBMc/GygVGvEdOq0L4DxhYgwQqYAz/7yPzuGi79oXrZG52WdpGA1wLBPrYb0T8uBaGFo7I6rvSKw==", + "optional": true + }, + "@parcel/watcher-darwin-x64": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.3.0.tgz", + "integrity": "sha512-20oBj8LcEOnLE3mgpy6zuOq8AplPu9NcSSSfyVKgfOhNAc4eF4ob3ldj0xWjGGbOF7Dcy1Tvm6ytvgdjlfUeow==", + "optional": true + }, + "@parcel/watcher-freebsd-x64": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.3.0.tgz", + "integrity": "sha512-7LftKlaHunueAEiojhCn+Ef2CTXWsLgTl4hq0pkhkTBFI3ssj2bJXmH2L67mKpiAD5dz66JYk4zS66qzdnIOgw==", + "optional": true + }, + "@parcel/watcher-linux-arm-glibc": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.3.0.tgz", + "integrity": "sha512-1apPw5cD2xBv1XIHPUlq0cO6iAaEUQ3BcY0ysSyD9Kuyw4MoWm1DV+W9mneWI+1g6OeP6dhikiFE6BlU+AToTQ==", + "optional": true + }, + "@parcel/watcher-linux-arm64-glibc": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.3.0.tgz", + "integrity": "sha512-mQ0gBSQEiq1k/MMkgcSB0Ic47UORZBmWoAWlMrTW6nbAGoLZP+h7AtUM7H3oDu34TBFFvjy4JCGP43JlylkTQA==", + "optional": true + }, + "@parcel/watcher-linux-arm64-musl": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.3.0.tgz", + "integrity": "sha512-LXZAExpepJew0Gp8ZkJ+xDZaTQjLHv48h0p0Vw2VMFQ8A+RKrAvpFuPVCVwKJCr5SE+zvaG+Etg56qXvTDIedw==", + "optional": true + }, + "@parcel/watcher-linux-x64-glibc": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.3.0.tgz", + "integrity": "sha512-P7Wo91lKSeSgMTtG7CnBS6WrA5otr1K7shhSjKHNePVmfBHDoAOHYRXgUmhiNfbcGk0uMCHVcdbfxtuiZCHVow==", + "optional": true + }, + "@parcel/watcher-linux-x64-musl": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.3.0.tgz", + "integrity": "sha512-+kiRE1JIq8QdxzwoYY+wzBs9YbJ34guBweTK8nlzLKimn5EQ2b2FSC+tAOpq302BuIMjyuUGvBiUhEcLIGMQ5g==", + "optional": true + }, + "@parcel/watcher-win32-arm64": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.3.0.tgz", + "integrity": "sha512-35gXCnaz1AqIXpG42evcoP2+sNL62gZTMZne3IackM+6QlfMcJLy3DrjuL6Iks7Czpd3j4xRBzez3ADCj1l7Aw==", + "optional": true + }, + "@parcel/watcher-win32-ia32": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.3.0.tgz", + "integrity": "sha512-FJS/IBQHhRpZ6PiCjFt1UAcPr0YmCLHRbTc00IBTrelEjlmmgIVLeOx4MSXzx2HFEy5Jo5YdhGpxCuqCyDJ5ow==", + "optional": true + }, + "@parcel/watcher-win32-x64": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.3.0.tgz", + "integrity": "sha512-dLx+0XRdMnVI62kU3wbXvbIRhLck4aE28bIGKbRGS7BJNt54IIj9+c/Dkqb+7DJEbHUZAX1bwaoM8PqVlHJmCA==", + "optional": true + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "requires": { + "fill-range": "^7.0.1" + } + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==" + }, + "esbuild": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", + "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", + "dev": true, + "requires": { + "@esbuild/android-arm": "0.18.20", + "@esbuild/android-arm64": "0.18.20", + "@esbuild/android-x64": "0.18.20", + "@esbuild/darwin-arm64": "0.18.20", + "@esbuild/darwin-x64": "0.18.20", + "@esbuild/freebsd-arm64": "0.18.20", + "@esbuild/freebsd-x64": "0.18.20", + "@esbuild/linux-arm": "0.18.20", + "@esbuild/linux-arm64": "0.18.20", + "@esbuild/linux-ia32": "0.18.20", + "@esbuild/linux-loong64": "0.18.20", + "@esbuild/linux-mips64el": "0.18.20", + "@esbuild/linux-ppc64": "0.18.20", + "@esbuild/linux-riscv64": "0.18.20", + "@esbuild/linux-s390x": "0.18.20", + "@esbuild/linux-x64": "0.18.20", + "@esbuild/netbsd-x64": "0.18.20", + "@esbuild/openbsd-x64": "0.18.20", + "@esbuild/sunos-x64": "0.18.20", + "@esbuild/win32-arm64": "0.18.20", + "@esbuild/win32-ia32": "0.18.20", + "@esbuild/win32-x64": "0.18.20" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "optional": true + }, + "get-tsconfig": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.0.tgz", + "integrity": "sha512-pmjiZ7xtB8URYm74PlGJozDNyhvsVLUcpBa8DZBG3bWHwaHa9bPiRpiSfovw+fjhwONSCWKRyk+JQHEGZmMrzw==", + "dev": true, + "requires": { + "resolve-pkg-maps": "^1.0.0" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "node-addon-api": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.0.0.tgz", + "integrity": "sha512-vgbBJTS4m5/KkE16t5Ly0WW9hz46swAstv0hYYwMtbG7AznRhNyfLRe8HZAiWIpcHzoO7HxhLuBQj9rJ/Ho0ZA==" + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + }, + "resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + } + }, + "tsx": { + "version": "3.12.8", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-3.12.8.tgz", + "integrity": "sha512-Lt9KYaRGF023tlLInPj8rgHwsZU8qWLBj4iRXNWxTfjIkU7canGL806AqKear1j722plHuiYNcL2ZCo6uS9UJA==", + "dev": true, + "requires": { + "@esbuild-kit/cjs-loader": "^2.4.2", + "@esbuild-kit/core-utils": "^3.2.2", + "@esbuild-kit/esm-loader": "^2.5.5", + "fsevents": "~2.3.2" + } + } + } +} diff --git a/shared-module-v2/package.json b/shared-module-v2/package.json new file mode 100644 index 000000000000..c705432d7331 --- /dev/null +++ b/shared-module-v2/package.json @@ -0,0 +1,17 @@ +{ + "name": "secret-project-shared-module", + "version": "0.0.0", + "description": "", + "main": "index.js", + "scripts": { + "sync": "tsx sync.ts" + }, + "keywords": [], + "author": "Henrik Nygren ", + "devDependencies": { + "tsx": "^3.12.8" + }, + "dependencies": { + "@parcel/watcher": "^2.3.0" + } +} diff --git a/shared-module-v2/packages/create-exercise-service/index.ts b/shared-module-v2/packages/create-exercise-service/index.ts new file mode 100644 index 000000000000..fef3a6bfb0de --- /dev/null +++ b/shared-module-v2/packages/create-exercise-service/index.ts @@ -0,0 +1,58 @@ +import { confirm, input, select } from "@inquirer/prompts" +import { resolve } from "path" + +async function main() { + const projectName = await input({ + message: "Project name", + validate: (value) => value.length > 0, + }) + const projectPath = await input({ + message: "Path to the project", + validate: (value) => value.length > 0, + default: `${projectName}`, + }) + const projectType = await select({ + message: "Project type", + choices: [ + { + name: "React", + value: "react", + description: + "An exercise service built with React using the Next.js framework and using Typescript..", + }, + { + name: "Svelte", + disabled: "Not implemented yet", + value: "svelte", + description: "Svelte with SvelteKit, using typescript", + }, + { + name: "No framework (not recommended)", + disabled: "Not implemented yet", + value: "no-framework", + description: + "No framework, just plain HTML, CSS and JS. This is a simplistic example that demonstrates that the exercise services are not tied to any frontend frameworks. Please choose some framework if you want to build something that is both usable and maintainable.", + }, + ], + }) + const packageManager = await select({ + message: "Package manager", + choices: [ + { name: "npm", value: "npm" }, + { name: "yarn", value: "yarn" }, + { name: "pnpm", value: "pnpm" }, + ], + }) + // convert projectPath to an absolute path + const absoluteProjectPath = resolve(projectPath) + const confirmation = await confirm({ + message: `The project will be created in ${absoluteProjectPath}. Continue?`, + default: false, + }) + if (!confirmation) { + console.log("Aborting") + return + } +} + +main() diff --git a/shared-module-v2/packages/create-exercise-service/package-lock.json b/shared-module-v2/packages/create-exercise-service/package-lock.json new file mode 100644 index 000000000000..cb7ed469bf50 --- /dev/null +++ b/shared-module-v2/packages/create-exercise-service/package-lock.json @@ -0,0 +1,1562 @@ +{ + "name": "@moocfi/create-exercise-service", + "version": "0.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "@moocfi/create-exercise-service", + "version": "0.0.0", + "license": "Apache-2.0", + "dependencies": { + "@inquirer/prompts": "^3.0.4" + }, + "devDependencies": { + "tsx": "^3.12.8", + "typescript": "^5.2.2" + } + }, + "node_modules/@esbuild-kit/cjs-loader": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@esbuild-kit/cjs-loader/-/cjs-loader-2.4.2.tgz", + "integrity": "sha512-BDXFbYOJzT/NBEtp71cvsrGPwGAMGRB/349rwKuoxNSiKjPraNNnlK6MIIabViCjqZugu6j+xeMDlEkWdHHJSg==", + "dev": true, + "dependencies": { + "@esbuild-kit/core-utils": "^3.0.0", + "get-tsconfig": "^4.4.0" + } + }, + "node_modules/@esbuild-kit/core-utils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@esbuild-kit/core-utils/-/core-utils-3.2.2.tgz", + "integrity": "sha512-Ub6LaRaAgF80dTSzUdXpFLM1pVDdmEVB9qb5iAzSpyDlX/mfJTFGOnZ516O05p5uWWteNviMKi4PAyEuRxI5gA==", + "dev": true, + "dependencies": { + "esbuild": "~0.18.20", + "source-map-support": "^0.5.21" + } + }, + "node_modules/@esbuild-kit/esm-loader": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@esbuild-kit/esm-loader/-/esm-loader-2.5.5.tgz", + "integrity": "sha512-Qwfvj/qoPbClxCRNuac1Du01r9gvNOT+pMYtJDapfB1eoGN1YlJ1BixLyL9WVENRx5RXgNLdfYdx/CuswlGhMw==", + "dev": true, + "dependencies": { + "@esbuild-kit/core-utils": "^3.0.0", + "get-tsconfig": "^4.4.0" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", + "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", + "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", + "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", + "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", + "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", + "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", + "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", + "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", + "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", + "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", + "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", + "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", + "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", + "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", + "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", + "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", + "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", + "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", + "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", + "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", + "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", + "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@inquirer/checkbox": { + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-1.3.9.tgz", + "integrity": "sha512-PQJ0XEijmoXxp7QBnUIiYvqx9YC4c/MyJY5UIDXzsyrSY56xuWyi95ggaKq4KMbcjXfxmXSwuqEYbzWu3hAFuQ==", + "dependencies": { + "@inquirer/core": "^4.0.0", + "@inquirer/type": "^1.1.2", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "figures": "^3.2.0" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/@inquirer/confirm": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-2.0.10.tgz", + "integrity": "sha512-P2B3LgCn26EfK9LeSGbi6WWNg/Q7ZTZYERZ2YRJtNaQC4dEXDWt5xDkgKEHXopBeaBXrlBpHQ7Lb3IdhvWnCfQ==", + "dependencies": { + "@inquirer/core": "^4.0.0", + "@inquirer/type": "^1.1.2", + "chalk": "^4.1.2" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/@inquirer/core": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-4.0.0.tgz", + "integrity": "sha512-YBo2o6ijIatBU1l1ziByZeVF4YdzKQnYs8tBJ8SnysgmK3YYQz/L/w5w7QXs4OVnbzTWhXiC4mn9gQGbDihsPQ==", + "dependencies": { + "@inquirer/type": "^1.1.2", + "@types/mute-stream": "^0.0.1", + "@types/node": "^20.5.6", + "@types/wrap-ansi": "^3.0.0", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "cli-spinners": "^2.9.0", + "cli-width": "^4.1.0", + "figures": "^3.2.0", + "mute-stream": "^1.0.0", + "run-async": "^3.0.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/@inquirer/editor": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-1.2.8.tgz", + "integrity": "sha512-DzvzhtLmkVEzfphCbEQz63IuTwmgpeSyyaKrHwCsKYr/eUaMLksQz33VrHbwYbsBq4oNm14OkikrVIMC/XhhPw==", + "dependencies": { + "@inquirer/core": "^4.0.0", + "@inquirer/type": "^1.1.2", + "chalk": "^4.1.2", + "external-editor": "^3.1.0" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/@inquirer/expand": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-1.1.9.tgz", + "integrity": "sha512-8XuyeEVAEDCuDfK4+LVsOKfIOaC/Hen5nq+yMgyoQi4DgG77uLFtzjFBgOC0+HTEOugznF66DoWskUOmIN4x5Q==", + "dependencies": { + "@inquirer/core": "^4.0.0", + "@inquirer/type": "^1.1.2", + "chalk": "^4.1.2", + "figures": "^3.2.0" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/@inquirer/input": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-1.2.9.tgz", + "integrity": "sha512-FC/wnXklGwUcGtlOU67T3pKHu6l1L5tIOHbZcqoLTlsdG8ukNARrX8h9Xrdgfr29t/LbvSxqdvYRmn4u2XRz0Q==", + "dependencies": { + "@inquirer/core": "^4.0.0", + "@inquirer/type": "^1.1.2", + "chalk": "^4.1.2" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/@inquirer/password": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-1.1.9.tgz", + "integrity": "sha512-6L/SimCHutKVPDjkJBAkGO0POdJA3VXbdgAhCsX9katuyQSiMq5WGGa2Nqv7zXqiZxL5YuTPFqNNKKq00Q1HxA==", + "dependencies": { + "@inquirer/input": "^1.2.9", + "@inquirer/type": "^1.1.2", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/@inquirer/prompts": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-3.0.4.tgz", + "integrity": "sha512-xSBQjaj0zKGb+o6MiTd/Igl609JOwFf/DyU0vyiFiFR7u65n8JgCFVWLSeOWEFUP8L+AOGxZolhvuJ8KgCxIrg==", + "dependencies": { + "@inquirer/checkbox": "^1.3.9", + "@inquirer/confirm": "^2.0.10", + "@inquirer/core": "^4.0.0", + "@inquirer/editor": "^1.2.8", + "@inquirer/expand": "^1.1.9", + "@inquirer/input": "^1.2.9", + "@inquirer/password": "^1.1.9", + "@inquirer/rawlist": "^1.2.9", + "@inquirer/select": "^1.2.9" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/@inquirer/rawlist": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-1.2.9.tgz", + "integrity": "sha512-HqZeTP/F0l9LE0uCSbPHUbxVjoh8TLPzy8+BJzXyS9Na+XbbMOGN7KVNkNEGY+GH7X05jdOtd4gsO9DtAJUM2Q==", + "dependencies": { + "@inquirer/core": "^4.0.0", + "@inquirer/type": "^1.1.2", + "chalk": "^4.1.2" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/@inquirer/select": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-1.2.9.tgz", + "integrity": "sha512-WXMQfUGzxrxdbDCU50xKqYCMoz+SOZnyV8sOeEJ8Ei5AjANz1fap3xA7EF8aZLJ9K1//m4OnyS/XDoi31Tqn+g==", + "dependencies": { + "@inquirer/core": "^4.0.0", + "@inquirer/type": "^1.1.2", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "figures": "^3.2.0" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/@inquirer/type": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.1.2.tgz", + "integrity": "sha512-lowHTIBAE/bltg7/EchMDLfKUdT0BCyS2xzqgjsyKADybz2QZ0cLWtDXzjT1C6rdZI07Ng9jU4d2R9rDoU+6Hw==", + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/@types/mute-stream": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@types/mute-stream/-/mute-stream-0.0.1.tgz", + "integrity": "sha512-0yQLzYhCqGz7CQPE3iDmYjhb7KMBFOP+tBkyw+/Y2YyDI5wpS7itXXxneN1zSsUwWx3Ji6YiVYrhAnpQGS/vkw==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "20.5.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.9.tgz", + "integrity": "sha512-PcGNd//40kHAS3sTlzKB9C9XL4K0sTup8nbG5lC14kzEteTNuAFh9u5nA0o5TWnSG2r/JNPRXFVcHJIIeRlmqQ==" + }, + "node_modules/@types/wrap-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz", + "integrity": "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==" + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" + }, + "node_modules/cli-spinners": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.0.tgz", + "integrity": "sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "engines": { + "node": ">= 12" + } + }, + "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==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "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==" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/esbuild": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", + "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.18.20", + "@esbuild/android-arm64": "0.18.20", + "@esbuild/android-x64": "0.18.20", + "@esbuild/darwin-arm64": "0.18.20", + "@esbuild/darwin-x64": "0.18.20", + "@esbuild/freebsd-arm64": "0.18.20", + "@esbuild/freebsd-x64": "0.18.20", + "@esbuild/linux-arm": "0.18.20", + "@esbuild/linux-arm64": "0.18.20", + "@esbuild/linux-ia32": "0.18.20", + "@esbuild/linux-loong64": "0.18.20", + "@esbuild/linux-mips64el": "0.18.20", + "@esbuild/linux-ppc64": "0.18.20", + "@esbuild/linux-riscv64": "0.18.20", + "@esbuild/linux-s390x": "0.18.20", + "@esbuild/linux-x64": "0.18.20", + "@esbuild/netbsd-x64": "0.18.20", + "@esbuild/openbsd-x64": "0.18.20", + "@esbuild/sunos-x64": "0.18.20", + "@esbuild/win32-arm64": "0.18.20", + "@esbuild/win32-ia32": "0.18.20", + "@esbuild/win32-x64": "0.18.20" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-tsconfig": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.0.tgz", + "integrity": "sha512-pmjiZ7xtB8URYm74PlGJozDNyhvsVLUcpBa8DZBG3bWHwaHa9bPiRpiSfovw+fjhwONSCWKRyk+JQHEGZmMrzw==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/mute-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/run-async": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", + "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/tsx": { + "version": "3.12.8", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-3.12.8.tgz", + "integrity": "sha512-Lt9KYaRGF023tlLInPj8rgHwsZU8qWLBj4iRXNWxTfjIkU7canGL806AqKear1j722plHuiYNcL2ZCo6uS9UJA==", + "dev": true, + "dependencies": { + "@esbuild-kit/cjs-loader": "^2.4.2", + "@esbuild-kit/core-utils": "^3.2.2", + "@esbuild-kit/esm-loader": "^2.5.5" + }, + "bin": { + "tsx": "dist/cli.js" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + } + }, + "dependencies": { + "@esbuild-kit/cjs-loader": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@esbuild-kit/cjs-loader/-/cjs-loader-2.4.2.tgz", + "integrity": "sha512-BDXFbYOJzT/NBEtp71cvsrGPwGAMGRB/349rwKuoxNSiKjPraNNnlK6MIIabViCjqZugu6j+xeMDlEkWdHHJSg==", + "dev": true, + "requires": { + "@esbuild-kit/core-utils": "^3.0.0", + "get-tsconfig": "^4.4.0" + } + }, + "@esbuild-kit/core-utils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@esbuild-kit/core-utils/-/core-utils-3.2.2.tgz", + "integrity": "sha512-Ub6LaRaAgF80dTSzUdXpFLM1pVDdmEVB9qb5iAzSpyDlX/mfJTFGOnZ516O05p5uWWteNviMKi4PAyEuRxI5gA==", + "dev": true, + "requires": { + "esbuild": "~0.18.20", + "source-map-support": "^0.5.21" + } + }, + "@esbuild-kit/esm-loader": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@esbuild-kit/esm-loader/-/esm-loader-2.5.5.tgz", + "integrity": "sha512-Qwfvj/qoPbClxCRNuac1Du01r9gvNOT+pMYtJDapfB1eoGN1YlJ1BixLyL9WVENRx5RXgNLdfYdx/CuswlGhMw==", + "dev": true, + "requires": { + "@esbuild-kit/core-utils": "^3.0.0", + "get-tsconfig": "^4.4.0" + } + }, + "@esbuild/android-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", + "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", + "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", + "dev": true, + "optional": true + }, + "@esbuild/android-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", + "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", + "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", + "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", + "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", + "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", + "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", + "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", + "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", + "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-mips64el": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", + "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ppc64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", + "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-riscv64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", + "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", + "dev": true, + "optional": true + }, + "@esbuild/linux-s390x": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", + "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", + "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", + "dev": true, + "optional": true + }, + "@esbuild/netbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", + "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", + "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", + "dev": true, + "optional": true + }, + "@esbuild/sunos-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", + "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", + "dev": true, + "optional": true + }, + "@esbuild/win32-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", + "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", + "dev": true, + "optional": true + }, + "@esbuild/win32-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", + "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", + "dev": true, + "optional": true + }, + "@esbuild/win32-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", + "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", + "dev": true, + "optional": true + }, + "@inquirer/checkbox": { + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-1.3.9.tgz", + "integrity": "sha512-PQJ0XEijmoXxp7QBnUIiYvqx9YC4c/MyJY5UIDXzsyrSY56xuWyi95ggaKq4KMbcjXfxmXSwuqEYbzWu3hAFuQ==", + "requires": { + "@inquirer/core": "^4.0.0", + "@inquirer/type": "^1.1.2", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "figures": "^3.2.0" + } + }, + "@inquirer/confirm": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-2.0.10.tgz", + "integrity": "sha512-P2B3LgCn26EfK9LeSGbi6WWNg/Q7ZTZYERZ2YRJtNaQC4dEXDWt5xDkgKEHXopBeaBXrlBpHQ7Lb3IdhvWnCfQ==", + "requires": { + "@inquirer/core": "^4.0.0", + "@inquirer/type": "^1.1.2", + "chalk": "^4.1.2" + } + }, + "@inquirer/core": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-4.0.0.tgz", + "integrity": "sha512-YBo2o6ijIatBU1l1ziByZeVF4YdzKQnYs8tBJ8SnysgmK3YYQz/L/w5w7QXs4OVnbzTWhXiC4mn9gQGbDihsPQ==", + "requires": { + "@inquirer/type": "^1.1.2", + "@types/mute-stream": "^0.0.1", + "@types/node": "^20.5.6", + "@types/wrap-ansi": "^3.0.0", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "cli-spinners": "^2.9.0", + "cli-width": "^4.1.0", + "figures": "^3.2.0", + "mute-stream": "^1.0.0", + "run-async": "^3.0.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0" + } + }, + "@inquirer/editor": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-1.2.8.tgz", + "integrity": "sha512-DzvzhtLmkVEzfphCbEQz63IuTwmgpeSyyaKrHwCsKYr/eUaMLksQz33VrHbwYbsBq4oNm14OkikrVIMC/XhhPw==", + "requires": { + "@inquirer/core": "^4.0.0", + "@inquirer/type": "^1.1.2", + "chalk": "^4.1.2", + "external-editor": "^3.1.0" + } + }, + "@inquirer/expand": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-1.1.9.tgz", + "integrity": "sha512-8XuyeEVAEDCuDfK4+LVsOKfIOaC/Hen5nq+yMgyoQi4DgG77uLFtzjFBgOC0+HTEOugznF66DoWskUOmIN4x5Q==", + "requires": { + "@inquirer/core": "^4.0.0", + "@inquirer/type": "^1.1.2", + "chalk": "^4.1.2", + "figures": "^3.2.0" + } + }, + "@inquirer/input": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-1.2.9.tgz", + "integrity": "sha512-FC/wnXklGwUcGtlOU67T3pKHu6l1L5tIOHbZcqoLTlsdG8ukNARrX8h9Xrdgfr29t/LbvSxqdvYRmn4u2XRz0Q==", + "requires": { + "@inquirer/core": "^4.0.0", + "@inquirer/type": "^1.1.2", + "chalk": "^4.1.2" + } + }, + "@inquirer/password": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-1.1.9.tgz", + "integrity": "sha512-6L/SimCHutKVPDjkJBAkGO0POdJA3VXbdgAhCsX9katuyQSiMq5WGGa2Nqv7zXqiZxL5YuTPFqNNKKq00Q1HxA==", + "requires": { + "@inquirer/input": "^1.2.9", + "@inquirer/type": "^1.1.2", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2" + } + }, + "@inquirer/prompts": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-3.0.4.tgz", + "integrity": "sha512-xSBQjaj0zKGb+o6MiTd/Igl609JOwFf/DyU0vyiFiFR7u65n8JgCFVWLSeOWEFUP8L+AOGxZolhvuJ8KgCxIrg==", + "requires": { + "@inquirer/checkbox": "^1.3.9", + "@inquirer/confirm": "^2.0.10", + "@inquirer/core": "^4.0.0", + "@inquirer/editor": "^1.2.8", + "@inquirer/expand": "^1.1.9", + "@inquirer/input": "^1.2.9", + "@inquirer/password": "^1.1.9", + "@inquirer/rawlist": "^1.2.9", + "@inquirer/select": "^1.2.9" + } + }, + "@inquirer/rawlist": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-1.2.9.tgz", + "integrity": "sha512-HqZeTP/F0l9LE0uCSbPHUbxVjoh8TLPzy8+BJzXyS9Na+XbbMOGN7KVNkNEGY+GH7X05jdOtd4gsO9DtAJUM2Q==", + "requires": { + "@inquirer/core": "^4.0.0", + "@inquirer/type": "^1.1.2", + "chalk": "^4.1.2" + } + }, + "@inquirer/select": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-1.2.9.tgz", + "integrity": "sha512-WXMQfUGzxrxdbDCU50xKqYCMoz+SOZnyV8sOeEJ8Ei5AjANz1fap3xA7EF8aZLJ9K1//m4OnyS/XDoi31Tqn+g==", + "requires": { + "@inquirer/core": "^4.0.0", + "@inquirer/type": "^1.1.2", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "figures": "^3.2.0" + } + }, + "@inquirer/type": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.1.2.tgz", + "integrity": "sha512-lowHTIBAE/bltg7/EchMDLfKUdT0BCyS2xzqgjsyKADybz2QZ0cLWtDXzjT1C6rdZI07Ng9jU4d2R9rDoU+6Hw==" + }, + "@types/mute-stream": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@types/mute-stream/-/mute-stream-0.0.1.tgz", + "integrity": "sha512-0yQLzYhCqGz7CQPE3iDmYjhb7KMBFOP+tBkyw+/Y2YyDI5wpS7itXXxneN1zSsUwWx3Ji6YiVYrhAnpQGS/vkw==", + "requires": { + "@types/node": "*" + } + }, + "@types/node": { + "version": "20.5.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.9.tgz", + "integrity": "sha512-PcGNd//40kHAS3sTlzKB9C9XL4K0sTup8nbG5lC14kzEteTNuAFh9u5nA0o5TWnSG2r/JNPRXFVcHJIIeRlmqQ==" + }, + "@types/wrap-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz", + "integrity": "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==" + }, + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "requires": { + "type-fest": "^0.21.3" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" + }, + "cli-spinners": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.0.tgz", + "integrity": "sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g==" + }, + "cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==" + }, + "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==", + "requires": { + "color-name": "~1.1.4" + } + }, + "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==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "esbuild": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", + "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", + "dev": true, + "requires": { + "@esbuild/android-arm": "0.18.20", + "@esbuild/android-arm64": "0.18.20", + "@esbuild/android-x64": "0.18.20", + "@esbuild/darwin-arm64": "0.18.20", + "@esbuild/darwin-x64": "0.18.20", + "@esbuild/freebsd-arm64": "0.18.20", + "@esbuild/freebsd-x64": "0.18.20", + "@esbuild/linux-arm": "0.18.20", + "@esbuild/linux-arm64": "0.18.20", + "@esbuild/linux-ia32": "0.18.20", + "@esbuild/linux-loong64": "0.18.20", + "@esbuild/linux-mips64el": "0.18.20", + "@esbuild/linux-ppc64": "0.18.20", + "@esbuild/linux-riscv64": "0.18.20", + "@esbuild/linux-s390x": "0.18.20", + "@esbuild/linux-x64": "0.18.20", + "@esbuild/netbsd-x64": "0.18.20", + "@esbuild/openbsd-x64": "0.18.20", + "@esbuild/sunos-x64": "0.18.20", + "@esbuild/win32-arm64": "0.18.20", + "@esbuild/win32-ia32": "0.18.20", + "@esbuild/win32-x64": "0.18.20" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "optional": true + }, + "get-tsconfig": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.0.tgz", + "integrity": "sha512-pmjiZ7xtB8URYm74PlGJozDNyhvsVLUcpBa8DZBG3bWHwaHa9bPiRpiSfovw+fjhwONSCWKRyk+JQHEGZmMrzw==", + "dev": true, + "requires": { + "resolve-pkg-maps": "^1.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "mute-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==" + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==" + }, + "resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true + }, + "run-async": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", + "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "tsx": { + "version": "3.12.8", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-3.12.8.tgz", + "integrity": "sha512-Lt9KYaRGF023tlLInPj8rgHwsZU8qWLBj4iRXNWxTfjIkU7canGL806AqKear1j722plHuiYNcL2ZCo6uS9UJA==", + "dev": true, + "requires": { + "@esbuild-kit/cjs-loader": "^2.4.2", + "@esbuild-kit/core-utils": "^3.2.2", + "@esbuild-kit/esm-loader": "^2.5.5", + "fsevents": "~2.3.2" + } + }, + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==" + }, + "typescript": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "dev": true + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + } + } +} diff --git a/shared-module-v2/packages/create-exercise-service/package.json b/shared-module-v2/packages/create-exercise-service/package.json new file mode 100644 index 000000000000..59d2522679ab --- /dev/null +++ b/shared-module-v2/packages/create-exercise-service/package.json @@ -0,0 +1,18 @@ +{ + "name": "@moocfi/create-exercise-service", + "version": "0.0.0", + "description": "", + "main": "index.js", + "scripts": { + "start": "tsx index.ts" + }, + "author": "Henrik Nygren ", + "license": "Apache-2.0", + "devDependencies": { + "tsx": "^3.12.8", + "typescript": "^5.2.2" + }, + "dependencies": { + "@inquirer/prompts": "^3.0.4" + } +} diff --git a/shared-module-v2/sync.ts b/shared-module-v2/sync.ts new file mode 100644 index 000000000000..0bb636789b58 --- /dev/null +++ b/shared-module-v2/sync.ts @@ -0,0 +1,21 @@ +import watcher from "@parcel/watcher" + +async function main() { + // Subscribe to events + let subscription: watcher.AsyncSubscription | null = null + try { + subscription = await watcher.subscribe(process.cwd(), (err, events) => { + if (err) { + console.error(`Error occurred while watching:`) + console.error(err) + } + console.log(events) + }) + } finally { + if (subscription) { + subscription.unsubscribe() + } + } +} + +main() From 3cb4cabdffd84f238aee633b995e8ea93017882a Mon Sep 17 00:00:00 2001 From: Henrik Nygren Date: Wed, 1 Nov 2023 14:41:35 +0200 Subject: [PATCH 02/38] Fixes to the sync-tmc-users-cronjob --- bin/run-cronjob | 28 +++++++++ .../base/headless-lms/sync-tmc-users.yml | 60 +++++++++++++++++++ kubernetes/base/kustomization.yaml | 1 + services/headless-lms/models/src/users.rs | 43 ++++++------- 4 files changed, 112 insertions(+), 20 deletions(-) create mode 100755 bin/run-cronjob create mode 100644 kubernetes/base/headless-lms/sync-tmc-users.yml diff --git a/bin/run-cronjob b/bin/run-cronjob new file mode 100755 index 000000000000..c32795aeeac0 --- /dev/null +++ b/bin/run-cronjob @@ -0,0 +1,28 @@ +#!/bin/bash +set -euo pipefail +source "$(dirname "$0")/.common" + +echo "This command creates a new job from a cronjob. Give it a cronjob name to run the job it once." +echo -e "${BLUE}Tip: if you changed some code you'll need to restart bin/dev or bin/test to see your changes.${RESET_EVERYTHING}" + +POD_NAME=$(kubectl get pods -l app=headless-lms -o name --sort-by=.metadata.creationTimestamp | tac | head -n 1) +[ -z "$POD_NAME" ] && { echo "Failed to find the headless-lms pod. Note that you'll need to have either bin/dev or bin/test running for this to work."; exit 1; } + +# check if first argument is a cronjob name +if [ -z "${1:-}" ]; then + echo -e "${RED}Error: you need to give a cronjob name as the first argument.${RESET_EVERYTHING}" + echo "" + echo "List of available cronjobs:" + run_command kubectl get cronjobs + exit 1 +fi + +CRONJOB_NAME="$1" +JOB_NAME="$CRONJOB_NAME-$(date --iso-8601=ns | sha256sum | cut -d ' ' -f 1 | cut -c -10)" + +run_command kubectl create job --from=cronjob/"$CRONJOB_NAME" "$JOB_NAME" + +echo "" +echo -e "${GREEN}✅ The job $JOB_NAME has been created. You should see its output in the bin/dev or bin/test terminal.${RESET_EVERYTHING}" + +echo -e "${GREEN}Alternatively, you should be able to see the logs with ${BOLD}kubectl logs -f job.batch/$JOB_NAME${RESET_EVERYTHING}" diff --git a/kubernetes/base/headless-lms/sync-tmc-users.yml b/kubernetes/base/headless-lms/sync-tmc-users.yml new file mode 100644 index 000000000000..1a487dce76fc --- /dev/null +++ b/kubernetes/base/headless-lms/sync-tmc-users.yml @@ -0,0 +1,60 @@ +apiVersion: batch/v1 +kind: CronJob +metadata: + name: sync-tmc-users + labels: + app: sync-tmc-users + deploymentType: with-init-container-cronjob + needs-db: "job" +spec: + schedule: "13 3 * * *" + startingDeadlineSeconds: 900 + concurrencyPolicy: Forbid + failedJobsHistoryLimit: 1 + successfulJobsHistoryLimit: 3 + jobTemplate: + spec: + activeDeadlineSeconds: 10800 + template: + spec: + restartPolicy: OnFailure + containers: + - name: sync-tmc-users + image: headless-lms + command: + [ + "cargo", + "run", + "--", + "sync-tmc-users", + ] + resources: + requests: + memory: 100Mi + cpu: 20m + limits: + memory: 300Mi + cpu: 200m + envFrom: + - secretRef: + name: headless-lms-secrets + initContainers: + - name: headless-lms-wait-for-db + image: headless-lms + command: + - bash + - "-c" + - | + echo Waiting for postgres to be available + timeout 120 ./wait-for-db.sh + ./wait-for-db-migrations.sh + resources: + requests: + memory: 100Mi + cpu: 20m + limits: + memory: 300Mi + cpu: 200m + envFrom: + - secretRef: + name: headless-lms-secrets diff --git a/kubernetes/base/kustomization.yaml b/kubernetes/base/kustomization.yaml index 49e9c62c4f82..e085cdce8cad 100644 --- a/kubernetes/base/kustomization.yaml +++ b/kubernetes/base/kustomization.yaml @@ -16,3 +16,4 @@ resources: - headless-lms/service-info-fetcher.yml - headless-lms/regrader.yml - headless-lms/peer-review-updater.yml + - headless-lms/sync-tmc-users.yml diff --git a/services/headless-lms/models/src/users.rs b/services/headless-lms/models/src/users.rs index 0f9a7c47731b..a58f7a109c5f 100644 --- a/services/headless-lms/models/src/users.rs +++ b/services/headless-lms/models/src/users.rs @@ -220,36 +220,39 @@ pub async fn update_email_for_user( new_email: String, ) -> ModelResult<()> { info!("Updating user (Upstream id: {upstream_id})"); - let mut tx = conn.begin().await?; - let user = sqlx::query_as!( User, "SELECT * FROM users WHERE upstream_id = $1", upstream_id ) - .fetch_one(&mut *tx) + .fetch_optional(&mut *conn) .await?; + if let Some(user) = user { + let mut tx = conn.begin().await?; - sqlx::query!( - "UPDATE user_details SET email = $1 WHERE user_id = $2", - new_email, - user.id, - ) - .execute(&mut *tx) - .await?; + sqlx::query!( + "UPDATE user_details SET email = $1 WHERE user_id = $2", + new_email, + user.id, + ) + .execute(&mut *tx) + .await?; - let email_domain = new_email.trim().split('@').last(); - sqlx::query!( - "UPDATE users SET email_domain = $1 WHERE id = $2", - email_domain, - user.id, - ) - .execute(&mut *tx) - .await?; + let email_domain = new_email.trim().split('@').last(); + sqlx::query!( + "UPDATE users SET email_domain = $1 WHERE id = $2", + email_domain, + user.id, + ) + .execute(&mut *tx) + .await?; - tx.commit().await?; + tx.commit().await?; - info!("Email change succeeded"); + info!("Email change succeeded"); + } else { + info!("User not in database, skipping"); + } Ok(()) } From 60802e7840e8d008d3b68015bf79eb90e3409649 Mon Sep 17 00:00:00 2001 From: Henrik Nygren Date: Thu, 2 Nov 2023 13:48:07 +0200 Subject: [PATCH 03/38] Finish new syncing --- shared-module-v2/file.ts | 0 shared-module-v2/file.ts2 | 0 shared-module-v2/package-lock.json | 26 ++++- shared-module-v2/package.json | 4 +- shared-module-v2/sync.ts | 171 +++++++++++++++++++++++++++-- 5 files changed, 188 insertions(+), 13 deletions(-) delete mode 100644 shared-module-v2/file.ts delete mode 100644 shared-module-v2/file.ts2 diff --git a/shared-module-v2/file.ts b/shared-module-v2/file.ts deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/shared-module-v2/file.ts2 b/shared-module-v2/file.ts2 deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/shared-module-v2/package-lock.json b/shared-module-v2/package-lock.json index 950f9ee0b622..0b42417da88e 100644 --- a/shared-module-v2/package-lock.json +++ b/shared-module-v2/package-lock.json @@ -8,9 +8,11 @@ "name": "secret-project-shared-module", "version": "0.0.0", "dependencies": { - "@parcel/watcher": "^2.3.0" + "@parcel/watcher": "^2.3.0", + "lodash": "^4.17.21" }, "devDependencies": { + "@types/lodash": "^4.14.200", "tsx": "^3.12.8" } }, @@ -657,6 +659,12 @@ "url": "https://opencollective.com/parcel" } }, + "node_modules/@types/lodash": { + "version": "4.14.200", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.200.tgz", + "integrity": "sha512-YI/M/4HRImtNf3pJgbF+W6FrXovqj+T+/HpENLTooK9PnkacBsDpeP3IpHab40CClUfhNmdM2WTNP2sa2dni5Q==", + "dev": true + }, "node_modules/braces": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", @@ -786,6 +794,11 @@ "node": ">=0.12.0" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, "node_modules/micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", @@ -1151,6 +1164,12 @@ "integrity": "sha512-dLx+0XRdMnVI62kU3wbXvbIRhLck4aE28bIGKbRGS7BJNt54IIj9+c/Dkqb+7DJEbHUZAX1bwaoM8PqVlHJmCA==", "optional": true }, + "@types/lodash": { + "version": "4.14.200", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.200.tgz", + "integrity": "sha512-YI/M/4HRImtNf3pJgbF+W6FrXovqj+T+/HpENLTooK9PnkacBsDpeP3IpHab40CClUfhNmdM2WTNP2sa2dni5Q==", + "dev": true + }, "braces": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", @@ -1242,6 +1261,11 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, "micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", diff --git a/shared-module-v2/package.json b/shared-module-v2/package.json index c705432d7331..36e531580029 100644 --- a/shared-module-v2/package.json +++ b/shared-module-v2/package.json @@ -9,9 +9,11 @@ "keywords": [], "author": "Henrik Nygren ", "devDependencies": { + "@types/lodash": "^4.14.200", "tsx": "^3.12.8" }, "dependencies": { - "@parcel/watcher": "^2.3.0" + "@parcel/watcher": "^2.3.0", + "lodash": "^4.17.21" } } diff --git a/shared-module-v2/sync.ts b/shared-module-v2/sync.ts index 0bb636789b58..974df5ac907f 100644 --- a/shared-module-v2/sync.ts +++ b/shared-module-v2/sync.ts @@ -1,21 +1,170 @@ import watcher from "@parcel/watcher" +import { exec as execOriginal } from "child_process" +import { stat } from "fs/promises" +import { groupBy } from "lodash" +import path from "path" +import { promisify } from "util" + +const exec = promisify(execOriginal) + +const ALL_SERVICES_TARGETS = [ + "services/cms/src/shared-module-v2", + "services/course-material/src/shared-module-v2", + "services/example-exercise/src/shared-module-v2", + "services/headless-lms/shared-module-v2", + "services/main-frontend/src/shared-module-v2", + "services/quizzes/src/shared-module-v2", + "services/tmc/src/shared-module-v2", + "system-tests/src/shared-module-v2", +] + +const SYNC_TARGETS = [ + { + source: "common", + destinations: ALL_SERVICES_TARGETS, + }, +] + +const DEBUG = false + +interface ChangeDescription { + path: string + syncFolder: string | null + operation: watcher.EventType +} async function main() { - // Subscribe to events - let subscription: watcher.AsyncSubscription | null = null - try { - subscription = await watcher.subscribe(process.cwd(), (err, events) => { - if (err) { - console.error(`Error occurred while watching:`) - console.error(err) + await syncEverything() + // Subscribe to events, one subscription per sync target + const subscriptions = await Promise.all( + SYNC_TARGETS.map(async (target) => { + return await watcher.subscribe( + path.resolve(__dirname, "packages", target.source, "src"), + async (err, events) => { + if (err) { + console.error(`Error occurred while watching:`) + console.error(err) + } + const changes = groupBy( + events.map((event) => { + const relativePath = path.relative(__dirname, event.path) + const syncFolder = + SYNC_TARGETS.find((target) => + relativePath.startsWith(`packages` + path.sep + target.source), + ) ?? null + return { + path: relativePath, + syncFolder: syncFolder?.source ?? null, + operation: event.type, + } satisfies ChangeDescription + }), + (event) => event.syncFolder, + ) + if (DEBUG) { + console.log("Changes:", JSON.stringify(changes, null, 2)) + } + + for (const [syncFolder, events] of Object.entries(changes)) { + const targets = SYNC_TARGETS.find((target) => target.source === syncFolder) + + // Syncing is done with rsync, but we'll want to minimize the number of files rsync has to go through + // Therefore we'll find the common root of all changed files and sync from there + const commonRoot = getCommonRootOfChanges(events) + console.info( + `Syncing changes in "${commonRoot}" to ${targets?.destinations.length} destinations.`, + ) + for (const destination of targets?.destinations ?? []) { + await syncPath(commonRoot, destination) + } + } + }, + ) + }), + ) + + process.once("SIGINT", function (_signal) { + console.log("Exitting...") + for (const subscription of subscriptions) { + subscription.unsubscribe() + } + }) + + console.log("Watching...") + // eslint-disable-next-line no-constant-condition + while (true) { + await new Promise((resolve) => setTimeout(resolve, 100_000)) + } +} + +function getCommonRootOfChanges(changes: ChangeDescription[]) { + if (changes.length === 0) { + throw new Error("Cannot get common root of empty list of changes") + } + const startingPoints = changes + .map((event) => { + if (event.operation === "delete") { + // Since the source file no longer exists, we'll sync from the parent directory + return path.dirname(event.path) } - console.log(events) + return event.path }) - } finally { - if (subscription) { - subscription.unsubscribe() + .map((pathString) => pathString.split(path.sep)) + + let commonRoot = "" + const firstPathParts = startingPoints[0] + for (let i = 0; i < firstPathParts.length; i++) { + const currentPart = firstPathParts[i] + if ( + currentPart !== undefined && + startingPoints.every((pathParts) => pathParts[i] === currentPart) + ) { + if (commonRoot !== "") { + commonRoot += path.sep + } + commonRoot += currentPart + } else { + break } } + if (commonRoot === "") { + throw new Error("Could not find common root of changes") + } + return commonRoot +} + +async function syncEverything() { + for (const target of SYNC_TARGETS) { + console.log( + `Syncing packages${path.sep}${target.source}${path.sep}src to ${target.destinations.length} destinations.`, + ) + for (const destination of target.destinations) { + const fullPathToDestination = path.resolve(__dirname, "..", destination, target.source) + await exec(`mkdir -p '${fullPathToDestination}'`) + + await syncPath(`packages${path.sep}${target.source}${path.sep}src`, destination) + } + } +} + +async function syncPath(relativeSource: string, pathToTargetSharedModule: string) { + let source = path.resolve(__dirname, relativeSource) + // check if source is a directory + const sourceStat = await stat(source) + if (sourceStat.isDirectory()) { + source = source + path.sep + } + const target = path.resolve( + __dirname, + "..", + pathToTargetSharedModule, + relativeSource.replace(`packages${path.sep}`, "").replace(`${path.sep}src`, ""), + ) + + const command = `rsync -a --checksum --delete --link-dest='${source}' '${source}' '${target}'` + if (DEBUG) { + console.log(`> ${command}`) + } + await exec(command) } main() From 9abadc6ca70743f3bec5a4c2ad24b24cf427e5b7 Mon Sep 17 00:00:00 2001 From: Henrik Nygren Date: Fri, 3 Nov 2023 10:51:40 +0200 Subject: [PATCH 04/38] Small improvements --- shared-module-v2/sync.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/shared-module-v2/sync.ts b/shared-module-v2/sync.ts index 974df5ac907f..329de7f96831 100644 --- a/shared-module-v2/sync.ts +++ b/shared-module-v2/sync.ts @@ -34,6 +34,7 @@ interface ChangeDescription { } async function main() { + console.clear() await syncEverything() // Subscribe to events, one subscription per sync target const subscriptions = await Promise.all( @@ -82,11 +83,10 @@ async function main() { }), ) - process.once("SIGINT", function (_signal) { + process.once("SIGINT", async function (_signal) { console.log("Exitting...") - for (const subscription of subscriptions) { - subscription.unsubscribe() - } + await Promise.all(subscriptions.map((subscription) => subscription.unsubscribe())) + process.exit(0) }) console.log("Watching...") From 3a4a628157f8896fdcd7ad9ec031e093029aebae Mon Sep 17 00:00:00 2001 From: Henrik Nygren Date: Fri, 3 Nov 2023 13:33:13 +0200 Subject: [PATCH 05/38] WIP --- .../packages/create-exercise-service/package.json | 4 ++-- .../packages/create-exercise-service/{ => src}/index.ts | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename shared-module-v2/packages/create-exercise-service/{ => src}/index.ts (100%) diff --git a/shared-module-v2/packages/create-exercise-service/package.json b/shared-module-v2/packages/create-exercise-service/package.json index 59d2522679ab..78541b607f04 100644 --- a/shared-module-v2/packages/create-exercise-service/package.json +++ b/shared-module-v2/packages/create-exercise-service/package.json @@ -2,9 +2,9 @@ "name": "@moocfi/create-exercise-service", "version": "0.0.0", "description": "", - "main": "index.js", + "main": "src/index.js", "scripts": { - "start": "tsx index.ts" + "start": "tsx src/index.ts" }, "author": "Henrik Nygren ", "license": "Apache-2.0", diff --git a/shared-module-v2/packages/create-exercise-service/index.ts b/shared-module-v2/packages/create-exercise-service/src/index.ts similarity index 100% rename from shared-module-v2/packages/create-exercise-service/index.ts rename to shared-module-v2/packages/create-exercise-service/src/index.ts From 77789cf34e216d3b148a6306d3a568fe78c3abd5 Mon Sep 17 00:00:00 2001 From: Henrik Nygren Date: Mon, 15 Jan 2024 15:43:45 +0200 Subject: [PATCH 06/38] Restart syncing automatically --- shared-module-v2/sync.ts | 47 +++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/shared-module-v2/sync.ts b/shared-module-v2/sync.ts index 329de7f96831..202541f524c4 100644 --- a/shared-module-v2/sync.ts +++ b/shared-module-v2/sync.ts @@ -32,12 +32,42 @@ interface ChangeDescription { syncFolder: string | null operation: watcher.EventType } +let subscriptions: watcher.AsyncSubscription[] = [] async function main() { + let restarted = false + + process.once("SIGINT", async function (_signal) { + console.log("Exitting...") + await Promise.all(subscriptions.map((subscription) => subscription.unsubscribe())) + process.exit(0) + }) + + // Loop to make sure restarts work + // eslint-disable-next-line no-constant-condition + while (true) { + await runSync(restarted) + restarted = true + } +} + +async function runSync(restarted: boolean) { + const startTime = Date.now() console.clear() + if (restarted) { + console.log( + "Restarted syncing at " + + new Date(Date.now() - new Date().getTimezoneOffset() * 60000) + .toISOString() + .replace("T", " ") + .replace("Z", "") + .split(".")[0], + ) + } await syncEverything() + // Subscribe to events, one subscription per sync target - const subscriptions = await Promise.all( + subscriptions = await Promise.all( SYNC_TARGETS.map(async (target) => { return await watcher.subscribe( path.resolve(__dirname, "packages", target.source, "src"), @@ -83,17 +113,18 @@ async function main() { }), ) - process.once("SIGINT", async function (_signal) { - console.log("Exitting...") - await Promise.all(subscriptions.map((subscription) => subscription.unsubscribe())) - process.exit(0) - }) - console.log("Watching...") // eslint-disable-next-line no-constant-condition while (true) { - await new Promise((resolve) => setTimeout(resolve, 100_000)) + await new Promise((resolve) => setTimeout(resolve, 300_000)) + if (Date.now() - startTime > 3_600_000) { + // Restarting the watching process to make sure nothing is missed in case of something like https://github.com/parcel-bundler/watcher/issues/97 + console.log("One hour has elapsed, restarting...") + break + } } + await Promise.all(subscriptions.map((subscription) => subscription.unsubscribe())) + subscriptions = [] } function getCommonRootOfChanges(changes: ChangeDescription[]) { From 6bdb35402e186bde72ddaf7dd3ae5e4f7d6ad2f0 Mon Sep 17 00:00:00 2001 From: Henrik Nygren Date: Mon, 15 Jan 2024 15:46:11 +0200 Subject: [PATCH 07/38] Add bin/shared-module-sync-watch --- bin/shared-module-sync-watch | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100755 bin/shared-module-sync-watch diff --git a/bin/shared-module-sync-watch b/bin/shared-module-sync-watch new file mode 100755 index 000000000000..985d47aca543 --- /dev/null +++ b/bin/shared-module-sync-watch @@ -0,0 +1,14 @@ +#!/bin/bash +# Only meant to be ran against the database in minikube. You can start it with +# either `bin/dev` or `bin/dev-only-db`. +set -euo pipefail +source "$(dirname "$0")/.common" + + +BASEDIR="$(dirname "${BASH_SOURCE[0]}")" +FOLDER_PATH="$BASEDIR/../shared-module-v2" +RELATIVE_PATH=$(realpath --relative-to="$(pwd)" "$FOLDER_PATH") + +cd "$RELATIVE_PATH" + +run_command npm run sync From 435d9da27bb34bfcaeea031261f1e1deed51360c Mon Sep 17 00:00:00 2001 From: Henrik Nygren Date: Mon, 22 Jan 2024 15:42:55 +0200 Subject: [PATCH 08/38] Move shared module contents --- .../packages/common}/src/bindings.guard.ts | 0 .../packages/common}/src/bindings.ts | 0 .../src/components/Accordion/DetailAccordion.tsx | 0 .../common}/src/components/Accordion/index.tsx | 0 .../common}/src/components/Banner/Banner.tsx | 0 .../src/components/Banner/ContributeBanner.tsx | 0 .../src/components/Banner/ReadOnlyBanner.tsx | 0 .../common}/src/components/BooleanAsText.tsx | 0 .../packages/common}/src/components/Breadcrumbs.tsx | 0 .../packages/common}/src/components/Button.tsx | 0 .../src/components/Card/CardOpenTextOverlay.tsx | 0 .../common}/src/components/Card/CardOpensText.tsx | 0 .../src/components/Card/IllustrationCard.tsx | 0 .../common}/src/components/Card/SimpleCard.tsx | 0 .../packages/common}/src/components/Card/index.tsx | 0 .../src/components/Centering/BreakFromCentered.tsx | 0 .../common}/src/components/Centering/Centered.tsx | 0 .../common}/src/components/CircularProgressBar.tsx | 0 .../components/CourseProgress/CircularProgress.tsx | 0 .../src/components/CourseProgress/ProgressBar.tsx | 0 .../common}/src/components/CourseProgress/index.tsx | 0 .../packages/common}/src/components/DebugModal.tsx | 0 .../packages/common}/src/components/Dialog.tsx | 0 .../common}/src/components/DiffFormatter.tsx | 0 .../components/DropdownMenu/DropdownMenuItem.tsx | 0 .../common}/src/components/DropdownMenu/index.tsx | 0 .../packages/common}/src/components/ErrorBanner.tsx | 0 .../src/components/ExerciseList/ExerciseBox.tsx | 0 .../common}/src/components/ExerciseList/PageBox.tsx | 0 .../common}/src/components/FloatingErrorBox.tsx | 0 .../packages/common}/src/components/Footer.tsx | 0 .../packages/common}/src/components/Forum/Forum.tsx | 0 .../common}/src/components/Forum/SideNavigation.tsx | 0 .../common}/src/components/Forum/Thread.tsx | 0 .../common}/src/components/Forum/Threads.tsx | 0 .../common}/src/components/GenericInfobox.tsx | 0 .../src/components/HeightTrackingContainer.tsx | 0 .../common}/src/components/InputFields/CheckBox.tsx | 0 .../components/InputFields/CheckboxFieldWrapper.tsx | 0 .../src/components/InputFields/DatePickerField.tsx | 0 .../src/components/InputFields/DateTimeLocal.tsx | 0 .../InputFields/EditableComponentTextArea.tsx | 0 .../src/components/InputFields/FileField.tsx | 0 .../src/components/InputFields/RadioButton.tsx | 0 .../src/components/InputFields/SelectField.tsx | 0 .../src/components/InputFields/TextAreaField.tsx | 0 .../src/components/InputFields/TextField.tsx | 0 .../src/components/InputFields/TimePickerField.tsx | 0 .../src/components/LanguageSelection/Language.tsx | 0 .../components/LanguageSelection/LanguageMenu.tsx | 0 .../components/LanguageSelection/LanguageOption.tsx | 0 .../src/components/LanguageSelection/index.tsx | 0 .../common}/src/components/LinkOrNoLink.tsx | 0 .../common}/src/components/LoginControls.tsx | 0 .../common}/src/components/MessageChannelIFrame.tsx | 0 .../src/components/Navigation/NavBar/ComplexNav.tsx | 0 .../Navigation/NavBar/Menu/Hamburger/Hamburger.tsx | 0 .../NavBar/Menu/Hamburger/HamburgerSpring.tsx | 0 .../src/components/Navigation/NavBar/Menu/Menu.tsx | 0 .../components/Navigation/NavBar/Menu/MenuItem.tsx | 0 .../components/Navigation/NavBar/NavContainer.tsx | 0 .../src/components/Navigation/NavBar/NavItem.tsx | 0 .../src/components/Navigation/NavBar/NavItems.tsx | 0 .../src/components/Navigation/NavBar/NavLink.tsx | 0 .../src/components/Navigation/NavBar/SimpleNav.tsx | 0 .../src/components/Navigation/NavBar/index.tsx | 0 .../src/components/Navigation/TabLinks/TabLink.tsx | 0 .../Navigation/TabLinks/TabLinkNavigation.tsx | 0 .../components/Navigation/TabLinks/TabLinkPanel.tsx | 0 .../packages/common}/src/components/Nested.tsx | 0 .../common}/src/components/NextSectionLink.tsx | 0 .../common}/src/components/Notifications/Base.tsx | 0 .../common}/src/components/Notifications/Delete.tsx | 0 .../common}/src/components/Notifications/Error.tsx | 0 .../src/components/Notifications/Loading.tsx | 0 .../src/components/Notifications/Success.tsx | 0 .../Notifications/ToasterNotifications.tsx | 0 .../src/components/OnlyRenderIfPermissions.tsx | 0 .../common}/src/components/PagesInChapterBox.tsx | 0 .../packages/common}/src/components/Pagination.tsx | 0 .../src/components/PaginationItemsPerPage.tsx | 0 .../src/components/PeerReview/LikertScale.tsx | 0 .../common}/src/components/PeerReview/Option.tsx | 0 .../components/PeerReview/PeerReviewProgress.tsx | 0 .../common}/src/components/PeerReview/Review.tsx | 0 .../packages/common}/src/components/Quote.tsx | 0 .../packages/common}/src/components/Reference.tsx | 0 .../packages/common}/src/components/SelectMenu.tsx | 0 .../packages/common}/src/components/SkipLink.tsx | 0 .../common}/src/components/SpeechBalloon.tsx | 0 .../packages/common}/src/components/Spinner.tsx | 0 .../packages/common}/src/components/Sponsor.tsx | 0 .../packages/common}/src/components/Test.tsx | 0 .../common}/src/components/TimeComponent.tsx | 0 .../packages/common}/src/components/Title.tsx | 0 .../common}/src/components/TopLevelPage.tsx | 0 .../common}/src/components/TopicObjectives.tsx | 0 .../src/components/layout/PageMarginOffset.tsx | 0 .../src/components/monaco/MonacoDiffEditor.tsx | 0 .../common}/src/components/monaco/MonacoEditor.tsx | 0 .../components/monaco/impl/MonacoDiffEditorImpl.tsx | 0 .../src/components/monaco/impl/MonacoEditorImpl.tsx | 0 .../common}/src/components/monaco/impl/loader.ts | 0 .../system-tests/HideChildrenInSystemTests.tsx | 0 .../system-tests/HideTextInSystemTests.tsx | 0 .../system-tests/MaskOverThisInSystemTests.tsx | 0 .../common}/src/contexts/ExerciseServiceContext.tsx | 0 .../common}/src/contexts/IframeHeightContext.tsx | 0 .../common}/src/contexts/LoginStateContext.tsx | 0 .../src/exercise-service-protocol-types-2.ts | 0 .../src/exercise-service-protocol-types.guard.ts | 0 .../common}/src/exercise-service-protocol-types.ts | 0 .../useExerciseServiceOutputState.tsx | 0 .../common}/src/hooks/useAuthorizeMultiple.tsx | 0 .../common}/src/hooks/useDateStringAsDate.tsx | 0 .../hooks/useExerciseServiceParentConnection.tsx | 0 .../packages/common}/src/hooks/useLanguage.tsx | 0 .../packages/common}/src/hooks/useMedia.ts | 0 .../common}/src/hooks/useMessageChannel.tsx | 0 .../common}/src/hooks/usePaginationInfo.tsx | 0 .../packages/common}/src/hooks/useQueryParameter.ts | 0 .../useShouldHideStuffForSystemTestScreenshots.tsx | 0 .../common}/src/hooks/useShowToastInfinitely.tsx | 0 .../packages/common}/src/hooks/useStateQuery.ts | 0 .../packages/common}/src/hooks/useToastMutation.tsx | 0 .../packages/common}/src/hooks/useUserInfo.tsx | 0 .../packages/common}/src/img/UHBrandLogo.svg | 0 .../packages/common}/src/img/accordion-arrow.svg | 0 .../packages/common}/src/img/arrow.svg | 0 .../packages/common}/src/img/backarrow.svg | 0 .../packages/common}/src/img/blackArrow.svg | 0 .../packages/common}/src/img/bulleye.svg | 0 .../packages/common}/src/img/card-bg-circle.svg | 0 .../packages/common}/src/img/card-bg-star.svg | 0 .../packages/common}/src/img/card-bg-zigzag.svg | 0 .../common}/src/img/card-defualt-bg/circle.svg | 0 .../common}/src/img/card-defualt-bg/cross.svg | 0 .../common}/src/img/card-defualt-bg/dot-circle.svg | 0 .../common}/src/img/card-defualt-bg/equal.svg | 0 .../src/img/card-defualt-bg/intersection.svg | 0 .../src/img/card-defualt-bg/pixel-square.svg | 0 .../src/img/card-defualt-bg/quadruple-circle.svg | 0 .../common}/src/img/card-defualt-bg/triangle.svg | 0 .../packages/common}/src/img/cardNext.svg | 0 .../packages/common}/src/img/caret-arrow-down.svg | 0 .../packages/common}/src/img/caret-arrow-left.svg | 0 .../packages/common}/src/img/caret-arrow-right.svg | 0 .../packages/common}/src/img/caret-arrow-up.svg | 0 .../packages/common}/src/img/check.svg | 0 .../packages/common}/src/img/checkmark.svg | 0 .../packages/common}/src/img/china.svg | 0 .../packages/common}/src/img/close.svg | 0 .../packages/common}/src/img/cross.svg | 0 .../packages/common}/src/img/diamond.png | Bin .../packages/common}/src/img/diamond.svg | 0 .../packages/common}/src/img/exist-icon.svg | 0 .../packages/common}/src/img/external-link.svg | 0 .../packages/common}/src/img/flags/Austria.svg | 0 .../packages/common}/src/img/flags/Belgium.svg | 0 .../packages/common}/src/img/flags/Bulgaria.svg | 0 .../packages/common}/src/img/flags/Croatia.svg | 0 .../packages/common}/src/img/flags/Czech.svg | 0 .../packages/common}/src/img/flags/Denmark.svg | 0 .../packages/common}/src/img/flags/Estonia.svg | 0 .../packages/common}/src/img/flags/Finland.svg | 0 .../packages/common}/src/img/flags/France.svg | 0 .../packages/common}/src/img/flags/Germany.svg | 0 .../packages/common}/src/img/flags/Greece.svg | 0 .../packages/common}/src/img/flags/Ireland.svg | 0 .../packages/common}/src/img/flags/Italy.svg | 0 .../packages/common}/src/img/flags/Latvia.svg | 0 .../packages/common}/src/img/flags/Lithuania.svg | 0 .../packages/common}/src/img/flags/Netherlands.svg | 0 .../packages/common}/src/img/flags/Norway.svg | 0 .../packages/common}/src/img/flags/Poland.svg | 0 .../packages/common}/src/img/flags/Portugal.svg | 0 .../packages/common}/src/img/flags/Romania.svg | 0 .../packages/common}/src/img/flags/Slovenia.svg | 0 .../packages/common}/src/img/flags/Spain.svg | 0 .../packages/common}/src/img/flags/Sweden.svg | 0 .../packages/common}/src/img/flags/USA.svg | 0 .../common}/src/img/flags/United_Kingdom.svg | 0 .../common}/src/img/hero-default-bg-image.svg | 0 .../packages/common}/src/img/likert/agree.svg | 0 .../packages/common}/src/img/likert/disagree.svg | 0 .../packages/common}/src/img/likert/neutral.svg | 0 .../common}/src/img/likert/stronglyAgree.svg | 0 .../common}/src/img/likert/stronglyDisagree.svg | 0 .../packages/common}/src/img/lock.svg | 0 .../packages/common}/src/img/moocfiLogo.svg | 0 .../packages/common}/src/img/next.svg | 0 .../packages/common}/src/img/quote.svg | 0 .../packages/common}/src/img/score.svg | 0 .../packages/common}/src/img/screwedArrow.svg | 0 .../packages/common}/src/img/setting.svg | 0 .../packages/common}/src/img/swoosh.svg | 0 .../packages/common}/src/img/tick-03.svg | 0 .../packages/common}/src/img/tick.svg | 0 .../common}/src/img/uh_without_background.svg | 0 .../packages/common}/src/img/unitedStates.svg | 0 .../packages/common}/src/img/up-arrow.svg | 0 .../packages/common}/src/locales/en/cms.json | 0 .../common}/src/locales/en/course-material.json | 0 .../common}/src/locales/en/example-exercise.json | 0 .../common}/src/locales/en/main-frontend.json | 0 .../packages/common}/src/locales/en/quizzes.json | 0 .../common}/src/locales/en/shared-module.json | 0 .../packages/common}/src/locales/en/tmc.json | 0 .../packages/common}/src/locales/fi/cms.json | 0 .../common}/src/locales/fi/course-material.json | 0 .../common}/src/locales/fi/example-exercise.json | 0 .../common}/src/locales/fi/main-frontend.json | 0 .../packages/common}/src/locales/fi/quizzes.json | 0 .../common}/src/locales/fi/shared-module.json | 0 .../packages/common}/src/locales/fi/tmc.json | 0 .../packages/common}/src/services/appQueryClient.ts | 0 .../packages/common}/src/services/backend/auth.ts | 0 .../packages/common}/src/services/backend/files.ts | 0 .../packages/common}/src/styles/GlobalStyles.tsx | 0 .../packages/common}/src/styles/constants.ts | 0 .../packages/common}/src/styles/cssReset.ts | 0 .../packages/common}/src/styles/index.ts | 0 .../packages/common}/src/styles/monacoFontFixer.ts | 0 .../packages/common}/src/styles/muiTheme.ts | 0 .../packages/common}/src/styles/respond.ts | 0 .../packages/common}/src/styles/theme.ts | 0 .../packages/common}/src/styles/typography.ts | 0 .../packages/common}/src/types/imageTypes.d.ts | 0 .../packages/common}/src/utils/accessibility.ts | 0 .../packages/common}/src/utils/base-path.ts | 0 .../packages/common}/src/utils/constants.ts | 0 .../packages/common}/src/utils/cookies.ts | 0 .../packages/common}/src/utils/cross-routing.ts | 0 .../packages/common}/src/utils/dateUtil.ts | 0 .../packages/common}/src/utils/dom.ts | 0 .../utils/dontRenderUntilQueryParametersReady.tsx | 0 .../packages/common}/src/utils/exerciseServices.ts | 0 .../packages/common}/src/utils/fetching.ts | 0 .../packages/common}/src/utils/files.ts | 0 .../common}/src/utils/generateWebVitalsReporter.ts | 0 .../common}/src/utils/getGuestPseudonymousUserId.ts | 0 .../src/utils/i18next-parser.config.template.js | 0 .../src/utils/ietfLanguageTagToHumanReadableName.ts | 0 .../packages/common}/src/utils/initI18n.ts | 0 .../packages/common}/src/utils/nullability.ts | 0 .../packages/common}/src/utils/numbers.ts | 0 .../src/utils/redirectBackAfterLoginOrSignup.tsx | 0 .../packages/common}/src/utils/responseHeaders.js | 0 .../packages/common}/src/utils/routes.ts | 0 .../packages/common}/src/utils/strings.ts | 0 .../packages/common}/src/utils/styles.ts | 0 .../packages/common}/src/utils/svgoConfig.js | 0 .../packages/common}/src/utils/testing/i18nTest.ts | 0 .../utils/testing/replaceUuidsWithPlaceholders.ts | 0 .../packages/common}/src/utils/time.ts | 0 .../packages/common}/src/utils/typeMappter.ts | 0 .../packages/common}/src/utils/urlManipulation.ts | 0 .../packages/common}/src/utils/validation.ts | 0 .../common}/src/utils/withErrorBoundary.tsx | 0 .../packages/common}/src/utils/withNoSsr.tsx | 0 260 files changed, 0 insertions(+), 0 deletions(-) rename {shared-module => shared-module-v2/packages/common}/src/bindings.guard.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/bindings.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Accordion/DetailAccordion.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Accordion/index.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Banner/Banner.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Banner/ContributeBanner.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Banner/ReadOnlyBanner.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/BooleanAsText.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Breadcrumbs.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Button.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Card/CardOpenTextOverlay.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Card/CardOpensText.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Card/IllustrationCard.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Card/SimpleCard.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Card/index.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Centering/BreakFromCentered.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Centering/Centered.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/CircularProgressBar.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/CourseProgress/CircularProgress.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/CourseProgress/ProgressBar.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/CourseProgress/index.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/DebugModal.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Dialog.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/DiffFormatter.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/DropdownMenu/DropdownMenuItem.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/DropdownMenu/index.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/ErrorBanner.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/ExerciseList/ExerciseBox.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/ExerciseList/PageBox.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/FloatingErrorBox.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Footer.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Forum/Forum.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Forum/SideNavigation.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Forum/Thread.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Forum/Threads.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/GenericInfobox.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/HeightTrackingContainer.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/InputFields/CheckBox.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/InputFields/CheckboxFieldWrapper.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/InputFields/DatePickerField.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/InputFields/DateTimeLocal.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/InputFields/EditableComponentTextArea.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/InputFields/FileField.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/InputFields/RadioButton.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/InputFields/SelectField.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/InputFields/TextAreaField.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/InputFields/TextField.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/InputFields/TimePickerField.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/LanguageSelection/Language.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/LanguageSelection/LanguageMenu.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/LanguageSelection/LanguageOption.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/LanguageSelection/index.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/LinkOrNoLink.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/LoginControls.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/MessageChannelIFrame.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Navigation/NavBar/ComplexNav.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Navigation/NavBar/Menu/Hamburger/Hamburger.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Navigation/NavBar/Menu/Hamburger/HamburgerSpring.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Navigation/NavBar/Menu/Menu.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Navigation/NavBar/Menu/MenuItem.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Navigation/NavBar/NavContainer.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Navigation/NavBar/NavItem.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Navigation/NavBar/NavItems.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Navigation/NavBar/NavLink.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Navigation/NavBar/SimpleNav.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Navigation/NavBar/index.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Navigation/TabLinks/TabLink.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Navigation/TabLinks/TabLinkNavigation.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Navigation/TabLinks/TabLinkPanel.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Nested.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/NextSectionLink.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Notifications/Base.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Notifications/Delete.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Notifications/Error.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Notifications/Loading.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Notifications/Success.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Notifications/ToasterNotifications.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/OnlyRenderIfPermissions.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/PagesInChapterBox.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Pagination.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/PaginationItemsPerPage.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/PeerReview/LikertScale.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/PeerReview/Option.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/PeerReview/PeerReviewProgress.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/PeerReview/Review.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Quote.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Reference.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/SelectMenu.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/SkipLink.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/SpeechBalloon.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Spinner.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Sponsor.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Test.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/TimeComponent.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/Title.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/TopLevelPage.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/TopicObjectives.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/layout/PageMarginOffset.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/monaco/MonacoDiffEditor.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/monaco/MonacoEditor.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/monaco/impl/MonacoDiffEditorImpl.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/monaco/impl/MonacoEditorImpl.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/monaco/impl/loader.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/system-tests/HideChildrenInSystemTests.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/system-tests/HideTextInSystemTests.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/components/system-tests/MaskOverThisInSystemTests.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/contexts/ExerciseServiceContext.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/contexts/IframeHeightContext.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/contexts/LoginStateContext.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/exercise-service-protocol-types-2.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/exercise-service-protocol-types.guard.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/exercise-service-protocol-types.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/hooks/exerciseServiceHooks/useExerciseServiceOutputState.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/hooks/useAuthorizeMultiple.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/hooks/useDateStringAsDate.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/hooks/useExerciseServiceParentConnection.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/hooks/useLanguage.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/hooks/useMedia.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/hooks/useMessageChannel.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/hooks/usePaginationInfo.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/hooks/useQueryParameter.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/hooks/useShouldHideStuffForSystemTestScreenshots.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/hooks/useShowToastInfinitely.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/hooks/useStateQuery.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/hooks/useToastMutation.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/hooks/useUserInfo.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/UHBrandLogo.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/accordion-arrow.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/arrow.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/backarrow.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/blackArrow.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/bulleye.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/card-bg-circle.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/card-bg-star.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/card-bg-zigzag.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/card-defualt-bg/circle.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/card-defualt-bg/cross.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/card-defualt-bg/dot-circle.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/card-defualt-bg/equal.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/card-defualt-bg/intersection.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/card-defualt-bg/pixel-square.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/card-defualt-bg/quadruple-circle.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/card-defualt-bg/triangle.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/cardNext.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/caret-arrow-down.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/caret-arrow-left.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/caret-arrow-right.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/caret-arrow-up.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/check.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/checkmark.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/china.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/close.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/cross.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/diamond.png (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/diamond.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/exist-icon.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/external-link.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/flags/Austria.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/flags/Belgium.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/flags/Bulgaria.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/flags/Croatia.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/flags/Czech.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/flags/Denmark.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/flags/Estonia.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/flags/Finland.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/flags/France.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/flags/Germany.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/flags/Greece.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/flags/Ireland.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/flags/Italy.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/flags/Latvia.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/flags/Lithuania.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/flags/Netherlands.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/flags/Norway.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/flags/Poland.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/flags/Portugal.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/flags/Romania.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/flags/Slovenia.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/flags/Spain.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/flags/Sweden.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/flags/USA.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/flags/United_Kingdom.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/hero-default-bg-image.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/likert/agree.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/likert/disagree.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/likert/neutral.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/likert/stronglyAgree.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/likert/stronglyDisagree.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/lock.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/moocfiLogo.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/next.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/quote.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/score.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/screwedArrow.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/setting.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/swoosh.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/tick-03.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/tick.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/uh_without_background.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/unitedStates.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/img/up-arrow.svg (100%) rename {shared-module => shared-module-v2/packages/common}/src/locales/en/cms.json (100%) rename {shared-module => shared-module-v2/packages/common}/src/locales/en/course-material.json (100%) rename {shared-module => shared-module-v2/packages/common}/src/locales/en/example-exercise.json (100%) rename {shared-module => shared-module-v2/packages/common}/src/locales/en/main-frontend.json (100%) rename {shared-module => shared-module-v2/packages/common}/src/locales/en/quizzes.json (100%) rename {shared-module => shared-module-v2/packages/common}/src/locales/en/shared-module.json (100%) rename {shared-module => shared-module-v2/packages/common}/src/locales/en/tmc.json (100%) rename {shared-module => shared-module-v2/packages/common}/src/locales/fi/cms.json (100%) rename {shared-module => shared-module-v2/packages/common}/src/locales/fi/course-material.json (100%) rename {shared-module => shared-module-v2/packages/common}/src/locales/fi/example-exercise.json (100%) rename {shared-module => shared-module-v2/packages/common}/src/locales/fi/main-frontend.json (100%) rename {shared-module => shared-module-v2/packages/common}/src/locales/fi/quizzes.json (100%) rename {shared-module => shared-module-v2/packages/common}/src/locales/fi/shared-module.json (100%) rename {shared-module => shared-module-v2/packages/common}/src/locales/fi/tmc.json (100%) rename {shared-module => shared-module-v2/packages/common}/src/services/appQueryClient.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/services/backend/auth.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/services/backend/files.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/styles/GlobalStyles.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/styles/constants.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/styles/cssReset.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/styles/index.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/styles/monacoFontFixer.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/styles/muiTheme.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/styles/respond.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/styles/theme.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/styles/typography.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/types/imageTypes.d.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/utils/accessibility.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/utils/base-path.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/utils/constants.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/utils/cookies.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/utils/cross-routing.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/utils/dateUtil.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/utils/dom.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/utils/dontRenderUntilQueryParametersReady.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/utils/exerciseServices.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/utils/fetching.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/utils/files.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/utils/generateWebVitalsReporter.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/utils/getGuestPseudonymousUserId.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/utils/i18next-parser.config.template.js (100%) rename {shared-module => shared-module-v2/packages/common}/src/utils/ietfLanguageTagToHumanReadableName.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/utils/initI18n.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/utils/nullability.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/utils/numbers.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/utils/redirectBackAfterLoginOrSignup.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/utils/responseHeaders.js (100%) rename {shared-module => shared-module-v2/packages/common}/src/utils/routes.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/utils/strings.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/utils/styles.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/utils/svgoConfig.js (100%) rename {shared-module => shared-module-v2/packages/common}/src/utils/testing/i18nTest.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/utils/testing/replaceUuidsWithPlaceholders.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/utils/time.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/utils/typeMappter.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/utils/urlManipulation.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/utils/validation.ts (100%) rename {shared-module => shared-module-v2/packages/common}/src/utils/withErrorBoundary.tsx (100%) rename {shared-module => shared-module-v2/packages/common}/src/utils/withNoSsr.tsx (100%) diff --git a/shared-module/src/bindings.guard.ts b/shared-module-v2/packages/common/src/bindings.guard.ts similarity index 100% rename from shared-module/src/bindings.guard.ts rename to shared-module-v2/packages/common/src/bindings.guard.ts diff --git a/shared-module/src/bindings.ts b/shared-module-v2/packages/common/src/bindings.ts similarity index 100% rename from shared-module/src/bindings.ts rename to shared-module-v2/packages/common/src/bindings.ts diff --git a/shared-module/src/components/Accordion/DetailAccordion.tsx b/shared-module-v2/packages/common/src/components/Accordion/DetailAccordion.tsx similarity index 100% rename from shared-module/src/components/Accordion/DetailAccordion.tsx rename to shared-module-v2/packages/common/src/components/Accordion/DetailAccordion.tsx diff --git a/shared-module/src/components/Accordion/index.tsx b/shared-module-v2/packages/common/src/components/Accordion/index.tsx similarity index 100% rename from shared-module/src/components/Accordion/index.tsx rename to shared-module-v2/packages/common/src/components/Accordion/index.tsx diff --git a/shared-module/src/components/Banner/Banner.tsx b/shared-module-v2/packages/common/src/components/Banner/Banner.tsx similarity index 100% rename from shared-module/src/components/Banner/Banner.tsx rename to shared-module-v2/packages/common/src/components/Banner/Banner.tsx diff --git a/shared-module/src/components/Banner/ContributeBanner.tsx b/shared-module-v2/packages/common/src/components/Banner/ContributeBanner.tsx similarity index 100% rename from shared-module/src/components/Banner/ContributeBanner.tsx rename to shared-module-v2/packages/common/src/components/Banner/ContributeBanner.tsx diff --git a/shared-module/src/components/Banner/ReadOnlyBanner.tsx b/shared-module-v2/packages/common/src/components/Banner/ReadOnlyBanner.tsx similarity index 100% rename from shared-module/src/components/Banner/ReadOnlyBanner.tsx rename to shared-module-v2/packages/common/src/components/Banner/ReadOnlyBanner.tsx diff --git a/shared-module/src/components/BooleanAsText.tsx b/shared-module-v2/packages/common/src/components/BooleanAsText.tsx similarity index 100% rename from shared-module/src/components/BooleanAsText.tsx rename to shared-module-v2/packages/common/src/components/BooleanAsText.tsx diff --git a/shared-module/src/components/Breadcrumbs.tsx b/shared-module-v2/packages/common/src/components/Breadcrumbs.tsx similarity index 100% rename from shared-module/src/components/Breadcrumbs.tsx rename to shared-module-v2/packages/common/src/components/Breadcrumbs.tsx diff --git a/shared-module/src/components/Button.tsx b/shared-module-v2/packages/common/src/components/Button.tsx similarity index 100% rename from shared-module/src/components/Button.tsx rename to shared-module-v2/packages/common/src/components/Button.tsx diff --git a/shared-module/src/components/Card/CardOpenTextOverlay.tsx b/shared-module-v2/packages/common/src/components/Card/CardOpenTextOverlay.tsx similarity index 100% rename from shared-module/src/components/Card/CardOpenTextOverlay.tsx rename to shared-module-v2/packages/common/src/components/Card/CardOpenTextOverlay.tsx diff --git a/shared-module/src/components/Card/CardOpensText.tsx b/shared-module-v2/packages/common/src/components/Card/CardOpensText.tsx similarity index 100% rename from shared-module/src/components/Card/CardOpensText.tsx rename to shared-module-v2/packages/common/src/components/Card/CardOpensText.tsx diff --git a/shared-module/src/components/Card/IllustrationCard.tsx b/shared-module-v2/packages/common/src/components/Card/IllustrationCard.tsx similarity index 100% rename from shared-module/src/components/Card/IllustrationCard.tsx rename to shared-module-v2/packages/common/src/components/Card/IllustrationCard.tsx diff --git a/shared-module/src/components/Card/SimpleCard.tsx b/shared-module-v2/packages/common/src/components/Card/SimpleCard.tsx similarity index 100% rename from shared-module/src/components/Card/SimpleCard.tsx rename to shared-module-v2/packages/common/src/components/Card/SimpleCard.tsx diff --git a/shared-module/src/components/Card/index.tsx b/shared-module-v2/packages/common/src/components/Card/index.tsx similarity index 100% rename from shared-module/src/components/Card/index.tsx rename to shared-module-v2/packages/common/src/components/Card/index.tsx diff --git a/shared-module/src/components/Centering/BreakFromCentered.tsx b/shared-module-v2/packages/common/src/components/Centering/BreakFromCentered.tsx similarity index 100% rename from shared-module/src/components/Centering/BreakFromCentered.tsx rename to shared-module-v2/packages/common/src/components/Centering/BreakFromCentered.tsx diff --git a/shared-module/src/components/Centering/Centered.tsx b/shared-module-v2/packages/common/src/components/Centering/Centered.tsx similarity index 100% rename from shared-module/src/components/Centering/Centered.tsx rename to shared-module-v2/packages/common/src/components/Centering/Centered.tsx diff --git a/shared-module/src/components/CircularProgressBar.tsx b/shared-module-v2/packages/common/src/components/CircularProgressBar.tsx similarity index 100% rename from shared-module/src/components/CircularProgressBar.tsx rename to shared-module-v2/packages/common/src/components/CircularProgressBar.tsx diff --git a/shared-module/src/components/CourseProgress/CircularProgress.tsx b/shared-module-v2/packages/common/src/components/CourseProgress/CircularProgress.tsx similarity index 100% rename from shared-module/src/components/CourseProgress/CircularProgress.tsx rename to shared-module-v2/packages/common/src/components/CourseProgress/CircularProgress.tsx diff --git a/shared-module/src/components/CourseProgress/ProgressBar.tsx b/shared-module-v2/packages/common/src/components/CourseProgress/ProgressBar.tsx similarity index 100% rename from shared-module/src/components/CourseProgress/ProgressBar.tsx rename to shared-module-v2/packages/common/src/components/CourseProgress/ProgressBar.tsx diff --git a/shared-module/src/components/CourseProgress/index.tsx b/shared-module-v2/packages/common/src/components/CourseProgress/index.tsx similarity index 100% rename from shared-module/src/components/CourseProgress/index.tsx rename to shared-module-v2/packages/common/src/components/CourseProgress/index.tsx diff --git a/shared-module/src/components/DebugModal.tsx b/shared-module-v2/packages/common/src/components/DebugModal.tsx similarity index 100% rename from shared-module/src/components/DebugModal.tsx rename to shared-module-v2/packages/common/src/components/DebugModal.tsx diff --git a/shared-module/src/components/Dialog.tsx b/shared-module-v2/packages/common/src/components/Dialog.tsx similarity index 100% rename from shared-module/src/components/Dialog.tsx rename to shared-module-v2/packages/common/src/components/Dialog.tsx diff --git a/shared-module/src/components/DiffFormatter.tsx b/shared-module-v2/packages/common/src/components/DiffFormatter.tsx similarity index 100% rename from shared-module/src/components/DiffFormatter.tsx rename to shared-module-v2/packages/common/src/components/DiffFormatter.tsx diff --git a/shared-module/src/components/DropdownMenu/DropdownMenuItem.tsx b/shared-module-v2/packages/common/src/components/DropdownMenu/DropdownMenuItem.tsx similarity index 100% rename from shared-module/src/components/DropdownMenu/DropdownMenuItem.tsx rename to shared-module-v2/packages/common/src/components/DropdownMenu/DropdownMenuItem.tsx diff --git a/shared-module/src/components/DropdownMenu/index.tsx b/shared-module-v2/packages/common/src/components/DropdownMenu/index.tsx similarity index 100% rename from shared-module/src/components/DropdownMenu/index.tsx rename to shared-module-v2/packages/common/src/components/DropdownMenu/index.tsx diff --git a/shared-module/src/components/ErrorBanner.tsx b/shared-module-v2/packages/common/src/components/ErrorBanner.tsx similarity index 100% rename from shared-module/src/components/ErrorBanner.tsx rename to shared-module-v2/packages/common/src/components/ErrorBanner.tsx diff --git a/shared-module/src/components/ExerciseList/ExerciseBox.tsx b/shared-module-v2/packages/common/src/components/ExerciseList/ExerciseBox.tsx similarity index 100% rename from shared-module/src/components/ExerciseList/ExerciseBox.tsx rename to shared-module-v2/packages/common/src/components/ExerciseList/ExerciseBox.tsx diff --git a/shared-module/src/components/ExerciseList/PageBox.tsx b/shared-module-v2/packages/common/src/components/ExerciseList/PageBox.tsx similarity index 100% rename from shared-module/src/components/ExerciseList/PageBox.tsx rename to shared-module-v2/packages/common/src/components/ExerciseList/PageBox.tsx diff --git a/shared-module/src/components/FloatingErrorBox.tsx b/shared-module-v2/packages/common/src/components/FloatingErrorBox.tsx similarity index 100% rename from shared-module/src/components/FloatingErrorBox.tsx rename to shared-module-v2/packages/common/src/components/FloatingErrorBox.tsx diff --git a/shared-module/src/components/Footer.tsx b/shared-module-v2/packages/common/src/components/Footer.tsx similarity index 100% rename from shared-module/src/components/Footer.tsx rename to shared-module-v2/packages/common/src/components/Footer.tsx diff --git a/shared-module/src/components/Forum/Forum.tsx b/shared-module-v2/packages/common/src/components/Forum/Forum.tsx similarity index 100% rename from shared-module/src/components/Forum/Forum.tsx rename to shared-module-v2/packages/common/src/components/Forum/Forum.tsx diff --git a/shared-module/src/components/Forum/SideNavigation.tsx b/shared-module-v2/packages/common/src/components/Forum/SideNavigation.tsx similarity index 100% rename from shared-module/src/components/Forum/SideNavigation.tsx rename to shared-module-v2/packages/common/src/components/Forum/SideNavigation.tsx diff --git a/shared-module/src/components/Forum/Thread.tsx b/shared-module-v2/packages/common/src/components/Forum/Thread.tsx similarity index 100% rename from shared-module/src/components/Forum/Thread.tsx rename to shared-module-v2/packages/common/src/components/Forum/Thread.tsx diff --git a/shared-module/src/components/Forum/Threads.tsx b/shared-module-v2/packages/common/src/components/Forum/Threads.tsx similarity index 100% rename from shared-module/src/components/Forum/Threads.tsx rename to shared-module-v2/packages/common/src/components/Forum/Threads.tsx diff --git a/shared-module/src/components/GenericInfobox.tsx b/shared-module-v2/packages/common/src/components/GenericInfobox.tsx similarity index 100% rename from shared-module/src/components/GenericInfobox.tsx rename to shared-module-v2/packages/common/src/components/GenericInfobox.tsx diff --git a/shared-module/src/components/HeightTrackingContainer.tsx b/shared-module-v2/packages/common/src/components/HeightTrackingContainer.tsx similarity index 100% rename from shared-module/src/components/HeightTrackingContainer.tsx rename to shared-module-v2/packages/common/src/components/HeightTrackingContainer.tsx diff --git a/shared-module/src/components/InputFields/CheckBox.tsx b/shared-module-v2/packages/common/src/components/InputFields/CheckBox.tsx similarity index 100% rename from shared-module/src/components/InputFields/CheckBox.tsx rename to shared-module-v2/packages/common/src/components/InputFields/CheckBox.tsx diff --git a/shared-module/src/components/InputFields/CheckboxFieldWrapper.tsx b/shared-module-v2/packages/common/src/components/InputFields/CheckboxFieldWrapper.tsx similarity index 100% rename from shared-module/src/components/InputFields/CheckboxFieldWrapper.tsx rename to shared-module-v2/packages/common/src/components/InputFields/CheckboxFieldWrapper.tsx diff --git a/shared-module/src/components/InputFields/DatePickerField.tsx b/shared-module-v2/packages/common/src/components/InputFields/DatePickerField.tsx similarity index 100% rename from shared-module/src/components/InputFields/DatePickerField.tsx rename to shared-module-v2/packages/common/src/components/InputFields/DatePickerField.tsx diff --git a/shared-module/src/components/InputFields/DateTimeLocal.tsx b/shared-module-v2/packages/common/src/components/InputFields/DateTimeLocal.tsx similarity index 100% rename from shared-module/src/components/InputFields/DateTimeLocal.tsx rename to shared-module-v2/packages/common/src/components/InputFields/DateTimeLocal.tsx diff --git a/shared-module/src/components/InputFields/EditableComponentTextArea.tsx b/shared-module-v2/packages/common/src/components/InputFields/EditableComponentTextArea.tsx similarity index 100% rename from shared-module/src/components/InputFields/EditableComponentTextArea.tsx rename to shared-module-v2/packages/common/src/components/InputFields/EditableComponentTextArea.tsx diff --git a/shared-module/src/components/InputFields/FileField.tsx b/shared-module-v2/packages/common/src/components/InputFields/FileField.tsx similarity index 100% rename from shared-module/src/components/InputFields/FileField.tsx rename to shared-module-v2/packages/common/src/components/InputFields/FileField.tsx diff --git a/shared-module/src/components/InputFields/RadioButton.tsx b/shared-module-v2/packages/common/src/components/InputFields/RadioButton.tsx similarity index 100% rename from shared-module/src/components/InputFields/RadioButton.tsx rename to shared-module-v2/packages/common/src/components/InputFields/RadioButton.tsx diff --git a/shared-module/src/components/InputFields/SelectField.tsx b/shared-module-v2/packages/common/src/components/InputFields/SelectField.tsx similarity index 100% rename from shared-module/src/components/InputFields/SelectField.tsx rename to shared-module-v2/packages/common/src/components/InputFields/SelectField.tsx diff --git a/shared-module/src/components/InputFields/TextAreaField.tsx b/shared-module-v2/packages/common/src/components/InputFields/TextAreaField.tsx similarity index 100% rename from shared-module/src/components/InputFields/TextAreaField.tsx rename to shared-module-v2/packages/common/src/components/InputFields/TextAreaField.tsx diff --git a/shared-module/src/components/InputFields/TextField.tsx b/shared-module-v2/packages/common/src/components/InputFields/TextField.tsx similarity index 100% rename from shared-module/src/components/InputFields/TextField.tsx rename to shared-module-v2/packages/common/src/components/InputFields/TextField.tsx diff --git a/shared-module/src/components/InputFields/TimePickerField.tsx b/shared-module-v2/packages/common/src/components/InputFields/TimePickerField.tsx similarity index 100% rename from shared-module/src/components/InputFields/TimePickerField.tsx rename to shared-module-v2/packages/common/src/components/InputFields/TimePickerField.tsx diff --git a/shared-module/src/components/LanguageSelection/Language.tsx b/shared-module-v2/packages/common/src/components/LanguageSelection/Language.tsx similarity index 100% rename from shared-module/src/components/LanguageSelection/Language.tsx rename to shared-module-v2/packages/common/src/components/LanguageSelection/Language.tsx diff --git a/shared-module/src/components/LanguageSelection/LanguageMenu.tsx b/shared-module-v2/packages/common/src/components/LanguageSelection/LanguageMenu.tsx similarity index 100% rename from shared-module/src/components/LanguageSelection/LanguageMenu.tsx rename to shared-module-v2/packages/common/src/components/LanguageSelection/LanguageMenu.tsx diff --git a/shared-module/src/components/LanguageSelection/LanguageOption.tsx b/shared-module-v2/packages/common/src/components/LanguageSelection/LanguageOption.tsx similarity index 100% rename from shared-module/src/components/LanguageSelection/LanguageOption.tsx rename to shared-module-v2/packages/common/src/components/LanguageSelection/LanguageOption.tsx diff --git a/shared-module/src/components/LanguageSelection/index.tsx b/shared-module-v2/packages/common/src/components/LanguageSelection/index.tsx similarity index 100% rename from shared-module/src/components/LanguageSelection/index.tsx rename to shared-module-v2/packages/common/src/components/LanguageSelection/index.tsx diff --git a/shared-module/src/components/LinkOrNoLink.tsx b/shared-module-v2/packages/common/src/components/LinkOrNoLink.tsx similarity index 100% rename from shared-module/src/components/LinkOrNoLink.tsx rename to shared-module-v2/packages/common/src/components/LinkOrNoLink.tsx diff --git a/shared-module/src/components/LoginControls.tsx b/shared-module-v2/packages/common/src/components/LoginControls.tsx similarity index 100% rename from shared-module/src/components/LoginControls.tsx rename to shared-module-v2/packages/common/src/components/LoginControls.tsx diff --git a/shared-module/src/components/MessageChannelIFrame.tsx b/shared-module-v2/packages/common/src/components/MessageChannelIFrame.tsx similarity index 100% rename from shared-module/src/components/MessageChannelIFrame.tsx rename to shared-module-v2/packages/common/src/components/MessageChannelIFrame.tsx diff --git a/shared-module/src/components/Navigation/NavBar/ComplexNav.tsx b/shared-module-v2/packages/common/src/components/Navigation/NavBar/ComplexNav.tsx similarity index 100% rename from shared-module/src/components/Navigation/NavBar/ComplexNav.tsx rename to shared-module-v2/packages/common/src/components/Navigation/NavBar/ComplexNav.tsx diff --git a/shared-module/src/components/Navigation/NavBar/Menu/Hamburger/Hamburger.tsx b/shared-module-v2/packages/common/src/components/Navigation/NavBar/Menu/Hamburger/Hamburger.tsx similarity index 100% rename from shared-module/src/components/Navigation/NavBar/Menu/Hamburger/Hamburger.tsx rename to shared-module-v2/packages/common/src/components/Navigation/NavBar/Menu/Hamburger/Hamburger.tsx diff --git a/shared-module/src/components/Navigation/NavBar/Menu/Hamburger/HamburgerSpring.tsx b/shared-module-v2/packages/common/src/components/Navigation/NavBar/Menu/Hamburger/HamburgerSpring.tsx similarity index 100% rename from shared-module/src/components/Navigation/NavBar/Menu/Hamburger/HamburgerSpring.tsx rename to shared-module-v2/packages/common/src/components/Navigation/NavBar/Menu/Hamburger/HamburgerSpring.tsx diff --git a/shared-module/src/components/Navigation/NavBar/Menu/Menu.tsx b/shared-module-v2/packages/common/src/components/Navigation/NavBar/Menu/Menu.tsx similarity index 100% rename from shared-module/src/components/Navigation/NavBar/Menu/Menu.tsx rename to shared-module-v2/packages/common/src/components/Navigation/NavBar/Menu/Menu.tsx diff --git a/shared-module/src/components/Navigation/NavBar/Menu/MenuItem.tsx b/shared-module-v2/packages/common/src/components/Navigation/NavBar/Menu/MenuItem.tsx similarity index 100% rename from shared-module/src/components/Navigation/NavBar/Menu/MenuItem.tsx rename to shared-module-v2/packages/common/src/components/Navigation/NavBar/Menu/MenuItem.tsx diff --git a/shared-module/src/components/Navigation/NavBar/NavContainer.tsx b/shared-module-v2/packages/common/src/components/Navigation/NavBar/NavContainer.tsx similarity index 100% rename from shared-module/src/components/Navigation/NavBar/NavContainer.tsx rename to shared-module-v2/packages/common/src/components/Navigation/NavBar/NavContainer.tsx diff --git a/shared-module/src/components/Navigation/NavBar/NavItem.tsx b/shared-module-v2/packages/common/src/components/Navigation/NavBar/NavItem.tsx similarity index 100% rename from shared-module/src/components/Navigation/NavBar/NavItem.tsx rename to shared-module-v2/packages/common/src/components/Navigation/NavBar/NavItem.tsx diff --git a/shared-module/src/components/Navigation/NavBar/NavItems.tsx b/shared-module-v2/packages/common/src/components/Navigation/NavBar/NavItems.tsx similarity index 100% rename from shared-module/src/components/Navigation/NavBar/NavItems.tsx rename to shared-module-v2/packages/common/src/components/Navigation/NavBar/NavItems.tsx diff --git a/shared-module/src/components/Navigation/NavBar/NavLink.tsx b/shared-module-v2/packages/common/src/components/Navigation/NavBar/NavLink.tsx similarity index 100% rename from shared-module/src/components/Navigation/NavBar/NavLink.tsx rename to shared-module-v2/packages/common/src/components/Navigation/NavBar/NavLink.tsx diff --git a/shared-module/src/components/Navigation/NavBar/SimpleNav.tsx b/shared-module-v2/packages/common/src/components/Navigation/NavBar/SimpleNav.tsx similarity index 100% rename from shared-module/src/components/Navigation/NavBar/SimpleNav.tsx rename to shared-module-v2/packages/common/src/components/Navigation/NavBar/SimpleNav.tsx diff --git a/shared-module/src/components/Navigation/NavBar/index.tsx b/shared-module-v2/packages/common/src/components/Navigation/NavBar/index.tsx similarity index 100% rename from shared-module/src/components/Navigation/NavBar/index.tsx rename to shared-module-v2/packages/common/src/components/Navigation/NavBar/index.tsx diff --git a/shared-module/src/components/Navigation/TabLinks/TabLink.tsx b/shared-module-v2/packages/common/src/components/Navigation/TabLinks/TabLink.tsx similarity index 100% rename from shared-module/src/components/Navigation/TabLinks/TabLink.tsx rename to shared-module-v2/packages/common/src/components/Navigation/TabLinks/TabLink.tsx diff --git a/shared-module/src/components/Navigation/TabLinks/TabLinkNavigation.tsx b/shared-module-v2/packages/common/src/components/Navigation/TabLinks/TabLinkNavigation.tsx similarity index 100% rename from shared-module/src/components/Navigation/TabLinks/TabLinkNavigation.tsx rename to shared-module-v2/packages/common/src/components/Navigation/TabLinks/TabLinkNavigation.tsx diff --git a/shared-module/src/components/Navigation/TabLinks/TabLinkPanel.tsx b/shared-module-v2/packages/common/src/components/Navigation/TabLinks/TabLinkPanel.tsx similarity index 100% rename from shared-module/src/components/Navigation/TabLinks/TabLinkPanel.tsx rename to shared-module-v2/packages/common/src/components/Navigation/TabLinks/TabLinkPanel.tsx diff --git a/shared-module/src/components/Nested.tsx b/shared-module-v2/packages/common/src/components/Nested.tsx similarity index 100% rename from shared-module/src/components/Nested.tsx rename to shared-module-v2/packages/common/src/components/Nested.tsx diff --git a/shared-module/src/components/NextSectionLink.tsx b/shared-module-v2/packages/common/src/components/NextSectionLink.tsx similarity index 100% rename from shared-module/src/components/NextSectionLink.tsx rename to shared-module-v2/packages/common/src/components/NextSectionLink.tsx diff --git a/shared-module/src/components/Notifications/Base.tsx b/shared-module-v2/packages/common/src/components/Notifications/Base.tsx similarity index 100% rename from shared-module/src/components/Notifications/Base.tsx rename to shared-module-v2/packages/common/src/components/Notifications/Base.tsx diff --git a/shared-module/src/components/Notifications/Delete.tsx b/shared-module-v2/packages/common/src/components/Notifications/Delete.tsx similarity index 100% rename from shared-module/src/components/Notifications/Delete.tsx rename to shared-module-v2/packages/common/src/components/Notifications/Delete.tsx diff --git a/shared-module/src/components/Notifications/Error.tsx b/shared-module-v2/packages/common/src/components/Notifications/Error.tsx similarity index 100% rename from shared-module/src/components/Notifications/Error.tsx rename to shared-module-v2/packages/common/src/components/Notifications/Error.tsx diff --git a/shared-module/src/components/Notifications/Loading.tsx b/shared-module-v2/packages/common/src/components/Notifications/Loading.tsx similarity index 100% rename from shared-module/src/components/Notifications/Loading.tsx rename to shared-module-v2/packages/common/src/components/Notifications/Loading.tsx diff --git a/shared-module/src/components/Notifications/Success.tsx b/shared-module-v2/packages/common/src/components/Notifications/Success.tsx similarity index 100% rename from shared-module/src/components/Notifications/Success.tsx rename to shared-module-v2/packages/common/src/components/Notifications/Success.tsx diff --git a/shared-module/src/components/Notifications/ToasterNotifications.tsx b/shared-module-v2/packages/common/src/components/Notifications/ToasterNotifications.tsx similarity index 100% rename from shared-module/src/components/Notifications/ToasterNotifications.tsx rename to shared-module-v2/packages/common/src/components/Notifications/ToasterNotifications.tsx diff --git a/shared-module/src/components/OnlyRenderIfPermissions.tsx b/shared-module-v2/packages/common/src/components/OnlyRenderIfPermissions.tsx similarity index 100% rename from shared-module/src/components/OnlyRenderIfPermissions.tsx rename to shared-module-v2/packages/common/src/components/OnlyRenderIfPermissions.tsx diff --git a/shared-module/src/components/PagesInChapterBox.tsx b/shared-module-v2/packages/common/src/components/PagesInChapterBox.tsx similarity index 100% rename from shared-module/src/components/PagesInChapterBox.tsx rename to shared-module-v2/packages/common/src/components/PagesInChapterBox.tsx diff --git a/shared-module/src/components/Pagination.tsx b/shared-module-v2/packages/common/src/components/Pagination.tsx similarity index 100% rename from shared-module/src/components/Pagination.tsx rename to shared-module-v2/packages/common/src/components/Pagination.tsx diff --git a/shared-module/src/components/PaginationItemsPerPage.tsx b/shared-module-v2/packages/common/src/components/PaginationItemsPerPage.tsx similarity index 100% rename from shared-module/src/components/PaginationItemsPerPage.tsx rename to shared-module-v2/packages/common/src/components/PaginationItemsPerPage.tsx diff --git a/shared-module/src/components/PeerReview/LikertScale.tsx b/shared-module-v2/packages/common/src/components/PeerReview/LikertScale.tsx similarity index 100% rename from shared-module/src/components/PeerReview/LikertScale.tsx rename to shared-module-v2/packages/common/src/components/PeerReview/LikertScale.tsx diff --git a/shared-module/src/components/PeerReview/Option.tsx b/shared-module-v2/packages/common/src/components/PeerReview/Option.tsx similarity index 100% rename from shared-module/src/components/PeerReview/Option.tsx rename to shared-module-v2/packages/common/src/components/PeerReview/Option.tsx diff --git a/shared-module/src/components/PeerReview/PeerReviewProgress.tsx b/shared-module-v2/packages/common/src/components/PeerReview/PeerReviewProgress.tsx similarity index 100% rename from shared-module/src/components/PeerReview/PeerReviewProgress.tsx rename to shared-module-v2/packages/common/src/components/PeerReview/PeerReviewProgress.tsx diff --git a/shared-module/src/components/PeerReview/Review.tsx b/shared-module-v2/packages/common/src/components/PeerReview/Review.tsx similarity index 100% rename from shared-module/src/components/PeerReview/Review.tsx rename to shared-module-v2/packages/common/src/components/PeerReview/Review.tsx diff --git a/shared-module/src/components/Quote.tsx b/shared-module-v2/packages/common/src/components/Quote.tsx similarity index 100% rename from shared-module/src/components/Quote.tsx rename to shared-module-v2/packages/common/src/components/Quote.tsx diff --git a/shared-module/src/components/Reference.tsx b/shared-module-v2/packages/common/src/components/Reference.tsx similarity index 100% rename from shared-module/src/components/Reference.tsx rename to shared-module-v2/packages/common/src/components/Reference.tsx diff --git a/shared-module/src/components/SelectMenu.tsx b/shared-module-v2/packages/common/src/components/SelectMenu.tsx similarity index 100% rename from shared-module/src/components/SelectMenu.tsx rename to shared-module-v2/packages/common/src/components/SelectMenu.tsx diff --git a/shared-module/src/components/SkipLink.tsx b/shared-module-v2/packages/common/src/components/SkipLink.tsx similarity index 100% rename from shared-module/src/components/SkipLink.tsx rename to shared-module-v2/packages/common/src/components/SkipLink.tsx diff --git a/shared-module/src/components/SpeechBalloon.tsx b/shared-module-v2/packages/common/src/components/SpeechBalloon.tsx similarity index 100% rename from shared-module/src/components/SpeechBalloon.tsx rename to shared-module-v2/packages/common/src/components/SpeechBalloon.tsx diff --git a/shared-module/src/components/Spinner.tsx b/shared-module-v2/packages/common/src/components/Spinner.tsx similarity index 100% rename from shared-module/src/components/Spinner.tsx rename to shared-module-v2/packages/common/src/components/Spinner.tsx diff --git a/shared-module/src/components/Sponsor.tsx b/shared-module-v2/packages/common/src/components/Sponsor.tsx similarity index 100% rename from shared-module/src/components/Sponsor.tsx rename to shared-module-v2/packages/common/src/components/Sponsor.tsx diff --git a/shared-module/src/components/Test.tsx b/shared-module-v2/packages/common/src/components/Test.tsx similarity index 100% rename from shared-module/src/components/Test.tsx rename to shared-module-v2/packages/common/src/components/Test.tsx diff --git a/shared-module/src/components/TimeComponent.tsx b/shared-module-v2/packages/common/src/components/TimeComponent.tsx similarity index 100% rename from shared-module/src/components/TimeComponent.tsx rename to shared-module-v2/packages/common/src/components/TimeComponent.tsx diff --git a/shared-module/src/components/Title.tsx b/shared-module-v2/packages/common/src/components/Title.tsx similarity index 100% rename from shared-module/src/components/Title.tsx rename to shared-module-v2/packages/common/src/components/Title.tsx diff --git a/shared-module/src/components/TopLevelPage.tsx b/shared-module-v2/packages/common/src/components/TopLevelPage.tsx similarity index 100% rename from shared-module/src/components/TopLevelPage.tsx rename to shared-module-v2/packages/common/src/components/TopLevelPage.tsx diff --git a/shared-module/src/components/TopicObjectives.tsx b/shared-module-v2/packages/common/src/components/TopicObjectives.tsx similarity index 100% rename from shared-module/src/components/TopicObjectives.tsx rename to shared-module-v2/packages/common/src/components/TopicObjectives.tsx diff --git a/shared-module/src/components/layout/PageMarginOffset.tsx b/shared-module-v2/packages/common/src/components/layout/PageMarginOffset.tsx similarity index 100% rename from shared-module/src/components/layout/PageMarginOffset.tsx rename to shared-module-v2/packages/common/src/components/layout/PageMarginOffset.tsx diff --git a/shared-module/src/components/monaco/MonacoDiffEditor.tsx b/shared-module-v2/packages/common/src/components/monaco/MonacoDiffEditor.tsx similarity index 100% rename from shared-module/src/components/monaco/MonacoDiffEditor.tsx rename to shared-module-v2/packages/common/src/components/monaco/MonacoDiffEditor.tsx diff --git a/shared-module/src/components/monaco/MonacoEditor.tsx b/shared-module-v2/packages/common/src/components/monaco/MonacoEditor.tsx similarity index 100% rename from shared-module/src/components/monaco/MonacoEditor.tsx rename to shared-module-v2/packages/common/src/components/monaco/MonacoEditor.tsx diff --git a/shared-module/src/components/monaco/impl/MonacoDiffEditorImpl.tsx b/shared-module-v2/packages/common/src/components/monaco/impl/MonacoDiffEditorImpl.tsx similarity index 100% rename from shared-module/src/components/monaco/impl/MonacoDiffEditorImpl.tsx rename to shared-module-v2/packages/common/src/components/monaco/impl/MonacoDiffEditorImpl.tsx diff --git a/shared-module/src/components/monaco/impl/MonacoEditorImpl.tsx b/shared-module-v2/packages/common/src/components/monaco/impl/MonacoEditorImpl.tsx similarity index 100% rename from shared-module/src/components/monaco/impl/MonacoEditorImpl.tsx rename to shared-module-v2/packages/common/src/components/monaco/impl/MonacoEditorImpl.tsx diff --git a/shared-module/src/components/monaco/impl/loader.ts b/shared-module-v2/packages/common/src/components/monaco/impl/loader.ts similarity index 100% rename from shared-module/src/components/monaco/impl/loader.ts rename to shared-module-v2/packages/common/src/components/monaco/impl/loader.ts diff --git a/shared-module/src/components/system-tests/HideChildrenInSystemTests.tsx b/shared-module-v2/packages/common/src/components/system-tests/HideChildrenInSystemTests.tsx similarity index 100% rename from shared-module/src/components/system-tests/HideChildrenInSystemTests.tsx rename to shared-module-v2/packages/common/src/components/system-tests/HideChildrenInSystemTests.tsx diff --git a/shared-module/src/components/system-tests/HideTextInSystemTests.tsx b/shared-module-v2/packages/common/src/components/system-tests/HideTextInSystemTests.tsx similarity index 100% rename from shared-module/src/components/system-tests/HideTextInSystemTests.tsx rename to shared-module-v2/packages/common/src/components/system-tests/HideTextInSystemTests.tsx diff --git a/shared-module/src/components/system-tests/MaskOverThisInSystemTests.tsx b/shared-module-v2/packages/common/src/components/system-tests/MaskOverThisInSystemTests.tsx similarity index 100% rename from shared-module/src/components/system-tests/MaskOverThisInSystemTests.tsx rename to shared-module-v2/packages/common/src/components/system-tests/MaskOverThisInSystemTests.tsx diff --git a/shared-module/src/contexts/ExerciseServiceContext.tsx b/shared-module-v2/packages/common/src/contexts/ExerciseServiceContext.tsx similarity index 100% rename from shared-module/src/contexts/ExerciseServiceContext.tsx rename to shared-module-v2/packages/common/src/contexts/ExerciseServiceContext.tsx diff --git a/shared-module/src/contexts/IframeHeightContext.tsx b/shared-module-v2/packages/common/src/contexts/IframeHeightContext.tsx similarity index 100% rename from shared-module/src/contexts/IframeHeightContext.tsx rename to shared-module-v2/packages/common/src/contexts/IframeHeightContext.tsx diff --git a/shared-module/src/contexts/LoginStateContext.tsx b/shared-module-v2/packages/common/src/contexts/LoginStateContext.tsx similarity index 100% rename from shared-module/src/contexts/LoginStateContext.tsx rename to shared-module-v2/packages/common/src/contexts/LoginStateContext.tsx diff --git a/shared-module/src/exercise-service-protocol-types-2.ts b/shared-module-v2/packages/common/src/exercise-service-protocol-types-2.ts similarity index 100% rename from shared-module/src/exercise-service-protocol-types-2.ts rename to shared-module-v2/packages/common/src/exercise-service-protocol-types-2.ts diff --git a/shared-module/src/exercise-service-protocol-types.guard.ts b/shared-module-v2/packages/common/src/exercise-service-protocol-types.guard.ts similarity index 100% rename from shared-module/src/exercise-service-protocol-types.guard.ts rename to shared-module-v2/packages/common/src/exercise-service-protocol-types.guard.ts diff --git a/shared-module/src/exercise-service-protocol-types.ts b/shared-module-v2/packages/common/src/exercise-service-protocol-types.ts similarity index 100% rename from shared-module/src/exercise-service-protocol-types.ts rename to shared-module-v2/packages/common/src/exercise-service-protocol-types.ts diff --git a/shared-module/src/hooks/exerciseServiceHooks/useExerciseServiceOutputState.tsx b/shared-module-v2/packages/common/src/hooks/exerciseServiceHooks/useExerciseServiceOutputState.tsx similarity index 100% rename from shared-module/src/hooks/exerciseServiceHooks/useExerciseServiceOutputState.tsx rename to shared-module-v2/packages/common/src/hooks/exerciseServiceHooks/useExerciseServiceOutputState.tsx diff --git a/shared-module/src/hooks/useAuthorizeMultiple.tsx b/shared-module-v2/packages/common/src/hooks/useAuthorizeMultiple.tsx similarity index 100% rename from shared-module/src/hooks/useAuthorizeMultiple.tsx rename to shared-module-v2/packages/common/src/hooks/useAuthorizeMultiple.tsx diff --git a/shared-module/src/hooks/useDateStringAsDate.tsx b/shared-module-v2/packages/common/src/hooks/useDateStringAsDate.tsx similarity index 100% rename from shared-module/src/hooks/useDateStringAsDate.tsx rename to shared-module-v2/packages/common/src/hooks/useDateStringAsDate.tsx diff --git a/shared-module/src/hooks/useExerciseServiceParentConnection.tsx b/shared-module-v2/packages/common/src/hooks/useExerciseServiceParentConnection.tsx similarity index 100% rename from shared-module/src/hooks/useExerciseServiceParentConnection.tsx rename to shared-module-v2/packages/common/src/hooks/useExerciseServiceParentConnection.tsx diff --git a/shared-module/src/hooks/useLanguage.tsx b/shared-module-v2/packages/common/src/hooks/useLanguage.tsx similarity index 100% rename from shared-module/src/hooks/useLanguage.tsx rename to shared-module-v2/packages/common/src/hooks/useLanguage.tsx diff --git a/shared-module/src/hooks/useMedia.ts b/shared-module-v2/packages/common/src/hooks/useMedia.ts similarity index 100% rename from shared-module/src/hooks/useMedia.ts rename to shared-module-v2/packages/common/src/hooks/useMedia.ts diff --git a/shared-module/src/hooks/useMessageChannel.tsx b/shared-module-v2/packages/common/src/hooks/useMessageChannel.tsx similarity index 100% rename from shared-module/src/hooks/useMessageChannel.tsx rename to shared-module-v2/packages/common/src/hooks/useMessageChannel.tsx diff --git a/shared-module/src/hooks/usePaginationInfo.tsx b/shared-module-v2/packages/common/src/hooks/usePaginationInfo.tsx similarity index 100% rename from shared-module/src/hooks/usePaginationInfo.tsx rename to shared-module-v2/packages/common/src/hooks/usePaginationInfo.tsx diff --git a/shared-module/src/hooks/useQueryParameter.ts b/shared-module-v2/packages/common/src/hooks/useQueryParameter.ts similarity index 100% rename from shared-module/src/hooks/useQueryParameter.ts rename to shared-module-v2/packages/common/src/hooks/useQueryParameter.ts diff --git a/shared-module/src/hooks/useShouldHideStuffForSystemTestScreenshots.tsx b/shared-module-v2/packages/common/src/hooks/useShouldHideStuffForSystemTestScreenshots.tsx similarity index 100% rename from shared-module/src/hooks/useShouldHideStuffForSystemTestScreenshots.tsx rename to shared-module-v2/packages/common/src/hooks/useShouldHideStuffForSystemTestScreenshots.tsx diff --git a/shared-module/src/hooks/useShowToastInfinitely.tsx b/shared-module-v2/packages/common/src/hooks/useShowToastInfinitely.tsx similarity index 100% rename from shared-module/src/hooks/useShowToastInfinitely.tsx rename to shared-module-v2/packages/common/src/hooks/useShowToastInfinitely.tsx diff --git a/shared-module/src/hooks/useStateQuery.ts b/shared-module-v2/packages/common/src/hooks/useStateQuery.ts similarity index 100% rename from shared-module/src/hooks/useStateQuery.ts rename to shared-module-v2/packages/common/src/hooks/useStateQuery.ts diff --git a/shared-module/src/hooks/useToastMutation.tsx b/shared-module-v2/packages/common/src/hooks/useToastMutation.tsx similarity index 100% rename from shared-module/src/hooks/useToastMutation.tsx rename to shared-module-v2/packages/common/src/hooks/useToastMutation.tsx diff --git a/shared-module/src/hooks/useUserInfo.tsx b/shared-module-v2/packages/common/src/hooks/useUserInfo.tsx similarity index 100% rename from shared-module/src/hooks/useUserInfo.tsx rename to shared-module-v2/packages/common/src/hooks/useUserInfo.tsx diff --git a/shared-module/src/img/UHBrandLogo.svg b/shared-module-v2/packages/common/src/img/UHBrandLogo.svg similarity index 100% rename from shared-module/src/img/UHBrandLogo.svg rename to shared-module-v2/packages/common/src/img/UHBrandLogo.svg diff --git a/shared-module/src/img/accordion-arrow.svg b/shared-module-v2/packages/common/src/img/accordion-arrow.svg similarity index 100% rename from shared-module/src/img/accordion-arrow.svg rename to shared-module-v2/packages/common/src/img/accordion-arrow.svg diff --git a/shared-module/src/img/arrow.svg b/shared-module-v2/packages/common/src/img/arrow.svg similarity index 100% rename from shared-module/src/img/arrow.svg rename to shared-module-v2/packages/common/src/img/arrow.svg diff --git a/shared-module/src/img/backarrow.svg b/shared-module-v2/packages/common/src/img/backarrow.svg similarity index 100% rename from shared-module/src/img/backarrow.svg rename to shared-module-v2/packages/common/src/img/backarrow.svg diff --git a/shared-module/src/img/blackArrow.svg b/shared-module-v2/packages/common/src/img/blackArrow.svg similarity index 100% rename from shared-module/src/img/blackArrow.svg rename to shared-module-v2/packages/common/src/img/blackArrow.svg diff --git a/shared-module/src/img/bulleye.svg b/shared-module-v2/packages/common/src/img/bulleye.svg similarity index 100% rename from shared-module/src/img/bulleye.svg rename to shared-module-v2/packages/common/src/img/bulleye.svg diff --git a/shared-module/src/img/card-bg-circle.svg b/shared-module-v2/packages/common/src/img/card-bg-circle.svg similarity index 100% rename from shared-module/src/img/card-bg-circle.svg rename to shared-module-v2/packages/common/src/img/card-bg-circle.svg diff --git a/shared-module/src/img/card-bg-star.svg b/shared-module-v2/packages/common/src/img/card-bg-star.svg similarity index 100% rename from shared-module/src/img/card-bg-star.svg rename to shared-module-v2/packages/common/src/img/card-bg-star.svg diff --git a/shared-module/src/img/card-bg-zigzag.svg b/shared-module-v2/packages/common/src/img/card-bg-zigzag.svg similarity index 100% rename from shared-module/src/img/card-bg-zigzag.svg rename to shared-module-v2/packages/common/src/img/card-bg-zigzag.svg diff --git a/shared-module/src/img/card-defualt-bg/circle.svg b/shared-module-v2/packages/common/src/img/card-defualt-bg/circle.svg similarity index 100% rename from shared-module/src/img/card-defualt-bg/circle.svg rename to shared-module-v2/packages/common/src/img/card-defualt-bg/circle.svg diff --git a/shared-module/src/img/card-defualt-bg/cross.svg b/shared-module-v2/packages/common/src/img/card-defualt-bg/cross.svg similarity index 100% rename from shared-module/src/img/card-defualt-bg/cross.svg rename to shared-module-v2/packages/common/src/img/card-defualt-bg/cross.svg diff --git a/shared-module/src/img/card-defualt-bg/dot-circle.svg b/shared-module-v2/packages/common/src/img/card-defualt-bg/dot-circle.svg similarity index 100% rename from shared-module/src/img/card-defualt-bg/dot-circle.svg rename to shared-module-v2/packages/common/src/img/card-defualt-bg/dot-circle.svg diff --git a/shared-module/src/img/card-defualt-bg/equal.svg b/shared-module-v2/packages/common/src/img/card-defualt-bg/equal.svg similarity index 100% rename from shared-module/src/img/card-defualt-bg/equal.svg rename to shared-module-v2/packages/common/src/img/card-defualt-bg/equal.svg diff --git a/shared-module/src/img/card-defualt-bg/intersection.svg b/shared-module-v2/packages/common/src/img/card-defualt-bg/intersection.svg similarity index 100% rename from shared-module/src/img/card-defualt-bg/intersection.svg rename to shared-module-v2/packages/common/src/img/card-defualt-bg/intersection.svg diff --git a/shared-module/src/img/card-defualt-bg/pixel-square.svg b/shared-module-v2/packages/common/src/img/card-defualt-bg/pixel-square.svg similarity index 100% rename from shared-module/src/img/card-defualt-bg/pixel-square.svg rename to shared-module-v2/packages/common/src/img/card-defualt-bg/pixel-square.svg diff --git a/shared-module/src/img/card-defualt-bg/quadruple-circle.svg b/shared-module-v2/packages/common/src/img/card-defualt-bg/quadruple-circle.svg similarity index 100% rename from shared-module/src/img/card-defualt-bg/quadruple-circle.svg rename to shared-module-v2/packages/common/src/img/card-defualt-bg/quadruple-circle.svg diff --git a/shared-module/src/img/card-defualt-bg/triangle.svg b/shared-module-v2/packages/common/src/img/card-defualt-bg/triangle.svg similarity index 100% rename from shared-module/src/img/card-defualt-bg/triangle.svg rename to shared-module-v2/packages/common/src/img/card-defualt-bg/triangle.svg diff --git a/shared-module/src/img/cardNext.svg b/shared-module-v2/packages/common/src/img/cardNext.svg similarity index 100% rename from shared-module/src/img/cardNext.svg rename to shared-module-v2/packages/common/src/img/cardNext.svg diff --git a/shared-module/src/img/caret-arrow-down.svg b/shared-module-v2/packages/common/src/img/caret-arrow-down.svg similarity index 100% rename from shared-module/src/img/caret-arrow-down.svg rename to shared-module-v2/packages/common/src/img/caret-arrow-down.svg diff --git a/shared-module/src/img/caret-arrow-left.svg b/shared-module-v2/packages/common/src/img/caret-arrow-left.svg similarity index 100% rename from shared-module/src/img/caret-arrow-left.svg rename to shared-module-v2/packages/common/src/img/caret-arrow-left.svg diff --git a/shared-module/src/img/caret-arrow-right.svg b/shared-module-v2/packages/common/src/img/caret-arrow-right.svg similarity index 100% rename from shared-module/src/img/caret-arrow-right.svg rename to shared-module-v2/packages/common/src/img/caret-arrow-right.svg diff --git a/shared-module/src/img/caret-arrow-up.svg b/shared-module-v2/packages/common/src/img/caret-arrow-up.svg similarity index 100% rename from shared-module/src/img/caret-arrow-up.svg rename to shared-module-v2/packages/common/src/img/caret-arrow-up.svg diff --git a/shared-module/src/img/check.svg b/shared-module-v2/packages/common/src/img/check.svg similarity index 100% rename from shared-module/src/img/check.svg rename to shared-module-v2/packages/common/src/img/check.svg diff --git a/shared-module/src/img/checkmark.svg b/shared-module-v2/packages/common/src/img/checkmark.svg similarity index 100% rename from shared-module/src/img/checkmark.svg rename to shared-module-v2/packages/common/src/img/checkmark.svg diff --git a/shared-module/src/img/china.svg b/shared-module-v2/packages/common/src/img/china.svg similarity index 100% rename from shared-module/src/img/china.svg rename to shared-module-v2/packages/common/src/img/china.svg diff --git a/shared-module/src/img/close.svg b/shared-module-v2/packages/common/src/img/close.svg similarity index 100% rename from shared-module/src/img/close.svg rename to shared-module-v2/packages/common/src/img/close.svg diff --git a/shared-module/src/img/cross.svg b/shared-module-v2/packages/common/src/img/cross.svg similarity index 100% rename from shared-module/src/img/cross.svg rename to shared-module-v2/packages/common/src/img/cross.svg diff --git a/shared-module/src/img/diamond.png b/shared-module-v2/packages/common/src/img/diamond.png similarity index 100% rename from shared-module/src/img/diamond.png rename to shared-module-v2/packages/common/src/img/diamond.png diff --git a/shared-module/src/img/diamond.svg b/shared-module-v2/packages/common/src/img/diamond.svg similarity index 100% rename from shared-module/src/img/diamond.svg rename to shared-module-v2/packages/common/src/img/diamond.svg diff --git a/shared-module/src/img/exist-icon.svg b/shared-module-v2/packages/common/src/img/exist-icon.svg similarity index 100% rename from shared-module/src/img/exist-icon.svg rename to shared-module-v2/packages/common/src/img/exist-icon.svg diff --git a/shared-module/src/img/external-link.svg b/shared-module-v2/packages/common/src/img/external-link.svg similarity index 100% rename from shared-module/src/img/external-link.svg rename to shared-module-v2/packages/common/src/img/external-link.svg diff --git a/shared-module/src/img/flags/Austria.svg b/shared-module-v2/packages/common/src/img/flags/Austria.svg similarity index 100% rename from shared-module/src/img/flags/Austria.svg rename to shared-module-v2/packages/common/src/img/flags/Austria.svg diff --git a/shared-module/src/img/flags/Belgium.svg b/shared-module-v2/packages/common/src/img/flags/Belgium.svg similarity index 100% rename from shared-module/src/img/flags/Belgium.svg rename to shared-module-v2/packages/common/src/img/flags/Belgium.svg diff --git a/shared-module/src/img/flags/Bulgaria.svg b/shared-module-v2/packages/common/src/img/flags/Bulgaria.svg similarity index 100% rename from shared-module/src/img/flags/Bulgaria.svg rename to shared-module-v2/packages/common/src/img/flags/Bulgaria.svg diff --git a/shared-module/src/img/flags/Croatia.svg b/shared-module-v2/packages/common/src/img/flags/Croatia.svg similarity index 100% rename from shared-module/src/img/flags/Croatia.svg rename to shared-module-v2/packages/common/src/img/flags/Croatia.svg diff --git a/shared-module/src/img/flags/Czech.svg b/shared-module-v2/packages/common/src/img/flags/Czech.svg similarity index 100% rename from shared-module/src/img/flags/Czech.svg rename to shared-module-v2/packages/common/src/img/flags/Czech.svg diff --git a/shared-module/src/img/flags/Denmark.svg b/shared-module-v2/packages/common/src/img/flags/Denmark.svg similarity index 100% rename from shared-module/src/img/flags/Denmark.svg rename to shared-module-v2/packages/common/src/img/flags/Denmark.svg diff --git a/shared-module/src/img/flags/Estonia.svg b/shared-module-v2/packages/common/src/img/flags/Estonia.svg similarity index 100% rename from shared-module/src/img/flags/Estonia.svg rename to shared-module-v2/packages/common/src/img/flags/Estonia.svg diff --git a/shared-module/src/img/flags/Finland.svg b/shared-module-v2/packages/common/src/img/flags/Finland.svg similarity index 100% rename from shared-module/src/img/flags/Finland.svg rename to shared-module-v2/packages/common/src/img/flags/Finland.svg diff --git a/shared-module/src/img/flags/France.svg b/shared-module-v2/packages/common/src/img/flags/France.svg similarity index 100% rename from shared-module/src/img/flags/France.svg rename to shared-module-v2/packages/common/src/img/flags/France.svg diff --git a/shared-module/src/img/flags/Germany.svg b/shared-module-v2/packages/common/src/img/flags/Germany.svg similarity index 100% rename from shared-module/src/img/flags/Germany.svg rename to shared-module-v2/packages/common/src/img/flags/Germany.svg diff --git a/shared-module/src/img/flags/Greece.svg b/shared-module-v2/packages/common/src/img/flags/Greece.svg similarity index 100% rename from shared-module/src/img/flags/Greece.svg rename to shared-module-v2/packages/common/src/img/flags/Greece.svg diff --git a/shared-module/src/img/flags/Ireland.svg b/shared-module-v2/packages/common/src/img/flags/Ireland.svg similarity index 100% rename from shared-module/src/img/flags/Ireland.svg rename to shared-module-v2/packages/common/src/img/flags/Ireland.svg diff --git a/shared-module/src/img/flags/Italy.svg b/shared-module-v2/packages/common/src/img/flags/Italy.svg similarity index 100% rename from shared-module/src/img/flags/Italy.svg rename to shared-module-v2/packages/common/src/img/flags/Italy.svg diff --git a/shared-module/src/img/flags/Latvia.svg b/shared-module-v2/packages/common/src/img/flags/Latvia.svg similarity index 100% rename from shared-module/src/img/flags/Latvia.svg rename to shared-module-v2/packages/common/src/img/flags/Latvia.svg diff --git a/shared-module/src/img/flags/Lithuania.svg b/shared-module-v2/packages/common/src/img/flags/Lithuania.svg similarity index 100% rename from shared-module/src/img/flags/Lithuania.svg rename to shared-module-v2/packages/common/src/img/flags/Lithuania.svg diff --git a/shared-module/src/img/flags/Netherlands.svg b/shared-module-v2/packages/common/src/img/flags/Netherlands.svg similarity index 100% rename from shared-module/src/img/flags/Netherlands.svg rename to shared-module-v2/packages/common/src/img/flags/Netherlands.svg diff --git a/shared-module/src/img/flags/Norway.svg b/shared-module-v2/packages/common/src/img/flags/Norway.svg similarity index 100% rename from shared-module/src/img/flags/Norway.svg rename to shared-module-v2/packages/common/src/img/flags/Norway.svg diff --git a/shared-module/src/img/flags/Poland.svg b/shared-module-v2/packages/common/src/img/flags/Poland.svg similarity index 100% rename from shared-module/src/img/flags/Poland.svg rename to shared-module-v2/packages/common/src/img/flags/Poland.svg diff --git a/shared-module/src/img/flags/Portugal.svg b/shared-module-v2/packages/common/src/img/flags/Portugal.svg similarity index 100% rename from shared-module/src/img/flags/Portugal.svg rename to shared-module-v2/packages/common/src/img/flags/Portugal.svg diff --git a/shared-module/src/img/flags/Romania.svg b/shared-module-v2/packages/common/src/img/flags/Romania.svg similarity index 100% rename from shared-module/src/img/flags/Romania.svg rename to shared-module-v2/packages/common/src/img/flags/Romania.svg diff --git a/shared-module/src/img/flags/Slovenia.svg b/shared-module-v2/packages/common/src/img/flags/Slovenia.svg similarity index 100% rename from shared-module/src/img/flags/Slovenia.svg rename to shared-module-v2/packages/common/src/img/flags/Slovenia.svg diff --git a/shared-module/src/img/flags/Spain.svg b/shared-module-v2/packages/common/src/img/flags/Spain.svg similarity index 100% rename from shared-module/src/img/flags/Spain.svg rename to shared-module-v2/packages/common/src/img/flags/Spain.svg diff --git a/shared-module/src/img/flags/Sweden.svg b/shared-module-v2/packages/common/src/img/flags/Sweden.svg similarity index 100% rename from shared-module/src/img/flags/Sweden.svg rename to shared-module-v2/packages/common/src/img/flags/Sweden.svg diff --git a/shared-module/src/img/flags/USA.svg b/shared-module-v2/packages/common/src/img/flags/USA.svg similarity index 100% rename from shared-module/src/img/flags/USA.svg rename to shared-module-v2/packages/common/src/img/flags/USA.svg diff --git a/shared-module/src/img/flags/United_Kingdom.svg b/shared-module-v2/packages/common/src/img/flags/United_Kingdom.svg similarity index 100% rename from shared-module/src/img/flags/United_Kingdom.svg rename to shared-module-v2/packages/common/src/img/flags/United_Kingdom.svg diff --git a/shared-module/src/img/hero-default-bg-image.svg b/shared-module-v2/packages/common/src/img/hero-default-bg-image.svg similarity index 100% rename from shared-module/src/img/hero-default-bg-image.svg rename to shared-module-v2/packages/common/src/img/hero-default-bg-image.svg diff --git a/shared-module/src/img/likert/agree.svg b/shared-module-v2/packages/common/src/img/likert/agree.svg similarity index 100% rename from shared-module/src/img/likert/agree.svg rename to shared-module-v2/packages/common/src/img/likert/agree.svg diff --git a/shared-module/src/img/likert/disagree.svg b/shared-module-v2/packages/common/src/img/likert/disagree.svg similarity index 100% rename from shared-module/src/img/likert/disagree.svg rename to shared-module-v2/packages/common/src/img/likert/disagree.svg diff --git a/shared-module/src/img/likert/neutral.svg b/shared-module-v2/packages/common/src/img/likert/neutral.svg similarity index 100% rename from shared-module/src/img/likert/neutral.svg rename to shared-module-v2/packages/common/src/img/likert/neutral.svg diff --git a/shared-module/src/img/likert/stronglyAgree.svg b/shared-module-v2/packages/common/src/img/likert/stronglyAgree.svg similarity index 100% rename from shared-module/src/img/likert/stronglyAgree.svg rename to shared-module-v2/packages/common/src/img/likert/stronglyAgree.svg diff --git a/shared-module/src/img/likert/stronglyDisagree.svg b/shared-module-v2/packages/common/src/img/likert/stronglyDisagree.svg similarity index 100% rename from shared-module/src/img/likert/stronglyDisagree.svg rename to shared-module-v2/packages/common/src/img/likert/stronglyDisagree.svg diff --git a/shared-module/src/img/lock.svg b/shared-module-v2/packages/common/src/img/lock.svg similarity index 100% rename from shared-module/src/img/lock.svg rename to shared-module-v2/packages/common/src/img/lock.svg diff --git a/shared-module/src/img/moocfiLogo.svg b/shared-module-v2/packages/common/src/img/moocfiLogo.svg similarity index 100% rename from shared-module/src/img/moocfiLogo.svg rename to shared-module-v2/packages/common/src/img/moocfiLogo.svg diff --git a/shared-module/src/img/next.svg b/shared-module-v2/packages/common/src/img/next.svg similarity index 100% rename from shared-module/src/img/next.svg rename to shared-module-v2/packages/common/src/img/next.svg diff --git a/shared-module/src/img/quote.svg b/shared-module-v2/packages/common/src/img/quote.svg similarity index 100% rename from shared-module/src/img/quote.svg rename to shared-module-v2/packages/common/src/img/quote.svg diff --git a/shared-module/src/img/score.svg b/shared-module-v2/packages/common/src/img/score.svg similarity index 100% rename from shared-module/src/img/score.svg rename to shared-module-v2/packages/common/src/img/score.svg diff --git a/shared-module/src/img/screwedArrow.svg b/shared-module-v2/packages/common/src/img/screwedArrow.svg similarity index 100% rename from shared-module/src/img/screwedArrow.svg rename to shared-module-v2/packages/common/src/img/screwedArrow.svg diff --git a/shared-module/src/img/setting.svg b/shared-module-v2/packages/common/src/img/setting.svg similarity index 100% rename from shared-module/src/img/setting.svg rename to shared-module-v2/packages/common/src/img/setting.svg diff --git a/shared-module/src/img/swoosh.svg b/shared-module-v2/packages/common/src/img/swoosh.svg similarity index 100% rename from shared-module/src/img/swoosh.svg rename to shared-module-v2/packages/common/src/img/swoosh.svg diff --git a/shared-module/src/img/tick-03.svg b/shared-module-v2/packages/common/src/img/tick-03.svg similarity index 100% rename from shared-module/src/img/tick-03.svg rename to shared-module-v2/packages/common/src/img/tick-03.svg diff --git a/shared-module/src/img/tick.svg b/shared-module-v2/packages/common/src/img/tick.svg similarity index 100% rename from shared-module/src/img/tick.svg rename to shared-module-v2/packages/common/src/img/tick.svg diff --git a/shared-module/src/img/uh_without_background.svg b/shared-module-v2/packages/common/src/img/uh_without_background.svg similarity index 100% rename from shared-module/src/img/uh_without_background.svg rename to shared-module-v2/packages/common/src/img/uh_without_background.svg diff --git a/shared-module/src/img/unitedStates.svg b/shared-module-v2/packages/common/src/img/unitedStates.svg similarity index 100% rename from shared-module/src/img/unitedStates.svg rename to shared-module-v2/packages/common/src/img/unitedStates.svg diff --git a/shared-module/src/img/up-arrow.svg b/shared-module-v2/packages/common/src/img/up-arrow.svg similarity index 100% rename from shared-module/src/img/up-arrow.svg rename to shared-module-v2/packages/common/src/img/up-arrow.svg diff --git a/shared-module/src/locales/en/cms.json b/shared-module-v2/packages/common/src/locales/en/cms.json similarity index 100% rename from shared-module/src/locales/en/cms.json rename to shared-module-v2/packages/common/src/locales/en/cms.json diff --git a/shared-module/src/locales/en/course-material.json b/shared-module-v2/packages/common/src/locales/en/course-material.json similarity index 100% rename from shared-module/src/locales/en/course-material.json rename to shared-module-v2/packages/common/src/locales/en/course-material.json diff --git a/shared-module/src/locales/en/example-exercise.json b/shared-module-v2/packages/common/src/locales/en/example-exercise.json similarity index 100% rename from shared-module/src/locales/en/example-exercise.json rename to shared-module-v2/packages/common/src/locales/en/example-exercise.json diff --git a/shared-module/src/locales/en/main-frontend.json b/shared-module-v2/packages/common/src/locales/en/main-frontend.json similarity index 100% rename from shared-module/src/locales/en/main-frontend.json rename to shared-module-v2/packages/common/src/locales/en/main-frontend.json diff --git a/shared-module/src/locales/en/quizzes.json b/shared-module-v2/packages/common/src/locales/en/quizzes.json similarity index 100% rename from shared-module/src/locales/en/quizzes.json rename to shared-module-v2/packages/common/src/locales/en/quizzes.json diff --git a/shared-module/src/locales/en/shared-module.json b/shared-module-v2/packages/common/src/locales/en/shared-module.json similarity index 100% rename from shared-module/src/locales/en/shared-module.json rename to shared-module-v2/packages/common/src/locales/en/shared-module.json diff --git a/shared-module/src/locales/en/tmc.json b/shared-module-v2/packages/common/src/locales/en/tmc.json similarity index 100% rename from shared-module/src/locales/en/tmc.json rename to shared-module-v2/packages/common/src/locales/en/tmc.json diff --git a/shared-module/src/locales/fi/cms.json b/shared-module-v2/packages/common/src/locales/fi/cms.json similarity index 100% rename from shared-module/src/locales/fi/cms.json rename to shared-module-v2/packages/common/src/locales/fi/cms.json diff --git a/shared-module/src/locales/fi/course-material.json b/shared-module-v2/packages/common/src/locales/fi/course-material.json similarity index 100% rename from shared-module/src/locales/fi/course-material.json rename to shared-module-v2/packages/common/src/locales/fi/course-material.json diff --git a/shared-module/src/locales/fi/example-exercise.json b/shared-module-v2/packages/common/src/locales/fi/example-exercise.json similarity index 100% rename from shared-module/src/locales/fi/example-exercise.json rename to shared-module-v2/packages/common/src/locales/fi/example-exercise.json diff --git a/shared-module/src/locales/fi/main-frontend.json b/shared-module-v2/packages/common/src/locales/fi/main-frontend.json similarity index 100% rename from shared-module/src/locales/fi/main-frontend.json rename to shared-module-v2/packages/common/src/locales/fi/main-frontend.json diff --git a/shared-module/src/locales/fi/quizzes.json b/shared-module-v2/packages/common/src/locales/fi/quizzes.json similarity index 100% rename from shared-module/src/locales/fi/quizzes.json rename to shared-module-v2/packages/common/src/locales/fi/quizzes.json diff --git a/shared-module/src/locales/fi/shared-module.json b/shared-module-v2/packages/common/src/locales/fi/shared-module.json similarity index 100% rename from shared-module/src/locales/fi/shared-module.json rename to shared-module-v2/packages/common/src/locales/fi/shared-module.json diff --git a/shared-module/src/locales/fi/tmc.json b/shared-module-v2/packages/common/src/locales/fi/tmc.json similarity index 100% rename from shared-module/src/locales/fi/tmc.json rename to shared-module-v2/packages/common/src/locales/fi/tmc.json diff --git a/shared-module/src/services/appQueryClient.ts b/shared-module-v2/packages/common/src/services/appQueryClient.ts similarity index 100% rename from shared-module/src/services/appQueryClient.ts rename to shared-module-v2/packages/common/src/services/appQueryClient.ts diff --git a/shared-module/src/services/backend/auth.ts b/shared-module-v2/packages/common/src/services/backend/auth.ts similarity index 100% rename from shared-module/src/services/backend/auth.ts rename to shared-module-v2/packages/common/src/services/backend/auth.ts diff --git a/shared-module/src/services/backend/files.ts b/shared-module-v2/packages/common/src/services/backend/files.ts similarity index 100% rename from shared-module/src/services/backend/files.ts rename to shared-module-v2/packages/common/src/services/backend/files.ts diff --git a/shared-module/src/styles/GlobalStyles.tsx b/shared-module-v2/packages/common/src/styles/GlobalStyles.tsx similarity index 100% rename from shared-module/src/styles/GlobalStyles.tsx rename to shared-module-v2/packages/common/src/styles/GlobalStyles.tsx diff --git a/shared-module/src/styles/constants.ts b/shared-module-v2/packages/common/src/styles/constants.ts similarity index 100% rename from shared-module/src/styles/constants.ts rename to shared-module-v2/packages/common/src/styles/constants.ts diff --git a/shared-module/src/styles/cssReset.ts b/shared-module-v2/packages/common/src/styles/cssReset.ts similarity index 100% rename from shared-module/src/styles/cssReset.ts rename to shared-module-v2/packages/common/src/styles/cssReset.ts diff --git a/shared-module/src/styles/index.ts b/shared-module-v2/packages/common/src/styles/index.ts similarity index 100% rename from shared-module/src/styles/index.ts rename to shared-module-v2/packages/common/src/styles/index.ts diff --git a/shared-module/src/styles/monacoFontFixer.ts b/shared-module-v2/packages/common/src/styles/monacoFontFixer.ts similarity index 100% rename from shared-module/src/styles/monacoFontFixer.ts rename to shared-module-v2/packages/common/src/styles/monacoFontFixer.ts diff --git a/shared-module/src/styles/muiTheme.ts b/shared-module-v2/packages/common/src/styles/muiTheme.ts similarity index 100% rename from shared-module/src/styles/muiTheme.ts rename to shared-module-v2/packages/common/src/styles/muiTheme.ts diff --git a/shared-module/src/styles/respond.ts b/shared-module-v2/packages/common/src/styles/respond.ts similarity index 100% rename from shared-module/src/styles/respond.ts rename to shared-module-v2/packages/common/src/styles/respond.ts diff --git a/shared-module/src/styles/theme.ts b/shared-module-v2/packages/common/src/styles/theme.ts similarity index 100% rename from shared-module/src/styles/theme.ts rename to shared-module-v2/packages/common/src/styles/theme.ts diff --git a/shared-module/src/styles/typography.ts b/shared-module-v2/packages/common/src/styles/typography.ts similarity index 100% rename from shared-module/src/styles/typography.ts rename to shared-module-v2/packages/common/src/styles/typography.ts diff --git a/shared-module/src/types/imageTypes.d.ts b/shared-module-v2/packages/common/src/types/imageTypes.d.ts similarity index 100% rename from shared-module/src/types/imageTypes.d.ts rename to shared-module-v2/packages/common/src/types/imageTypes.d.ts diff --git a/shared-module/src/utils/accessibility.ts b/shared-module-v2/packages/common/src/utils/accessibility.ts similarity index 100% rename from shared-module/src/utils/accessibility.ts rename to shared-module-v2/packages/common/src/utils/accessibility.ts diff --git a/shared-module/src/utils/base-path.ts b/shared-module-v2/packages/common/src/utils/base-path.ts similarity index 100% rename from shared-module/src/utils/base-path.ts rename to shared-module-v2/packages/common/src/utils/base-path.ts diff --git a/shared-module/src/utils/constants.ts b/shared-module-v2/packages/common/src/utils/constants.ts similarity index 100% rename from shared-module/src/utils/constants.ts rename to shared-module-v2/packages/common/src/utils/constants.ts diff --git a/shared-module/src/utils/cookies.ts b/shared-module-v2/packages/common/src/utils/cookies.ts similarity index 100% rename from shared-module/src/utils/cookies.ts rename to shared-module-v2/packages/common/src/utils/cookies.ts diff --git a/shared-module/src/utils/cross-routing.ts b/shared-module-v2/packages/common/src/utils/cross-routing.ts similarity index 100% rename from shared-module/src/utils/cross-routing.ts rename to shared-module-v2/packages/common/src/utils/cross-routing.ts diff --git a/shared-module/src/utils/dateUtil.ts b/shared-module-v2/packages/common/src/utils/dateUtil.ts similarity index 100% rename from shared-module/src/utils/dateUtil.ts rename to shared-module-v2/packages/common/src/utils/dateUtil.ts diff --git a/shared-module/src/utils/dom.ts b/shared-module-v2/packages/common/src/utils/dom.ts similarity index 100% rename from shared-module/src/utils/dom.ts rename to shared-module-v2/packages/common/src/utils/dom.ts diff --git a/shared-module/src/utils/dontRenderUntilQueryParametersReady.tsx b/shared-module-v2/packages/common/src/utils/dontRenderUntilQueryParametersReady.tsx similarity index 100% rename from shared-module/src/utils/dontRenderUntilQueryParametersReady.tsx rename to shared-module-v2/packages/common/src/utils/dontRenderUntilQueryParametersReady.tsx diff --git a/shared-module/src/utils/exerciseServices.ts b/shared-module-v2/packages/common/src/utils/exerciseServices.ts similarity index 100% rename from shared-module/src/utils/exerciseServices.ts rename to shared-module-v2/packages/common/src/utils/exerciseServices.ts diff --git a/shared-module/src/utils/fetching.ts b/shared-module-v2/packages/common/src/utils/fetching.ts similarity index 100% rename from shared-module/src/utils/fetching.ts rename to shared-module-v2/packages/common/src/utils/fetching.ts diff --git a/shared-module/src/utils/files.ts b/shared-module-v2/packages/common/src/utils/files.ts similarity index 100% rename from shared-module/src/utils/files.ts rename to shared-module-v2/packages/common/src/utils/files.ts diff --git a/shared-module/src/utils/generateWebVitalsReporter.ts b/shared-module-v2/packages/common/src/utils/generateWebVitalsReporter.ts similarity index 100% rename from shared-module/src/utils/generateWebVitalsReporter.ts rename to shared-module-v2/packages/common/src/utils/generateWebVitalsReporter.ts diff --git a/shared-module/src/utils/getGuestPseudonymousUserId.ts b/shared-module-v2/packages/common/src/utils/getGuestPseudonymousUserId.ts similarity index 100% rename from shared-module/src/utils/getGuestPseudonymousUserId.ts rename to shared-module-v2/packages/common/src/utils/getGuestPseudonymousUserId.ts diff --git a/shared-module/src/utils/i18next-parser.config.template.js b/shared-module-v2/packages/common/src/utils/i18next-parser.config.template.js similarity index 100% rename from shared-module/src/utils/i18next-parser.config.template.js rename to shared-module-v2/packages/common/src/utils/i18next-parser.config.template.js diff --git a/shared-module/src/utils/ietfLanguageTagToHumanReadableName.ts b/shared-module-v2/packages/common/src/utils/ietfLanguageTagToHumanReadableName.ts similarity index 100% rename from shared-module/src/utils/ietfLanguageTagToHumanReadableName.ts rename to shared-module-v2/packages/common/src/utils/ietfLanguageTagToHumanReadableName.ts diff --git a/shared-module/src/utils/initI18n.ts b/shared-module-v2/packages/common/src/utils/initI18n.ts similarity index 100% rename from shared-module/src/utils/initI18n.ts rename to shared-module-v2/packages/common/src/utils/initI18n.ts diff --git a/shared-module/src/utils/nullability.ts b/shared-module-v2/packages/common/src/utils/nullability.ts similarity index 100% rename from shared-module/src/utils/nullability.ts rename to shared-module-v2/packages/common/src/utils/nullability.ts diff --git a/shared-module/src/utils/numbers.ts b/shared-module-v2/packages/common/src/utils/numbers.ts similarity index 100% rename from shared-module/src/utils/numbers.ts rename to shared-module-v2/packages/common/src/utils/numbers.ts diff --git a/shared-module/src/utils/redirectBackAfterLoginOrSignup.tsx b/shared-module-v2/packages/common/src/utils/redirectBackAfterLoginOrSignup.tsx similarity index 100% rename from shared-module/src/utils/redirectBackAfterLoginOrSignup.tsx rename to shared-module-v2/packages/common/src/utils/redirectBackAfterLoginOrSignup.tsx diff --git a/shared-module/src/utils/responseHeaders.js b/shared-module-v2/packages/common/src/utils/responseHeaders.js similarity index 100% rename from shared-module/src/utils/responseHeaders.js rename to shared-module-v2/packages/common/src/utils/responseHeaders.js diff --git a/shared-module/src/utils/routes.ts b/shared-module-v2/packages/common/src/utils/routes.ts similarity index 100% rename from shared-module/src/utils/routes.ts rename to shared-module-v2/packages/common/src/utils/routes.ts diff --git a/shared-module/src/utils/strings.ts b/shared-module-v2/packages/common/src/utils/strings.ts similarity index 100% rename from shared-module/src/utils/strings.ts rename to shared-module-v2/packages/common/src/utils/strings.ts diff --git a/shared-module/src/utils/styles.ts b/shared-module-v2/packages/common/src/utils/styles.ts similarity index 100% rename from shared-module/src/utils/styles.ts rename to shared-module-v2/packages/common/src/utils/styles.ts diff --git a/shared-module/src/utils/svgoConfig.js b/shared-module-v2/packages/common/src/utils/svgoConfig.js similarity index 100% rename from shared-module/src/utils/svgoConfig.js rename to shared-module-v2/packages/common/src/utils/svgoConfig.js diff --git a/shared-module/src/utils/testing/i18nTest.ts b/shared-module-v2/packages/common/src/utils/testing/i18nTest.ts similarity index 100% rename from shared-module/src/utils/testing/i18nTest.ts rename to shared-module-v2/packages/common/src/utils/testing/i18nTest.ts diff --git a/shared-module/src/utils/testing/replaceUuidsWithPlaceholders.ts b/shared-module-v2/packages/common/src/utils/testing/replaceUuidsWithPlaceholders.ts similarity index 100% rename from shared-module/src/utils/testing/replaceUuidsWithPlaceholders.ts rename to shared-module-v2/packages/common/src/utils/testing/replaceUuidsWithPlaceholders.ts diff --git a/shared-module/src/utils/time.ts b/shared-module-v2/packages/common/src/utils/time.ts similarity index 100% rename from shared-module/src/utils/time.ts rename to shared-module-v2/packages/common/src/utils/time.ts diff --git a/shared-module/src/utils/typeMappter.ts b/shared-module-v2/packages/common/src/utils/typeMappter.ts similarity index 100% rename from shared-module/src/utils/typeMappter.ts rename to shared-module-v2/packages/common/src/utils/typeMappter.ts diff --git a/shared-module/src/utils/urlManipulation.ts b/shared-module-v2/packages/common/src/utils/urlManipulation.ts similarity index 100% rename from shared-module/src/utils/urlManipulation.ts rename to shared-module-v2/packages/common/src/utils/urlManipulation.ts diff --git a/shared-module/src/utils/validation.ts b/shared-module-v2/packages/common/src/utils/validation.ts similarity index 100% rename from shared-module/src/utils/validation.ts rename to shared-module-v2/packages/common/src/utils/validation.ts diff --git a/shared-module/src/utils/withErrorBoundary.tsx b/shared-module-v2/packages/common/src/utils/withErrorBoundary.tsx similarity index 100% rename from shared-module/src/utils/withErrorBoundary.tsx rename to shared-module-v2/packages/common/src/utils/withErrorBoundary.tsx diff --git a/shared-module/src/utils/withNoSsr.tsx b/shared-module-v2/packages/common/src/utils/withNoSsr.tsx similarity index 100% rename from shared-module/src/utils/withNoSsr.tsx rename to shared-module-v2/packages/common/src/utils/withNoSsr.tsx From 2cf6e4cda612f68a2bae1d43a33735dfe45d2beb Mon Sep 17 00:00:00 2001 From: Henrik Nygren Date: Wed, 24 Jan 2024 10:58:29 +0200 Subject: [PATCH 09/38] WIP --- .../shared-module-v2/common/bindings.guard.ts | 3360 +++ .../src/shared-module-v2/common/bindings.ts | 1900 ++ .../components/Accordion/DetailAccordion.tsx | 132 + .../common/components/Accordion/index.tsx | 148 + .../common/components/Banner/Banner.tsx | 110 + .../components/Banner/ContributeBanner.tsx | 110 + .../components/Banner/ReadOnlyBanner.tsx | 51 + .../common/components/BooleanAsText.tsx | 8 + .../common/components/Breadcrumbs.tsx | 108 + .../common/components/Button.tsx | 323 + .../components/Card/CardOpenTextOverlay.tsx | 50 + .../common/components/Card/CardOpensText.tsx | 47 + .../components/Card/IllustrationCard.tsx | 142 + .../common/components/Card/SimpleCard.tsx | 161 + .../common/components/Card/index.tsx | 68 + .../Centering/BreakFromCentered.tsx | 80 + .../common/components/Centering/Centered.tsx | 46 + .../common/components/CircularProgressBar.tsx | 86 + .../CourseProgress/CircularProgress.tsx | 185 + .../components/CourseProgress/ProgressBar.tsx | 132 + .../components/CourseProgress/index.tsx | 35 + .../common/components/DebugModal.tsx | 107 + .../common/components/Dialog.tsx | 132 + .../common/components/DiffFormatter.tsx | 73 + .../DropdownMenu/DropdownMenuItem.tsx | 77 + .../common/components/DropdownMenu/index.tsx | 154 + .../common/components/ErrorBanner.tsx | 304 + .../components/ExerciseList/ExerciseBox.tsx | 166 + .../components/ExerciseList/PageBox.tsx | 55 + .../common/components/FloatingErrorBox.tsx | 77 + .../common/components/Footer.tsx | 205 + .../common/components/Forum/Forum.tsx | 187 + .../components/Forum/SideNavigation.tsx | 176 + .../common/components/Forum/Thread.tsx | 207 + .../common/components/Forum/Threads.tsx | 98 + .../common/components/GenericInfobox.tsx | 36 + .../components/HeightTrackingContainer.tsx | 106 + .../components/InputFields/CheckBox.tsx | 140 + .../InputFields/CheckboxFieldWrapper.tsx | 44 + .../InputFields/DatePickerField.tsx | 67 + .../components/InputFields/DateTimeLocal.tsx | 116 + .../InputFields/EditableComponentTextArea.tsx | 93 + .../components/InputFields/FileField.tsx | 143 + .../components/InputFields/RadioButton.tsx | 77 + .../components/InputFields/SelectField.tsx | 138 + .../components/InputFields/TextAreaField.tsx | 106 + .../components/InputFields/TextField.tsx | 147 + .../InputFields/TimePickerField.tsx | 67 + .../components/LanguageSelection/Language.tsx | 65 + .../LanguageSelection/LanguageMenu.tsx | 29 + .../LanguageSelection/LanguageOption.tsx | 63 + .../components/LanguageSelection/index.tsx | 125 + .../common/components/LinkOrNoLink.tsx | 18 + .../common/components/LoginControls.tsx | 73 + .../components/MessageChannelIFrame.tsx | 219 + .../Navigation/NavBar/ComplexNav.tsx | 277 + .../NavBar/Menu/Hamburger/Hamburger.tsx | 31 + .../NavBar/Menu/Hamburger/HamburgerSpring.tsx | 210 + .../Navigation/NavBar/Menu/Menu.tsx | 125 + .../Navigation/NavBar/Menu/MenuItem.tsx | 7 + .../Navigation/NavBar/NavContainer.tsx | 18 + .../components/Navigation/NavBar/NavItem.tsx | 7 + .../components/Navigation/NavBar/NavItems.tsx | 23 + .../components/Navigation/NavBar/NavLink.tsx | 62 + .../Navigation/NavBar/SimpleNav.tsx | 82 + .../components/Navigation/NavBar/index.tsx | 28 + .../Navigation/TabLinks/TabLink.tsx | 100 + .../Navigation/TabLinks/TabLinkNavigation.tsx | 134 + .../Navigation/TabLinks/TabLinkPanel.tsx | 11 + .../common/components/Nested.tsx | 20 + .../common/components/NextSectionLink.tsx | 308 + .../common/components/Notifications/Base.tsx | 17 + .../components/Notifications/Delete.tsx | 111 + .../common/components/Notifications/Error.tsx | 114 + .../components/Notifications/Loading.tsx | 93 + .../components/Notifications/Success.tsx | 111 + .../Notifications/ToasterNotifications.tsx | 21 + .../components/OnlyRenderIfPermissions.tsx | 38 + .../common/components/PagesInChapterBox.tsx | 134 + .../common/components/Pagination.tsx | 353 + .../components/PaginationItemsPerPage.tsx | 49 + .../components/PeerReview/LikertScale.tsx | 140 + .../common/components/PeerReview/Option.tsx | 83 + .../PeerReview/PeerReviewProgress.tsx | 48 + .../common/components/PeerReview/Review.tsx | 70 + .../common/components/Quote.tsx | 57 + .../common/components/Reference.tsx | 245 + .../common/components/SelectMenu.tsx | 120 + .../common/components/SkipLink.tsx | 23 + .../common/components/SpeechBalloon.tsx | 60 + .../common/components/Spinner.tsx | 63 + .../common/components/Sponsor.tsx | 110 + .../common/components/Test.tsx | 20 + .../common/components/TimeComponent.tsx | 109 + .../common/components/Title.tsx | 24 + .../common/components/TopLevelPage.tsx | 113 + .../common/components/TopicObjectives.tsx | 96 + .../components/layout/PageMarginOffset.tsx | 21 + .../components/monaco/MonacoDiffEditor.tsx | 20 + .../common/components/monaco/MonacoEditor.tsx | 20 + .../monaco/impl/MonacoDiffEditorImpl.tsx | 25 + .../monaco/impl/MonacoEditorImpl.tsx | 25 + .../common/components/monaco/impl/loader.ts | 8 + .../HideChildrenInSystemTests.tsx | 18 + .../system-tests/HideTextInSystemTests.tsx | 21 + .../MaskOverThisInSystemTests.tsx | 30 + .../contexts/ExerciseServiceContext.tsx | 25 + .../common/contexts/IframeHeightContext.tsx | 9 + .../common/contexts/LoginStateContext.tsx | 77 + .../exercise-service-protocol-types-2.ts | 22 + .../exercise-service-protocol-types.guard.ts | 267 + .../common/exercise-service-protocol-types.ts | 133 + .../useExerciseServiceOutputState.tsx | 63 + .../common/hooks/useAuthorizeMultiple.tsx | 32 + .../common/hooks/useClickOutside.tsx | 24 + .../common/hooks/useDateStringAsDate.tsx | 19 + .../useExerciseServiceParentConnection.tsx | 61 + .../common/hooks/useLanguage.tsx | 106 + .../shared-module-v2/common/hooks/useMedia.ts | 23 + .../common/hooks/useMessageChannel.tsx | 9 + .../common/hooks/usePaginationInfo.tsx | 82 + .../common/hooks/useQueryParameter.ts | 22 + ...houldHideStuffForSystemTestScreenshots.tsx | 25 + .../common/hooks/useShowToastInfinitely.tsx | 28 + .../common/hooks/useStateQuery.ts | 107 + .../common/hooks/useToastMutation.tsx | 148 + .../common/hooks/useUserInfo.tsx | 10 + .../common/img/UHBrandLogo.svg | 8 + .../common/img/accordion-arrow.svg | 3 + .../src/shared-module-v2/common/img/arrow.svg | 3 + .../shared-module-v2/common/img/backarrow.svg | 3 + .../common/img/blackArrow.svg | 3 + .../shared-module-v2/common/img/bulleye.svg | 5 + .../common/img/card-bg-circle.svg | 3 + .../common/img/card-bg-star.svg | 6 + .../common/img/card-bg-zigzag.svg | 8 + .../common/img/card-defualt-bg/circle.svg | 3 + .../common/img/card-defualt-bg/cross.svg | 4 + .../common/img/card-defualt-bg/dot-circle.svg | 4 + .../common/img/card-defualt-bg/equal.svg | 4 + .../img/card-defualt-bg/intersection.svg | 4 + .../img/card-defualt-bg/pixel-square.svg | 5 + .../img/card-defualt-bg/quadruple-circle.svg | 6 + .../common/img/card-defualt-bg/triangle.svg | 3 + .../shared-module-v2/common/img/cardNext.svg | 3 + .../common/img/caret-arrow-down.svg | 3 + .../common/img/caret-arrow-left.svg | 3 + .../common/img/caret-arrow-right.svg | 3 + .../common/img/caret-arrow-up.svg | 3 + .../src/shared-module-v2/common/img/check.svg | 3 + .../shared-module-v2/common/img/checkmark.svg | 3 + .../src/shared-module-v2/common/img/china.svg | 22 + .../src/shared-module-v2/common/img/close.svg | 11 + .../src/shared-module-v2/common/img/cross.svg | 6 + .../shared-module-v2/common/img/diamond.png | Bin 0 -> 840 bytes .../shared-module-v2/common/img/diamond.svg | 3 + .../common/img/exist-icon.svg | 3 + .../common/img/external-link.svg | 1 + .../common/img/flags/Austria.svg | 5 + .../common/img/flags/Belgium.svg | 1 + .../common/img/flags/Bulgaria.svg | 6 + .../common/img/flags/Croatia.svg | 276 + .../common/img/flags/Czech.svg | 6 + .../common/img/flags/Denmark.svg | 1 + .../common/img/flags/Estonia.svg | 5 + .../common/img/flags/Finland.svg | 6 + .../common/img/flags/France.svg | 6 + .../common/img/flags/Germany.svg | 7 + .../common/img/flags/Greece.svg | 5 + .../common/img/flags/Ireland.svg | 6 + .../common/img/flags/Italy.svg | 6 + .../common/img/flags/Latvia.svg | 5 + .../common/img/flags/Lithuania.svg | 1 + .../common/img/flags/Netherlands.svg | 5 + .../common/img/flags/Norway.svg | 13 + .../common/img/flags/Poland.svg | 1 + .../common/img/flags/Portugal.svg | 196 + .../common/img/flags/Romania.svg | 6 + .../common/img/flags/Slovenia.svg | 24 + .../common/img/flags/Spain.svg | 1 + .../common/img/flags/Sweden.svg | 1 + .../shared-module-v2/common/img/flags/USA.svg | 97 + .../common/img/flags/United_Kingdom.svg | 16 + .../common/img/hero-default-bg-image.svg | 302 + .../common/img/likert/agree.svg | 8 + .../common/img/likert/disagree.svg | 7 + .../common/img/likert/neutral.svg | 7 + .../common/img/likert/stronglyAgree.svg | 8 + .../common/img/likert/stronglyDisagree.svg | 7 + .../src/shared-module-v2/common/img/lock.svg | 7 + .../common/img/moocfiLogo.svg | 10 + .../src/shared-module-v2/common/img/next.svg | 14 + .../src/shared-module-v2/common/img/quote.svg | 20 + .../src/shared-module-v2/common/img/score.svg | 17 + .../common/img/screwedArrow.svg | 3 + .../shared-module-v2/common/img/setting.svg | 8 + .../shared-module-v2/common/img/swoosh.svg | 11 + .../shared-module-v2/common/img/tick-03.svg | 6 + .../src/shared-module-v2/common/img/tick.svg | 8 + .../common/img/uh_without_background.svg | 6 + .../common/img/unitedStates.svg | 53 + .../shared-module-v2/common/img/up-arrow.svg | 3 + .../common/locales/en/cms.json | 114 + .../common/locales/en/course-material.json | 181 + .../common/locales/en/example-exercise.json | 8 + .../common/locales/en/main-frontend.json | 606 + .../common/locales/en/quizzes.json | 161 + .../common/locales/en/shared-module.json | 108 + .../common/locales/en/tmc.json | 21 + .../common/locales/fi/cms.json | 104 + .../common/locales/fi/course-material.json | 176 + .../common/locales/fi/example-exercise.json | 8 + .../common/locales/fi/main-frontend.json | 601 + .../common/locales/fi/quizzes.json | 163 + .../common/locales/fi/shared-module.json | 106 + .../common/locales/fi/tmc.json | 21 + .../common/services/appQueryClient.ts | 39 + .../common/services/backend/auth.ts | 44 + .../common/services/backend/files.ts | 17 + .../common/styles/GlobalStyles.tsx | 94 + .../common/styles/constants.ts | 9 + .../common/styles/cssReset.ts | 84 + .../shared-module-v2/common/styles/index.ts | 2 + .../common/styles/monacoFontFixer.ts | 13 + .../common/styles/muiTheme.ts | 15 + .../shared-module-v2/common/styles/respond.ts | 16 + .../shared-module-v2/common/styles/theme.ts | 170 + .../common/styles/typography.ts | 34 + .../common/types/imageTypes.d.ts | 10 + .../common/utils/accessibility.ts | 6 + .../common/utils/base-path.ts | 3 + .../common/utils/constants.ts | 13 + .../shared-module-v2/common/utils/cookies.ts | 12 + .../common/utils/cross-routing.ts | 12 + .../shared-module-v2/common/utils/dateUtil.ts | 36 + .../src/shared-module-v2/common/utils/dom.ts | 11 + .../dontRenderUntilQueryParametersReady.tsx | 64 + .../common/utils/exerciseServices.ts | 5 + .../shared-module-v2/common/utils/fetching.ts | 88 + .../shared-module-v2/common/utils/files.ts | 93 + .../common/utils/generateWebVitalsReporter.ts | 26 + .../utils/getGuestPseudonymousUserId.ts | 19 + .../utils/i18next-parser.config.template.js | 43 + .../ietfLanguageTagToHumanReadableName.ts | 21 + .../shared-module-v2/common/utils/initI18n.ts | 51 + .../common/utils/nullability.ts | 7 + .../shared-module-v2/common/utils/numbers.ts | 66 + .../utils/redirectBackAfterLoginOrSignup.tsx | 58 + .../common/utils/responseHeaders.js | 89 + .../shared-module-v2/common/utils/routes.ts | 14 + .../shared-module-v2/common/utils/strings.ts | 93 + .../shared-module-v2/common/utils/styles.ts | 4 + .../common/utils/svgoConfig.js | 24 + .../common/utils/testing/i18nTest.ts | 26 + .../testing/replaceUuidsWithPlaceholders.ts | 7 + .../src/shared-module-v2/common/utils/time.ts | 20 + .../common/utils/typeMappter.ts | 16 + .../common/utils/urlManipulation.ts | 9 + .../common/utils/validation.ts | 25 + .../common/utils/withErrorBoundary.tsx | 71 + .../common/utils/withNoSsr.tsx | 28 + .../shared-module-v2/common/bindings.guard.ts | 3360 +++ .../src/shared-module-v2/common/bindings.ts | 1900 ++ .../components/Accordion/DetailAccordion.tsx | 132 + .../common/components/Accordion/index.tsx | 148 + .../common/components/Banner/Banner.tsx | 110 + .../components/Banner/ContributeBanner.tsx | 110 + .../components/Banner/ReadOnlyBanner.tsx | 51 + .../common/components/BooleanAsText.tsx | 8 + .../common/components/Breadcrumbs.tsx | 108 + .../common/components/Button.tsx | 323 + .../components/Card/CardOpenTextOverlay.tsx | 50 + .../common/components/Card/CardOpensText.tsx | 47 + .../components/Card/IllustrationCard.tsx | 142 + .../common/components/Card/SimpleCard.tsx | 161 + .../common/components/Card/index.tsx | 68 + .../Centering/BreakFromCentered.tsx | 80 + .../common/components/Centering/Centered.tsx | 46 + .../common/components/CircularProgressBar.tsx | 86 + .../CourseProgress/CircularProgress.tsx | 185 + .../components/CourseProgress/ProgressBar.tsx | 132 + .../components/CourseProgress/index.tsx | 35 + .../common/components/DebugModal.tsx | 107 + .../common/components/Dialog.tsx | 132 + .../common/components/DiffFormatter.tsx | 73 + .../DropdownMenu/DropdownMenuItem.tsx | 77 + .../common/components/DropdownMenu/index.tsx | 154 + .../common/components/ErrorBanner.tsx | 304 + .../components/ExerciseList/ExerciseBox.tsx | 166 + .../components/ExerciseList/PageBox.tsx | 55 + .../common/components/FloatingErrorBox.tsx | 77 + .../common/components/Footer.tsx | 205 + .../common/components/Forum/Forum.tsx | 187 + .../components/Forum/SideNavigation.tsx | 176 + .../common/components/Forum/Thread.tsx | 207 + .../common/components/Forum/Threads.tsx | 98 + .../common/components/GenericInfobox.tsx | 36 + .../components/HeightTrackingContainer.tsx | 106 + .../components/InputFields/CheckBox.tsx | 140 + .../InputFields/CheckboxFieldWrapper.tsx | 44 + .../InputFields/DatePickerField.tsx | 67 + .../components/InputFields/DateTimeLocal.tsx | 116 + .../InputFields/EditableComponentTextArea.tsx | 93 + .../components/InputFields/FileField.tsx | 143 + .../components/InputFields/RadioButton.tsx | 77 + .../components/InputFields/SelectField.tsx | 138 + .../components/InputFields/TextAreaField.tsx | 106 + .../components/InputFields/TextField.tsx | 147 + .../InputFields/TimePickerField.tsx | 67 + .../components/LanguageSelection/Language.tsx | 65 + .../LanguageSelection/LanguageMenu.tsx | 29 + .../LanguageSelection/LanguageOption.tsx | 63 + .../components/LanguageSelection/index.tsx | 125 + .../common/components/LinkOrNoLink.tsx | 18 + .../common/components/LoginControls.tsx | 73 + .../components/MessageChannelIFrame.tsx | 219 + .../Navigation/NavBar/ComplexNav.tsx | 277 + .../NavBar/Menu/Hamburger/Hamburger.tsx | 31 + .../NavBar/Menu/Hamburger/HamburgerSpring.tsx | 210 + .../Navigation/NavBar/Menu/Menu.tsx | 125 + .../Navigation/NavBar/Menu/MenuItem.tsx | 7 + .../Navigation/NavBar/NavContainer.tsx | 18 + .../components/Navigation/NavBar/NavItem.tsx | 7 + .../components/Navigation/NavBar/NavItems.tsx | 23 + .../components/Navigation/NavBar/NavLink.tsx | 62 + .../Navigation/NavBar/SimpleNav.tsx | 82 + .../components/Navigation/NavBar/index.tsx | 28 + .../Navigation/TabLinks/TabLink.tsx | 100 + .../Navigation/TabLinks/TabLinkNavigation.tsx | 134 + .../Navigation/TabLinks/TabLinkPanel.tsx | 11 + .../common/components/Nested.tsx | 20 + .../common/components/NextSectionLink.tsx | 308 + .../common/components/Notifications/Base.tsx | 17 + .../components/Notifications/Delete.tsx | 111 + .../common/components/Notifications/Error.tsx | 114 + .../components/Notifications/Loading.tsx | 93 + .../components/Notifications/Success.tsx | 111 + .../Notifications/ToasterNotifications.tsx | 21 + .../components/OnlyRenderIfPermissions.tsx | 38 + .../common/components/PagesInChapterBox.tsx | 134 + .../common/components/Pagination.tsx | 353 + .../components/PaginationItemsPerPage.tsx | 49 + .../components/PeerReview/LikertScale.tsx | 140 + .../common/components/PeerReview/Option.tsx | 83 + .../PeerReview/PeerReviewProgress.tsx | 48 + .../common/components/PeerReview/Review.tsx | 70 + .../common/components/Quote.tsx | 57 + .../common/components/Reference.tsx | 245 + .../common/components/SelectMenu.tsx | 120 + .../common/components/SkipLink.tsx | 23 + .../common/components/SpeechBalloon.tsx | 60 + .../common/components/Spinner.tsx | 63 + .../common/components/Sponsor.tsx | 110 + .../common/components/Test.tsx | 20 + .../common/components/TimeComponent.tsx | 109 + .../common/components/Title.tsx | 24 + .../common/components/TopLevelPage.tsx | 113 + .../common/components/TopicObjectives.tsx | 96 + .../components/layout/PageMarginOffset.tsx | 21 + .../components/monaco/MonacoDiffEditor.tsx | 20 + .../common/components/monaco/MonacoEditor.tsx | 20 + .../monaco/impl/MonacoDiffEditorImpl.tsx | 25 + .../monaco/impl/MonacoEditorImpl.tsx | 25 + .../common/components/monaco/impl/loader.ts | 8 + .../HideChildrenInSystemTests.tsx | 18 + .../system-tests/HideTextInSystemTests.tsx | 21 + .../MaskOverThisInSystemTests.tsx | 30 + .../contexts/ExerciseServiceContext.tsx | 25 + .../common/contexts/IframeHeightContext.tsx | 9 + .../common/contexts/LoginStateContext.tsx | 77 + .../exercise-service-protocol-types-2.ts | 22 + .../exercise-service-protocol-types.guard.ts | 267 + .../common/exercise-service-protocol-types.ts | 133 + .../useExerciseServiceOutputState.tsx | 63 + .../common/hooks/useAuthorizeMultiple.tsx | 32 + .../common/hooks/useClickOutside.tsx | 24 + .../common/hooks/useDateStringAsDate.tsx | 19 + .../useExerciseServiceParentConnection.tsx | 61 + .../common/hooks/useLanguage.tsx | 106 + .../shared-module-v2/common/hooks/useMedia.ts | 23 + .../common/hooks/useMessageChannel.tsx | 9 + .../common/hooks/usePaginationInfo.tsx | 82 + .../common/hooks/useQueryParameter.ts | 22 + ...houldHideStuffForSystemTestScreenshots.tsx | 25 + .../common/hooks/useShowToastInfinitely.tsx | 28 + .../common/hooks/useStateQuery.ts | 107 + .../common/hooks/useToastMutation.tsx | 148 + .../common/hooks/useUserInfo.tsx | 10 + .../common/img/UHBrandLogo.svg | 8 + .../common/img/accordion-arrow.svg | 3 + .../src/shared-module-v2/common/img/arrow.svg | 3 + .../shared-module-v2/common/img/backarrow.svg | 3 + .../common/img/blackArrow.svg | 3 + .../shared-module-v2/common/img/bulleye.svg | 5 + .../common/img/card-bg-circle.svg | 3 + .../common/img/card-bg-star.svg | 6 + .../common/img/card-bg-zigzag.svg | 8 + .../common/img/card-defualt-bg/circle.svg | 3 + .../common/img/card-defualt-bg/cross.svg | 4 + .../common/img/card-defualt-bg/dot-circle.svg | 4 + .../common/img/card-defualt-bg/equal.svg | 4 + .../img/card-defualt-bg/intersection.svg | 4 + .../img/card-defualt-bg/pixel-square.svg | 5 + .../img/card-defualt-bg/quadruple-circle.svg | 6 + .../common/img/card-defualt-bg/triangle.svg | 3 + .../shared-module-v2/common/img/cardNext.svg | 3 + .../common/img/caret-arrow-down.svg | 3 + .../common/img/caret-arrow-left.svg | 3 + .../common/img/caret-arrow-right.svg | 3 + .../common/img/caret-arrow-up.svg | 3 + .../src/shared-module-v2/common/img/check.svg | 3 + .../shared-module-v2/common/img/checkmark.svg | 3 + .../src/shared-module-v2/common/img/china.svg | 22 + .../src/shared-module-v2/common/img/close.svg | 11 + .../src/shared-module-v2/common/img/cross.svg | 6 + .../shared-module-v2/common/img/diamond.png | Bin 0 -> 840 bytes .../shared-module-v2/common/img/diamond.svg | 3 + .../common/img/exist-icon.svg | 3 + .../common/img/external-link.svg | 1 + .../common/img/flags/Austria.svg | 5 + .../common/img/flags/Belgium.svg | 1 + .../common/img/flags/Bulgaria.svg | 6 + .../common/img/flags/Croatia.svg | 276 + .../common/img/flags/Czech.svg | 6 + .../common/img/flags/Denmark.svg | 1 + .../common/img/flags/Estonia.svg | 5 + .../common/img/flags/Finland.svg | 6 + .../common/img/flags/France.svg | 6 + .../common/img/flags/Germany.svg | 7 + .../common/img/flags/Greece.svg | 5 + .../common/img/flags/Ireland.svg | 6 + .../common/img/flags/Italy.svg | 6 + .../common/img/flags/Latvia.svg | 5 + .../common/img/flags/Lithuania.svg | 1 + .../common/img/flags/Netherlands.svg | 5 + .../common/img/flags/Norway.svg | 13 + .../common/img/flags/Poland.svg | 1 + .../common/img/flags/Portugal.svg | 196 + .../common/img/flags/Romania.svg | 6 + .../common/img/flags/Slovenia.svg | 24 + .../common/img/flags/Spain.svg | 1 + .../common/img/flags/Sweden.svg | 1 + .../shared-module-v2/common/img/flags/USA.svg | 97 + .../common/img/flags/United_Kingdom.svg | 16 + .../common/img/hero-default-bg-image.svg | 302 + .../common/img/likert/agree.svg | 8 + .../common/img/likert/disagree.svg | 7 + .../common/img/likert/neutral.svg | 7 + .../common/img/likert/stronglyAgree.svg | 8 + .../common/img/likert/stronglyDisagree.svg | 7 + .../src/shared-module-v2/common/img/lock.svg | 7 + .../common/img/moocfiLogo.svg | 10 + .../src/shared-module-v2/common/img/next.svg | 14 + .../src/shared-module-v2/common/img/quote.svg | 20 + .../src/shared-module-v2/common/img/score.svg | 17 + .../common/img/screwedArrow.svg | 3 + .../shared-module-v2/common/img/setting.svg | 8 + .../shared-module-v2/common/img/swoosh.svg | 11 + .../shared-module-v2/common/img/tick-03.svg | 6 + .../src/shared-module-v2/common/img/tick.svg | 8 + .../common/img/uh_without_background.svg | 6 + .../common/img/unitedStates.svg | 53 + .../shared-module-v2/common/img/up-arrow.svg | 3 + .../common/locales/en/cms.json | 114 + .../common/locales/en/course-material.json | 181 + .../common/locales/en/example-exercise.json | 8 + .../common/locales/en/main-frontend.json | 606 + .../common/locales/en/quizzes.json | 161 + .../common/locales/en/shared-module.json | 108 + .../common/locales/en/tmc.json | 21 + .../common/locales/fi/cms.json | 104 + .../common/locales/fi/course-material.json | 176 + .../common/locales/fi/example-exercise.json | 8 + .../common/locales/fi/main-frontend.json | 601 + .../common/locales/fi/quizzes.json | 163 + .../common/locales/fi/shared-module.json | 106 + .../common/locales/fi/tmc.json | 21 + .../common/services/appQueryClient.ts | 39 + .../common/services/backend/auth.ts | 44 + .../common/services/backend/files.ts | 17 + .../common/styles/GlobalStyles.tsx | 94 + .../common/styles/constants.ts | 9 + .../common/styles/cssReset.ts | 84 + .../shared-module-v2/common/styles/index.ts | 2 + .../common/styles/monacoFontFixer.ts | 13 + .../common/styles/muiTheme.ts | 15 + .../shared-module-v2/common/styles/respond.ts | 16 + .../shared-module-v2/common/styles/theme.ts | 170 + .../common/styles/typography.ts | 34 + .../common/types/imageTypes.d.ts | 10 + .../common/utils/accessibility.ts | 6 + .../common/utils/base-path.ts | 3 + .../common/utils/constants.ts | 13 + .../shared-module-v2/common/utils/cookies.ts | 12 + .../common/utils/cross-routing.ts | 12 + .../shared-module-v2/common/utils/dateUtil.ts | 36 + .../src/shared-module-v2/common/utils/dom.ts | 11 + .../dontRenderUntilQueryParametersReady.tsx | 64 + .../common/utils/exerciseServices.ts | 5 + .../shared-module-v2/common/utils/fetching.ts | 88 + .../shared-module-v2/common/utils/files.ts | 93 + .../common/utils/generateWebVitalsReporter.ts | 26 + .../utils/getGuestPseudonymousUserId.ts | 19 + .../utils/i18next-parser.config.template.js | 43 + .../ietfLanguageTagToHumanReadableName.ts | 21 + .../shared-module-v2/common/utils/initI18n.ts | 51 + .../common/utils/nullability.ts | 7 + .../shared-module-v2/common/utils/numbers.ts | 66 + .../utils/redirectBackAfterLoginOrSignup.tsx | 58 + .../common/utils/responseHeaders.js | 89 + .../shared-module-v2/common/utils/routes.ts | 14 + .../shared-module-v2/common/utils/strings.ts | 93 + .../shared-module-v2/common/utils/styles.ts | 4 + .../common/utils/svgoConfig.js | 24 + .../common/utils/testing/i18nTest.ts | 26 + .../testing/replaceUuidsWithPlaceholders.ts | 7 + .../src/shared-module-v2/common/utils/time.ts | 20 + .../common/utils/typeMappter.ts | 16 + .../common/utils/urlManipulation.ts | 9 + .../common/utils/validation.ts | 25 + .../common/utils/withErrorBoundary.tsx | 71 + .../common/utils/withNoSsr.tsx | 28 + .../shared-module-v2/common/bindings.guard.ts | 3360 +++ .../src/shared-module-v2/common/bindings.ts | 1900 ++ .../components/Accordion/DetailAccordion.tsx | 132 + .../common/components/Accordion/index.tsx | 148 + .../common/components/Banner/Banner.tsx | 110 + .../components/Banner/ContributeBanner.tsx | 110 + .../components/Banner/ReadOnlyBanner.tsx | 51 + .../common/components/BooleanAsText.tsx | 8 + .../common/components/Breadcrumbs.tsx | 108 + .../common/components/Button.tsx | 323 + .../components/Card/CardOpenTextOverlay.tsx | 50 + .../common/components/Card/CardOpensText.tsx | 47 + .../components/Card/IllustrationCard.tsx | 142 + .../common/components/Card/SimpleCard.tsx | 161 + .../common/components/Card/index.tsx | 68 + .../Centering/BreakFromCentered.tsx | 80 + .../common/components/Centering/Centered.tsx | 46 + .../common/components/CircularProgressBar.tsx | 86 + .../CourseProgress/CircularProgress.tsx | 185 + .../components/CourseProgress/ProgressBar.tsx | 132 + .../components/CourseProgress/index.tsx | 35 + .../common/components/DebugModal.tsx | 107 + .../common/components/Dialog.tsx | 132 + .../common/components/DiffFormatter.tsx | 73 + .../DropdownMenu/DropdownMenuItem.tsx | 77 + .../common/components/DropdownMenu/index.tsx | 154 + .../common/components/ErrorBanner.tsx | 304 + .../components/ExerciseList/ExerciseBox.tsx | 166 + .../components/ExerciseList/PageBox.tsx | 55 + .../common/components/FloatingErrorBox.tsx | 77 + .../common/components/Footer.tsx | 205 + .../common/components/Forum/Forum.tsx | 187 + .../components/Forum/SideNavigation.tsx | 176 + .../common/components/Forum/Thread.tsx | 207 + .../common/components/Forum/Threads.tsx | 98 + .../common/components/GenericInfobox.tsx | 36 + .../components/HeightTrackingContainer.tsx | 106 + .../components/InputFields/CheckBox.tsx | 140 + .../InputFields/CheckboxFieldWrapper.tsx | 44 + .../InputFields/DatePickerField.tsx | 67 + .../components/InputFields/DateTimeLocal.tsx | 116 + .../InputFields/EditableComponentTextArea.tsx | 93 + .../components/InputFields/FileField.tsx | 143 + .../components/InputFields/RadioButton.tsx | 77 + .../components/InputFields/SelectField.tsx | 138 + .../components/InputFields/TextAreaField.tsx | 106 + .../components/InputFields/TextField.tsx | 147 + .../InputFields/TimePickerField.tsx | 67 + .../components/LanguageSelection/Language.tsx | 65 + .../LanguageSelection/LanguageMenu.tsx | 29 + .../LanguageSelection/LanguageOption.tsx | 63 + .../components/LanguageSelection/index.tsx | 125 + .../common/components/LinkOrNoLink.tsx | 18 + .../common/components/LoginControls.tsx | 73 + .../components/MessageChannelIFrame.tsx | 219 + .../Navigation/NavBar/ComplexNav.tsx | 277 + .../NavBar/Menu/Hamburger/Hamburger.tsx | 31 + .../NavBar/Menu/Hamburger/HamburgerSpring.tsx | 210 + .../Navigation/NavBar/Menu/Menu.tsx | 125 + .../Navigation/NavBar/Menu/MenuItem.tsx | 7 + .../Navigation/NavBar/NavContainer.tsx | 18 + .../components/Navigation/NavBar/NavItem.tsx | 7 + .../components/Navigation/NavBar/NavItems.tsx | 23 + .../components/Navigation/NavBar/NavLink.tsx | 62 + .../Navigation/NavBar/SimpleNav.tsx | 82 + .../components/Navigation/NavBar/index.tsx | 28 + .../Navigation/TabLinks/TabLink.tsx | 100 + .../Navigation/TabLinks/TabLinkNavigation.tsx | 134 + .../Navigation/TabLinks/TabLinkPanel.tsx | 11 + .../common/components/Nested.tsx | 20 + .../common/components/NextSectionLink.tsx | 308 + .../common/components/Notifications/Base.tsx | 17 + .../components/Notifications/Delete.tsx | 111 + .../common/components/Notifications/Error.tsx | 114 + .../components/Notifications/Loading.tsx | 93 + .../components/Notifications/Success.tsx | 111 + .../Notifications/ToasterNotifications.tsx | 21 + .../components/OnlyRenderIfPermissions.tsx | 38 + .../common/components/PagesInChapterBox.tsx | 134 + .../common/components/Pagination.tsx | 353 + .../components/PaginationItemsPerPage.tsx | 49 + .../components/PeerReview/LikertScale.tsx | 140 + .../common/components/PeerReview/Option.tsx | 83 + .../PeerReview/PeerReviewProgress.tsx | 48 + .../common/components/PeerReview/Review.tsx | 70 + .../common/components/Quote.tsx | 57 + .../common/components/Reference.tsx | 245 + .../common/components/SelectMenu.tsx | 120 + .../common/components/SkipLink.tsx | 23 + .../common/components/SpeechBalloon.tsx | 60 + .../common/components/Spinner.tsx | 63 + .../common/components/Sponsor.tsx | 110 + .../common/components/Test.tsx | 20 + .../common/components/TimeComponent.tsx | 109 + .../common/components/Title.tsx | 24 + .../common/components/TopLevelPage.tsx | 113 + .../common/components/TopicObjectives.tsx | 96 + .../components/layout/PageMarginOffset.tsx | 21 + .../components/monaco/MonacoDiffEditor.tsx | 20 + .../common/components/monaco/MonacoEditor.tsx | 20 + .../monaco/impl/MonacoDiffEditorImpl.tsx | 25 + .../monaco/impl/MonacoEditorImpl.tsx | 25 + .../common/components/monaco/impl/loader.ts | 8 + .../HideChildrenInSystemTests.tsx | 18 + .../system-tests/HideTextInSystemTests.tsx | 21 + .../MaskOverThisInSystemTests.tsx | 30 + .../contexts/ExerciseServiceContext.tsx | 25 + .../common/contexts/IframeHeightContext.tsx | 9 + .../common/contexts/LoginStateContext.tsx | 77 + .../exercise-service-protocol-types-2.ts | 22 + .../exercise-service-protocol-types.guard.ts | 267 + .../common/exercise-service-protocol-types.ts | 133 + .../useExerciseServiceOutputState.tsx | 63 + .../common/hooks/useAuthorizeMultiple.tsx | 32 + .../common/hooks/useClickOutside.tsx | 24 + .../common/hooks/useDateStringAsDate.tsx | 19 + .../useExerciseServiceParentConnection.tsx | 61 + .../common/hooks/useLanguage.tsx | 106 + .../shared-module-v2/common/hooks/useMedia.ts | 23 + .../common/hooks/useMessageChannel.tsx | 9 + .../common/hooks/usePaginationInfo.tsx | 82 + .../common/hooks/useQueryParameter.ts | 22 + ...houldHideStuffForSystemTestScreenshots.tsx | 25 + .../common/hooks/useShowToastInfinitely.tsx | 28 + .../common/hooks/useStateQuery.ts | 107 + .../common/hooks/useToastMutation.tsx | 148 + .../common/hooks/useUserInfo.tsx | 10 + .../common/img/UHBrandLogo.svg | 8 + .../common/img/accordion-arrow.svg | 3 + .../src/shared-module-v2/common/img/arrow.svg | 3 + .../shared-module-v2/common/img/backarrow.svg | 3 + .../common/img/blackArrow.svg | 3 + .../shared-module-v2/common/img/bulleye.svg | 5 + .../common/img/card-bg-circle.svg | 3 + .../common/img/card-bg-star.svg | 6 + .../common/img/card-bg-zigzag.svg | 8 + .../common/img/card-defualt-bg/circle.svg | 3 + .../common/img/card-defualt-bg/cross.svg | 4 + .../common/img/card-defualt-bg/dot-circle.svg | 4 + .../common/img/card-defualt-bg/equal.svg | 4 + .../img/card-defualt-bg/intersection.svg | 4 + .../img/card-defualt-bg/pixel-square.svg | 5 + .../img/card-defualt-bg/quadruple-circle.svg | 6 + .../common/img/card-defualt-bg/triangle.svg | 3 + .../shared-module-v2/common/img/cardNext.svg | 3 + .../common/img/caret-arrow-down.svg | 3 + .../common/img/caret-arrow-left.svg | 3 + .../common/img/caret-arrow-right.svg | 3 + .../common/img/caret-arrow-up.svg | 3 + .../src/shared-module-v2/common/img/check.svg | 3 + .../shared-module-v2/common/img/checkmark.svg | 3 + .../src/shared-module-v2/common/img/china.svg | 22 + .../src/shared-module-v2/common/img/close.svg | 11 + .../src/shared-module-v2/common/img/cross.svg | 6 + .../shared-module-v2/common/img/diamond.png | Bin 0 -> 840 bytes .../shared-module-v2/common/img/diamond.svg | 3 + .../common/img/exist-icon.svg | 3 + .../common/img/external-link.svg | 1 + .../common/img/flags/Austria.svg | 5 + .../common/img/flags/Belgium.svg | 1 + .../common/img/flags/Bulgaria.svg | 6 + .../common/img/flags/Croatia.svg | 276 + .../common/img/flags/Czech.svg | 6 + .../common/img/flags/Denmark.svg | 1 + .../common/img/flags/Estonia.svg | 5 + .../common/img/flags/Finland.svg | 6 + .../common/img/flags/France.svg | 6 + .../common/img/flags/Germany.svg | 7 + .../common/img/flags/Greece.svg | 5 + .../common/img/flags/Ireland.svg | 6 + .../common/img/flags/Italy.svg | 6 + .../common/img/flags/Latvia.svg | 5 + .../common/img/flags/Lithuania.svg | 1 + .../common/img/flags/Netherlands.svg | 5 + .../common/img/flags/Norway.svg | 13 + .../common/img/flags/Poland.svg | 1 + .../common/img/flags/Portugal.svg | 196 + .../common/img/flags/Romania.svg | 6 + .../common/img/flags/Slovenia.svg | 24 + .../common/img/flags/Spain.svg | 1 + .../common/img/flags/Sweden.svg | 1 + .../shared-module-v2/common/img/flags/USA.svg | 97 + .../common/img/flags/United_Kingdom.svg | 16 + .../common/img/hero-default-bg-image.svg | 302 + .../common/img/likert/agree.svg | 8 + .../common/img/likert/disagree.svg | 7 + .../common/img/likert/neutral.svg | 7 + .../common/img/likert/stronglyAgree.svg | 8 + .../common/img/likert/stronglyDisagree.svg | 7 + .../src/shared-module-v2/common/img/lock.svg | 7 + .../common/img/moocfiLogo.svg | 10 + .../src/shared-module-v2/common/img/next.svg | 14 + .../src/shared-module-v2/common/img/quote.svg | 20 + .../src/shared-module-v2/common/img/score.svg | 17 + .../common/img/screwedArrow.svg | 3 + .../shared-module-v2/common/img/setting.svg | 8 + .../shared-module-v2/common/img/swoosh.svg | 11 + .../shared-module-v2/common/img/tick-03.svg | 6 + .../src/shared-module-v2/common/img/tick.svg | 8 + .../common/img/uh_without_background.svg | 6 + .../common/img/unitedStates.svg | 53 + .../shared-module-v2/common/img/up-arrow.svg | 3 + .../common/locales/en/cms.json | 114 + .../common/locales/en/course-material.json | 181 + .../common/locales/en/example-exercise.json | 8 + .../common/locales/en/main-frontend.json | 606 + .../common/locales/en/quizzes.json | 161 + .../common/locales/en/shared-module.json | 108 + .../common/locales/en/tmc.json | 21 + .../common/locales/fi/cms.json | 104 + .../common/locales/fi/course-material.json | 176 + .../common/locales/fi/example-exercise.json | 8 + .../common/locales/fi/main-frontend.json | 601 + .../common/locales/fi/quizzes.json | 163 + .../common/locales/fi/shared-module.json | 106 + .../common/locales/fi/tmc.json | 21 + .../common/services/appQueryClient.ts | 39 + .../common/services/backend/auth.ts | 44 + .../common/services/backend/files.ts | 17 + .../common/styles/GlobalStyles.tsx | 94 + .../common/styles/constants.ts | 9 + .../common/styles/cssReset.ts | 84 + .../shared-module-v2/common/styles/index.ts | 2 + .../common/styles/monacoFontFixer.ts | 13 + .../common/styles/muiTheme.ts | 15 + .../shared-module-v2/common/styles/respond.ts | 16 + .../shared-module-v2/common/styles/theme.ts | 170 + .../common/styles/typography.ts | 34 + .../common/types/imageTypes.d.ts | 10 + .../common/utils/accessibility.ts | 6 + .../common/utils/base-path.ts | 3 + .../common/utils/constants.ts | 13 + .../shared-module-v2/common/utils/cookies.ts | 12 + .../common/utils/cross-routing.ts | 12 + .../shared-module-v2/common/utils/dateUtil.ts | 36 + .../src/shared-module-v2/common/utils/dom.ts | 11 + .../dontRenderUntilQueryParametersReady.tsx | 64 + .../common/utils/exerciseServices.ts | 5 + .../shared-module-v2/common/utils/fetching.ts | 88 + .../shared-module-v2/common/utils/files.ts | 93 + .../common/utils/generateWebVitalsReporter.ts | 26 + .../utils/getGuestPseudonymousUserId.ts | 19 + .../utils/i18next-parser.config.template.js | 43 + .../ietfLanguageTagToHumanReadableName.ts | 21 + .../shared-module-v2/common/utils/initI18n.ts | 51 + .../common/utils/nullability.ts | 7 + .../shared-module-v2/common/utils/numbers.ts | 66 + .../utils/redirectBackAfterLoginOrSignup.tsx | 58 + .../common/utils/responseHeaders.js | 89 + .../shared-module-v2/common/utils/routes.ts | 14 + .../shared-module-v2/common/utils/strings.ts | 93 + .../shared-module-v2/common/utils/styles.ts | 4 + .../common/utils/svgoConfig.js | 24 + .../common/utils/testing/i18nTest.ts | 26 + .../testing/replaceUuidsWithPlaceholders.ts | 7 + .../src/shared-module-v2/common/utils/time.ts | 20 + .../common/utils/typeMappter.ts | 16 + .../common/utils/urlManipulation.ts | 9 + .../common/utils/validation.ts | 25 + .../common/utils/withErrorBoundary.tsx | 71 + .../common/utils/withNoSsr.tsx | 28 + .../shared-module-v2/common/bindings.guard.ts | 3360 +++ .../shared-module-v2/common/bindings.ts | 1900 ++ .../components/Accordion/DetailAccordion.tsx | 132 + .../common/components/Accordion/index.tsx | 148 + .../common/components/Banner/Banner.tsx | 110 + .../components/Banner/ContributeBanner.tsx | 110 + .../components/Banner/ReadOnlyBanner.tsx | 51 + .../common/components/BooleanAsText.tsx | 8 + .../common/components/Breadcrumbs.tsx | 108 + .../common/components/Button.tsx | 323 + .../components/Card/CardOpenTextOverlay.tsx | 50 + .../common/components/Card/CardOpensText.tsx | 47 + .../components/Card/IllustrationCard.tsx | 142 + .../common/components/Card/SimpleCard.tsx | 161 + .../common/components/Card/index.tsx | 68 + .../Centering/BreakFromCentered.tsx | 80 + .../common/components/Centering/Centered.tsx | 46 + .../common/components/CircularProgressBar.tsx | 86 + .../CourseProgress/CircularProgress.tsx | 185 + .../components/CourseProgress/ProgressBar.tsx | 132 + .../components/CourseProgress/index.tsx | 35 + .../common/components/DebugModal.tsx | 107 + .../common/components/Dialog.tsx | 132 + .../common/components/DiffFormatter.tsx | 73 + .../DropdownMenu/DropdownMenuItem.tsx | 77 + .../common/components/DropdownMenu/index.tsx | 154 + .../common/components/ErrorBanner.tsx | 304 + .../components/ExerciseList/ExerciseBox.tsx | 166 + .../components/ExerciseList/PageBox.tsx | 55 + .../common/components/FloatingErrorBox.tsx | 77 + .../common/components/Footer.tsx | 205 + .../common/components/Forum/Forum.tsx | 187 + .../components/Forum/SideNavigation.tsx | 176 + .../common/components/Forum/Thread.tsx | 207 + .../common/components/Forum/Threads.tsx | 98 + .../common/components/GenericInfobox.tsx | 36 + .../components/HeightTrackingContainer.tsx | 106 + .../components/InputFields/CheckBox.tsx | 140 + .../InputFields/CheckboxFieldWrapper.tsx | 44 + .../InputFields/DatePickerField.tsx | 67 + .../components/InputFields/DateTimeLocal.tsx | 116 + .../InputFields/EditableComponentTextArea.tsx | 93 + .../components/InputFields/FileField.tsx | 143 + .../components/InputFields/RadioButton.tsx | 77 + .../components/InputFields/SelectField.tsx | 138 + .../components/InputFields/TextAreaField.tsx | 106 + .../components/InputFields/TextField.tsx | 147 + .../InputFields/TimePickerField.tsx | 67 + .../components/LanguageSelection/Language.tsx | 65 + .../LanguageSelection/LanguageMenu.tsx | 29 + .../LanguageSelection/LanguageOption.tsx | 63 + .../components/LanguageSelection/index.tsx | 125 + .../common/components/LinkOrNoLink.tsx | 18 + .../common/components/LoginControls.tsx | 73 + .../components/MessageChannelIFrame.tsx | 219 + .../Navigation/NavBar/ComplexNav.tsx | 277 + .../NavBar/Menu/Hamburger/Hamburger.tsx | 31 + .../NavBar/Menu/Hamburger/HamburgerSpring.tsx | 210 + .../Navigation/NavBar/Menu/Menu.tsx | 125 + .../Navigation/NavBar/Menu/MenuItem.tsx | 7 + .../Navigation/NavBar/NavContainer.tsx | 18 + .../components/Navigation/NavBar/NavItem.tsx | 7 + .../components/Navigation/NavBar/NavItems.tsx | 23 + .../components/Navigation/NavBar/NavLink.tsx | 62 + .../Navigation/NavBar/SimpleNav.tsx | 82 + .../components/Navigation/NavBar/index.tsx | 28 + .../Navigation/TabLinks/TabLink.tsx | 100 + .../Navigation/TabLinks/TabLinkNavigation.tsx | 134 + .../Navigation/TabLinks/TabLinkPanel.tsx | 11 + .../common/components/Nested.tsx | 20 + .../common/components/NextSectionLink.tsx | 308 + .../common/components/Notifications/Base.tsx | 17 + .../components/Notifications/Delete.tsx | 111 + .../common/components/Notifications/Error.tsx | 114 + .../components/Notifications/Loading.tsx | 93 + .../components/Notifications/Success.tsx | 111 + .../Notifications/ToasterNotifications.tsx | 21 + .../components/OnlyRenderIfPermissions.tsx | 38 + .../common/components/PagesInChapterBox.tsx | 134 + .../common/components/Pagination.tsx | 353 + .../components/PaginationItemsPerPage.tsx | 49 + .../components/PeerReview/LikertScale.tsx | 140 + .../common/components/PeerReview/Option.tsx | 83 + .../PeerReview/PeerReviewProgress.tsx | 48 + .../common/components/PeerReview/Review.tsx | 70 + .../common/components/Quote.tsx | 57 + .../common/components/Reference.tsx | 245 + .../common/components/SelectMenu.tsx | 120 + .../common/components/SkipLink.tsx | 23 + .../common/components/SpeechBalloon.tsx | 60 + .../common/components/Spinner.tsx | 63 + .../common/components/Sponsor.tsx | 110 + .../common/components/Test.tsx | 20 + .../common/components/TimeComponent.tsx | 109 + .../common/components/Title.tsx | 24 + .../common/components/TopLevelPage.tsx | 113 + .../common/components/TopicObjectives.tsx | 96 + .../components/layout/PageMarginOffset.tsx | 21 + .../components/monaco/MonacoDiffEditor.tsx | 20 + .../common/components/monaco/MonacoEditor.tsx | 20 + .../monaco/impl/MonacoDiffEditorImpl.tsx | 25 + .../monaco/impl/MonacoEditorImpl.tsx | 25 + .../common/components/monaco/impl/loader.ts | 8 + .../HideChildrenInSystemTests.tsx | 18 + .../system-tests/HideTextInSystemTests.tsx | 21 + .../MaskOverThisInSystemTests.tsx | 30 + .../contexts/ExerciseServiceContext.tsx | 25 + .../common/contexts/IframeHeightContext.tsx | 9 + .../common/contexts/LoginStateContext.tsx | 77 + .../exercise-service-protocol-types-2.ts | 22 + .../exercise-service-protocol-types.guard.ts | 267 + .../common/exercise-service-protocol-types.ts | 133 + .../useExerciseServiceOutputState.tsx | 63 + .../common/hooks/useAuthorizeMultiple.tsx | 32 + .../common/hooks/useClickOutside.tsx | 24 + .../common/hooks/useDateStringAsDate.tsx | 19 + .../useExerciseServiceParentConnection.tsx | 61 + .../common/hooks/useLanguage.tsx | 106 + .../shared-module-v2/common/hooks/useMedia.ts | 23 + .../common/hooks/useMessageChannel.tsx | 9 + .../common/hooks/usePaginationInfo.tsx | 82 + .../common/hooks/useQueryParameter.ts | 22 + ...houldHideStuffForSystemTestScreenshots.tsx | 25 + .../common/hooks/useShowToastInfinitely.tsx | 28 + .../common/hooks/useStateQuery.ts | 107 + .../common/hooks/useToastMutation.tsx | 148 + .../common/hooks/useUserInfo.tsx | 10 + .../common/img/UHBrandLogo.svg | 8 + .../common/img/accordion-arrow.svg | 3 + .../shared-module-v2/common/img/arrow.svg | 3 + .../shared-module-v2/common/img/backarrow.svg | 3 + .../common/img/blackArrow.svg | 3 + .../shared-module-v2/common/img/bulleye.svg | 5 + .../common/img/card-bg-circle.svg | 3 + .../common/img/card-bg-star.svg | 6 + .../common/img/card-bg-zigzag.svg | 8 + .../common/img/card-defualt-bg/circle.svg | 3 + .../common/img/card-defualt-bg/cross.svg | 4 + .../common/img/card-defualt-bg/dot-circle.svg | 4 + .../common/img/card-defualt-bg/equal.svg | 4 + .../img/card-defualt-bg/intersection.svg | 4 + .../img/card-defualt-bg/pixel-square.svg | 5 + .../img/card-defualt-bg/quadruple-circle.svg | 6 + .../common/img/card-defualt-bg/triangle.svg | 3 + .../shared-module-v2/common/img/cardNext.svg | 3 + .../common/img/caret-arrow-down.svg | 3 + .../common/img/caret-arrow-left.svg | 3 + .../common/img/caret-arrow-right.svg | 3 + .../common/img/caret-arrow-up.svg | 3 + .../shared-module-v2/common/img/check.svg | 3 + .../shared-module-v2/common/img/checkmark.svg | 3 + .../shared-module-v2/common/img/china.svg | 22 + .../shared-module-v2/common/img/close.svg | 11 + .../shared-module-v2/common/img/cross.svg | 6 + .../shared-module-v2/common/img/diamond.png | Bin 0 -> 840 bytes .../shared-module-v2/common/img/diamond.svg | 3 + .../common/img/exist-icon.svg | 3 + .../common/img/external-link.svg | 1 + .../common/img/flags/Austria.svg | 5 + .../common/img/flags/Belgium.svg | 1 + .../common/img/flags/Bulgaria.svg | 6 + .../common/img/flags/Croatia.svg | 276 + .../common/img/flags/Czech.svg | 6 + .../common/img/flags/Denmark.svg | 1 + .../common/img/flags/Estonia.svg | 5 + .../common/img/flags/Finland.svg | 6 + .../common/img/flags/France.svg | 6 + .../common/img/flags/Germany.svg | 7 + .../common/img/flags/Greece.svg | 5 + .../common/img/flags/Ireland.svg | 6 + .../common/img/flags/Italy.svg | 6 + .../common/img/flags/Latvia.svg | 5 + .../common/img/flags/Lithuania.svg | 1 + .../common/img/flags/Netherlands.svg | 5 + .../common/img/flags/Norway.svg | 13 + .../common/img/flags/Poland.svg | 1 + .../common/img/flags/Portugal.svg | 196 + .../common/img/flags/Romania.svg | 6 + .../common/img/flags/Slovenia.svg | 24 + .../common/img/flags/Spain.svg | 1 + .../common/img/flags/Sweden.svg | 1 + .../shared-module-v2/common/img/flags/USA.svg | 97 + .../common/img/flags/United_Kingdom.svg | 16 + .../common/img/hero-default-bg-image.svg | 302 + .../common/img/likert/agree.svg | 8 + .../common/img/likert/disagree.svg | 7 + .../common/img/likert/neutral.svg | 7 + .../common/img/likert/stronglyAgree.svg | 8 + .../common/img/likert/stronglyDisagree.svg | 7 + .../shared-module-v2/common/img/lock.svg | 7 + .../common/img/moocfiLogo.svg | 10 + .../shared-module-v2/common/img/next.svg | 14 + .../shared-module-v2/common/img/quote.svg | 20 + .../shared-module-v2/common/img/score.svg | 17 + .../common/img/screwedArrow.svg | 3 + .../shared-module-v2/common/img/setting.svg | 8 + .../shared-module-v2/common/img/swoosh.svg | 11 + .../shared-module-v2/common/img/tick-03.svg | 6 + .../shared-module-v2/common/img/tick.svg | 8 + .../common/img/uh_without_background.svg | 6 + .../common/img/unitedStates.svg | 53 + .../shared-module-v2/common/img/up-arrow.svg | 3 + .../common/locales/en/cms.json | 114 + .../common/locales/en/course-material.json | 181 + .../common/locales/en/example-exercise.json | 8 + .../common/locales/en/main-frontend.json | 606 + .../common/locales/en/quizzes.json | 161 + .../common/locales/en/shared-module.json | 108 + .../common/locales/en/tmc.json | 21 + .../common/locales/fi/cms.json | 104 + .../common/locales/fi/course-material.json | 176 + .../common/locales/fi/example-exercise.json | 8 + .../common/locales/fi/main-frontend.json | 601 + .../common/locales/fi/quizzes.json | 163 + .../common/locales/fi/shared-module.json | 106 + .../common/locales/fi/tmc.json | 21 + .../common/services/appQueryClient.ts | 39 + .../common/services/backend/auth.ts | 44 + .../common/services/backend/files.ts | 17 + .../common/styles/GlobalStyles.tsx | 94 + .../common/styles/constants.ts | 9 + .../common/styles/cssReset.ts | 84 + .../shared-module-v2/common/styles/index.ts | 2 + .../common/styles/monacoFontFixer.ts | 13 + .../common/styles/muiTheme.ts | 15 + .../shared-module-v2/common/styles/respond.ts | 16 + .../shared-module-v2/common/styles/theme.ts | 170 + .../common/styles/typography.ts | 34 + .../common/types/imageTypes.d.ts | 10 + .../common/utils/accessibility.ts | 6 + .../common/utils/base-path.ts | 3 + .../common/utils/constants.ts | 13 + .../shared-module-v2/common/utils/cookies.ts | 12 + .../common/utils/cross-routing.ts | 12 + .../shared-module-v2/common/utils/dateUtil.ts | 36 + .../shared-module-v2/common/utils/dom.ts | 11 + .../dontRenderUntilQueryParametersReady.tsx | 64 + .../common/utils/exerciseServices.ts | 5 + .../shared-module-v2/common/utils/fetching.ts | 88 + .../shared-module-v2/common/utils/files.ts | 93 + .../common/utils/generateWebVitalsReporter.ts | 26 + .../utils/getGuestPseudonymousUserId.ts | 19 + .../utils/i18next-parser.config.template.js | 43 + .../ietfLanguageTagToHumanReadableName.ts | 21 + .../shared-module-v2/common/utils/initI18n.ts | 51 + .../common/utils/nullability.ts | 7 + .../shared-module-v2/common/utils/numbers.ts | 66 + .../utils/redirectBackAfterLoginOrSignup.tsx | 58 + .../common/utils/responseHeaders.js | 89 + .../shared-module-v2/common/utils/routes.ts | 14 + .../shared-module-v2/common/utils/strings.ts | 93 + .../shared-module-v2/common/utils/styles.ts | 4 + .../common/utils/svgoConfig.js | 24 + .../common/utils/testing/i18nTest.ts | 26 + .../testing/replaceUuidsWithPlaceholders.ts | 7 + .../shared-module-v2/common/utils/time.ts | 20 + .../common/utils/typeMappter.ts | 16 + .../common/utils/urlManipulation.ts | 9 + .../common/utils/validation.ts | 25 + .../common/utils/withErrorBoundary.tsx | 71 + .../common/utils/withNoSsr.tsx | 28 + .../shared-module-v2/common/bindings.guard.ts | 3360 +++ .../src/shared-module-v2/common/bindings.ts | 1900 ++ .../components/Accordion/DetailAccordion.tsx | 132 + .../common/components/Accordion/index.tsx | 148 + .../common/components/Banner/Banner.tsx | 110 + .../components/Banner/ContributeBanner.tsx | 110 + .../components/Banner/ReadOnlyBanner.tsx | 51 + .../common/components/BooleanAsText.tsx | 8 + .../common/components/Breadcrumbs.tsx | 108 + .../common/components/Button.tsx | 323 + .../components/Card/CardOpenTextOverlay.tsx | 50 + .../common/components/Card/CardOpensText.tsx | 47 + .../components/Card/IllustrationCard.tsx | 142 + .../common/components/Card/SimpleCard.tsx | 161 + .../common/components/Card/index.tsx | 68 + .../Centering/BreakFromCentered.tsx | 80 + .../common/components/Centering/Centered.tsx | 46 + .../common/components/CircularProgressBar.tsx | 86 + .../CourseProgress/CircularProgress.tsx | 185 + .../components/CourseProgress/ProgressBar.tsx | 132 + .../components/CourseProgress/index.tsx | 35 + .../common/components/DebugModal.tsx | 107 + .../common/components/Dialog.tsx | 132 + .../common/components/DiffFormatter.tsx | 73 + .../DropdownMenu/DropdownMenuItem.tsx | 77 + .../common/components/DropdownMenu/index.tsx | 154 + .../common/components/ErrorBanner.tsx | 304 + .../components/ExerciseList/ExerciseBox.tsx | 166 + .../components/ExerciseList/PageBox.tsx | 55 + .../common/components/FloatingErrorBox.tsx | 77 + .../common/components/Footer.tsx | 205 + .../common/components/Forum/Forum.tsx | 187 + .../components/Forum/SideNavigation.tsx | 176 + .../common/components/Forum/Thread.tsx | 207 + .../common/components/Forum/Threads.tsx | 98 + .../common/components/GenericInfobox.tsx | 36 + .../components/HeightTrackingContainer.tsx | 106 + .../components/InputFields/CheckBox.tsx | 140 + .../InputFields/CheckboxFieldWrapper.tsx | 44 + .../InputFields/DatePickerField.tsx | 67 + .../components/InputFields/DateTimeLocal.tsx | 116 + .../InputFields/EditableComponentTextArea.tsx | 93 + .../components/InputFields/FileField.tsx | 143 + .../components/InputFields/RadioButton.tsx | 77 + .../components/InputFields/SelectField.tsx | 138 + .../components/InputFields/TextAreaField.tsx | 106 + .../components/InputFields/TextField.tsx | 147 + .../InputFields/TimePickerField.tsx | 67 + .../components/LanguageSelection/Language.tsx | 65 + .../LanguageSelection/LanguageMenu.tsx | 29 + .../LanguageSelection/LanguageOption.tsx | 63 + .../components/LanguageSelection/index.tsx | 125 + .../common/components/LinkOrNoLink.tsx | 18 + .../common/components/LoginControls.tsx | 73 + .../components/MessageChannelIFrame.tsx | 219 + .../Navigation/NavBar/ComplexNav.tsx | 277 + .../NavBar/Menu/Hamburger/Hamburger.tsx | 31 + .../NavBar/Menu/Hamburger/HamburgerSpring.tsx | 210 + .../Navigation/NavBar/Menu/Menu.tsx | 125 + .../Navigation/NavBar/Menu/MenuItem.tsx | 7 + .../Navigation/NavBar/NavContainer.tsx | 18 + .../components/Navigation/NavBar/NavItem.tsx | 7 + .../components/Navigation/NavBar/NavItems.tsx | 23 + .../components/Navigation/NavBar/NavLink.tsx | 62 + .../Navigation/NavBar/SimpleNav.tsx | 82 + .../components/Navigation/NavBar/index.tsx | 28 + .../Navigation/TabLinks/TabLink.tsx | 100 + .../Navigation/TabLinks/TabLinkNavigation.tsx | 134 + .../Navigation/TabLinks/TabLinkPanel.tsx | 11 + .../common/components/Nested.tsx | 20 + .../common/components/NextSectionLink.tsx | 308 + .../common/components/Notifications/Base.tsx | 17 + .../components/Notifications/Delete.tsx | 111 + .../common/components/Notifications/Error.tsx | 114 + .../components/Notifications/Loading.tsx | 93 + .../components/Notifications/Success.tsx | 111 + .../Notifications/ToasterNotifications.tsx | 21 + .../components/OnlyRenderIfPermissions.tsx | 38 + .../common/components/PagesInChapterBox.tsx | 134 + .../common/components/Pagination.tsx | 353 + .../components/PaginationItemsPerPage.tsx | 49 + .../components/PeerReview/LikertScale.tsx | 140 + .../common/components/PeerReview/Option.tsx | 83 + .../PeerReview/PeerReviewProgress.tsx | 48 + .../common/components/PeerReview/Review.tsx | 70 + .../common/components/Quote.tsx | 57 + .../common/components/Reference.tsx | 245 + .../common/components/SelectMenu.tsx | 120 + .../common/components/SkipLink.tsx | 23 + .../common/components/SpeechBalloon.tsx | 60 + .../common/components/Spinner.tsx | 63 + .../common/components/Sponsor.tsx | 110 + .../common/components/Test.tsx | 20 + .../common/components/TimeComponent.tsx | 109 + .../common/components/Title.tsx | 24 + .../common/components/TopLevelPage.tsx | 113 + .../common/components/TopicObjectives.tsx | 96 + .../components/layout/PageMarginOffset.tsx | 21 + .../components/monaco/MonacoDiffEditor.tsx | 20 + .../common/components/monaco/MonacoEditor.tsx | 20 + .../monaco/impl/MonacoDiffEditorImpl.tsx | 25 + .../monaco/impl/MonacoEditorImpl.tsx | 25 + .../common/components/monaco/impl/loader.ts | 8 + .../HideChildrenInSystemTests.tsx | 18 + .../system-tests/HideTextInSystemTests.tsx | 21 + .../MaskOverThisInSystemTests.tsx | 30 + .../contexts/ExerciseServiceContext.tsx | 25 + .../common/contexts/IframeHeightContext.tsx | 9 + .../common/contexts/LoginStateContext.tsx | 77 + .../exercise-service-protocol-types-2.ts | 22 + .../exercise-service-protocol-types.guard.ts | 267 + .../common/exercise-service-protocol-types.ts | 133 + .../useExerciseServiceOutputState.tsx | 63 + .../common/hooks/useAuthorizeMultiple.tsx | 32 + .../common/hooks/useClickOutside.tsx | 24 + .../common/hooks/useDateStringAsDate.tsx | 19 + .../useExerciseServiceParentConnection.tsx | 61 + .../common/hooks/useLanguage.tsx | 106 + .../shared-module-v2/common/hooks/useMedia.ts | 23 + .../common/hooks/useMessageChannel.tsx | 9 + .../common/hooks/usePaginationInfo.tsx | 82 + .../common/hooks/useQueryParameter.ts | 22 + ...houldHideStuffForSystemTestScreenshots.tsx | 25 + .../common/hooks/useShowToastInfinitely.tsx | 28 + .../common/hooks/useStateQuery.ts | 107 + .../common/hooks/useToastMutation.tsx | 148 + .../common/hooks/useUserInfo.tsx | 10 + .../common/img/UHBrandLogo.svg | 8 + .../common/img/accordion-arrow.svg | 3 + .../src/shared-module-v2/common/img/arrow.svg | 3 + .../shared-module-v2/common/img/backarrow.svg | 3 + .../common/img/blackArrow.svg | 3 + .../shared-module-v2/common/img/bulleye.svg | 5 + .../common/img/card-bg-circle.svg | 3 + .../common/img/card-bg-star.svg | 6 + .../common/img/card-bg-zigzag.svg | 8 + .../common/img/card-defualt-bg/circle.svg | 3 + .../common/img/card-defualt-bg/cross.svg | 4 + .../common/img/card-defualt-bg/dot-circle.svg | 4 + .../common/img/card-defualt-bg/equal.svg | 4 + .../img/card-defualt-bg/intersection.svg | 4 + .../img/card-defualt-bg/pixel-square.svg | 5 + .../img/card-defualt-bg/quadruple-circle.svg | 6 + .../common/img/card-defualt-bg/triangle.svg | 3 + .../shared-module-v2/common/img/cardNext.svg | 3 + .../common/img/caret-arrow-down.svg | 3 + .../common/img/caret-arrow-left.svg | 3 + .../common/img/caret-arrow-right.svg | 3 + .../common/img/caret-arrow-up.svg | 3 + .../src/shared-module-v2/common/img/check.svg | 3 + .../shared-module-v2/common/img/checkmark.svg | 3 + .../src/shared-module-v2/common/img/china.svg | 22 + .../src/shared-module-v2/common/img/close.svg | 11 + .../src/shared-module-v2/common/img/cross.svg | 6 + .../shared-module-v2/common/img/diamond.png | Bin 0 -> 840 bytes .../shared-module-v2/common/img/diamond.svg | 3 + .../common/img/exist-icon.svg | 3 + .../common/img/external-link.svg | 1 + .../common/img/flags/Austria.svg | 5 + .../common/img/flags/Belgium.svg | 1 + .../common/img/flags/Bulgaria.svg | 6 + .../common/img/flags/Croatia.svg | 276 + .../common/img/flags/Czech.svg | 6 + .../common/img/flags/Denmark.svg | 1 + .../common/img/flags/Estonia.svg | 5 + .../common/img/flags/Finland.svg | 6 + .../common/img/flags/France.svg | 6 + .../common/img/flags/Germany.svg | 7 + .../common/img/flags/Greece.svg | 5 + .../common/img/flags/Ireland.svg | 6 + .../common/img/flags/Italy.svg | 6 + .../common/img/flags/Latvia.svg | 5 + .../common/img/flags/Lithuania.svg | 1 + .../common/img/flags/Netherlands.svg | 5 + .../common/img/flags/Norway.svg | 13 + .../common/img/flags/Poland.svg | 1 + .../common/img/flags/Portugal.svg | 196 + .../common/img/flags/Romania.svg | 6 + .../common/img/flags/Slovenia.svg | 24 + .../common/img/flags/Spain.svg | 1 + .../common/img/flags/Sweden.svg | 1 + .../shared-module-v2/common/img/flags/USA.svg | 97 + .../common/img/flags/United_Kingdom.svg | 16 + .../common/img/hero-default-bg-image.svg | 302 + .../common/img/likert/agree.svg | 8 + .../common/img/likert/disagree.svg | 7 + .../common/img/likert/neutral.svg | 7 + .../common/img/likert/stronglyAgree.svg | 8 + .../common/img/likert/stronglyDisagree.svg | 7 + .../src/shared-module-v2/common/img/lock.svg | 7 + .../common/img/moocfiLogo.svg | 10 + .../src/shared-module-v2/common/img/next.svg | 14 + .../src/shared-module-v2/common/img/quote.svg | 20 + .../src/shared-module-v2/common/img/score.svg | 17 + .../common/img/screwedArrow.svg | 3 + .../shared-module-v2/common/img/setting.svg | 8 + .../shared-module-v2/common/img/swoosh.svg | 11 + .../shared-module-v2/common/img/tick-03.svg | 6 + .../src/shared-module-v2/common/img/tick.svg | 8 + .../common/img/uh_without_background.svg | 6 + .../common/img/unitedStates.svg | 53 + .../shared-module-v2/common/img/up-arrow.svg | 3 + .../common/locales/en/cms.json | 114 + .../common/locales/en/course-material.json | 181 + .../common/locales/en/example-exercise.json | 8 + .../common/locales/en/main-frontend.json | 606 + .../common/locales/en/quizzes.json | 161 + .../common/locales/en/shared-module.json | 108 + .../common/locales/en/tmc.json | 21 + .../common/locales/fi/cms.json | 104 + .../common/locales/fi/course-material.json | 176 + .../common/locales/fi/example-exercise.json | 8 + .../common/locales/fi/main-frontend.json | 601 + .../common/locales/fi/quizzes.json | 163 + .../common/locales/fi/shared-module.json | 106 + .../common/locales/fi/tmc.json | 21 + .../common/services/appQueryClient.ts | 39 + .../common/services/backend/auth.ts | 44 + .../common/services/backend/files.ts | 17 + .../common/styles/GlobalStyles.tsx | 94 + .../common/styles/constants.ts | 9 + .../common/styles/cssReset.ts | 84 + .../shared-module-v2/common/styles/index.ts | 2 + .../common/styles/monacoFontFixer.ts | 13 + .../common/styles/muiTheme.ts | 15 + .../shared-module-v2/common/styles/respond.ts | 16 + .../shared-module-v2/common/styles/theme.ts | 170 + .../common/styles/typography.ts | 34 + .../common/types/imageTypes.d.ts | 10 + .../common/utils/accessibility.ts | 6 + .../common/utils/base-path.ts | 3 + .../common/utils/constants.ts | 13 + .../shared-module-v2/common/utils/cookies.ts | 12 + .../common/utils/cross-routing.ts | 12 + .../shared-module-v2/common/utils/dateUtil.ts | 36 + .../src/shared-module-v2/common/utils/dom.ts | 11 + .../dontRenderUntilQueryParametersReady.tsx | 64 + .../common/utils/exerciseServices.ts | 5 + .../shared-module-v2/common/utils/fetching.ts | 88 + .../shared-module-v2/common/utils/files.ts | 93 + .../common/utils/generateWebVitalsReporter.ts | 26 + .../utils/getGuestPseudonymousUserId.ts | 19 + .../utils/i18next-parser.config.template.js | 43 + .../ietfLanguageTagToHumanReadableName.ts | 21 + .../shared-module-v2/common/utils/initI18n.ts | 51 + .../common/utils/nullability.ts | 7 + .../shared-module-v2/common/utils/numbers.ts | 66 + .../utils/redirectBackAfterLoginOrSignup.tsx | 58 + .../common/utils/responseHeaders.js | 89 + .../shared-module-v2/common/utils/routes.ts | 14 + .../shared-module-v2/common/utils/strings.ts | 93 + .../shared-module-v2/common/utils/styles.ts | 4 + .../common/utils/svgoConfig.js | 24 + .../common/utils/testing/i18nTest.ts | 26 + .../testing/replaceUuidsWithPlaceholders.ts | 7 + .../src/shared-module-v2/common/utils/time.ts | 20 + .../common/utils/typeMappter.ts | 16 + .../common/utils/urlManipulation.ts | 9 + .../common/utils/validation.ts | 25 + .../common/utils/withErrorBoundary.tsx | 71 + .../common/utils/withNoSsr.tsx | 28 + .../shared-module-v2/common/bindings.guard.ts | 3360 +++ .../src/shared-module-v2/common/bindings.ts | 1900 ++ .../components/Accordion/DetailAccordion.tsx | 132 + .../common/components/Accordion/index.tsx | 148 + .../common/components/Banner/Banner.tsx | 110 + .../components/Banner/ContributeBanner.tsx | 110 + .../components/Banner/ReadOnlyBanner.tsx | 51 + .../common/components/BooleanAsText.tsx | 8 + .../common/components/Breadcrumbs.tsx | 108 + .../common/components/Button.tsx | 323 + .../components/Card/CardOpenTextOverlay.tsx | 50 + .../common/components/Card/CardOpensText.tsx | 47 + .../components/Card/IllustrationCard.tsx | 142 + .../common/components/Card/SimpleCard.tsx | 161 + .../common/components/Card/index.tsx | 68 + .../Centering/BreakFromCentered.tsx | 80 + .../common/components/Centering/Centered.tsx | 46 + .../common/components/CircularProgressBar.tsx | 86 + .../CourseProgress/CircularProgress.tsx | 185 + .../components/CourseProgress/ProgressBar.tsx | 132 + .../components/CourseProgress/index.tsx | 35 + .../common/components/DebugModal.tsx | 107 + .../common/components/Dialog.tsx | 132 + .../common/components/DiffFormatter.tsx | 73 + .../DropdownMenu/DropdownMenuItem.tsx | 77 + .../common/components/DropdownMenu/index.tsx | 154 + .../common/components/ErrorBanner.tsx | 304 + .../components/ExerciseList/ExerciseBox.tsx | 166 + .../components/ExerciseList/PageBox.tsx | 55 + .../common/components/FloatingErrorBox.tsx | 77 + .../common/components/Footer.tsx | 205 + .../common/components/Forum/Forum.tsx | 187 + .../components/Forum/SideNavigation.tsx | 176 + .../common/components/Forum/Thread.tsx | 207 + .../common/components/Forum/Threads.tsx | 98 + .../common/components/GenericInfobox.tsx | 36 + .../components/HeightTrackingContainer.tsx | 106 + .../components/InputFields/CheckBox.tsx | 140 + .../InputFields/CheckboxFieldWrapper.tsx | 44 + .../InputFields/DatePickerField.tsx | 67 + .../components/InputFields/DateTimeLocal.tsx | 116 + .../InputFields/EditableComponentTextArea.tsx | 93 + .../components/InputFields/FileField.tsx | 143 + .../components/InputFields/RadioButton.tsx | 77 + .../components/InputFields/SelectField.tsx | 138 + .../components/InputFields/TextAreaField.tsx | 106 + .../components/InputFields/TextField.tsx | 147 + .../InputFields/TimePickerField.tsx | 67 + .../components/LanguageSelection/Language.tsx | 65 + .../LanguageSelection/LanguageMenu.tsx | 29 + .../LanguageSelection/LanguageOption.tsx | 63 + .../components/LanguageSelection/index.tsx | 125 + .../common/components/LinkOrNoLink.tsx | 18 + .../common/components/LoginControls.tsx | 73 + .../components/MessageChannelIFrame.tsx | 219 + .../Navigation/NavBar/ComplexNav.tsx | 277 + .../NavBar/Menu/Hamburger/Hamburger.tsx | 31 + .../NavBar/Menu/Hamburger/HamburgerSpring.tsx | 210 + .../Navigation/NavBar/Menu/Menu.tsx | 125 + .../Navigation/NavBar/Menu/MenuItem.tsx | 7 + .../Navigation/NavBar/NavContainer.tsx | 18 + .../components/Navigation/NavBar/NavItem.tsx | 7 + .../components/Navigation/NavBar/NavItems.tsx | 23 + .../components/Navigation/NavBar/NavLink.tsx | 62 + .../Navigation/NavBar/SimpleNav.tsx | 82 + .../components/Navigation/NavBar/index.tsx | 28 + .../Navigation/TabLinks/TabLink.tsx | 100 + .../Navigation/TabLinks/TabLinkNavigation.tsx | 134 + .../Navigation/TabLinks/TabLinkPanel.tsx | 11 + .../common/components/Nested.tsx | 20 + .../common/components/NextSectionLink.tsx | 308 + .../common/components/Notifications/Base.tsx | 17 + .../components/Notifications/Delete.tsx | 111 + .../common/components/Notifications/Error.tsx | 114 + .../components/Notifications/Loading.tsx | 93 + .../components/Notifications/Success.tsx | 111 + .../Notifications/ToasterNotifications.tsx | 21 + .../components/OnlyRenderIfPermissions.tsx | 38 + .../common/components/PagesInChapterBox.tsx | 134 + .../common/components/Pagination.tsx | 353 + .../components/PaginationItemsPerPage.tsx | 49 + .../components/PeerReview/LikertScale.tsx | 140 + .../common/components/PeerReview/Option.tsx | 83 + .../PeerReview/PeerReviewProgress.tsx | 48 + .../common/components/PeerReview/Review.tsx | 70 + .../common/components/Quote.tsx | 57 + .../common/components/Reference.tsx | 245 + .../common/components/SelectMenu.tsx | 120 + .../common/components/SkipLink.tsx | 23 + .../common/components/SpeechBalloon.tsx | 60 + .../common/components/Spinner.tsx | 63 + .../common/components/Sponsor.tsx | 110 + .../common/components/Test.tsx | 20 + .../common/components/TimeComponent.tsx | 109 + .../common/components/Title.tsx | 24 + .../common/components/TopLevelPage.tsx | 113 + .../common/components/TopicObjectives.tsx | 96 + .../components/layout/PageMarginOffset.tsx | 21 + .../components/monaco/MonacoDiffEditor.tsx | 20 + .../common/components/monaco/MonacoEditor.tsx | 20 + .../monaco/impl/MonacoDiffEditorImpl.tsx | 25 + .../monaco/impl/MonacoEditorImpl.tsx | 25 + .../common/components/monaco/impl/loader.ts | 8 + .../HideChildrenInSystemTests.tsx | 18 + .../system-tests/HideTextInSystemTests.tsx | 21 + .../MaskOverThisInSystemTests.tsx | 30 + .../contexts/ExerciseServiceContext.tsx | 25 + .../common/contexts/IframeHeightContext.tsx | 9 + .../common/contexts/LoginStateContext.tsx | 77 + .../exercise-service-protocol-types-2.ts | 22 + .../exercise-service-protocol-types.guard.ts | 267 + .../common/exercise-service-protocol-types.ts | 133 + .../useExerciseServiceOutputState.tsx | 63 + .../common/hooks/useAuthorizeMultiple.tsx | 32 + .../common/hooks/useClickOutside.tsx | 24 + .../common/hooks/useDateStringAsDate.tsx | 19 + .../useExerciseServiceParentConnection.tsx | 61 + .../common/hooks/useLanguage.tsx | 106 + .../shared-module-v2/common/hooks/useMedia.ts | 23 + .../common/hooks/useMessageChannel.tsx | 9 + .../common/hooks/usePaginationInfo.tsx | 82 + .../common/hooks/useQueryParameter.ts | 22 + ...houldHideStuffForSystemTestScreenshots.tsx | 25 + .../common/hooks/useShowToastInfinitely.tsx | 28 + .../common/hooks/useStateQuery.ts | 107 + .../common/hooks/useToastMutation.tsx | 148 + .../common/hooks/useUserInfo.tsx | 10 + .../common/img/UHBrandLogo.svg | 8 + .../common/img/accordion-arrow.svg | 3 + .../src/shared-module-v2/common/img/arrow.svg | 3 + .../shared-module-v2/common/img/backarrow.svg | 3 + .../common/img/blackArrow.svg | 3 + .../shared-module-v2/common/img/bulleye.svg | 5 + .../common/img/card-bg-circle.svg | 3 + .../common/img/card-bg-star.svg | 6 + .../common/img/card-bg-zigzag.svg | 8 + .../common/img/card-defualt-bg/circle.svg | 3 + .../common/img/card-defualt-bg/cross.svg | 4 + .../common/img/card-defualt-bg/dot-circle.svg | 4 + .../common/img/card-defualt-bg/equal.svg | 4 + .../img/card-defualt-bg/intersection.svg | 4 + .../img/card-defualt-bg/pixel-square.svg | 5 + .../img/card-defualt-bg/quadruple-circle.svg | 6 + .../common/img/card-defualt-bg/triangle.svg | 3 + .../shared-module-v2/common/img/cardNext.svg | 3 + .../common/img/caret-arrow-down.svg | 3 + .../common/img/caret-arrow-left.svg | 3 + .../common/img/caret-arrow-right.svg | 3 + .../common/img/caret-arrow-up.svg | 3 + .../src/shared-module-v2/common/img/check.svg | 3 + .../shared-module-v2/common/img/checkmark.svg | 3 + .../src/shared-module-v2/common/img/china.svg | 22 + .../src/shared-module-v2/common/img/close.svg | 11 + .../src/shared-module-v2/common/img/cross.svg | 6 + .../shared-module-v2/common/img/diamond.png | Bin 0 -> 840 bytes .../shared-module-v2/common/img/diamond.svg | 3 + .../common/img/exist-icon.svg | 3 + .../common/img/external-link.svg | 1 + .../common/img/flags/Austria.svg | 5 + .../common/img/flags/Belgium.svg | 1 + .../common/img/flags/Bulgaria.svg | 6 + .../common/img/flags/Croatia.svg | 276 + .../common/img/flags/Czech.svg | 6 + .../common/img/flags/Denmark.svg | 1 + .../common/img/flags/Estonia.svg | 5 + .../common/img/flags/Finland.svg | 6 + .../common/img/flags/France.svg | 6 + .../common/img/flags/Germany.svg | 7 + .../common/img/flags/Greece.svg | 5 + .../common/img/flags/Ireland.svg | 6 + .../common/img/flags/Italy.svg | 6 + .../common/img/flags/Latvia.svg | 5 + .../common/img/flags/Lithuania.svg | 1 + .../common/img/flags/Netherlands.svg | 5 + .../common/img/flags/Norway.svg | 13 + .../common/img/flags/Poland.svg | 1 + .../common/img/flags/Portugal.svg | 196 + .../common/img/flags/Romania.svg | 6 + .../common/img/flags/Slovenia.svg | 24 + .../common/img/flags/Spain.svg | 1 + .../common/img/flags/Sweden.svg | 1 + .../shared-module-v2/common/img/flags/USA.svg | 97 + .../common/img/flags/United_Kingdom.svg | 16 + .../common/img/hero-default-bg-image.svg | 302 + .../common/img/likert/agree.svg | 8 + .../common/img/likert/disagree.svg | 7 + .../common/img/likert/neutral.svg | 7 + .../common/img/likert/stronglyAgree.svg | 8 + .../common/img/likert/stronglyDisagree.svg | 7 + .../src/shared-module-v2/common/img/lock.svg | 7 + .../common/img/moocfiLogo.svg | 10 + .../src/shared-module-v2/common/img/next.svg | 14 + .../src/shared-module-v2/common/img/quote.svg | 20 + .../src/shared-module-v2/common/img/score.svg | 17 + .../common/img/screwedArrow.svg | 3 + .../shared-module-v2/common/img/setting.svg | 8 + .../shared-module-v2/common/img/swoosh.svg | 11 + .../shared-module-v2/common/img/tick-03.svg | 6 + .../src/shared-module-v2/common/img/tick.svg | 8 + .../common/img/uh_without_background.svg | 6 + .../common/img/unitedStates.svg | 53 + .../shared-module-v2/common/img/up-arrow.svg | 3 + .../common/locales/en/cms.json | 114 + .../common/locales/en/course-material.json | 181 + .../common/locales/en/example-exercise.json | 8 + .../common/locales/en/main-frontend.json | 606 + .../common/locales/en/quizzes.json | 161 + .../common/locales/en/shared-module.json | 108 + .../common/locales/en/tmc.json | 21 + .../common/locales/fi/cms.json | 104 + .../common/locales/fi/course-material.json | 176 + .../common/locales/fi/example-exercise.json | 8 + .../common/locales/fi/main-frontend.json | 601 + .../common/locales/fi/quizzes.json | 163 + .../common/locales/fi/shared-module.json | 106 + .../common/locales/fi/tmc.json | 21 + .../common/services/appQueryClient.ts | 39 + .../common/services/backend/auth.ts | 44 + .../common/services/backend/files.ts | 17 + .../common/styles/GlobalStyles.tsx | 94 + .../common/styles/constants.ts | 9 + .../common/styles/cssReset.ts | 84 + .../shared-module-v2/common/styles/index.ts | 2 + .../common/styles/monacoFontFixer.ts | 13 + .../common/styles/muiTheme.ts | 15 + .../shared-module-v2/common/styles/respond.ts | 16 + .../shared-module-v2/common/styles/theme.ts | 170 + .../common/styles/typography.ts | 34 + .../common/types/imageTypes.d.ts | 10 + .../common/utils/accessibility.ts | 6 + .../common/utils/base-path.ts | 3 + .../common/utils/constants.ts | 13 + .../shared-module-v2/common/utils/cookies.ts | 12 + .../common/utils/cross-routing.ts | 12 + .../shared-module-v2/common/utils/dateUtil.ts | 36 + .../src/shared-module-v2/common/utils/dom.ts | 11 + .../dontRenderUntilQueryParametersReady.tsx | 64 + .../common/utils/exerciseServices.ts | 5 + .../shared-module-v2/common/utils/fetching.ts | 88 + .../shared-module-v2/common/utils/files.ts | 93 + .../common/utils/generateWebVitalsReporter.ts | 26 + .../utils/getGuestPseudonymousUserId.ts | 19 + .../utils/i18next-parser.config.template.js | 43 + .../ietfLanguageTagToHumanReadableName.ts | 21 + .../shared-module-v2/common/utils/initI18n.ts | 51 + .../common/utils/nullability.ts | 7 + .../shared-module-v2/common/utils/numbers.ts | 66 + .../utils/redirectBackAfterLoginOrSignup.tsx | 58 + .../common/utils/responseHeaders.js | 89 + .../shared-module-v2/common/utils/routes.ts | 14 + .../shared-module-v2/common/utils/strings.ts | 93 + .../shared-module-v2/common/utils/styles.ts | 4 + .../common/utils/svgoConfig.js | 24 + .../common/utils/testing/i18nTest.ts | 26 + .../testing/replaceUuidsWithPlaceholders.ts | 7 + .../src/shared-module-v2/common/utils/time.ts | 20 + .../common/utils/typeMappter.ts | 16 + .../common/utils/urlManipulation.ts | 9 + .../common/utils/validation.ts | 25 + .../common/utils/withErrorBoundary.tsx | 71 + .../common/utils/withNoSsr.tsx | 28 + .../shared-module-v2/common/bindings.guard.ts | 3360 +++ .../src/shared-module-v2/common/bindings.ts | 1900 ++ .../components/Accordion/DetailAccordion.tsx | 132 + .../common/components/Accordion/index.tsx | 148 + .../common/components/Banner/Banner.tsx | 110 + .../components/Banner/ContributeBanner.tsx | 110 + .../components/Banner/ReadOnlyBanner.tsx | 51 + .../common/components/BooleanAsText.tsx | 8 + .../common/components/Breadcrumbs.tsx | 108 + .../common/components/Button.tsx | 323 + .../components/Card/CardOpenTextOverlay.tsx | 50 + .../common/components/Card/CardOpensText.tsx | 47 + .../components/Card/IllustrationCard.tsx | 142 + .../common/components/Card/SimpleCard.tsx | 161 + .../common/components/Card/index.tsx | 68 + .../Centering/BreakFromCentered.tsx | 80 + .../common/components/Centering/Centered.tsx | 46 + .../common/components/CircularProgressBar.tsx | 86 + .../CourseProgress/CircularProgress.tsx | 185 + .../components/CourseProgress/ProgressBar.tsx | 132 + .../components/CourseProgress/index.tsx | 35 + .../common/components/DebugModal.tsx | 107 + .../common/components/Dialog.tsx | 132 + .../common/components/DiffFormatter.tsx | 73 + .../DropdownMenu/DropdownMenuItem.tsx | 77 + .../common/components/DropdownMenu/index.tsx | 154 + .../common/components/ErrorBanner.tsx | 304 + .../components/ExerciseList/ExerciseBox.tsx | 166 + .../components/ExerciseList/PageBox.tsx | 55 + .../common/components/FloatingErrorBox.tsx | 77 + .../common/components/Footer.tsx | 205 + .../common/components/Forum/Forum.tsx | 187 + .../components/Forum/SideNavigation.tsx | 176 + .../common/components/Forum/Thread.tsx | 207 + .../common/components/Forum/Threads.tsx | 98 + .../common/components/GenericInfobox.tsx | 36 + .../components/HeightTrackingContainer.tsx | 106 + .../components/InputFields/CheckBox.tsx | 140 + .../InputFields/CheckboxFieldWrapper.tsx | 44 + .../InputFields/DatePickerField.tsx | 67 + .../components/InputFields/DateTimeLocal.tsx | 116 + .../InputFields/EditableComponentTextArea.tsx | 93 + .../components/InputFields/FileField.tsx | 143 + .../components/InputFields/RadioButton.tsx | 77 + .../components/InputFields/SelectField.tsx | 138 + .../components/InputFields/TextAreaField.tsx | 106 + .../components/InputFields/TextField.tsx | 147 + .../InputFields/TimePickerField.tsx | 67 + .../components/LanguageSelection/Language.tsx | 65 + .../LanguageSelection/LanguageMenu.tsx | 29 + .../LanguageSelection/LanguageOption.tsx | 63 + .../components/LanguageSelection/index.tsx | 125 + .../common/components/LinkOrNoLink.tsx | 18 + .../common/components/LoginControls.tsx | 73 + .../components/MessageChannelIFrame.tsx | 219 + .../Navigation/NavBar/ComplexNav.tsx | 277 + .../NavBar/Menu/Hamburger/Hamburger.tsx | 31 + .../NavBar/Menu/Hamburger/HamburgerSpring.tsx | 210 + .../Navigation/NavBar/Menu/Menu.tsx | 125 + .../Navigation/NavBar/Menu/MenuItem.tsx | 7 + .../Navigation/NavBar/NavContainer.tsx | 18 + .../components/Navigation/NavBar/NavItem.tsx | 7 + .../components/Navigation/NavBar/NavItems.tsx | 23 + .../components/Navigation/NavBar/NavLink.tsx | 62 + .../Navigation/NavBar/SimpleNav.tsx | 82 + .../components/Navigation/NavBar/index.tsx | 28 + .../Navigation/TabLinks/TabLink.tsx | 100 + .../Navigation/TabLinks/TabLinkNavigation.tsx | 134 + .../Navigation/TabLinks/TabLinkPanel.tsx | 11 + .../common/components/Nested.tsx | 20 + .../common/components/NextSectionLink.tsx | 308 + .../common/components/Notifications/Base.tsx | 17 + .../components/Notifications/Delete.tsx | 111 + .../common/components/Notifications/Error.tsx | 114 + .../components/Notifications/Loading.tsx | 93 + .../components/Notifications/Success.tsx | 111 + .../Notifications/ToasterNotifications.tsx | 21 + .../components/OnlyRenderIfPermissions.tsx | 38 + .../common/components/PagesInChapterBox.tsx | 134 + .../common/components/Pagination.tsx | 353 + .../components/PaginationItemsPerPage.tsx | 49 + .../components/PeerReview/LikertScale.tsx | 140 + .../common/components/PeerReview/Option.tsx | 83 + .../PeerReview/PeerReviewProgress.tsx | 48 + .../common/components/PeerReview/Review.tsx | 70 + .../common/components/Quote.tsx | 57 + .../common/components/Reference.tsx | 245 + .../common/components/SelectMenu.tsx | 120 + .../common/components/SkipLink.tsx | 23 + .../common/components/SpeechBalloon.tsx | 60 + .../common/components/Spinner.tsx | 63 + .../common/components/Sponsor.tsx | 110 + .../common/components/Test.tsx | 20 + .../common/components/TimeComponent.tsx | 109 + .../common/components/Title.tsx | 24 + .../common/components/TopLevelPage.tsx | 113 + .../common/components/TopicObjectives.tsx | 96 + .../components/layout/PageMarginOffset.tsx | 21 + .../components/monaco/MonacoDiffEditor.tsx | 20 + .../common/components/monaco/MonacoEditor.tsx | 20 + .../monaco/impl/MonacoDiffEditorImpl.tsx | 25 + .../monaco/impl/MonacoEditorImpl.tsx | 25 + .../common/components/monaco/impl/loader.ts | 8 + .../HideChildrenInSystemTests.tsx | 18 + .../system-tests/HideTextInSystemTests.tsx | 21 + .../MaskOverThisInSystemTests.tsx | 30 + .../contexts/ExerciseServiceContext.tsx | 25 + .../common/contexts/IframeHeightContext.tsx | 9 + .../common/contexts/LoginStateContext.tsx | 77 + .../exercise-service-protocol-types-2.ts | 22 + .../exercise-service-protocol-types.guard.ts | 267 + .../common/exercise-service-protocol-types.ts | 133 + .../useExerciseServiceOutputState.tsx | 63 + .../common/hooks/useAuthorizeMultiple.tsx | 32 + .../common/hooks/useClickOutside.tsx | 24 + .../common/hooks/useDateStringAsDate.tsx | 19 + .../useExerciseServiceParentConnection.tsx | 61 + .../common/hooks/useLanguage.tsx | 106 + .../shared-module-v2/common/hooks/useMedia.ts | 23 + .../common/hooks/useMessageChannel.tsx | 9 + .../common/hooks/usePaginationInfo.tsx | 82 + .../common/hooks/useQueryParameter.ts | 22 + ...houldHideStuffForSystemTestScreenshots.tsx | 25 + .../common/hooks/useShowToastInfinitely.tsx | 28 + .../common/hooks/useStateQuery.ts | 107 + .../common/hooks/useToastMutation.tsx | 148 + .../common/hooks/useUserInfo.tsx | 10 + .../common/img/UHBrandLogo.svg | 8 + .../common/img/accordion-arrow.svg | 3 + .../src/shared-module-v2/common/img/arrow.svg | 3 + .../shared-module-v2/common/img/backarrow.svg | 3 + .../common/img/blackArrow.svg | 3 + .../shared-module-v2/common/img/bulleye.svg | 5 + .../common/img/card-bg-circle.svg | 3 + .../common/img/card-bg-star.svg | 6 + .../common/img/card-bg-zigzag.svg | 8 + .../common/img/card-defualt-bg/circle.svg | 3 + .../common/img/card-defualt-bg/cross.svg | 4 + .../common/img/card-defualt-bg/dot-circle.svg | 4 + .../common/img/card-defualt-bg/equal.svg | 4 + .../img/card-defualt-bg/intersection.svg | 4 + .../img/card-defualt-bg/pixel-square.svg | 5 + .../img/card-defualt-bg/quadruple-circle.svg | 6 + .../common/img/card-defualt-bg/triangle.svg | 3 + .../shared-module-v2/common/img/cardNext.svg | 3 + .../common/img/caret-arrow-down.svg | 3 + .../common/img/caret-arrow-left.svg | 3 + .../common/img/caret-arrow-right.svg | 3 + .../common/img/caret-arrow-up.svg | 3 + .../src/shared-module-v2/common/img/check.svg | 3 + .../shared-module-v2/common/img/checkmark.svg | 3 + .../src/shared-module-v2/common/img/china.svg | 22 + .../src/shared-module-v2/common/img/close.svg | 11 + .../src/shared-module-v2/common/img/cross.svg | 6 + .../shared-module-v2/common/img/diamond.png | Bin 0 -> 840 bytes .../shared-module-v2/common/img/diamond.svg | 3 + .../common/img/exist-icon.svg | 3 + .../common/img/external-link.svg | 1 + .../common/img/flags/Austria.svg | 5 + .../common/img/flags/Belgium.svg | 1 + .../common/img/flags/Bulgaria.svg | 6 + .../common/img/flags/Croatia.svg | 276 + .../common/img/flags/Czech.svg | 6 + .../common/img/flags/Denmark.svg | 1 + .../common/img/flags/Estonia.svg | 5 + .../common/img/flags/Finland.svg | 6 + .../common/img/flags/France.svg | 6 + .../common/img/flags/Germany.svg | 7 + .../common/img/flags/Greece.svg | 5 + .../common/img/flags/Ireland.svg | 6 + .../common/img/flags/Italy.svg | 6 + .../common/img/flags/Latvia.svg | 5 + .../common/img/flags/Lithuania.svg | 1 + .../common/img/flags/Netherlands.svg | 5 + .../common/img/flags/Norway.svg | 13 + .../common/img/flags/Poland.svg | 1 + .../common/img/flags/Portugal.svg | 196 + .../common/img/flags/Romania.svg | 6 + .../common/img/flags/Slovenia.svg | 24 + .../common/img/flags/Spain.svg | 1 + .../common/img/flags/Sweden.svg | 1 + .../shared-module-v2/common/img/flags/USA.svg | 97 + .../common/img/flags/United_Kingdom.svg | 16 + .../common/img/hero-default-bg-image.svg | 302 + .../common/img/likert/agree.svg | 8 + .../common/img/likert/disagree.svg | 7 + .../common/img/likert/neutral.svg | 7 + .../common/img/likert/stronglyAgree.svg | 8 + .../common/img/likert/stronglyDisagree.svg | 7 + .../src/shared-module-v2/common/img/lock.svg | 7 + .../common/img/moocfiLogo.svg | 10 + .../src/shared-module-v2/common/img/next.svg | 14 + .../src/shared-module-v2/common/img/quote.svg | 20 + .../src/shared-module-v2/common/img/score.svg | 17 + .../common/img/screwedArrow.svg | 3 + .../shared-module-v2/common/img/setting.svg | 8 + .../shared-module-v2/common/img/swoosh.svg | 11 + .../shared-module-v2/common/img/tick-03.svg | 6 + .../src/shared-module-v2/common/img/tick.svg | 8 + .../common/img/uh_without_background.svg | 6 + .../common/img/unitedStates.svg | 53 + .../shared-module-v2/common/img/up-arrow.svg | 3 + .../common/locales/en/cms.json | 114 + .../common/locales/en/course-material.json | 181 + .../common/locales/en/example-exercise.json | 8 + .../common/locales/en/main-frontend.json | 606 + .../common/locales/en/quizzes.json | 161 + .../common/locales/en/shared-module.json | 108 + .../common/locales/en/tmc.json | 21 + .../common/locales/fi/cms.json | 104 + .../common/locales/fi/course-material.json | 176 + .../common/locales/fi/example-exercise.json | 8 + .../common/locales/fi/main-frontend.json | 601 + .../common/locales/fi/quizzes.json | 163 + .../common/locales/fi/shared-module.json | 106 + .../common/locales/fi/tmc.json | 21 + .../common/services/appQueryClient.ts | 39 + .../common/services/backend/auth.ts | 44 + .../common/services/backend/files.ts | 17 + .../common/styles/GlobalStyles.tsx | 94 + .../common/styles/constants.ts | 9 + .../common/styles/cssReset.ts | 84 + .../shared-module-v2/common/styles/index.ts | 2 + .../common/styles/monacoFontFixer.ts | 13 + .../common/styles/muiTheme.ts | 15 + .../shared-module-v2/common/styles/respond.ts | 16 + .../shared-module-v2/common/styles/theme.ts | 170 + .../common/styles/typography.ts | 34 + .../common/types/imageTypes.d.ts | 10 + .../common/utils/accessibility.ts | 6 + .../common/utils/base-path.ts | 3 + .../common/utils/constants.ts | 13 + .../shared-module-v2/common/utils/cookies.ts | 12 + .../common/utils/cross-routing.ts | 12 + .../shared-module-v2/common/utils/dateUtil.ts | 36 + .../src/shared-module-v2/common/utils/dom.ts | 11 + .../dontRenderUntilQueryParametersReady.tsx | 64 + .../common/utils/exerciseServices.ts | 5 + .../shared-module-v2/common/utils/fetching.ts | 88 + .../shared-module-v2/common/utils/files.ts | 93 + .../common/utils/generateWebVitalsReporter.ts | 26 + .../utils/getGuestPseudonymousUserId.ts | 19 + .../utils/i18next-parser.config.template.js | 43 + .../ietfLanguageTagToHumanReadableName.ts | 21 + .../shared-module-v2/common/utils/initI18n.ts | 51 + .../common/utils/nullability.ts | 7 + .../shared-module-v2/common/utils/numbers.ts | 66 + .../utils/redirectBackAfterLoginOrSignup.tsx | 58 + .../common/utils/responseHeaders.js | 89 + .../shared-module-v2/common/utils/routes.ts | 14 + .../shared-module-v2/common/utils/strings.ts | 93 + .../shared-module-v2/common/utils/styles.ts | 4 + .../common/utils/svgoConfig.js | 24 + .../common/utils/testing/i18nTest.ts | 26 + .../testing/replaceUuidsWithPlaceholders.ts | 7 + .../src/shared-module-v2/common/utils/time.ts | 20 + .../common/utils/typeMappter.ts | 16 + .../common/utils/urlManipulation.ts | 9 + .../common/utils/validation.ts | 25 + .../common/utils/withErrorBoundary.tsx | 71 + .../common/utils/withNoSsr.tsx | 28 + .../packages/common/package-lock.json | 127 + shared-module-v2/packages/common/package.json | 14 + .../packages/common/src/components/Button.tsx | 87 +- .../packages/common/src/components/Dialog.tsx | 44 +- .../common/src/components/ErrorBanner.tsx | 11 +- .../src/components/InputFields/CheckBox.tsx | 4 +- .../components/InputFields/DateTimeLocal.tsx | 4 +- .../common/src/hooks/useClickOutside.tsx | 24 + shared-module-v2/sync.ts | 11 +- storybook/.storybook/main.ts | 19 + storybook/.storybook/preview.ts | 16 + storybook/package-lock.json | 22046 ++++++++++++++++ storybook/package.json | 34 + .../shared-module/common/bindings.guard.ts | 3360 +++ .../src/shared-module/common/bindings.ts | 1900 ++ .../components/Accordion/DetailAccordion.tsx | 132 + .../common/components/Accordion/index.tsx | 148 + .../common/components/Banner/Banner.tsx | 110 + .../components/Banner/ContributeBanner.tsx | 110 + .../components/Banner/ReadOnlyBanner.tsx | 51 + .../common/components/BooleanAsText.tsx | 8 + .../common/components/Breadcrumbs.tsx | 108 + .../common/components/Button.tsx | 323 + .../components/Card/CardOpenTextOverlay.tsx | 50 + .../common/components/Card/CardOpensText.tsx | 47 + .../components/Card/IllustrationCard.tsx | 142 + .../common/components/Card/SimpleCard.tsx | 161 + .../common/components/Card/index.tsx | 68 + .../Centering/BreakFromCentered.tsx | 80 + .../common/components/Centering/Centered.tsx | 46 + .../common/components/CircularProgressBar.tsx | 86 + .../CourseProgress/CircularProgress.tsx | 185 + .../components/CourseProgress/ProgressBar.tsx | 132 + .../components/CourseProgress/index.tsx | 35 + .../common/components/DebugModal.tsx | 107 + .../common/components/Dialog.tsx | 132 + .../common/components/DiffFormatter.tsx | 73 + .../DropdownMenu/DropdownMenuItem.tsx | 77 + .../common/components/DropdownMenu/index.tsx | 154 + .../common/components/ErrorBanner.tsx | 304 + .../components/ExerciseList/ExerciseBox.tsx | 166 + .../components/ExerciseList/PageBox.tsx | 55 + .../common/components/FloatingErrorBox.tsx | 77 + .../common/components/Footer.tsx | 205 + .../common/components/Forum/Forum.tsx | 187 + .../components/Forum/SideNavigation.tsx | 176 + .../common/components/Forum/Thread.tsx | 207 + .../common/components/Forum/Threads.tsx | 98 + .../common/components/GenericInfobox.tsx | 36 + .../components/HeightTrackingContainer.tsx | 106 + .../components/InputFields/CheckBox.tsx | 140 + .../InputFields/CheckboxFieldWrapper.tsx | 44 + .../InputFields/DatePickerField.tsx | 67 + .../components/InputFields/DateTimeLocal.tsx | 116 + .../InputFields/EditableComponentTextArea.tsx | 93 + .../components/InputFields/FileField.tsx | 143 + .../components/InputFields/RadioButton.tsx | 77 + .../components/InputFields/SelectField.tsx | 138 + .../components/InputFields/TextAreaField.tsx | 106 + .../components/InputFields/TextField.tsx | 147 + .../InputFields/TimePickerField.tsx | 67 + .../components/LanguageSelection/Language.tsx | 65 + .../LanguageSelection/LanguageMenu.tsx | 29 + .../LanguageSelection/LanguageOption.tsx | 63 + .../components/LanguageSelection/index.tsx | 125 + .../common/components/LinkOrNoLink.tsx | 18 + .../common/components/LoginControls.tsx | 73 + .../components/MessageChannelIFrame.tsx | 219 + .../Navigation/NavBar/ComplexNav.tsx | 277 + .../NavBar/Menu/Hamburger/Hamburger.tsx | 31 + .../NavBar/Menu/Hamburger/HamburgerSpring.tsx | 210 + .../Navigation/NavBar/Menu/Menu.tsx | 125 + .../Navigation/NavBar/Menu/MenuItem.tsx | 7 + .../Navigation/NavBar/NavContainer.tsx | 18 + .../components/Navigation/NavBar/NavItem.tsx | 7 + .../components/Navigation/NavBar/NavItems.tsx | 23 + .../components/Navigation/NavBar/NavLink.tsx | 62 + .../Navigation/NavBar/SimpleNav.tsx | 82 + .../components/Navigation/NavBar/index.tsx | 28 + .../Navigation/TabLinks/TabLink.tsx | 100 + .../Navigation/TabLinks/TabLinkNavigation.tsx | 134 + .../Navigation/TabLinks/TabLinkPanel.tsx | 11 + .../common/components/Nested.tsx | 20 + .../common/components/NextSectionLink.tsx | 308 + .../common/components/Notifications/Base.tsx | 17 + .../components/Notifications/Delete.tsx | 111 + .../common/components/Notifications/Error.tsx | 114 + .../components/Notifications/Loading.tsx | 93 + .../components/Notifications/Success.tsx | 111 + .../Notifications/ToasterNotifications.tsx | 21 + .../components/OnlyRenderIfPermissions.tsx | 38 + .../common/components/PagesInChapterBox.tsx | 134 + .../common/components/Pagination.tsx | 353 + .../components/PaginationItemsPerPage.tsx | 49 + .../components/PeerReview/LikertScale.tsx | 140 + .../common/components/PeerReview/Option.tsx | 83 + .../PeerReview/PeerReviewProgress.tsx | 48 + .../common/components/PeerReview/Review.tsx | 70 + .../shared-module/common/components/Quote.tsx | 57 + .../common/components/Reference.tsx | 245 + .../common/components/SelectMenu.tsx | 120 + .../common/components/SkipLink.tsx | 23 + .../common/components/SpeechBalloon.tsx | 60 + .../common/components/Spinner.tsx | 63 + .../common/components/Sponsor.tsx | 110 + .../shared-module/common/components/Test.tsx | 20 + .../common/components/TimeComponent.tsx | 109 + .../shared-module/common/components/Title.tsx | 24 + .../common/components/TopLevelPage.tsx | 113 + .../common/components/TopicObjectives.tsx | 96 + .../components/layout/PageMarginOffset.tsx | 21 + .../components/monaco/MonacoDiffEditor.tsx | 20 + .../common/components/monaco/MonacoEditor.tsx | 20 + .../monaco/impl/MonacoDiffEditorImpl.tsx | 25 + .../monaco/impl/MonacoEditorImpl.tsx | 25 + .../common/components/monaco/impl/loader.ts | 8 + .../HideChildrenInSystemTests.tsx | 18 + .../system-tests/HideTextInSystemTests.tsx | 21 + .../MaskOverThisInSystemTests.tsx | 30 + .../contexts/ExerciseServiceContext.tsx | 25 + .../common/contexts/IframeHeightContext.tsx | 9 + .../common/contexts/LoginStateContext.tsx | 77 + .../exercise-service-protocol-types-2.ts | 22 + .../exercise-service-protocol-types.guard.ts | 267 + .../common/exercise-service-protocol-types.ts | 133 + .../useExerciseServiceOutputState.tsx | 63 + .../common/hooks/useAuthorizeMultiple.tsx | 32 + .../common/hooks/useClickOutside.tsx | 24 + .../common/hooks/useDateStringAsDate.tsx | 19 + .../useExerciseServiceParentConnection.tsx | 61 + .../common/hooks/useLanguage.tsx | 106 + .../shared-module/common/hooks/useMedia.ts | 23 + .../common/hooks/useMessageChannel.tsx | 9 + .../common/hooks/usePaginationInfo.tsx | 82 + .../common/hooks/useQueryParameter.ts | 22 + ...houldHideStuffForSystemTestScreenshots.tsx | 25 + .../common/hooks/useShowToastInfinitely.tsx | 28 + .../common/hooks/useStateQuery.ts | 107 + .../common/hooks/useToastMutation.tsx | 148 + .../common/hooks/useUserInfo.tsx | 10 + .../shared-module/common/img/UHBrandLogo.svg | 8 + .../common/img/accordion-arrow.svg | 3 + .../src/shared-module/common/img/arrow.svg | 3 + .../shared-module/common/img/backarrow.svg | 3 + .../shared-module/common/img/blackArrow.svg | 3 + .../src/shared-module/common/img/bulleye.svg | 5 + .../common/img/card-bg-circle.svg | 3 + .../shared-module/common/img/card-bg-star.svg | 6 + .../common/img/card-bg-zigzag.svg | 8 + .../common/img/card-defualt-bg/circle.svg | 3 + .../common/img/card-defualt-bg/cross.svg | 4 + .../common/img/card-defualt-bg/dot-circle.svg | 4 + .../common/img/card-defualt-bg/equal.svg | 4 + .../img/card-defualt-bg/intersection.svg | 4 + .../img/card-defualt-bg/pixel-square.svg | 5 + .../img/card-defualt-bg/quadruple-circle.svg | 6 + .../common/img/card-defualt-bg/triangle.svg | 3 + .../src/shared-module/common/img/cardNext.svg | 3 + .../common/img/caret-arrow-down.svg | 3 + .../common/img/caret-arrow-left.svg | 3 + .../common/img/caret-arrow-right.svg | 3 + .../common/img/caret-arrow-up.svg | 3 + .../src/shared-module/common/img/check.svg | 3 + .../shared-module/common/img/checkmark.svg | 3 + .../src/shared-module/common/img/china.svg | 22 + .../src/shared-module/common/img/close.svg | 11 + .../src/shared-module/common/img/cross.svg | 6 + .../src/shared-module/common/img/diamond.png | Bin 0 -> 840 bytes .../src/shared-module/common/img/diamond.svg | 3 + .../shared-module/common/img/exist-icon.svg | 3 + .../common/img/external-link.svg | 1 + .../common/img/flags/Austria.svg | 5 + .../common/img/flags/Belgium.svg | 1 + .../common/img/flags/Bulgaria.svg | 6 + .../common/img/flags/Croatia.svg | 276 + .../shared-module/common/img/flags/Czech.svg | 6 + .../common/img/flags/Denmark.svg | 1 + .../common/img/flags/Estonia.svg | 5 + .../common/img/flags/Finland.svg | 6 + .../shared-module/common/img/flags/France.svg | 6 + .../common/img/flags/Germany.svg | 7 + .../shared-module/common/img/flags/Greece.svg | 5 + .../common/img/flags/Ireland.svg | 6 + .../shared-module/common/img/flags/Italy.svg | 6 + .../shared-module/common/img/flags/Latvia.svg | 5 + .../common/img/flags/Lithuania.svg | 1 + .../common/img/flags/Netherlands.svg | 5 + .../shared-module/common/img/flags/Norway.svg | 13 + .../shared-module/common/img/flags/Poland.svg | 1 + .../common/img/flags/Portugal.svg | 196 + .../common/img/flags/Romania.svg | 6 + .../common/img/flags/Slovenia.svg | 24 + .../shared-module/common/img/flags/Spain.svg | 1 + .../shared-module/common/img/flags/Sweden.svg | 1 + .../shared-module/common/img/flags/USA.svg | 97 + .../common/img/flags/United_Kingdom.svg | 16 + .../common/img/hero-default-bg-image.svg | 302 + .../shared-module/common/img/likert/agree.svg | 8 + .../common/img/likert/disagree.svg | 7 + .../common/img/likert/neutral.svg | 7 + .../common/img/likert/stronglyAgree.svg | 8 + .../common/img/likert/stronglyDisagree.svg | 7 + .../src/shared-module/common/img/lock.svg | 7 + .../shared-module/common/img/moocfiLogo.svg | 10 + .../src/shared-module/common/img/next.svg | 14 + .../src/shared-module/common/img/quote.svg | 20 + .../src/shared-module/common/img/score.svg | 17 + .../shared-module/common/img/screwedArrow.svg | 3 + .../src/shared-module/common/img/setting.svg | 8 + .../src/shared-module/common/img/swoosh.svg | 11 + .../src/shared-module/common/img/tick-03.svg | 6 + .../src/shared-module/common/img/tick.svg | 8 + .../common/img/uh_without_background.svg | 6 + .../shared-module/common/img/unitedStates.svg | 53 + .../src/shared-module/common/img/up-arrow.svg | 3 + .../shared-module/common/locales/en/cms.json | 114 + .../common/locales/en/course-material.json | 181 + .../common/locales/en/example-exercise.json | 8 + .../common/locales/en/main-frontend.json | 606 + .../common/locales/en/quizzes.json | 161 + .../common/locales/en/shared-module.json | 108 + .../shared-module/common/locales/en/tmc.json | 21 + .../shared-module/common/locales/fi/cms.json | 104 + .../common/locales/fi/course-material.json | 176 + .../common/locales/fi/example-exercise.json | 8 + .../common/locales/fi/main-frontend.json | 601 + .../common/locales/fi/quizzes.json | 163 + .../common/locales/fi/shared-module.json | 106 + .../shared-module/common/locales/fi/tmc.json | 21 + .../common/services/appQueryClient.ts | 39 + .../common/services/backend/auth.ts | 44 + .../common/services/backend/files.ts | 17 + .../common/styles/GlobalStyles.tsx | 94 + .../shared-module/common/styles/constants.ts | 9 + .../shared-module/common/styles/cssReset.ts | 84 + .../src/shared-module/common/styles/index.ts | 2 + .../common/styles/monacoFontFixer.ts | 13 + .../shared-module/common/styles/muiTheme.ts | 15 + .../shared-module/common/styles/respond.ts | 16 + .../src/shared-module/common/styles/theme.ts | 170 + .../shared-module/common/styles/typography.ts | 34 + .../common/types/imageTypes.d.ts | 10 + .../common/utils/accessibility.ts | 6 + .../shared-module/common/utils/base-path.ts | 3 + .../shared-module/common/utils/constants.ts | 13 + .../src/shared-module/common/utils/cookies.ts | 12 + .../common/utils/cross-routing.ts | 12 + .../shared-module/common/utils/dateUtil.ts | 36 + .../src/shared-module/common/utils/dom.ts | 11 + .../dontRenderUntilQueryParametersReady.tsx | 64 + .../common/utils/exerciseServices.ts | 5 + .../shared-module/common/utils/fetching.ts | 88 + .../src/shared-module/common/utils/files.ts | 93 + .../common/utils/generateWebVitalsReporter.ts | 26 + .../utils/getGuestPseudonymousUserId.ts | 19 + .../utils/i18next-parser.config.template.js | 43 + .../ietfLanguageTagToHumanReadableName.ts | 21 + .../shared-module/common/utils/initI18n.ts | 51 + .../shared-module/common/utils/nullability.ts | 7 + .../src/shared-module/common/utils/numbers.ts | 66 + .../utils/redirectBackAfterLoginOrSignup.tsx | 58 + .../common/utils/responseHeaders.js | 89 + .../src/shared-module/common/utils/routes.ts | 14 + .../src/shared-module/common/utils/strings.ts | 93 + .../src/shared-module/common/utils/styles.ts | 4 + .../shared-module/common/utils/svgoConfig.js | 24 + .../common/utils/testing/i18nTest.ts | 26 + .../testing/replaceUuidsWithPlaceholders.ts | 7 + .../src/shared-module/common/utils/time.ts | 20 + .../shared-module/common/utils/typeMappter.ts | 16 + .../common/utils/urlManipulation.ts | 9 + .../shared-module/common/utils/validation.ts | 25 + .../common/utils/withErrorBoundary.tsx | 71 + .../shared-module/common/utils/withNoSsr.tsx | 28 + storybook/stories/common/Button.stories.tsx | 57 + storybook/stories/common/Dialog.stories.tsx | 39 + .../stories/common/ErrorBanner.stories.tsx | 25 + .../stories/common/GenericInfoBox.stories.tsx | 26 + storybook/stories/common/Spinner.stories.tsx | 37 + .../common/inputs/Checkbox.stories.tsx | 31 + .../common/inputs/DatePickerField.stories.tsx | 33 + .../common/inputs/DateTimeLocal.stories.tsx | 33 + .../common/inputs/FileField.stories.tsx | 30 + .../common/inputs/RadioButton.stories.tsx | 31 + .../common/inputs/SelectField.stories.tsx | 36 + .../common/inputs/TextAreaField.stories.tsx | 34 + .../common/inputs/TextField.stories.tsx | 32 + .../inputs/TimerPickerField.stories.tsx | 33 + .../shared-module-v2/common/bindings.guard.ts | 3360 +++ .../src/shared-module-v2/common/bindings.ts | 1900 ++ .../components/Accordion/DetailAccordion.tsx | 132 + .../common/components/Accordion/index.tsx | 148 + .../common/components/Banner/Banner.tsx | 110 + .../components/Banner/ContributeBanner.tsx | 110 + .../components/Banner/ReadOnlyBanner.tsx | 51 + .../common/components/BooleanAsText.tsx | 8 + .../common/components/Breadcrumbs.tsx | 108 + .../common/components/Button.tsx | 323 + .../components/Card/CardOpenTextOverlay.tsx | 50 + .../common/components/Card/CardOpensText.tsx | 47 + .../components/Card/IllustrationCard.tsx | 142 + .../common/components/Card/SimpleCard.tsx | 161 + .../common/components/Card/index.tsx | 68 + .../Centering/BreakFromCentered.tsx | 80 + .../common/components/Centering/Centered.tsx | 46 + .../common/components/CircularProgressBar.tsx | 86 + .../CourseProgress/CircularProgress.tsx | 185 + .../components/CourseProgress/ProgressBar.tsx | 132 + .../components/CourseProgress/index.tsx | 35 + .../common/components/DebugModal.tsx | 107 + .../common/components/Dialog.tsx | 132 + .../common/components/DiffFormatter.tsx | 73 + .../DropdownMenu/DropdownMenuItem.tsx | 77 + .../common/components/DropdownMenu/index.tsx | 154 + .../common/components/ErrorBanner.tsx | 304 + .../components/ExerciseList/ExerciseBox.tsx | 166 + .../components/ExerciseList/PageBox.tsx | 55 + .../common/components/FloatingErrorBox.tsx | 77 + .../common/components/Footer.tsx | 205 + .../common/components/Forum/Forum.tsx | 187 + .../components/Forum/SideNavigation.tsx | 176 + .../common/components/Forum/Thread.tsx | 207 + .../common/components/Forum/Threads.tsx | 98 + .../common/components/GenericInfobox.tsx | 36 + .../components/HeightTrackingContainer.tsx | 106 + .../components/InputFields/CheckBox.tsx | 140 + .../InputFields/CheckboxFieldWrapper.tsx | 44 + .../InputFields/DatePickerField.tsx | 67 + .../components/InputFields/DateTimeLocal.tsx | 116 + .../InputFields/EditableComponentTextArea.tsx | 93 + .../components/InputFields/FileField.tsx | 143 + .../components/InputFields/RadioButton.tsx | 77 + .../components/InputFields/SelectField.tsx | 138 + .../components/InputFields/TextAreaField.tsx | 106 + .../components/InputFields/TextField.tsx | 147 + .../InputFields/TimePickerField.tsx | 67 + .../components/LanguageSelection/Language.tsx | 65 + .../LanguageSelection/LanguageMenu.tsx | 29 + .../LanguageSelection/LanguageOption.tsx | 63 + .../components/LanguageSelection/index.tsx | 125 + .../common/components/LinkOrNoLink.tsx | 18 + .../common/components/LoginControls.tsx | 73 + .../components/MessageChannelIFrame.tsx | 219 + .../Navigation/NavBar/ComplexNav.tsx | 277 + .../NavBar/Menu/Hamburger/Hamburger.tsx | 31 + .../NavBar/Menu/Hamburger/HamburgerSpring.tsx | 210 + .../Navigation/NavBar/Menu/Menu.tsx | 125 + .../Navigation/NavBar/Menu/MenuItem.tsx | 7 + .../Navigation/NavBar/NavContainer.tsx | 18 + .../components/Navigation/NavBar/NavItem.tsx | 7 + .../components/Navigation/NavBar/NavItems.tsx | 23 + .../components/Navigation/NavBar/NavLink.tsx | 62 + .../Navigation/NavBar/SimpleNav.tsx | 82 + .../components/Navigation/NavBar/index.tsx | 28 + .../Navigation/TabLinks/TabLink.tsx | 100 + .../Navigation/TabLinks/TabLinkNavigation.tsx | 134 + .../Navigation/TabLinks/TabLinkPanel.tsx | 11 + .../common/components/Nested.tsx | 20 + .../common/components/NextSectionLink.tsx | 308 + .../common/components/Notifications/Base.tsx | 17 + .../components/Notifications/Delete.tsx | 111 + .../common/components/Notifications/Error.tsx | 114 + .../components/Notifications/Loading.tsx | 93 + .../components/Notifications/Success.tsx | 111 + .../Notifications/ToasterNotifications.tsx | 21 + .../components/OnlyRenderIfPermissions.tsx | 38 + .../common/components/PagesInChapterBox.tsx | 134 + .../common/components/Pagination.tsx | 353 + .../components/PaginationItemsPerPage.tsx | 49 + .../components/PeerReview/LikertScale.tsx | 140 + .../common/components/PeerReview/Option.tsx | 83 + .../PeerReview/PeerReviewProgress.tsx | 48 + .../common/components/PeerReview/Review.tsx | 70 + .../common/components/Quote.tsx | 57 + .../common/components/Reference.tsx | 245 + .../common/components/SelectMenu.tsx | 120 + .../common/components/SkipLink.tsx | 23 + .../common/components/SpeechBalloon.tsx | 60 + .../common/components/Spinner.tsx | 63 + .../common/components/Sponsor.tsx | 110 + .../common/components/Test.tsx | 20 + .../common/components/TimeComponent.tsx | 109 + .../common/components/Title.tsx | 24 + .../common/components/TopLevelPage.tsx | 113 + .../common/components/TopicObjectives.tsx | 96 + .../components/layout/PageMarginOffset.tsx | 21 + .../components/monaco/MonacoDiffEditor.tsx | 20 + .../common/components/monaco/MonacoEditor.tsx | 20 + .../monaco/impl/MonacoDiffEditorImpl.tsx | 25 + .../monaco/impl/MonacoEditorImpl.tsx | 25 + .../common/components/monaco/impl/loader.ts | 8 + .../HideChildrenInSystemTests.tsx | 18 + .../system-tests/HideTextInSystemTests.tsx | 21 + .../MaskOverThisInSystemTests.tsx | 30 + .../contexts/ExerciseServiceContext.tsx | 25 + .../common/contexts/IframeHeightContext.tsx | 9 + .../common/contexts/LoginStateContext.tsx | 77 + .../exercise-service-protocol-types-2.ts | 22 + .../exercise-service-protocol-types.guard.ts | 267 + .../common/exercise-service-protocol-types.ts | 133 + .../useExerciseServiceOutputState.tsx | 63 + .../common/hooks/useAuthorizeMultiple.tsx | 32 + .../common/hooks/useClickOutside.tsx | 24 + .../common/hooks/useDateStringAsDate.tsx | 19 + .../useExerciseServiceParentConnection.tsx | 61 + .../common/hooks/useLanguage.tsx | 106 + .../shared-module-v2/common/hooks/useMedia.ts | 23 + .../common/hooks/useMessageChannel.tsx | 9 + .../common/hooks/usePaginationInfo.tsx | 82 + .../common/hooks/useQueryParameter.ts | 22 + ...houldHideStuffForSystemTestScreenshots.tsx | 25 + .../common/hooks/useShowToastInfinitely.tsx | 28 + .../common/hooks/useStateQuery.ts | 107 + .../common/hooks/useToastMutation.tsx | 148 + .../common/hooks/useUserInfo.tsx | 10 + .../common/img/UHBrandLogo.svg | 8 + .../common/img/accordion-arrow.svg | 3 + .../src/shared-module-v2/common/img/arrow.svg | 3 + .../shared-module-v2/common/img/backarrow.svg | 3 + .../common/img/blackArrow.svg | 3 + .../shared-module-v2/common/img/bulleye.svg | 5 + .../common/img/card-bg-circle.svg | 3 + .../common/img/card-bg-star.svg | 6 + .../common/img/card-bg-zigzag.svg | 8 + .../common/img/card-defualt-bg/circle.svg | 3 + .../common/img/card-defualt-bg/cross.svg | 4 + .../common/img/card-defualt-bg/dot-circle.svg | 4 + .../common/img/card-defualt-bg/equal.svg | 4 + .../img/card-defualt-bg/intersection.svg | 4 + .../img/card-defualt-bg/pixel-square.svg | 5 + .../img/card-defualt-bg/quadruple-circle.svg | 6 + .../common/img/card-defualt-bg/triangle.svg | 3 + .../shared-module-v2/common/img/cardNext.svg | 3 + .../common/img/caret-arrow-down.svg | 3 + .../common/img/caret-arrow-left.svg | 3 + .../common/img/caret-arrow-right.svg | 3 + .../common/img/caret-arrow-up.svg | 3 + .../src/shared-module-v2/common/img/check.svg | 3 + .../shared-module-v2/common/img/checkmark.svg | 3 + .../src/shared-module-v2/common/img/china.svg | 22 + .../src/shared-module-v2/common/img/close.svg | 11 + .../src/shared-module-v2/common/img/cross.svg | 6 + .../shared-module-v2/common/img/diamond.png | Bin 0 -> 840 bytes .../shared-module-v2/common/img/diamond.svg | 3 + .../common/img/exist-icon.svg | 3 + .../common/img/external-link.svg | 1 + .../common/img/flags/Austria.svg | 5 + .../common/img/flags/Belgium.svg | 1 + .../common/img/flags/Bulgaria.svg | 6 + .../common/img/flags/Croatia.svg | 276 + .../common/img/flags/Czech.svg | 6 + .../common/img/flags/Denmark.svg | 1 + .../common/img/flags/Estonia.svg | 5 + .../common/img/flags/Finland.svg | 6 + .../common/img/flags/France.svg | 6 + .../common/img/flags/Germany.svg | 7 + .../common/img/flags/Greece.svg | 5 + .../common/img/flags/Ireland.svg | 6 + .../common/img/flags/Italy.svg | 6 + .../common/img/flags/Latvia.svg | 5 + .../common/img/flags/Lithuania.svg | 1 + .../common/img/flags/Netherlands.svg | 5 + .../common/img/flags/Norway.svg | 13 + .../common/img/flags/Poland.svg | 1 + .../common/img/flags/Portugal.svg | 196 + .../common/img/flags/Romania.svg | 6 + .../common/img/flags/Slovenia.svg | 24 + .../common/img/flags/Spain.svg | 1 + .../common/img/flags/Sweden.svg | 1 + .../shared-module-v2/common/img/flags/USA.svg | 97 + .../common/img/flags/United_Kingdom.svg | 16 + .../common/img/hero-default-bg-image.svg | 302 + .../common/img/likert/agree.svg | 8 + .../common/img/likert/disagree.svg | 7 + .../common/img/likert/neutral.svg | 7 + .../common/img/likert/stronglyAgree.svg | 8 + .../common/img/likert/stronglyDisagree.svg | 7 + .../src/shared-module-v2/common/img/lock.svg | 7 + .../common/img/moocfiLogo.svg | 10 + .../src/shared-module-v2/common/img/next.svg | 14 + .../src/shared-module-v2/common/img/quote.svg | 20 + .../src/shared-module-v2/common/img/score.svg | 17 + .../common/img/screwedArrow.svg | 3 + .../shared-module-v2/common/img/setting.svg | 8 + .../shared-module-v2/common/img/swoosh.svg | 11 + .../shared-module-v2/common/img/tick-03.svg | 6 + .../src/shared-module-v2/common/img/tick.svg | 8 + .../common/img/uh_without_background.svg | 6 + .../common/img/unitedStates.svg | 53 + .../shared-module-v2/common/img/up-arrow.svg | 3 + .../common/locales/en/cms.json | 114 + .../common/locales/en/course-material.json | 181 + .../common/locales/en/example-exercise.json | 8 + .../common/locales/en/main-frontend.json | 606 + .../common/locales/en/quizzes.json | 161 + .../common/locales/en/shared-module.json | 108 + .../common/locales/en/tmc.json | 21 + .../common/locales/fi/cms.json | 104 + .../common/locales/fi/course-material.json | 176 + .../common/locales/fi/example-exercise.json | 8 + .../common/locales/fi/main-frontend.json | 601 + .../common/locales/fi/quizzes.json | 163 + .../common/locales/fi/shared-module.json | 106 + .../common/locales/fi/tmc.json | 21 + .../common/services/appQueryClient.ts | 39 + .../common/services/backend/auth.ts | 44 + .../common/services/backend/files.ts | 17 + .../common/styles/GlobalStyles.tsx | 94 + .../common/styles/constants.ts | 9 + .../common/styles/cssReset.ts | 84 + .../shared-module-v2/common/styles/index.ts | 2 + .../common/styles/monacoFontFixer.ts | 13 + .../common/styles/muiTheme.ts | 15 + .../shared-module-v2/common/styles/respond.ts | 16 + .../shared-module-v2/common/styles/theme.ts | 170 + .../common/styles/typography.ts | 34 + .../common/types/imageTypes.d.ts | 10 + .../common/utils/accessibility.ts | 6 + .../common/utils/base-path.ts | 3 + .../common/utils/constants.ts | 13 + .../shared-module-v2/common/utils/cookies.ts | 12 + .../common/utils/cross-routing.ts | 12 + .../shared-module-v2/common/utils/dateUtil.ts | 36 + .../src/shared-module-v2/common/utils/dom.ts | 11 + .../dontRenderUntilQueryParametersReady.tsx | 64 + .../common/utils/exerciseServices.ts | 5 + .../shared-module-v2/common/utils/fetching.ts | 88 + .../shared-module-v2/common/utils/files.ts | 93 + .../common/utils/generateWebVitalsReporter.ts | 26 + .../utils/getGuestPseudonymousUserId.ts | 19 + .../utils/i18next-parser.config.template.js | 43 + .../ietfLanguageTagToHumanReadableName.ts | 21 + .../shared-module-v2/common/utils/initI18n.ts | 51 + .../common/utils/nullability.ts | 7 + .../shared-module-v2/common/utils/numbers.ts | 66 + .../utils/redirectBackAfterLoginOrSignup.tsx | 58 + .../common/utils/responseHeaders.js | 89 + .../shared-module-v2/common/utils/routes.ts | 14 + .../shared-module-v2/common/utils/strings.ts | 93 + .../shared-module-v2/common/utils/styles.ts | 4 + .../common/utils/svgoConfig.js | 24 + .../common/utils/testing/i18nTest.ts | 26 + .../testing/replaceUuidsWithPlaceholders.ts | 7 + .../src/shared-module-v2/common/utils/time.ts | 20 + .../common/utils/typeMappter.ts | 16 + .../common/utils/urlManipulation.ts | 9 + .../common/utils/validation.ts | 25 + .../common/utils/withErrorBoundary.tsx | 71 + .../common/utils/withNoSsr.tsx | 28 + 2376 files changed, 219509 insertions(+), 68 deletions(-) create mode 100644 services/cms/src/shared-module-v2/common/bindings.guard.ts create mode 100644 services/cms/src/shared-module-v2/common/bindings.ts create mode 100644 services/cms/src/shared-module-v2/common/components/Accordion/DetailAccordion.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Accordion/index.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Banner/Banner.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Banner/ContributeBanner.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Banner/ReadOnlyBanner.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/BooleanAsText.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Breadcrumbs.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Button.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Card/CardOpenTextOverlay.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Card/CardOpensText.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Card/IllustrationCard.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Card/SimpleCard.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Card/index.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Centering/BreakFromCentered.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Centering/Centered.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/CircularProgressBar.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/CourseProgress/CircularProgress.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/CourseProgress/ProgressBar.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/CourseProgress/index.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/DebugModal.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Dialog.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/DiffFormatter.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/DropdownMenu/DropdownMenuItem.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/DropdownMenu/index.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/ErrorBanner.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/ExerciseList/ExerciseBox.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/ExerciseList/PageBox.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/FloatingErrorBox.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Footer.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Forum/Forum.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Forum/SideNavigation.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Forum/Thread.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Forum/Threads.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/GenericInfobox.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/HeightTrackingContainer.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/InputFields/CheckBox.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/InputFields/CheckboxFieldWrapper.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/InputFields/DatePickerField.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/InputFields/DateTimeLocal.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/InputFields/EditableComponentTextArea.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/InputFields/FileField.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/InputFields/RadioButton.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/InputFields/SelectField.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/InputFields/TextAreaField.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/InputFields/TextField.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/InputFields/TimePickerField.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/LanguageSelection/Language.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/LanguageSelection/LanguageMenu.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/LanguageSelection/LanguageOption.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/LanguageSelection/index.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/LinkOrNoLink.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/LoginControls.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/MessageChannelIFrame.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Navigation/NavBar/ComplexNav.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Navigation/NavBar/Menu/Hamburger/Hamburger.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Navigation/NavBar/Menu/Hamburger/HamburgerSpring.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Navigation/NavBar/Menu/Menu.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Navigation/NavBar/Menu/MenuItem.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Navigation/NavBar/NavContainer.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Navigation/NavBar/NavItem.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Navigation/NavBar/NavItems.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Navigation/NavBar/NavLink.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Navigation/NavBar/SimpleNav.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Navigation/NavBar/index.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Navigation/TabLinks/TabLink.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Navigation/TabLinks/TabLinkNavigation.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Navigation/TabLinks/TabLinkPanel.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Nested.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/NextSectionLink.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Notifications/Base.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Notifications/Delete.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Notifications/Error.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Notifications/Loading.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Notifications/Success.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Notifications/ToasterNotifications.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/OnlyRenderIfPermissions.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/PagesInChapterBox.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Pagination.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/PaginationItemsPerPage.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/PeerReview/LikertScale.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/PeerReview/Option.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/PeerReview/PeerReviewProgress.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/PeerReview/Review.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Quote.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Reference.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/SelectMenu.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/SkipLink.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/SpeechBalloon.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Spinner.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Sponsor.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Test.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/TimeComponent.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/Title.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/TopLevelPage.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/TopicObjectives.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/layout/PageMarginOffset.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/monaco/MonacoDiffEditor.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/monaco/MonacoEditor.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/monaco/impl/MonacoDiffEditorImpl.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/monaco/impl/MonacoEditorImpl.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/monaco/impl/loader.ts create mode 100644 services/cms/src/shared-module-v2/common/components/system-tests/HideChildrenInSystemTests.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/system-tests/HideTextInSystemTests.tsx create mode 100644 services/cms/src/shared-module-v2/common/components/system-tests/MaskOverThisInSystemTests.tsx create mode 100644 services/cms/src/shared-module-v2/common/contexts/ExerciseServiceContext.tsx create mode 100644 services/cms/src/shared-module-v2/common/contexts/IframeHeightContext.tsx create mode 100644 services/cms/src/shared-module-v2/common/contexts/LoginStateContext.tsx create mode 100644 services/cms/src/shared-module-v2/common/exercise-service-protocol-types-2.ts create mode 100644 services/cms/src/shared-module-v2/common/exercise-service-protocol-types.guard.ts create mode 100644 services/cms/src/shared-module-v2/common/exercise-service-protocol-types.ts create mode 100644 services/cms/src/shared-module-v2/common/hooks/exerciseServiceHooks/useExerciseServiceOutputState.tsx create mode 100644 services/cms/src/shared-module-v2/common/hooks/useAuthorizeMultiple.tsx create mode 100644 services/cms/src/shared-module-v2/common/hooks/useClickOutside.tsx create mode 100644 services/cms/src/shared-module-v2/common/hooks/useDateStringAsDate.tsx create mode 100644 services/cms/src/shared-module-v2/common/hooks/useExerciseServiceParentConnection.tsx create mode 100644 services/cms/src/shared-module-v2/common/hooks/useLanguage.tsx create mode 100644 services/cms/src/shared-module-v2/common/hooks/useMedia.ts create mode 100644 services/cms/src/shared-module-v2/common/hooks/useMessageChannel.tsx create mode 100644 services/cms/src/shared-module-v2/common/hooks/usePaginationInfo.tsx create mode 100644 services/cms/src/shared-module-v2/common/hooks/useQueryParameter.ts create mode 100644 services/cms/src/shared-module-v2/common/hooks/useShouldHideStuffForSystemTestScreenshots.tsx create mode 100644 services/cms/src/shared-module-v2/common/hooks/useShowToastInfinitely.tsx create mode 100644 services/cms/src/shared-module-v2/common/hooks/useStateQuery.ts create mode 100644 services/cms/src/shared-module-v2/common/hooks/useToastMutation.tsx create mode 100644 services/cms/src/shared-module-v2/common/hooks/useUserInfo.tsx create mode 100644 services/cms/src/shared-module-v2/common/img/UHBrandLogo.svg create mode 100644 services/cms/src/shared-module-v2/common/img/accordion-arrow.svg create mode 100644 services/cms/src/shared-module-v2/common/img/arrow.svg create mode 100644 services/cms/src/shared-module-v2/common/img/backarrow.svg create mode 100644 services/cms/src/shared-module-v2/common/img/blackArrow.svg create mode 100644 services/cms/src/shared-module-v2/common/img/bulleye.svg create mode 100644 services/cms/src/shared-module-v2/common/img/card-bg-circle.svg create mode 100644 services/cms/src/shared-module-v2/common/img/card-bg-star.svg create mode 100644 services/cms/src/shared-module-v2/common/img/card-bg-zigzag.svg create mode 100644 services/cms/src/shared-module-v2/common/img/card-defualt-bg/circle.svg create mode 100644 services/cms/src/shared-module-v2/common/img/card-defualt-bg/cross.svg create mode 100644 services/cms/src/shared-module-v2/common/img/card-defualt-bg/dot-circle.svg create mode 100644 services/cms/src/shared-module-v2/common/img/card-defualt-bg/equal.svg create mode 100644 services/cms/src/shared-module-v2/common/img/card-defualt-bg/intersection.svg create mode 100644 services/cms/src/shared-module-v2/common/img/card-defualt-bg/pixel-square.svg create mode 100644 services/cms/src/shared-module-v2/common/img/card-defualt-bg/quadruple-circle.svg create mode 100644 services/cms/src/shared-module-v2/common/img/card-defualt-bg/triangle.svg create mode 100644 services/cms/src/shared-module-v2/common/img/cardNext.svg create mode 100644 services/cms/src/shared-module-v2/common/img/caret-arrow-down.svg create mode 100644 services/cms/src/shared-module-v2/common/img/caret-arrow-left.svg create mode 100644 services/cms/src/shared-module-v2/common/img/caret-arrow-right.svg create mode 100644 services/cms/src/shared-module-v2/common/img/caret-arrow-up.svg create mode 100644 services/cms/src/shared-module-v2/common/img/check.svg create mode 100644 services/cms/src/shared-module-v2/common/img/checkmark.svg create mode 100644 services/cms/src/shared-module-v2/common/img/china.svg create mode 100644 services/cms/src/shared-module-v2/common/img/close.svg create mode 100644 services/cms/src/shared-module-v2/common/img/cross.svg create mode 100644 services/cms/src/shared-module-v2/common/img/diamond.png create mode 100644 services/cms/src/shared-module-v2/common/img/diamond.svg create mode 100644 services/cms/src/shared-module-v2/common/img/exist-icon.svg create mode 100644 services/cms/src/shared-module-v2/common/img/external-link.svg create mode 100644 services/cms/src/shared-module-v2/common/img/flags/Austria.svg create mode 100644 services/cms/src/shared-module-v2/common/img/flags/Belgium.svg create mode 100644 services/cms/src/shared-module-v2/common/img/flags/Bulgaria.svg create mode 100644 services/cms/src/shared-module-v2/common/img/flags/Croatia.svg create mode 100644 services/cms/src/shared-module-v2/common/img/flags/Czech.svg create mode 100644 services/cms/src/shared-module-v2/common/img/flags/Denmark.svg create mode 100644 services/cms/src/shared-module-v2/common/img/flags/Estonia.svg create mode 100644 services/cms/src/shared-module-v2/common/img/flags/Finland.svg create mode 100644 services/cms/src/shared-module-v2/common/img/flags/France.svg create mode 100644 services/cms/src/shared-module-v2/common/img/flags/Germany.svg create mode 100644 services/cms/src/shared-module-v2/common/img/flags/Greece.svg create mode 100644 services/cms/src/shared-module-v2/common/img/flags/Ireland.svg create mode 100644 services/cms/src/shared-module-v2/common/img/flags/Italy.svg create mode 100644 services/cms/src/shared-module-v2/common/img/flags/Latvia.svg create mode 100644 services/cms/src/shared-module-v2/common/img/flags/Lithuania.svg create mode 100644 services/cms/src/shared-module-v2/common/img/flags/Netherlands.svg create mode 100644 services/cms/src/shared-module-v2/common/img/flags/Norway.svg create mode 100644 services/cms/src/shared-module-v2/common/img/flags/Poland.svg create mode 100644 services/cms/src/shared-module-v2/common/img/flags/Portugal.svg create mode 100644 services/cms/src/shared-module-v2/common/img/flags/Romania.svg create mode 100644 services/cms/src/shared-module-v2/common/img/flags/Slovenia.svg create mode 100644 services/cms/src/shared-module-v2/common/img/flags/Spain.svg create mode 100644 services/cms/src/shared-module-v2/common/img/flags/Sweden.svg create mode 100644 services/cms/src/shared-module-v2/common/img/flags/USA.svg create mode 100644 services/cms/src/shared-module-v2/common/img/flags/United_Kingdom.svg create mode 100644 services/cms/src/shared-module-v2/common/img/hero-default-bg-image.svg create mode 100644 services/cms/src/shared-module-v2/common/img/likert/agree.svg create mode 100644 services/cms/src/shared-module-v2/common/img/likert/disagree.svg create mode 100644 services/cms/src/shared-module-v2/common/img/likert/neutral.svg create mode 100644 services/cms/src/shared-module-v2/common/img/likert/stronglyAgree.svg create mode 100644 services/cms/src/shared-module-v2/common/img/likert/stronglyDisagree.svg create mode 100644 services/cms/src/shared-module-v2/common/img/lock.svg create mode 100644 services/cms/src/shared-module-v2/common/img/moocfiLogo.svg create mode 100644 services/cms/src/shared-module-v2/common/img/next.svg create mode 100644 services/cms/src/shared-module-v2/common/img/quote.svg create mode 100644 services/cms/src/shared-module-v2/common/img/score.svg create mode 100644 services/cms/src/shared-module-v2/common/img/screwedArrow.svg create mode 100644 services/cms/src/shared-module-v2/common/img/setting.svg create mode 100644 services/cms/src/shared-module-v2/common/img/swoosh.svg create mode 100644 services/cms/src/shared-module-v2/common/img/tick-03.svg create mode 100644 services/cms/src/shared-module-v2/common/img/tick.svg create mode 100644 services/cms/src/shared-module-v2/common/img/uh_without_background.svg create mode 100644 services/cms/src/shared-module-v2/common/img/unitedStates.svg create mode 100644 services/cms/src/shared-module-v2/common/img/up-arrow.svg create mode 100644 services/cms/src/shared-module-v2/common/locales/en/cms.json create mode 100644 services/cms/src/shared-module-v2/common/locales/en/course-material.json create mode 100644 services/cms/src/shared-module-v2/common/locales/en/example-exercise.json create mode 100644 services/cms/src/shared-module-v2/common/locales/en/main-frontend.json create mode 100644 services/cms/src/shared-module-v2/common/locales/en/quizzes.json create mode 100644 services/cms/src/shared-module-v2/common/locales/en/shared-module.json create mode 100644 services/cms/src/shared-module-v2/common/locales/en/tmc.json create mode 100644 services/cms/src/shared-module-v2/common/locales/fi/cms.json create mode 100644 services/cms/src/shared-module-v2/common/locales/fi/course-material.json create mode 100644 services/cms/src/shared-module-v2/common/locales/fi/example-exercise.json create mode 100644 services/cms/src/shared-module-v2/common/locales/fi/main-frontend.json create mode 100644 services/cms/src/shared-module-v2/common/locales/fi/quizzes.json create mode 100644 services/cms/src/shared-module-v2/common/locales/fi/shared-module.json create mode 100644 services/cms/src/shared-module-v2/common/locales/fi/tmc.json create mode 100644 services/cms/src/shared-module-v2/common/services/appQueryClient.ts create mode 100644 services/cms/src/shared-module-v2/common/services/backend/auth.ts create mode 100644 services/cms/src/shared-module-v2/common/services/backend/files.ts create mode 100644 services/cms/src/shared-module-v2/common/styles/GlobalStyles.tsx create mode 100644 services/cms/src/shared-module-v2/common/styles/constants.ts create mode 100644 services/cms/src/shared-module-v2/common/styles/cssReset.ts create mode 100644 services/cms/src/shared-module-v2/common/styles/index.ts create mode 100644 services/cms/src/shared-module-v2/common/styles/monacoFontFixer.ts create mode 100644 services/cms/src/shared-module-v2/common/styles/muiTheme.ts create mode 100644 services/cms/src/shared-module-v2/common/styles/respond.ts create mode 100644 services/cms/src/shared-module-v2/common/styles/theme.ts create mode 100644 services/cms/src/shared-module-v2/common/styles/typography.ts create mode 100644 services/cms/src/shared-module-v2/common/types/imageTypes.d.ts create mode 100644 services/cms/src/shared-module-v2/common/utils/accessibility.ts create mode 100644 services/cms/src/shared-module-v2/common/utils/base-path.ts create mode 100644 services/cms/src/shared-module-v2/common/utils/constants.ts create mode 100644 services/cms/src/shared-module-v2/common/utils/cookies.ts create mode 100644 services/cms/src/shared-module-v2/common/utils/cross-routing.ts create mode 100644 services/cms/src/shared-module-v2/common/utils/dateUtil.ts create mode 100644 services/cms/src/shared-module-v2/common/utils/dom.ts create mode 100644 services/cms/src/shared-module-v2/common/utils/dontRenderUntilQueryParametersReady.tsx create mode 100644 services/cms/src/shared-module-v2/common/utils/exerciseServices.ts create mode 100644 services/cms/src/shared-module-v2/common/utils/fetching.ts create mode 100644 services/cms/src/shared-module-v2/common/utils/files.ts create mode 100644 services/cms/src/shared-module-v2/common/utils/generateWebVitalsReporter.ts create mode 100644 services/cms/src/shared-module-v2/common/utils/getGuestPseudonymousUserId.ts create mode 100644 services/cms/src/shared-module-v2/common/utils/i18next-parser.config.template.js create mode 100644 services/cms/src/shared-module-v2/common/utils/ietfLanguageTagToHumanReadableName.ts create mode 100644 services/cms/src/shared-module-v2/common/utils/initI18n.ts create mode 100644 services/cms/src/shared-module-v2/common/utils/nullability.ts create mode 100644 services/cms/src/shared-module-v2/common/utils/numbers.ts create mode 100644 services/cms/src/shared-module-v2/common/utils/redirectBackAfterLoginOrSignup.tsx create mode 100644 services/cms/src/shared-module-v2/common/utils/responseHeaders.js create mode 100644 services/cms/src/shared-module-v2/common/utils/routes.ts create mode 100644 services/cms/src/shared-module-v2/common/utils/strings.ts create mode 100644 services/cms/src/shared-module-v2/common/utils/styles.ts create mode 100644 services/cms/src/shared-module-v2/common/utils/svgoConfig.js create mode 100644 services/cms/src/shared-module-v2/common/utils/testing/i18nTest.ts create mode 100644 services/cms/src/shared-module-v2/common/utils/testing/replaceUuidsWithPlaceholders.ts create mode 100644 services/cms/src/shared-module-v2/common/utils/time.ts create mode 100644 services/cms/src/shared-module-v2/common/utils/typeMappter.ts create mode 100644 services/cms/src/shared-module-v2/common/utils/urlManipulation.ts create mode 100644 services/cms/src/shared-module-v2/common/utils/validation.ts create mode 100644 services/cms/src/shared-module-v2/common/utils/withErrorBoundary.tsx create mode 100644 services/cms/src/shared-module-v2/common/utils/withNoSsr.tsx create mode 100644 services/course-material/src/shared-module-v2/common/bindings.guard.ts create mode 100644 services/course-material/src/shared-module-v2/common/bindings.ts create mode 100644 services/course-material/src/shared-module-v2/common/components/Accordion/DetailAccordion.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Accordion/index.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Banner/Banner.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Banner/ContributeBanner.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Banner/ReadOnlyBanner.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/BooleanAsText.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Breadcrumbs.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Button.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Card/CardOpenTextOverlay.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Card/CardOpensText.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Card/IllustrationCard.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Card/SimpleCard.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Card/index.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Centering/BreakFromCentered.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Centering/Centered.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/CircularProgressBar.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/CourseProgress/CircularProgress.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/CourseProgress/ProgressBar.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/CourseProgress/index.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/DebugModal.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Dialog.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/DiffFormatter.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/DropdownMenu/DropdownMenuItem.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/DropdownMenu/index.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/ErrorBanner.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/ExerciseList/ExerciseBox.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/ExerciseList/PageBox.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/FloatingErrorBox.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Footer.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Forum/Forum.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Forum/SideNavigation.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Forum/Thread.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Forum/Threads.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/GenericInfobox.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/HeightTrackingContainer.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/InputFields/CheckBox.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/InputFields/CheckboxFieldWrapper.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/InputFields/DatePickerField.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/InputFields/DateTimeLocal.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/InputFields/EditableComponentTextArea.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/InputFields/FileField.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/InputFields/RadioButton.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/InputFields/SelectField.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/InputFields/TextAreaField.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/InputFields/TextField.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/InputFields/TimePickerField.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/LanguageSelection/Language.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/LanguageSelection/LanguageMenu.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/LanguageSelection/LanguageOption.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/LanguageSelection/index.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/LinkOrNoLink.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/LoginControls.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/MessageChannelIFrame.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Navigation/NavBar/ComplexNav.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Navigation/NavBar/Menu/Hamburger/Hamburger.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Navigation/NavBar/Menu/Hamburger/HamburgerSpring.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Navigation/NavBar/Menu/Menu.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Navigation/NavBar/Menu/MenuItem.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Navigation/NavBar/NavContainer.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Navigation/NavBar/NavItem.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Navigation/NavBar/NavItems.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Navigation/NavBar/NavLink.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Navigation/NavBar/SimpleNav.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Navigation/NavBar/index.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Navigation/TabLinks/TabLink.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Navigation/TabLinks/TabLinkNavigation.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Navigation/TabLinks/TabLinkPanel.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Nested.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/NextSectionLink.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Notifications/Base.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Notifications/Delete.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Notifications/Error.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Notifications/Loading.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Notifications/Success.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Notifications/ToasterNotifications.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/OnlyRenderIfPermissions.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/PagesInChapterBox.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Pagination.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/PaginationItemsPerPage.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/PeerReview/LikertScale.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/PeerReview/Option.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/PeerReview/PeerReviewProgress.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/PeerReview/Review.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Quote.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Reference.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/SelectMenu.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/SkipLink.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/SpeechBalloon.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Spinner.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Sponsor.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Test.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/TimeComponent.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/Title.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/TopLevelPage.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/TopicObjectives.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/layout/PageMarginOffset.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/monaco/MonacoDiffEditor.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/monaco/MonacoEditor.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/monaco/impl/MonacoDiffEditorImpl.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/monaco/impl/MonacoEditorImpl.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/monaco/impl/loader.ts create mode 100644 services/course-material/src/shared-module-v2/common/components/system-tests/HideChildrenInSystemTests.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/system-tests/HideTextInSystemTests.tsx create mode 100644 services/course-material/src/shared-module-v2/common/components/system-tests/MaskOverThisInSystemTests.tsx create mode 100644 services/course-material/src/shared-module-v2/common/contexts/ExerciseServiceContext.tsx create mode 100644 services/course-material/src/shared-module-v2/common/contexts/IframeHeightContext.tsx create mode 100644 services/course-material/src/shared-module-v2/common/contexts/LoginStateContext.tsx create mode 100644 services/course-material/src/shared-module-v2/common/exercise-service-protocol-types-2.ts create mode 100644 services/course-material/src/shared-module-v2/common/exercise-service-protocol-types.guard.ts create mode 100644 services/course-material/src/shared-module-v2/common/exercise-service-protocol-types.ts create mode 100644 services/course-material/src/shared-module-v2/common/hooks/exerciseServiceHooks/useExerciseServiceOutputState.tsx create mode 100644 services/course-material/src/shared-module-v2/common/hooks/useAuthorizeMultiple.tsx create mode 100644 services/course-material/src/shared-module-v2/common/hooks/useClickOutside.tsx create mode 100644 services/course-material/src/shared-module-v2/common/hooks/useDateStringAsDate.tsx create mode 100644 services/course-material/src/shared-module-v2/common/hooks/useExerciseServiceParentConnection.tsx create mode 100644 services/course-material/src/shared-module-v2/common/hooks/useLanguage.tsx create mode 100644 services/course-material/src/shared-module-v2/common/hooks/useMedia.ts create mode 100644 services/course-material/src/shared-module-v2/common/hooks/useMessageChannel.tsx create mode 100644 services/course-material/src/shared-module-v2/common/hooks/usePaginationInfo.tsx create mode 100644 services/course-material/src/shared-module-v2/common/hooks/useQueryParameter.ts create mode 100644 services/course-material/src/shared-module-v2/common/hooks/useShouldHideStuffForSystemTestScreenshots.tsx create mode 100644 services/course-material/src/shared-module-v2/common/hooks/useShowToastInfinitely.tsx create mode 100644 services/course-material/src/shared-module-v2/common/hooks/useStateQuery.ts create mode 100644 services/course-material/src/shared-module-v2/common/hooks/useToastMutation.tsx create mode 100644 services/course-material/src/shared-module-v2/common/hooks/useUserInfo.tsx create mode 100644 services/course-material/src/shared-module-v2/common/img/UHBrandLogo.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/accordion-arrow.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/arrow.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/backarrow.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/blackArrow.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/bulleye.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/card-bg-circle.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/card-bg-star.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/card-bg-zigzag.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/card-defualt-bg/circle.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/card-defualt-bg/cross.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/card-defualt-bg/dot-circle.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/card-defualt-bg/equal.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/card-defualt-bg/intersection.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/card-defualt-bg/pixel-square.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/card-defualt-bg/quadruple-circle.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/card-defualt-bg/triangle.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/cardNext.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/caret-arrow-down.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/caret-arrow-left.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/caret-arrow-right.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/caret-arrow-up.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/check.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/checkmark.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/china.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/close.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/cross.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/diamond.png create mode 100644 services/course-material/src/shared-module-v2/common/img/diamond.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/exist-icon.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/external-link.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/flags/Austria.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/flags/Belgium.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/flags/Bulgaria.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/flags/Croatia.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/flags/Czech.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/flags/Denmark.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/flags/Estonia.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/flags/Finland.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/flags/France.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/flags/Germany.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/flags/Greece.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/flags/Ireland.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/flags/Italy.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/flags/Latvia.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/flags/Lithuania.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/flags/Netherlands.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/flags/Norway.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/flags/Poland.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/flags/Portugal.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/flags/Romania.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/flags/Slovenia.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/flags/Spain.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/flags/Sweden.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/flags/USA.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/flags/United_Kingdom.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/hero-default-bg-image.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/likert/agree.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/likert/disagree.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/likert/neutral.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/likert/stronglyAgree.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/likert/stronglyDisagree.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/lock.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/moocfiLogo.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/next.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/quote.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/score.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/screwedArrow.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/setting.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/swoosh.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/tick-03.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/tick.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/uh_without_background.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/unitedStates.svg create mode 100644 services/course-material/src/shared-module-v2/common/img/up-arrow.svg create mode 100644 services/course-material/src/shared-module-v2/common/locales/en/cms.json create mode 100644 services/course-material/src/shared-module-v2/common/locales/en/course-material.json create mode 100644 services/course-material/src/shared-module-v2/common/locales/en/example-exercise.json create mode 100644 services/course-material/src/shared-module-v2/common/locales/en/main-frontend.json create mode 100644 services/course-material/src/shared-module-v2/common/locales/en/quizzes.json create mode 100644 services/course-material/src/shared-module-v2/common/locales/en/shared-module.json create mode 100644 services/course-material/src/shared-module-v2/common/locales/en/tmc.json create mode 100644 services/course-material/src/shared-module-v2/common/locales/fi/cms.json create mode 100644 services/course-material/src/shared-module-v2/common/locales/fi/course-material.json create mode 100644 services/course-material/src/shared-module-v2/common/locales/fi/example-exercise.json create mode 100644 services/course-material/src/shared-module-v2/common/locales/fi/main-frontend.json create mode 100644 services/course-material/src/shared-module-v2/common/locales/fi/quizzes.json create mode 100644 services/course-material/src/shared-module-v2/common/locales/fi/shared-module.json create mode 100644 services/course-material/src/shared-module-v2/common/locales/fi/tmc.json create mode 100644 services/course-material/src/shared-module-v2/common/services/appQueryClient.ts create mode 100644 services/course-material/src/shared-module-v2/common/services/backend/auth.ts create mode 100644 services/course-material/src/shared-module-v2/common/services/backend/files.ts create mode 100644 services/course-material/src/shared-module-v2/common/styles/GlobalStyles.tsx create mode 100644 services/course-material/src/shared-module-v2/common/styles/constants.ts create mode 100644 services/course-material/src/shared-module-v2/common/styles/cssReset.ts create mode 100644 services/course-material/src/shared-module-v2/common/styles/index.ts create mode 100644 services/course-material/src/shared-module-v2/common/styles/monacoFontFixer.ts create mode 100644 services/course-material/src/shared-module-v2/common/styles/muiTheme.ts create mode 100644 services/course-material/src/shared-module-v2/common/styles/respond.ts create mode 100644 services/course-material/src/shared-module-v2/common/styles/theme.ts create mode 100644 services/course-material/src/shared-module-v2/common/styles/typography.ts create mode 100644 services/course-material/src/shared-module-v2/common/types/imageTypes.d.ts create mode 100644 services/course-material/src/shared-module-v2/common/utils/accessibility.ts create mode 100644 services/course-material/src/shared-module-v2/common/utils/base-path.ts create mode 100644 services/course-material/src/shared-module-v2/common/utils/constants.ts create mode 100644 services/course-material/src/shared-module-v2/common/utils/cookies.ts create mode 100644 services/course-material/src/shared-module-v2/common/utils/cross-routing.ts create mode 100644 services/course-material/src/shared-module-v2/common/utils/dateUtil.ts create mode 100644 services/course-material/src/shared-module-v2/common/utils/dom.ts create mode 100644 services/course-material/src/shared-module-v2/common/utils/dontRenderUntilQueryParametersReady.tsx create mode 100644 services/course-material/src/shared-module-v2/common/utils/exerciseServices.ts create mode 100644 services/course-material/src/shared-module-v2/common/utils/fetching.ts create mode 100644 services/course-material/src/shared-module-v2/common/utils/files.ts create mode 100644 services/course-material/src/shared-module-v2/common/utils/generateWebVitalsReporter.ts create mode 100644 services/course-material/src/shared-module-v2/common/utils/getGuestPseudonymousUserId.ts create mode 100644 services/course-material/src/shared-module-v2/common/utils/i18next-parser.config.template.js create mode 100644 services/course-material/src/shared-module-v2/common/utils/ietfLanguageTagToHumanReadableName.ts create mode 100644 services/course-material/src/shared-module-v2/common/utils/initI18n.ts create mode 100644 services/course-material/src/shared-module-v2/common/utils/nullability.ts create mode 100644 services/course-material/src/shared-module-v2/common/utils/numbers.ts create mode 100644 services/course-material/src/shared-module-v2/common/utils/redirectBackAfterLoginOrSignup.tsx create mode 100644 services/course-material/src/shared-module-v2/common/utils/responseHeaders.js create mode 100644 services/course-material/src/shared-module-v2/common/utils/routes.ts create mode 100644 services/course-material/src/shared-module-v2/common/utils/strings.ts create mode 100644 services/course-material/src/shared-module-v2/common/utils/styles.ts create mode 100644 services/course-material/src/shared-module-v2/common/utils/svgoConfig.js create mode 100644 services/course-material/src/shared-module-v2/common/utils/testing/i18nTest.ts create mode 100644 services/course-material/src/shared-module-v2/common/utils/testing/replaceUuidsWithPlaceholders.ts create mode 100644 services/course-material/src/shared-module-v2/common/utils/time.ts create mode 100644 services/course-material/src/shared-module-v2/common/utils/typeMappter.ts create mode 100644 services/course-material/src/shared-module-v2/common/utils/urlManipulation.ts create mode 100644 services/course-material/src/shared-module-v2/common/utils/validation.ts create mode 100644 services/course-material/src/shared-module-v2/common/utils/withErrorBoundary.tsx create mode 100644 services/course-material/src/shared-module-v2/common/utils/withNoSsr.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/bindings.guard.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/bindings.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Accordion/DetailAccordion.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Accordion/index.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Banner/Banner.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Banner/ContributeBanner.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Banner/ReadOnlyBanner.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/BooleanAsText.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Breadcrumbs.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Button.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Card/CardOpenTextOverlay.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Card/CardOpensText.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Card/IllustrationCard.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Card/SimpleCard.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Card/index.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Centering/BreakFromCentered.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Centering/Centered.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/CircularProgressBar.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/CourseProgress/CircularProgress.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/CourseProgress/ProgressBar.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/CourseProgress/index.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/DebugModal.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Dialog.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/DiffFormatter.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/DropdownMenu/DropdownMenuItem.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/DropdownMenu/index.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/ErrorBanner.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/ExerciseList/ExerciseBox.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/ExerciseList/PageBox.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/FloatingErrorBox.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Footer.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Forum/Forum.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Forum/SideNavigation.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Forum/Thread.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Forum/Threads.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/GenericInfobox.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/HeightTrackingContainer.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/InputFields/CheckBox.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/InputFields/CheckboxFieldWrapper.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/InputFields/DatePickerField.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/InputFields/DateTimeLocal.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/InputFields/EditableComponentTextArea.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/InputFields/FileField.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/InputFields/RadioButton.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/InputFields/SelectField.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/InputFields/TextAreaField.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/InputFields/TextField.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/InputFields/TimePickerField.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/LanguageSelection/Language.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/LanguageSelection/LanguageMenu.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/LanguageSelection/LanguageOption.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/LanguageSelection/index.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/LinkOrNoLink.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/LoginControls.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/MessageChannelIFrame.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Navigation/NavBar/ComplexNav.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Navigation/NavBar/Menu/Hamburger/Hamburger.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Navigation/NavBar/Menu/Hamburger/HamburgerSpring.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Navigation/NavBar/Menu/Menu.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Navigation/NavBar/Menu/MenuItem.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Navigation/NavBar/NavContainer.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Navigation/NavBar/NavItem.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Navigation/NavBar/NavItems.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Navigation/NavBar/NavLink.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Navigation/NavBar/SimpleNav.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Navigation/NavBar/index.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Navigation/TabLinks/TabLink.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Navigation/TabLinks/TabLinkNavigation.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Navigation/TabLinks/TabLinkPanel.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Nested.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/NextSectionLink.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Notifications/Base.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Notifications/Delete.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Notifications/Error.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Notifications/Loading.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Notifications/Success.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Notifications/ToasterNotifications.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/OnlyRenderIfPermissions.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/PagesInChapterBox.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Pagination.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/PaginationItemsPerPage.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/PeerReview/LikertScale.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/PeerReview/Option.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/PeerReview/PeerReviewProgress.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/PeerReview/Review.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Quote.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Reference.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/SelectMenu.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/SkipLink.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/SpeechBalloon.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Spinner.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Sponsor.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Test.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/TimeComponent.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/Title.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/TopLevelPage.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/TopicObjectives.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/layout/PageMarginOffset.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/monaco/MonacoDiffEditor.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/monaco/MonacoEditor.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/monaco/impl/MonacoDiffEditorImpl.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/monaco/impl/MonacoEditorImpl.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/monaco/impl/loader.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/components/system-tests/HideChildrenInSystemTests.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/system-tests/HideTextInSystemTests.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/components/system-tests/MaskOverThisInSystemTests.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/contexts/ExerciseServiceContext.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/contexts/IframeHeightContext.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/contexts/LoginStateContext.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/exercise-service-protocol-types-2.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/exercise-service-protocol-types.guard.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/exercise-service-protocol-types.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/hooks/exerciseServiceHooks/useExerciseServiceOutputState.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/hooks/useAuthorizeMultiple.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/hooks/useClickOutside.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/hooks/useDateStringAsDate.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/hooks/useExerciseServiceParentConnection.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/hooks/useLanguage.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/hooks/useMedia.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/hooks/useMessageChannel.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/hooks/usePaginationInfo.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/hooks/useQueryParameter.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/hooks/useShouldHideStuffForSystemTestScreenshots.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/hooks/useShowToastInfinitely.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/hooks/useStateQuery.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/hooks/useToastMutation.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/hooks/useUserInfo.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/img/UHBrandLogo.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/accordion-arrow.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/arrow.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/backarrow.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/blackArrow.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/bulleye.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/card-bg-circle.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/card-bg-star.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/card-bg-zigzag.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/card-defualt-bg/circle.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/card-defualt-bg/cross.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/card-defualt-bg/dot-circle.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/card-defualt-bg/equal.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/card-defualt-bg/intersection.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/card-defualt-bg/pixel-square.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/card-defualt-bg/quadruple-circle.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/card-defualt-bg/triangle.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/cardNext.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/caret-arrow-down.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/caret-arrow-left.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/caret-arrow-right.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/caret-arrow-up.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/check.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/checkmark.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/china.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/close.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/cross.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/diamond.png create mode 100644 services/example-exercise/src/shared-module-v2/common/img/diamond.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/exist-icon.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/external-link.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/flags/Austria.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/flags/Belgium.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/flags/Bulgaria.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/flags/Croatia.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/flags/Czech.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/flags/Denmark.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/flags/Estonia.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/flags/Finland.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/flags/France.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/flags/Germany.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/flags/Greece.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/flags/Ireland.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/flags/Italy.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/flags/Latvia.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/flags/Lithuania.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/flags/Netherlands.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/flags/Norway.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/flags/Poland.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/flags/Portugal.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/flags/Romania.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/flags/Slovenia.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/flags/Spain.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/flags/Sweden.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/flags/USA.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/flags/United_Kingdom.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/hero-default-bg-image.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/likert/agree.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/likert/disagree.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/likert/neutral.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/likert/stronglyAgree.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/likert/stronglyDisagree.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/lock.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/moocfiLogo.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/next.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/quote.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/score.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/screwedArrow.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/setting.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/swoosh.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/tick-03.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/tick.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/uh_without_background.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/unitedStates.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/img/up-arrow.svg create mode 100644 services/example-exercise/src/shared-module-v2/common/locales/en/cms.json create mode 100644 services/example-exercise/src/shared-module-v2/common/locales/en/course-material.json create mode 100644 services/example-exercise/src/shared-module-v2/common/locales/en/example-exercise.json create mode 100644 services/example-exercise/src/shared-module-v2/common/locales/en/main-frontend.json create mode 100644 services/example-exercise/src/shared-module-v2/common/locales/en/quizzes.json create mode 100644 services/example-exercise/src/shared-module-v2/common/locales/en/shared-module.json create mode 100644 services/example-exercise/src/shared-module-v2/common/locales/en/tmc.json create mode 100644 services/example-exercise/src/shared-module-v2/common/locales/fi/cms.json create mode 100644 services/example-exercise/src/shared-module-v2/common/locales/fi/course-material.json create mode 100644 services/example-exercise/src/shared-module-v2/common/locales/fi/example-exercise.json create mode 100644 services/example-exercise/src/shared-module-v2/common/locales/fi/main-frontend.json create mode 100644 services/example-exercise/src/shared-module-v2/common/locales/fi/quizzes.json create mode 100644 services/example-exercise/src/shared-module-v2/common/locales/fi/shared-module.json create mode 100644 services/example-exercise/src/shared-module-v2/common/locales/fi/tmc.json create mode 100644 services/example-exercise/src/shared-module-v2/common/services/appQueryClient.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/services/backend/auth.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/services/backend/files.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/styles/GlobalStyles.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/styles/constants.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/styles/cssReset.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/styles/index.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/styles/monacoFontFixer.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/styles/muiTheme.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/styles/respond.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/styles/theme.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/styles/typography.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/types/imageTypes.d.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/utils/accessibility.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/utils/base-path.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/utils/constants.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/utils/cookies.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/utils/cross-routing.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/utils/dateUtil.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/utils/dom.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/utils/dontRenderUntilQueryParametersReady.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/utils/exerciseServices.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/utils/fetching.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/utils/files.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/utils/generateWebVitalsReporter.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/utils/getGuestPseudonymousUserId.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/utils/i18next-parser.config.template.js create mode 100644 services/example-exercise/src/shared-module-v2/common/utils/ietfLanguageTagToHumanReadableName.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/utils/initI18n.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/utils/nullability.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/utils/numbers.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/utils/redirectBackAfterLoginOrSignup.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/utils/responseHeaders.js create mode 100644 services/example-exercise/src/shared-module-v2/common/utils/routes.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/utils/strings.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/utils/styles.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/utils/svgoConfig.js create mode 100644 services/example-exercise/src/shared-module-v2/common/utils/testing/i18nTest.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/utils/testing/replaceUuidsWithPlaceholders.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/utils/time.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/utils/typeMappter.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/utils/urlManipulation.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/utils/validation.ts create mode 100644 services/example-exercise/src/shared-module-v2/common/utils/withErrorBoundary.tsx create mode 100644 services/example-exercise/src/shared-module-v2/common/utils/withNoSsr.tsx create mode 100644 services/headless-lms/shared-module-v2/common/bindings.guard.ts create mode 100644 services/headless-lms/shared-module-v2/common/bindings.ts create mode 100644 services/headless-lms/shared-module-v2/common/components/Accordion/DetailAccordion.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Accordion/index.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Banner/Banner.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Banner/ContributeBanner.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Banner/ReadOnlyBanner.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/BooleanAsText.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Breadcrumbs.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Button.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Card/CardOpenTextOverlay.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Card/CardOpensText.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Card/IllustrationCard.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Card/SimpleCard.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Card/index.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Centering/BreakFromCentered.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Centering/Centered.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/CircularProgressBar.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/CourseProgress/CircularProgress.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/CourseProgress/ProgressBar.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/CourseProgress/index.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/DebugModal.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Dialog.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/DiffFormatter.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/DropdownMenu/DropdownMenuItem.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/DropdownMenu/index.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/ErrorBanner.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/ExerciseList/ExerciseBox.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/ExerciseList/PageBox.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/FloatingErrorBox.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Footer.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Forum/Forum.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Forum/SideNavigation.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Forum/Thread.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Forum/Threads.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/GenericInfobox.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/HeightTrackingContainer.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/InputFields/CheckBox.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/InputFields/CheckboxFieldWrapper.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/InputFields/DatePickerField.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/InputFields/DateTimeLocal.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/InputFields/EditableComponentTextArea.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/InputFields/FileField.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/InputFields/RadioButton.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/InputFields/SelectField.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/InputFields/TextAreaField.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/InputFields/TextField.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/InputFields/TimePickerField.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/LanguageSelection/Language.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/LanguageSelection/LanguageMenu.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/LanguageSelection/LanguageOption.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/LanguageSelection/index.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/LinkOrNoLink.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/LoginControls.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/MessageChannelIFrame.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Navigation/NavBar/ComplexNav.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Navigation/NavBar/Menu/Hamburger/Hamburger.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Navigation/NavBar/Menu/Hamburger/HamburgerSpring.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Navigation/NavBar/Menu/Menu.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Navigation/NavBar/Menu/MenuItem.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Navigation/NavBar/NavContainer.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Navigation/NavBar/NavItem.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Navigation/NavBar/NavItems.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Navigation/NavBar/NavLink.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Navigation/NavBar/SimpleNav.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Navigation/NavBar/index.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Navigation/TabLinks/TabLink.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Navigation/TabLinks/TabLinkNavigation.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Navigation/TabLinks/TabLinkPanel.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Nested.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/NextSectionLink.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Notifications/Base.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Notifications/Delete.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Notifications/Error.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Notifications/Loading.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Notifications/Success.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Notifications/ToasterNotifications.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/OnlyRenderIfPermissions.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/PagesInChapterBox.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Pagination.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/PaginationItemsPerPage.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/PeerReview/LikertScale.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/PeerReview/Option.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/PeerReview/PeerReviewProgress.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/PeerReview/Review.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Quote.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Reference.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/SelectMenu.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/SkipLink.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/SpeechBalloon.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Spinner.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Sponsor.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Test.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/TimeComponent.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/Title.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/TopLevelPage.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/TopicObjectives.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/layout/PageMarginOffset.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/monaco/MonacoDiffEditor.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/monaco/MonacoEditor.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/monaco/impl/MonacoDiffEditorImpl.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/monaco/impl/MonacoEditorImpl.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/monaco/impl/loader.ts create mode 100644 services/headless-lms/shared-module-v2/common/components/system-tests/HideChildrenInSystemTests.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/system-tests/HideTextInSystemTests.tsx create mode 100644 services/headless-lms/shared-module-v2/common/components/system-tests/MaskOverThisInSystemTests.tsx create mode 100644 services/headless-lms/shared-module-v2/common/contexts/ExerciseServiceContext.tsx create mode 100644 services/headless-lms/shared-module-v2/common/contexts/IframeHeightContext.tsx create mode 100644 services/headless-lms/shared-module-v2/common/contexts/LoginStateContext.tsx create mode 100644 services/headless-lms/shared-module-v2/common/exercise-service-protocol-types-2.ts create mode 100644 services/headless-lms/shared-module-v2/common/exercise-service-protocol-types.guard.ts create mode 100644 services/headless-lms/shared-module-v2/common/exercise-service-protocol-types.ts create mode 100644 services/headless-lms/shared-module-v2/common/hooks/exerciseServiceHooks/useExerciseServiceOutputState.tsx create mode 100644 services/headless-lms/shared-module-v2/common/hooks/useAuthorizeMultiple.tsx create mode 100644 services/headless-lms/shared-module-v2/common/hooks/useClickOutside.tsx create mode 100644 services/headless-lms/shared-module-v2/common/hooks/useDateStringAsDate.tsx create mode 100644 services/headless-lms/shared-module-v2/common/hooks/useExerciseServiceParentConnection.tsx create mode 100644 services/headless-lms/shared-module-v2/common/hooks/useLanguage.tsx create mode 100644 services/headless-lms/shared-module-v2/common/hooks/useMedia.ts create mode 100644 services/headless-lms/shared-module-v2/common/hooks/useMessageChannel.tsx create mode 100644 services/headless-lms/shared-module-v2/common/hooks/usePaginationInfo.tsx create mode 100644 services/headless-lms/shared-module-v2/common/hooks/useQueryParameter.ts create mode 100644 services/headless-lms/shared-module-v2/common/hooks/useShouldHideStuffForSystemTestScreenshots.tsx create mode 100644 services/headless-lms/shared-module-v2/common/hooks/useShowToastInfinitely.tsx create mode 100644 services/headless-lms/shared-module-v2/common/hooks/useStateQuery.ts create mode 100644 services/headless-lms/shared-module-v2/common/hooks/useToastMutation.tsx create mode 100644 services/headless-lms/shared-module-v2/common/hooks/useUserInfo.tsx create mode 100644 services/headless-lms/shared-module-v2/common/img/UHBrandLogo.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/accordion-arrow.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/arrow.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/backarrow.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/blackArrow.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/bulleye.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/card-bg-circle.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/card-bg-star.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/card-bg-zigzag.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/card-defualt-bg/circle.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/card-defualt-bg/cross.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/card-defualt-bg/dot-circle.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/card-defualt-bg/equal.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/card-defualt-bg/intersection.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/card-defualt-bg/pixel-square.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/card-defualt-bg/quadruple-circle.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/card-defualt-bg/triangle.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/cardNext.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/caret-arrow-down.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/caret-arrow-left.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/caret-arrow-right.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/caret-arrow-up.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/check.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/checkmark.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/china.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/close.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/cross.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/diamond.png create mode 100644 services/headless-lms/shared-module-v2/common/img/diamond.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/exist-icon.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/external-link.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/flags/Austria.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/flags/Belgium.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/flags/Bulgaria.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/flags/Croatia.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/flags/Czech.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/flags/Denmark.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/flags/Estonia.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/flags/Finland.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/flags/France.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/flags/Germany.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/flags/Greece.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/flags/Ireland.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/flags/Italy.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/flags/Latvia.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/flags/Lithuania.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/flags/Netherlands.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/flags/Norway.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/flags/Poland.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/flags/Portugal.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/flags/Romania.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/flags/Slovenia.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/flags/Spain.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/flags/Sweden.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/flags/USA.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/flags/United_Kingdom.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/hero-default-bg-image.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/likert/agree.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/likert/disagree.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/likert/neutral.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/likert/stronglyAgree.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/likert/stronglyDisagree.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/lock.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/moocfiLogo.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/next.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/quote.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/score.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/screwedArrow.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/setting.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/swoosh.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/tick-03.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/tick.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/uh_without_background.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/unitedStates.svg create mode 100644 services/headless-lms/shared-module-v2/common/img/up-arrow.svg create mode 100644 services/headless-lms/shared-module-v2/common/locales/en/cms.json create mode 100644 services/headless-lms/shared-module-v2/common/locales/en/course-material.json create mode 100644 services/headless-lms/shared-module-v2/common/locales/en/example-exercise.json create mode 100644 services/headless-lms/shared-module-v2/common/locales/en/main-frontend.json create mode 100644 services/headless-lms/shared-module-v2/common/locales/en/quizzes.json create mode 100644 services/headless-lms/shared-module-v2/common/locales/en/shared-module.json create mode 100644 services/headless-lms/shared-module-v2/common/locales/en/tmc.json create mode 100644 services/headless-lms/shared-module-v2/common/locales/fi/cms.json create mode 100644 services/headless-lms/shared-module-v2/common/locales/fi/course-material.json create mode 100644 services/headless-lms/shared-module-v2/common/locales/fi/example-exercise.json create mode 100644 services/headless-lms/shared-module-v2/common/locales/fi/main-frontend.json create mode 100644 services/headless-lms/shared-module-v2/common/locales/fi/quizzes.json create mode 100644 services/headless-lms/shared-module-v2/common/locales/fi/shared-module.json create mode 100644 services/headless-lms/shared-module-v2/common/locales/fi/tmc.json create mode 100644 services/headless-lms/shared-module-v2/common/services/appQueryClient.ts create mode 100644 services/headless-lms/shared-module-v2/common/services/backend/auth.ts create mode 100644 services/headless-lms/shared-module-v2/common/services/backend/files.ts create mode 100644 services/headless-lms/shared-module-v2/common/styles/GlobalStyles.tsx create mode 100644 services/headless-lms/shared-module-v2/common/styles/constants.ts create mode 100644 services/headless-lms/shared-module-v2/common/styles/cssReset.ts create mode 100644 services/headless-lms/shared-module-v2/common/styles/index.ts create mode 100644 services/headless-lms/shared-module-v2/common/styles/monacoFontFixer.ts create mode 100644 services/headless-lms/shared-module-v2/common/styles/muiTheme.ts create mode 100644 services/headless-lms/shared-module-v2/common/styles/respond.ts create mode 100644 services/headless-lms/shared-module-v2/common/styles/theme.ts create mode 100644 services/headless-lms/shared-module-v2/common/styles/typography.ts create mode 100644 services/headless-lms/shared-module-v2/common/types/imageTypes.d.ts create mode 100644 services/headless-lms/shared-module-v2/common/utils/accessibility.ts create mode 100644 services/headless-lms/shared-module-v2/common/utils/base-path.ts create mode 100644 services/headless-lms/shared-module-v2/common/utils/constants.ts create mode 100644 services/headless-lms/shared-module-v2/common/utils/cookies.ts create mode 100644 services/headless-lms/shared-module-v2/common/utils/cross-routing.ts create mode 100644 services/headless-lms/shared-module-v2/common/utils/dateUtil.ts create mode 100644 services/headless-lms/shared-module-v2/common/utils/dom.ts create mode 100644 services/headless-lms/shared-module-v2/common/utils/dontRenderUntilQueryParametersReady.tsx create mode 100644 services/headless-lms/shared-module-v2/common/utils/exerciseServices.ts create mode 100644 services/headless-lms/shared-module-v2/common/utils/fetching.ts create mode 100644 services/headless-lms/shared-module-v2/common/utils/files.ts create mode 100644 services/headless-lms/shared-module-v2/common/utils/generateWebVitalsReporter.ts create mode 100644 services/headless-lms/shared-module-v2/common/utils/getGuestPseudonymousUserId.ts create mode 100644 services/headless-lms/shared-module-v2/common/utils/i18next-parser.config.template.js create mode 100644 services/headless-lms/shared-module-v2/common/utils/ietfLanguageTagToHumanReadableName.ts create mode 100644 services/headless-lms/shared-module-v2/common/utils/initI18n.ts create mode 100644 services/headless-lms/shared-module-v2/common/utils/nullability.ts create mode 100644 services/headless-lms/shared-module-v2/common/utils/numbers.ts create mode 100644 services/headless-lms/shared-module-v2/common/utils/redirectBackAfterLoginOrSignup.tsx create mode 100644 services/headless-lms/shared-module-v2/common/utils/responseHeaders.js create mode 100644 services/headless-lms/shared-module-v2/common/utils/routes.ts create mode 100644 services/headless-lms/shared-module-v2/common/utils/strings.ts create mode 100644 services/headless-lms/shared-module-v2/common/utils/styles.ts create mode 100644 services/headless-lms/shared-module-v2/common/utils/svgoConfig.js create mode 100644 services/headless-lms/shared-module-v2/common/utils/testing/i18nTest.ts create mode 100644 services/headless-lms/shared-module-v2/common/utils/testing/replaceUuidsWithPlaceholders.ts create mode 100644 services/headless-lms/shared-module-v2/common/utils/time.ts create mode 100644 services/headless-lms/shared-module-v2/common/utils/typeMappter.ts create mode 100644 services/headless-lms/shared-module-v2/common/utils/urlManipulation.ts create mode 100644 services/headless-lms/shared-module-v2/common/utils/validation.ts create mode 100644 services/headless-lms/shared-module-v2/common/utils/withErrorBoundary.tsx create mode 100644 services/headless-lms/shared-module-v2/common/utils/withNoSsr.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/bindings.guard.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/bindings.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Accordion/DetailAccordion.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Accordion/index.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Banner/Banner.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Banner/ContributeBanner.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Banner/ReadOnlyBanner.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/BooleanAsText.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Breadcrumbs.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Button.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Card/CardOpenTextOverlay.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Card/CardOpensText.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Card/IllustrationCard.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Card/SimpleCard.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Card/index.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Centering/BreakFromCentered.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Centering/Centered.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/CircularProgressBar.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/CourseProgress/CircularProgress.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/CourseProgress/ProgressBar.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/CourseProgress/index.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/DebugModal.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Dialog.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/DiffFormatter.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/DropdownMenu/DropdownMenuItem.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/DropdownMenu/index.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/ErrorBanner.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/ExerciseList/ExerciseBox.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/ExerciseList/PageBox.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/FloatingErrorBox.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Footer.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Forum/Forum.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Forum/SideNavigation.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Forum/Thread.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Forum/Threads.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/GenericInfobox.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/HeightTrackingContainer.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/InputFields/CheckBox.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/InputFields/CheckboxFieldWrapper.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/InputFields/DatePickerField.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/InputFields/DateTimeLocal.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/InputFields/EditableComponentTextArea.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/InputFields/FileField.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/InputFields/RadioButton.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/InputFields/SelectField.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/InputFields/TextAreaField.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/InputFields/TextField.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/InputFields/TimePickerField.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/LanguageSelection/Language.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/LanguageSelection/LanguageMenu.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/LanguageSelection/LanguageOption.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/LanguageSelection/index.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/LinkOrNoLink.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/LoginControls.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/MessageChannelIFrame.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Navigation/NavBar/ComplexNav.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Navigation/NavBar/Menu/Hamburger/Hamburger.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Navigation/NavBar/Menu/Hamburger/HamburgerSpring.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Navigation/NavBar/Menu/Menu.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Navigation/NavBar/Menu/MenuItem.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Navigation/NavBar/NavContainer.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Navigation/NavBar/NavItem.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Navigation/NavBar/NavItems.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Navigation/NavBar/NavLink.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Navigation/NavBar/SimpleNav.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Navigation/NavBar/index.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Navigation/TabLinks/TabLink.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Navigation/TabLinks/TabLinkNavigation.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Navigation/TabLinks/TabLinkPanel.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Nested.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/NextSectionLink.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Notifications/Base.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Notifications/Delete.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Notifications/Error.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Notifications/Loading.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Notifications/Success.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Notifications/ToasterNotifications.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/OnlyRenderIfPermissions.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/PagesInChapterBox.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Pagination.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/PaginationItemsPerPage.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/PeerReview/LikertScale.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/PeerReview/Option.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/PeerReview/PeerReviewProgress.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/PeerReview/Review.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Quote.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Reference.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/SelectMenu.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/SkipLink.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/SpeechBalloon.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Spinner.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Sponsor.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Test.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/TimeComponent.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/Title.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/TopLevelPage.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/TopicObjectives.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/layout/PageMarginOffset.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/monaco/MonacoDiffEditor.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/monaco/MonacoEditor.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/monaco/impl/MonacoDiffEditorImpl.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/monaco/impl/MonacoEditorImpl.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/monaco/impl/loader.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/components/system-tests/HideChildrenInSystemTests.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/system-tests/HideTextInSystemTests.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/components/system-tests/MaskOverThisInSystemTests.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/contexts/ExerciseServiceContext.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/contexts/IframeHeightContext.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/contexts/LoginStateContext.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/exercise-service-protocol-types-2.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/exercise-service-protocol-types.guard.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/exercise-service-protocol-types.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/hooks/exerciseServiceHooks/useExerciseServiceOutputState.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/hooks/useAuthorizeMultiple.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/hooks/useClickOutside.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/hooks/useDateStringAsDate.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/hooks/useExerciseServiceParentConnection.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/hooks/useLanguage.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/hooks/useMedia.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/hooks/useMessageChannel.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/hooks/usePaginationInfo.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/hooks/useQueryParameter.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/hooks/useShouldHideStuffForSystemTestScreenshots.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/hooks/useShowToastInfinitely.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/hooks/useStateQuery.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/hooks/useToastMutation.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/hooks/useUserInfo.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/img/UHBrandLogo.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/accordion-arrow.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/arrow.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/backarrow.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/blackArrow.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/bulleye.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/card-bg-circle.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/card-bg-star.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/card-bg-zigzag.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/card-defualt-bg/circle.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/card-defualt-bg/cross.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/card-defualt-bg/dot-circle.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/card-defualt-bg/equal.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/card-defualt-bg/intersection.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/card-defualt-bg/pixel-square.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/card-defualt-bg/quadruple-circle.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/card-defualt-bg/triangle.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/cardNext.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/caret-arrow-down.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/caret-arrow-left.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/caret-arrow-right.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/caret-arrow-up.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/check.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/checkmark.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/china.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/close.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/cross.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/diamond.png create mode 100644 services/main-frontend/src/shared-module-v2/common/img/diamond.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/exist-icon.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/external-link.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/flags/Austria.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/flags/Belgium.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/flags/Bulgaria.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/flags/Croatia.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/flags/Czech.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/flags/Denmark.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/flags/Estonia.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/flags/Finland.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/flags/France.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/flags/Germany.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/flags/Greece.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/flags/Ireland.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/flags/Italy.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/flags/Latvia.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/flags/Lithuania.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/flags/Netherlands.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/flags/Norway.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/flags/Poland.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/flags/Portugal.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/flags/Romania.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/flags/Slovenia.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/flags/Spain.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/flags/Sweden.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/flags/USA.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/flags/United_Kingdom.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/hero-default-bg-image.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/likert/agree.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/likert/disagree.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/likert/neutral.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/likert/stronglyAgree.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/likert/stronglyDisagree.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/lock.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/moocfiLogo.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/next.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/quote.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/score.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/screwedArrow.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/setting.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/swoosh.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/tick-03.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/tick.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/uh_without_background.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/unitedStates.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/img/up-arrow.svg create mode 100644 services/main-frontend/src/shared-module-v2/common/locales/en/cms.json create mode 100644 services/main-frontend/src/shared-module-v2/common/locales/en/course-material.json create mode 100644 services/main-frontend/src/shared-module-v2/common/locales/en/example-exercise.json create mode 100644 services/main-frontend/src/shared-module-v2/common/locales/en/main-frontend.json create mode 100644 services/main-frontend/src/shared-module-v2/common/locales/en/quizzes.json create mode 100644 services/main-frontend/src/shared-module-v2/common/locales/en/shared-module.json create mode 100644 services/main-frontend/src/shared-module-v2/common/locales/en/tmc.json create mode 100644 services/main-frontend/src/shared-module-v2/common/locales/fi/cms.json create mode 100644 services/main-frontend/src/shared-module-v2/common/locales/fi/course-material.json create mode 100644 services/main-frontend/src/shared-module-v2/common/locales/fi/example-exercise.json create mode 100644 services/main-frontend/src/shared-module-v2/common/locales/fi/main-frontend.json create mode 100644 services/main-frontend/src/shared-module-v2/common/locales/fi/quizzes.json create mode 100644 services/main-frontend/src/shared-module-v2/common/locales/fi/shared-module.json create mode 100644 services/main-frontend/src/shared-module-v2/common/locales/fi/tmc.json create mode 100644 services/main-frontend/src/shared-module-v2/common/services/appQueryClient.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/services/backend/auth.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/services/backend/files.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/styles/GlobalStyles.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/styles/constants.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/styles/cssReset.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/styles/index.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/styles/monacoFontFixer.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/styles/muiTheme.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/styles/respond.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/styles/theme.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/styles/typography.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/types/imageTypes.d.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/utils/accessibility.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/utils/base-path.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/utils/constants.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/utils/cookies.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/utils/cross-routing.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/utils/dateUtil.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/utils/dom.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/utils/dontRenderUntilQueryParametersReady.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/utils/exerciseServices.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/utils/fetching.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/utils/files.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/utils/generateWebVitalsReporter.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/utils/getGuestPseudonymousUserId.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/utils/i18next-parser.config.template.js create mode 100644 services/main-frontend/src/shared-module-v2/common/utils/ietfLanguageTagToHumanReadableName.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/utils/initI18n.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/utils/nullability.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/utils/numbers.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/utils/redirectBackAfterLoginOrSignup.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/utils/responseHeaders.js create mode 100644 services/main-frontend/src/shared-module-v2/common/utils/routes.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/utils/strings.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/utils/styles.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/utils/svgoConfig.js create mode 100644 services/main-frontend/src/shared-module-v2/common/utils/testing/i18nTest.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/utils/testing/replaceUuidsWithPlaceholders.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/utils/time.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/utils/typeMappter.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/utils/urlManipulation.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/utils/validation.ts create mode 100644 services/main-frontend/src/shared-module-v2/common/utils/withErrorBoundary.tsx create mode 100644 services/main-frontend/src/shared-module-v2/common/utils/withNoSsr.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/bindings.guard.ts create mode 100644 services/quizzes/src/shared-module-v2/common/bindings.ts create mode 100644 services/quizzes/src/shared-module-v2/common/components/Accordion/DetailAccordion.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Accordion/index.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Banner/Banner.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Banner/ContributeBanner.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Banner/ReadOnlyBanner.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/BooleanAsText.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Breadcrumbs.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Button.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Card/CardOpenTextOverlay.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Card/CardOpensText.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Card/IllustrationCard.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Card/SimpleCard.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Card/index.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Centering/BreakFromCentered.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Centering/Centered.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/CircularProgressBar.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/CourseProgress/CircularProgress.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/CourseProgress/ProgressBar.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/CourseProgress/index.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/DebugModal.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Dialog.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/DiffFormatter.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/DropdownMenu/DropdownMenuItem.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/DropdownMenu/index.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/ErrorBanner.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/ExerciseList/ExerciseBox.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/ExerciseList/PageBox.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/FloatingErrorBox.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Footer.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Forum/Forum.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Forum/SideNavigation.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Forum/Thread.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Forum/Threads.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/GenericInfobox.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/HeightTrackingContainer.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/InputFields/CheckBox.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/InputFields/CheckboxFieldWrapper.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/InputFields/DatePickerField.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/InputFields/DateTimeLocal.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/InputFields/EditableComponentTextArea.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/InputFields/FileField.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/InputFields/RadioButton.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/InputFields/SelectField.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/InputFields/TextAreaField.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/InputFields/TextField.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/InputFields/TimePickerField.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/LanguageSelection/Language.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/LanguageSelection/LanguageMenu.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/LanguageSelection/LanguageOption.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/LanguageSelection/index.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/LinkOrNoLink.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/LoginControls.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/MessageChannelIFrame.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Navigation/NavBar/ComplexNav.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Navigation/NavBar/Menu/Hamburger/Hamburger.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Navigation/NavBar/Menu/Hamburger/HamburgerSpring.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Navigation/NavBar/Menu/Menu.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Navigation/NavBar/Menu/MenuItem.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Navigation/NavBar/NavContainer.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Navigation/NavBar/NavItem.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Navigation/NavBar/NavItems.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Navigation/NavBar/NavLink.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Navigation/NavBar/SimpleNav.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Navigation/NavBar/index.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Navigation/TabLinks/TabLink.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Navigation/TabLinks/TabLinkNavigation.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Navigation/TabLinks/TabLinkPanel.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Nested.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/NextSectionLink.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Notifications/Base.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Notifications/Delete.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Notifications/Error.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Notifications/Loading.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Notifications/Success.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Notifications/ToasterNotifications.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/OnlyRenderIfPermissions.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/PagesInChapterBox.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Pagination.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/PaginationItemsPerPage.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/PeerReview/LikertScale.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/PeerReview/Option.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/PeerReview/PeerReviewProgress.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/PeerReview/Review.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Quote.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Reference.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/SelectMenu.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/SkipLink.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/SpeechBalloon.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Spinner.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Sponsor.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Test.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/TimeComponent.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/Title.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/TopLevelPage.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/TopicObjectives.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/layout/PageMarginOffset.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/monaco/MonacoDiffEditor.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/monaco/MonacoEditor.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/monaco/impl/MonacoDiffEditorImpl.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/monaco/impl/MonacoEditorImpl.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/monaco/impl/loader.ts create mode 100644 services/quizzes/src/shared-module-v2/common/components/system-tests/HideChildrenInSystemTests.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/system-tests/HideTextInSystemTests.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/components/system-tests/MaskOverThisInSystemTests.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/contexts/ExerciseServiceContext.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/contexts/IframeHeightContext.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/contexts/LoginStateContext.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/exercise-service-protocol-types-2.ts create mode 100644 services/quizzes/src/shared-module-v2/common/exercise-service-protocol-types.guard.ts create mode 100644 services/quizzes/src/shared-module-v2/common/exercise-service-protocol-types.ts create mode 100644 services/quizzes/src/shared-module-v2/common/hooks/exerciseServiceHooks/useExerciseServiceOutputState.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/hooks/useAuthorizeMultiple.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/hooks/useClickOutside.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/hooks/useDateStringAsDate.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/hooks/useExerciseServiceParentConnection.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/hooks/useLanguage.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/hooks/useMedia.ts create mode 100644 services/quizzes/src/shared-module-v2/common/hooks/useMessageChannel.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/hooks/usePaginationInfo.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/hooks/useQueryParameter.ts create mode 100644 services/quizzes/src/shared-module-v2/common/hooks/useShouldHideStuffForSystemTestScreenshots.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/hooks/useShowToastInfinitely.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/hooks/useStateQuery.ts create mode 100644 services/quizzes/src/shared-module-v2/common/hooks/useToastMutation.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/hooks/useUserInfo.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/img/UHBrandLogo.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/accordion-arrow.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/arrow.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/backarrow.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/blackArrow.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/bulleye.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/card-bg-circle.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/card-bg-star.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/card-bg-zigzag.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/card-defualt-bg/circle.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/card-defualt-bg/cross.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/card-defualt-bg/dot-circle.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/card-defualt-bg/equal.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/card-defualt-bg/intersection.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/card-defualt-bg/pixel-square.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/card-defualt-bg/quadruple-circle.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/card-defualt-bg/triangle.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/cardNext.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/caret-arrow-down.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/caret-arrow-left.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/caret-arrow-right.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/caret-arrow-up.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/check.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/checkmark.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/china.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/close.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/cross.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/diamond.png create mode 100644 services/quizzes/src/shared-module-v2/common/img/diamond.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/exist-icon.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/external-link.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/flags/Austria.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/flags/Belgium.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/flags/Bulgaria.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/flags/Croatia.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/flags/Czech.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/flags/Denmark.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/flags/Estonia.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/flags/Finland.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/flags/France.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/flags/Germany.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/flags/Greece.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/flags/Ireland.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/flags/Italy.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/flags/Latvia.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/flags/Lithuania.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/flags/Netherlands.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/flags/Norway.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/flags/Poland.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/flags/Portugal.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/flags/Romania.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/flags/Slovenia.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/flags/Spain.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/flags/Sweden.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/flags/USA.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/flags/United_Kingdom.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/hero-default-bg-image.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/likert/agree.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/likert/disagree.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/likert/neutral.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/likert/stronglyAgree.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/likert/stronglyDisagree.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/lock.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/moocfiLogo.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/next.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/quote.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/score.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/screwedArrow.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/setting.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/swoosh.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/tick-03.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/tick.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/uh_without_background.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/unitedStates.svg create mode 100644 services/quizzes/src/shared-module-v2/common/img/up-arrow.svg create mode 100644 services/quizzes/src/shared-module-v2/common/locales/en/cms.json create mode 100644 services/quizzes/src/shared-module-v2/common/locales/en/course-material.json create mode 100644 services/quizzes/src/shared-module-v2/common/locales/en/example-exercise.json create mode 100644 services/quizzes/src/shared-module-v2/common/locales/en/main-frontend.json create mode 100644 services/quizzes/src/shared-module-v2/common/locales/en/quizzes.json create mode 100644 services/quizzes/src/shared-module-v2/common/locales/en/shared-module.json create mode 100644 services/quizzes/src/shared-module-v2/common/locales/en/tmc.json create mode 100644 services/quizzes/src/shared-module-v2/common/locales/fi/cms.json create mode 100644 services/quizzes/src/shared-module-v2/common/locales/fi/course-material.json create mode 100644 services/quizzes/src/shared-module-v2/common/locales/fi/example-exercise.json create mode 100644 services/quizzes/src/shared-module-v2/common/locales/fi/main-frontend.json create mode 100644 services/quizzes/src/shared-module-v2/common/locales/fi/quizzes.json create mode 100644 services/quizzes/src/shared-module-v2/common/locales/fi/shared-module.json create mode 100644 services/quizzes/src/shared-module-v2/common/locales/fi/tmc.json create mode 100644 services/quizzes/src/shared-module-v2/common/services/appQueryClient.ts create mode 100644 services/quizzes/src/shared-module-v2/common/services/backend/auth.ts create mode 100644 services/quizzes/src/shared-module-v2/common/services/backend/files.ts create mode 100644 services/quizzes/src/shared-module-v2/common/styles/GlobalStyles.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/styles/constants.ts create mode 100644 services/quizzes/src/shared-module-v2/common/styles/cssReset.ts create mode 100644 services/quizzes/src/shared-module-v2/common/styles/index.ts create mode 100644 services/quizzes/src/shared-module-v2/common/styles/monacoFontFixer.ts create mode 100644 services/quizzes/src/shared-module-v2/common/styles/muiTheme.ts create mode 100644 services/quizzes/src/shared-module-v2/common/styles/respond.ts create mode 100644 services/quizzes/src/shared-module-v2/common/styles/theme.ts create mode 100644 services/quizzes/src/shared-module-v2/common/styles/typography.ts create mode 100644 services/quizzes/src/shared-module-v2/common/types/imageTypes.d.ts create mode 100644 services/quizzes/src/shared-module-v2/common/utils/accessibility.ts create mode 100644 services/quizzes/src/shared-module-v2/common/utils/base-path.ts create mode 100644 services/quizzes/src/shared-module-v2/common/utils/constants.ts create mode 100644 services/quizzes/src/shared-module-v2/common/utils/cookies.ts create mode 100644 services/quizzes/src/shared-module-v2/common/utils/cross-routing.ts create mode 100644 services/quizzes/src/shared-module-v2/common/utils/dateUtil.ts create mode 100644 services/quizzes/src/shared-module-v2/common/utils/dom.ts create mode 100644 services/quizzes/src/shared-module-v2/common/utils/dontRenderUntilQueryParametersReady.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/utils/exerciseServices.ts create mode 100644 services/quizzes/src/shared-module-v2/common/utils/fetching.ts create mode 100644 services/quizzes/src/shared-module-v2/common/utils/files.ts create mode 100644 services/quizzes/src/shared-module-v2/common/utils/generateWebVitalsReporter.ts create mode 100644 services/quizzes/src/shared-module-v2/common/utils/getGuestPseudonymousUserId.ts create mode 100644 services/quizzes/src/shared-module-v2/common/utils/i18next-parser.config.template.js create mode 100644 services/quizzes/src/shared-module-v2/common/utils/ietfLanguageTagToHumanReadableName.ts create mode 100644 services/quizzes/src/shared-module-v2/common/utils/initI18n.ts create mode 100644 services/quizzes/src/shared-module-v2/common/utils/nullability.ts create mode 100644 services/quizzes/src/shared-module-v2/common/utils/numbers.ts create mode 100644 services/quizzes/src/shared-module-v2/common/utils/redirectBackAfterLoginOrSignup.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/utils/responseHeaders.js create mode 100644 services/quizzes/src/shared-module-v2/common/utils/routes.ts create mode 100644 services/quizzes/src/shared-module-v2/common/utils/strings.ts create mode 100644 services/quizzes/src/shared-module-v2/common/utils/styles.ts create mode 100644 services/quizzes/src/shared-module-v2/common/utils/svgoConfig.js create mode 100644 services/quizzes/src/shared-module-v2/common/utils/testing/i18nTest.ts create mode 100644 services/quizzes/src/shared-module-v2/common/utils/testing/replaceUuidsWithPlaceholders.ts create mode 100644 services/quizzes/src/shared-module-v2/common/utils/time.ts create mode 100644 services/quizzes/src/shared-module-v2/common/utils/typeMappter.ts create mode 100644 services/quizzes/src/shared-module-v2/common/utils/urlManipulation.ts create mode 100644 services/quizzes/src/shared-module-v2/common/utils/validation.ts create mode 100644 services/quizzes/src/shared-module-v2/common/utils/withErrorBoundary.tsx create mode 100644 services/quizzes/src/shared-module-v2/common/utils/withNoSsr.tsx create mode 100644 services/tmc/src/shared-module-v2/common/bindings.guard.ts create mode 100644 services/tmc/src/shared-module-v2/common/bindings.ts create mode 100644 services/tmc/src/shared-module-v2/common/components/Accordion/DetailAccordion.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Accordion/index.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Banner/Banner.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Banner/ContributeBanner.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Banner/ReadOnlyBanner.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/BooleanAsText.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Breadcrumbs.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Button.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Card/CardOpenTextOverlay.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Card/CardOpensText.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Card/IllustrationCard.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Card/SimpleCard.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Card/index.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Centering/BreakFromCentered.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Centering/Centered.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/CircularProgressBar.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/CourseProgress/CircularProgress.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/CourseProgress/ProgressBar.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/CourseProgress/index.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/DebugModal.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Dialog.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/DiffFormatter.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/DropdownMenu/DropdownMenuItem.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/DropdownMenu/index.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/ErrorBanner.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/ExerciseList/ExerciseBox.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/ExerciseList/PageBox.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/FloatingErrorBox.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Footer.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Forum/Forum.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Forum/SideNavigation.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Forum/Thread.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Forum/Threads.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/GenericInfobox.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/HeightTrackingContainer.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/InputFields/CheckBox.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/InputFields/CheckboxFieldWrapper.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/InputFields/DatePickerField.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/InputFields/DateTimeLocal.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/InputFields/EditableComponentTextArea.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/InputFields/FileField.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/InputFields/RadioButton.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/InputFields/SelectField.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/InputFields/TextAreaField.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/InputFields/TextField.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/InputFields/TimePickerField.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/LanguageSelection/Language.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/LanguageSelection/LanguageMenu.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/LanguageSelection/LanguageOption.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/LanguageSelection/index.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/LinkOrNoLink.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/LoginControls.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/MessageChannelIFrame.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Navigation/NavBar/ComplexNav.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Navigation/NavBar/Menu/Hamburger/Hamburger.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Navigation/NavBar/Menu/Hamburger/HamburgerSpring.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Navigation/NavBar/Menu/Menu.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Navigation/NavBar/Menu/MenuItem.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Navigation/NavBar/NavContainer.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Navigation/NavBar/NavItem.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Navigation/NavBar/NavItems.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Navigation/NavBar/NavLink.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Navigation/NavBar/SimpleNav.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Navigation/NavBar/index.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Navigation/TabLinks/TabLink.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Navigation/TabLinks/TabLinkNavigation.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Navigation/TabLinks/TabLinkPanel.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Nested.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/NextSectionLink.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Notifications/Base.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Notifications/Delete.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Notifications/Error.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Notifications/Loading.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Notifications/Success.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Notifications/ToasterNotifications.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/OnlyRenderIfPermissions.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/PagesInChapterBox.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Pagination.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/PaginationItemsPerPage.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/PeerReview/LikertScale.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/PeerReview/Option.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/PeerReview/PeerReviewProgress.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/PeerReview/Review.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Quote.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Reference.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/SelectMenu.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/SkipLink.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/SpeechBalloon.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Spinner.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Sponsor.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Test.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/TimeComponent.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/Title.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/TopLevelPage.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/TopicObjectives.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/layout/PageMarginOffset.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/monaco/MonacoDiffEditor.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/monaco/MonacoEditor.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/monaco/impl/MonacoDiffEditorImpl.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/monaco/impl/MonacoEditorImpl.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/monaco/impl/loader.ts create mode 100644 services/tmc/src/shared-module-v2/common/components/system-tests/HideChildrenInSystemTests.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/system-tests/HideTextInSystemTests.tsx create mode 100644 services/tmc/src/shared-module-v2/common/components/system-tests/MaskOverThisInSystemTests.tsx create mode 100644 services/tmc/src/shared-module-v2/common/contexts/ExerciseServiceContext.tsx create mode 100644 services/tmc/src/shared-module-v2/common/contexts/IframeHeightContext.tsx create mode 100644 services/tmc/src/shared-module-v2/common/contexts/LoginStateContext.tsx create mode 100644 services/tmc/src/shared-module-v2/common/exercise-service-protocol-types-2.ts create mode 100644 services/tmc/src/shared-module-v2/common/exercise-service-protocol-types.guard.ts create mode 100644 services/tmc/src/shared-module-v2/common/exercise-service-protocol-types.ts create mode 100644 services/tmc/src/shared-module-v2/common/hooks/exerciseServiceHooks/useExerciseServiceOutputState.tsx create mode 100644 services/tmc/src/shared-module-v2/common/hooks/useAuthorizeMultiple.tsx create mode 100644 services/tmc/src/shared-module-v2/common/hooks/useClickOutside.tsx create mode 100644 services/tmc/src/shared-module-v2/common/hooks/useDateStringAsDate.tsx create mode 100644 services/tmc/src/shared-module-v2/common/hooks/useExerciseServiceParentConnection.tsx create mode 100644 services/tmc/src/shared-module-v2/common/hooks/useLanguage.tsx create mode 100644 services/tmc/src/shared-module-v2/common/hooks/useMedia.ts create mode 100644 services/tmc/src/shared-module-v2/common/hooks/useMessageChannel.tsx create mode 100644 services/tmc/src/shared-module-v2/common/hooks/usePaginationInfo.tsx create mode 100644 services/tmc/src/shared-module-v2/common/hooks/useQueryParameter.ts create mode 100644 services/tmc/src/shared-module-v2/common/hooks/useShouldHideStuffForSystemTestScreenshots.tsx create mode 100644 services/tmc/src/shared-module-v2/common/hooks/useShowToastInfinitely.tsx create mode 100644 services/tmc/src/shared-module-v2/common/hooks/useStateQuery.ts create mode 100644 services/tmc/src/shared-module-v2/common/hooks/useToastMutation.tsx create mode 100644 services/tmc/src/shared-module-v2/common/hooks/useUserInfo.tsx create mode 100644 services/tmc/src/shared-module-v2/common/img/UHBrandLogo.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/accordion-arrow.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/arrow.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/backarrow.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/blackArrow.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/bulleye.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/card-bg-circle.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/card-bg-star.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/card-bg-zigzag.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/card-defualt-bg/circle.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/card-defualt-bg/cross.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/card-defualt-bg/dot-circle.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/card-defualt-bg/equal.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/card-defualt-bg/intersection.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/card-defualt-bg/pixel-square.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/card-defualt-bg/quadruple-circle.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/card-defualt-bg/triangle.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/cardNext.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/caret-arrow-down.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/caret-arrow-left.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/caret-arrow-right.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/caret-arrow-up.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/check.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/checkmark.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/china.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/close.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/cross.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/diamond.png create mode 100644 services/tmc/src/shared-module-v2/common/img/diamond.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/exist-icon.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/external-link.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/flags/Austria.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/flags/Belgium.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/flags/Bulgaria.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/flags/Croatia.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/flags/Czech.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/flags/Denmark.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/flags/Estonia.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/flags/Finland.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/flags/France.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/flags/Germany.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/flags/Greece.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/flags/Ireland.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/flags/Italy.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/flags/Latvia.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/flags/Lithuania.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/flags/Netherlands.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/flags/Norway.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/flags/Poland.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/flags/Portugal.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/flags/Romania.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/flags/Slovenia.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/flags/Spain.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/flags/Sweden.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/flags/USA.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/flags/United_Kingdom.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/hero-default-bg-image.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/likert/agree.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/likert/disagree.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/likert/neutral.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/likert/stronglyAgree.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/likert/stronglyDisagree.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/lock.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/moocfiLogo.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/next.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/quote.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/score.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/screwedArrow.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/setting.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/swoosh.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/tick-03.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/tick.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/uh_without_background.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/unitedStates.svg create mode 100644 services/tmc/src/shared-module-v2/common/img/up-arrow.svg create mode 100644 services/tmc/src/shared-module-v2/common/locales/en/cms.json create mode 100644 services/tmc/src/shared-module-v2/common/locales/en/course-material.json create mode 100644 services/tmc/src/shared-module-v2/common/locales/en/example-exercise.json create mode 100644 services/tmc/src/shared-module-v2/common/locales/en/main-frontend.json create mode 100644 services/tmc/src/shared-module-v2/common/locales/en/quizzes.json create mode 100644 services/tmc/src/shared-module-v2/common/locales/en/shared-module.json create mode 100644 services/tmc/src/shared-module-v2/common/locales/en/tmc.json create mode 100644 services/tmc/src/shared-module-v2/common/locales/fi/cms.json create mode 100644 services/tmc/src/shared-module-v2/common/locales/fi/course-material.json create mode 100644 services/tmc/src/shared-module-v2/common/locales/fi/example-exercise.json create mode 100644 services/tmc/src/shared-module-v2/common/locales/fi/main-frontend.json create mode 100644 services/tmc/src/shared-module-v2/common/locales/fi/quizzes.json create mode 100644 services/tmc/src/shared-module-v2/common/locales/fi/shared-module.json create mode 100644 services/tmc/src/shared-module-v2/common/locales/fi/tmc.json create mode 100644 services/tmc/src/shared-module-v2/common/services/appQueryClient.ts create mode 100644 services/tmc/src/shared-module-v2/common/services/backend/auth.ts create mode 100644 services/tmc/src/shared-module-v2/common/services/backend/files.ts create mode 100644 services/tmc/src/shared-module-v2/common/styles/GlobalStyles.tsx create mode 100644 services/tmc/src/shared-module-v2/common/styles/constants.ts create mode 100644 services/tmc/src/shared-module-v2/common/styles/cssReset.ts create mode 100644 services/tmc/src/shared-module-v2/common/styles/index.ts create mode 100644 services/tmc/src/shared-module-v2/common/styles/monacoFontFixer.ts create mode 100644 services/tmc/src/shared-module-v2/common/styles/muiTheme.ts create mode 100644 services/tmc/src/shared-module-v2/common/styles/respond.ts create mode 100644 services/tmc/src/shared-module-v2/common/styles/theme.ts create mode 100644 services/tmc/src/shared-module-v2/common/styles/typography.ts create mode 100644 services/tmc/src/shared-module-v2/common/types/imageTypes.d.ts create mode 100644 services/tmc/src/shared-module-v2/common/utils/accessibility.ts create mode 100644 services/tmc/src/shared-module-v2/common/utils/base-path.ts create mode 100644 services/tmc/src/shared-module-v2/common/utils/constants.ts create mode 100644 services/tmc/src/shared-module-v2/common/utils/cookies.ts create mode 100644 services/tmc/src/shared-module-v2/common/utils/cross-routing.ts create mode 100644 services/tmc/src/shared-module-v2/common/utils/dateUtil.ts create mode 100644 services/tmc/src/shared-module-v2/common/utils/dom.ts create mode 100644 services/tmc/src/shared-module-v2/common/utils/dontRenderUntilQueryParametersReady.tsx create mode 100644 services/tmc/src/shared-module-v2/common/utils/exerciseServices.ts create mode 100644 services/tmc/src/shared-module-v2/common/utils/fetching.ts create mode 100644 services/tmc/src/shared-module-v2/common/utils/files.ts create mode 100644 services/tmc/src/shared-module-v2/common/utils/generateWebVitalsReporter.ts create mode 100644 services/tmc/src/shared-module-v2/common/utils/getGuestPseudonymousUserId.ts create mode 100644 services/tmc/src/shared-module-v2/common/utils/i18next-parser.config.template.js create mode 100644 services/tmc/src/shared-module-v2/common/utils/ietfLanguageTagToHumanReadableName.ts create mode 100644 services/tmc/src/shared-module-v2/common/utils/initI18n.ts create mode 100644 services/tmc/src/shared-module-v2/common/utils/nullability.ts create mode 100644 services/tmc/src/shared-module-v2/common/utils/numbers.ts create mode 100644 services/tmc/src/shared-module-v2/common/utils/redirectBackAfterLoginOrSignup.tsx create mode 100644 services/tmc/src/shared-module-v2/common/utils/responseHeaders.js create mode 100644 services/tmc/src/shared-module-v2/common/utils/routes.ts create mode 100644 services/tmc/src/shared-module-v2/common/utils/strings.ts create mode 100644 services/tmc/src/shared-module-v2/common/utils/styles.ts create mode 100644 services/tmc/src/shared-module-v2/common/utils/svgoConfig.js create mode 100644 services/tmc/src/shared-module-v2/common/utils/testing/i18nTest.ts create mode 100644 services/tmc/src/shared-module-v2/common/utils/testing/replaceUuidsWithPlaceholders.ts create mode 100644 services/tmc/src/shared-module-v2/common/utils/time.ts create mode 100644 services/tmc/src/shared-module-v2/common/utils/typeMappter.ts create mode 100644 services/tmc/src/shared-module-v2/common/utils/urlManipulation.ts create mode 100644 services/tmc/src/shared-module-v2/common/utils/validation.ts create mode 100644 services/tmc/src/shared-module-v2/common/utils/withErrorBoundary.tsx create mode 100644 services/tmc/src/shared-module-v2/common/utils/withNoSsr.tsx create mode 100644 shared-module-v2/packages/common/package-lock.json create mode 100644 shared-module-v2/packages/common/package.json create mode 100644 shared-module-v2/packages/common/src/hooks/useClickOutside.tsx create mode 100644 storybook/.storybook/main.ts create mode 100644 storybook/.storybook/preview.ts create mode 100644 storybook/package-lock.json create mode 100644 storybook/package.json create mode 100644 storybook/src/shared-module/common/bindings.guard.ts create mode 100644 storybook/src/shared-module/common/bindings.ts create mode 100644 storybook/src/shared-module/common/components/Accordion/DetailAccordion.tsx create mode 100644 storybook/src/shared-module/common/components/Accordion/index.tsx create mode 100644 storybook/src/shared-module/common/components/Banner/Banner.tsx create mode 100644 storybook/src/shared-module/common/components/Banner/ContributeBanner.tsx create mode 100644 storybook/src/shared-module/common/components/Banner/ReadOnlyBanner.tsx create mode 100644 storybook/src/shared-module/common/components/BooleanAsText.tsx create mode 100644 storybook/src/shared-module/common/components/Breadcrumbs.tsx create mode 100644 storybook/src/shared-module/common/components/Button.tsx create mode 100644 storybook/src/shared-module/common/components/Card/CardOpenTextOverlay.tsx create mode 100644 storybook/src/shared-module/common/components/Card/CardOpensText.tsx create mode 100644 storybook/src/shared-module/common/components/Card/IllustrationCard.tsx create mode 100644 storybook/src/shared-module/common/components/Card/SimpleCard.tsx create mode 100644 storybook/src/shared-module/common/components/Card/index.tsx create mode 100644 storybook/src/shared-module/common/components/Centering/BreakFromCentered.tsx create mode 100644 storybook/src/shared-module/common/components/Centering/Centered.tsx create mode 100644 storybook/src/shared-module/common/components/CircularProgressBar.tsx create mode 100644 storybook/src/shared-module/common/components/CourseProgress/CircularProgress.tsx create mode 100644 storybook/src/shared-module/common/components/CourseProgress/ProgressBar.tsx create mode 100644 storybook/src/shared-module/common/components/CourseProgress/index.tsx create mode 100644 storybook/src/shared-module/common/components/DebugModal.tsx create mode 100644 storybook/src/shared-module/common/components/Dialog.tsx create mode 100644 storybook/src/shared-module/common/components/DiffFormatter.tsx create mode 100644 storybook/src/shared-module/common/components/DropdownMenu/DropdownMenuItem.tsx create mode 100644 storybook/src/shared-module/common/components/DropdownMenu/index.tsx create mode 100644 storybook/src/shared-module/common/components/ErrorBanner.tsx create mode 100644 storybook/src/shared-module/common/components/ExerciseList/ExerciseBox.tsx create mode 100644 storybook/src/shared-module/common/components/ExerciseList/PageBox.tsx create mode 100644 storybook/src/shared-module/common/components/FloatingErrorBox.tsx create mode 100644 storybook/src/shared-module/common/components/Footer.tsx create mode 100644 storybook/src/shared-module/common/components/Forum/Forum.tsx create mode 100644 storybook/src/shared-module/common/components/Forum/SideNavigation.tsx create mode 100644 storybook/src/shared-module/common/components/Forum/Thread.tsx create mode 100644 storybook/src/shared-module/common/components/Forum/Threads.tsx create mode 100644 storybook/src/shared-module/common/components/GenericInfobox.tsx create mode 100644 storybook/src/shared-module/common/components/HeightTrackingContainer.tsx create mode 100644 storybook/src/shared-module/common/components/InputFields/CheckBox.tsx create mode 100644 storybook/src/shared-module/common/components/InputFields/CheckboxFieldWrapper.tsx create mode 100644 storybook/src/shared-module/common/components/InputFields/DatePickerField.tsx create mode 100644 storybook/src/shared-module/common/components/InputFields/DateTimeLocal.tsx create mode 100644 storybook/src/shared-module/common/components/InputFields/EditableComponentTextArea.tsx create mode 100644 storybook/src/shared-module/common/components/InputFields/FileField.tsx create mode 100644 storybook/src/shared-module/common/components/InputFields/RadioButton.tsx create mode 100644 storybook/src/shared-module/common/components/InputFields/SelectField.tsx create mode 100644 storybook/src/shared-module/common/components/InputFields/TextAreaField.tsx create mode 100644 storybook/src/shared-module/common/components/InputFields/TextField.tsx create mode 100644 storybook/src/shared-module/common/components/InputFields/TimePickerField.tsx create mode 100644 storybook/src/shared-module/common/components/LanguageSelection/Language.tsx create mode 100644 storybook/src/shared-module/common/components/LanguageSelection/LanguageMenu.tsx create mode 100644 storybook/src/shared-module/common/components/LanguageSelection/LanguageOption.tsx create mode 100644 storybook/src/shared-module/common/components/LanguageSelection/index.tsx create mode 100644 storybook/src/shared-module/common/components/LinkOrNoLink.tsx create mode 100644 storybook/src/shared-module/common/components/LoginControls.tsx create mode 100644 storybook/src/shared-module/common/components/MessageChannelIFrame.tsx create mode 100644 storybook/src/shared-module/common/components/Navigation/NavBar/ComplexNav.tsx create mode 100644 storybook/src/shared-module/common/components/Navigation/NavBar/Menu/Hamburger/Hamburger.tsx create mode 100644 storybook/src/shared-module/common/components/Navigation/NavBar/Menu/Hamburger/HamburgerSpring.tsx create mode 100644 storybook/src/shared-module/common/components/Navigation/NavBar/Menu/Menu.tsx create mode 100644 storybook/src/shared-module/common/components/Navigation/NavBar/Menu/MenuItem.tsx create mode 100644 storybook/src/shared-module/common/components/Navigation/NavBar/NavContainer.tsx create mode 100644 storybook/src/shared-module/common/components/Navigation/NavBar/NavItem.tsx create mode 100644 storybook/src/shared-module/common/components/Navigation/NavBar/NavItems.tsx create mode 100644 storybook/src/shared-module/common/components/Navigation/NavBar/NavLink.tsx create mode 100644 storybook/src/shared-module/common/components/Navigation/NavBar/SimpleNav.tsx create mode 100644 storybook/src/shared-module/common/components/Navigation/NavBar/index.tsx create mode 100644 storybook/src/shared-module/common/components/Navigation/TabLinks/TabLink.tsx create mode 100644 storybook/src/shared-module/common/components/Navigation/TabLinks/TabLinkNavigation.tsx create mode 100644 storybook/src/shared-module/common/components/Navigation/TabLinks/TabLinkPanel.tsx create mode 100644 storybook/src/shared-module/common/components/Nested.tsx create mode 100644 storybook/src/shared-module/common/components/NextSectionLink.tsx create mode 100644 storybook/src/shared-module/common/components/Notifications/Base.tsx create mode 100644 storybook/src/shared-module/common/components/Notifications/Delete.tsx create mode 100644 storybook/src/shared-module/common/components/Notifications/Error.tsx create mode 100644 storybook/src/shared-module/common/components/Notifications/Loading.tsx create mode 100644 storybook/src/shared-module/common/components/Notifications/Success.tsx create mode 100644 storybook/src/shared-module/common/components/Notifications/ToasterNotifications.tsx create mode 100644 storybook/src/shared-module/common/components/OnlyRenderIfPermissions.tsx create mode 100644 storybook/src/shared-module/common/components/PagesInChapterBox.tsx create mode 100644 storybook/src/shared-module/common/components/Pagination.tsx create mode 100644 storybook/src/shared-module/common/components/PaginationItemsPerPage.tsx create mode 100644 storybook/src/shared-module/common/components/PeerReview/LikertScale.tsx create mode 100644 storybook/src/shared-module/common/components/PeerReview/Option.tsx create mode 100644 storybook/src/shared-module/common/components/PeerReview/PeerReviewProgress.tsx create mode 100644 storybook/src/shared-module/common/components/PeerReview/Review.tsx create mode 100644 storybook/src/shared-module/common/components/Quote.tsx create mode 100644 storybook/src/shared-module/common/components/Reference.tsx create mode 100644 storybook/src/shared-module/common/components/SelectMenu.tsx create mode 100644 storybook/src/shared-module/common/components/SkipLink.tsx create mode 100644 storybook/src/shared-module/common/components/SpeechBalloon.tsx create mode 100644 storybook/src/shared-module/common/components/Spinner.tsx create mode 100644 storybook/src/shared-module/common/components/Sponsor.tsx create mode 100644 storybook/src/shared-module/common/components/Test.tsx create mode 100644 storybook/src/shared-module/common/components/TimeComponent.tsx create mode 100644 storybook/src/shared-module/common/components/Title.tsx create mode 100644 storybook/src/shared-module/common/components/TopLevelPage.tsx create mode 100644 storybook/src/shared-module/common/components/TopicObjectives.tsx create mode 100644 storybook/src/shared-module/common/components/layout/PageMarginOffset.tsx create mode 100644 storybook/src/shared-module/common/components/monaco/MonacoDiffEditor.tsx create mode 100644 storybook/src/shared-module/common/components/monaco/MonacoEditor.tsx create mode 100644 storybook/src/shared-module/common/components/monaco/impl/MonacoDiffEditorImpl.tsx create mode 100644 storybook/src/shared-module/common/components/monaco/impl/MonacoEditorImpl.tsx create mode 100644 storybook/src/shared-module/common/components/monaco/impl/loader.ts create mode 100644 storybook/src/shared-module/common/components/system-tests/HideChildrenInSystemTests.tsx create mode 100644 storybook/src/shared-module/common/components/system-tests/HideTextInSystemTests.tsx create mode 100644 storybook/src/shared-module/common/components/system-tests/MaskOverThisInSystemTests.tsx create mode 100644 storybook/src/shared-module/common/contexts/ExerciseServiceContext.tsx create mode 100644 storybook/src/shared-module/common/contexts/IframeHeightContext.tsx create mode 100644 storybook/src/shared-module/common/contexts/LoginStateContext.tsx create mode 100644 storybook/src/shared-module/common/exercise-service-protocol-types-2.ts create mode 100644 storybook/src/shared-module/common/exercise-service-protocol-types.guard.ts create mode 100644 storybook/src/shared-module/common/exercise-service-protocol-types.ts create mode 100644 storybook/src/shared-module/common/hooks/exerciseServiceHooks/useExerciseServiceOutputState.tsx create mode 100644 storybook/src/shared-module/common/hooks/useAuthorizeMultiple.tsx create mode 100644 storybook/src/shared-module/common/hooks/useClickOutside.tsx create mode 100644 storybook/src/shared-module/common/hooks/useDateStringAsDate.tsx create mode 100644 storybook/src/shared-module/common/hooks/useExerciseServiceParentConnection.tsx create mode 100644 storybook/src/shared-module/common/hooks/useLanguage.tsx create mode 100644 storybook/src/shared-module/common/hooks/useMedia.ts create mode 100644 storybook/src/shared-module/common/hooks/useMessageChannel.tsx create mode 100644 storybook/src/shared-module/common/hooks/usePaginationInfo.tsx create mode 100644 storybook/src/shared-module/common/hooks/useQueryParameter.ts create mode 100644 storybook/src/shared-module/common/hooks/useShouldHideStuffForSystemTestScreenshots.tsx create mode 100644 storybook/src/shared-module/common/hooks/useShowToastInfinitely.tsx create mode 100644 storybook/src/shared-module/common/hooks/useStateQuery.ts create mode 100644 storybook/src/shared-module/common/hooks/useToastMutation.tsx create mode 100644 storybook/src/shared-module/common/hooks/useUserInfo.tsx create mode 100644 storybook/src/shared-module/common/img/UHBrandLogo.svg create mode 100644 storybook/src/shared-module/common/img/accordion-arrow.svg create mode 100644 storybook/src/shared-module/common/img/arrow.svg create mode 100644 storybook/src/shared-module/common/img/backarrow.svg create mode 100644 storybook/src/shared-module/common/img/blackArrow.svg create mode 100644 storybook/src/shared-module/common/img/bulleye.svg create mode 100644 storybook/src/shared-module/common/img/card-bg-circle.svg create mode 100644 storybook/src/shared-module/common/img/card-bg-star.svg create mode 100644 storybook/src/shared-module/common/img/card-bg-zigzag.svg create mode 100644 storybook/src/shared-module/common/img/card-defualt-bg/circle.svg create mode 100644 storybook/src/shared-module/common/img/card-defualt-bg/cross.svg create mode 100644 storybook/src/shared-module/common/img/card-defualt-bg/dot-circle.svg create mode 100644 storybook/src/shared-module/common/img/card-defualt-bg/equal.svg create mode 100644 storybook/src/shared-module/common/img/card-defualt-bg/intersection.svg create mode 100644 storybook/src/shared-module/common/img/card-defualt-bg/pixel-square.svg create mode 100644 storybook/src/shared-module/common/img/card-defualt-bg/quadruple-circle.svg create mode 100644 storybook/src/shared-module/common/img/card-defualt-bg/triangle.svg create mode 100644 storybook/src/shared-module/common/img/cardNext.svg create mode 100644 storybook/src/shared-module/common/img/caret-arrow-down.svg create mode 100644 storybook/src/shared-module/common/img/caret-arrow-left.svg create mode 100644 storybook/src/shared-module/common/img/caret-arrow-right.svg create mode 100644 storybook/src/shared-module/common/img/caret-arrow-up.svg create mode 100644 storybook/src/shared-module/common/img/check.svg create mode 100644 storybook/src/shared-module/common/img/checkmark.svg create mode 100644 storybook/src/shared-module/common/img/china.svg create mode 100644 storybook/src/shared-module/common/img/close.svg create mode 100644 storybook/src/shared-module/common/img/cross.svg create mode 100644 storybook/src/shared-module/common/img/diamond.png create mode 100644 storybook/src/shared-module/common/img/diamond.svg create mode 100644 storybook/src/shared-module/common/img/exist-icon.svg create mode 100644 storybook/src/shared-module/common/img/external-link.svg create mode 100644 storybook/src/shared-module/common/img/flags/Austria.svg create mode 100644 storybook/src/shared-module/common/img/flags/Belgium.svg create mode 100644 storybook/src/shared-module/common/img/flags/Bulgaria.svg create mode 100644 storybook/src/shared-module/common/img/flags/Croatia.svg create mode 100644 storybook/src/shared-module/common/img/flags/Czech.svg create mode 100644 storybook/src/shared-module/common/img/flags/Denmark.svg create mode 100644 storybook/src/shared-module/common/img/flags/Estonia.svg create mode 100644 storybook/src/shared-module/common/img/flags/Finland.svg create mode 100644 storybook/src/shared-module/common/img/flags/France.svg create mode 100644 storybook/src/shared-module/common/img/flags/Germany.svg create mode 100644 storybook/src/shared-module/common/img/flags/Greece.svg create mode 100644 storybook/src/shared-module/common/img/flags/Ireland.svg create mode 100644 storybook/src/shared-module/common/img/flags/Italy.svg create mode 100644 storybook/src/shared-module/common/img/flags/Latvia.svg create mode 100644 storybook/src/shared-module/common/img/flags/Lithuania.svg create mode 100644 storybook/src/shared-module/common/img/flags/Netherlands.svg create mode 100644 storybook/src/shared-module/common/img/flags/Norway.svg create mode 100644 storybook/src/shared-module/common/img/flags/Poland.svg create mode 100644 storybook/src/shared-module/common/img/flags/Portugal.svg create mode 100644 storybook/src/shared-module/common/img/flags/Romania.svg create mode 100644 storybook/src/shared-module/common/img/flags/Slovenia.svg create mode 100644 storybook/src/shared-module/common/img/flags/Spain.svg create mode 100644 storybook/src/shared-module/common/img/flags/Sweden.svg create mode 100644 storybook/src/shared-module/common/img/flags/USA.svg create mode 100644 storybook/src/shared-module/common/img/flags/United_Kingdom.svg create mode 100644 storybook/src/shared-module/common/img/hero-default-bg-image.svg create mode 100644 storybook/src/shared-module/common/img/likert/agree.svg create mode 100644 storybook/src/shared-module/common/img/likert/disagree.svg create mode 100644 storybook/src/shared-module/common/img/likert/neutral.svg create mode 100644 storybook/src/shared-module/common/img/likert/stronglyAgree.svg create mode 100644 storybook/src/shared-module/common/img/likert/stronglyDisagree.svg create mode 100644 storybook/src/shared-module/common/img/lock.svg create mode 100644 storybook/src/shared-module/common/img/moocfiLogo.svg create mode 100644 storybook/src/shared-module/common/img/next.svg create mode 100644 storybook/src/shared-module/common/img/quote.svg create mode 100644 storybook/src/shared-module/common/img/score.svg create mode 100644 storybook/src/shared-module/common/img/screwedArrow.svg create mode 100644 storybook/src/shared-module/common/img/setting.svg create mode 100644 storybook/src/shared-module/common/img/swoosh.svg create mode 100644 storybook/src/shared-module/common/img/tick-03.svg create mode 100644 storybook/src/shared-module/common/img/tick.svg create mode 100644 storybook/src/shared-module/common/img/uh_without_background.svg create mode 100644 storybook/src/shared-module/common/img/unitedStates.svg create mode 100644 storybook/src/shared-module/common/img/up-arrow.svg create mode 100644 storybook/src/shared-module/common/locales/en/cms.json create mode 100644 storybook/src/shared-module/common/locales/en/course-material.json create mode 100644 storybook/src/shared-module/common/locales/en/example-exercise.json create mode 100644 storybook/src/shared-module/common/locales/en/main-frontend.json create mode 100644 storybook/src/shared-module/common/locales/en/quizzes.json create mode 100644 storybook/src/shared-module/common/locales/en/shared-module.json create mode 100644 storybook/src/shared-module/common/locales/en/tmc.json create mode 100644 storybook/src/shared-module/common/locales/fi/cms.json create mode 100644 storybook/src/shared-module/common/locales/fi/course-material.json create mode 100644 storybook/src/shared-module/common/locales/fi/example-exercise.json create mode 100644 storybook/src/shared-module/common/locales/fi/main-frontend.json create mode 100644 storybook/src/shared-module/common/locales/fi/quizzes.json create mode 100644 storybook/src/shared-module/common/locales/fi/shared-module.json create mode 100644 storybook/src/shared-module/common/locales/fi/tmc.json create mode 100644 storybook/src/shared-module/common/services/appQueryClient.ts create mode 100644 storybook/src/shared-module/common/services/backend/auth.ts create mode 100644 storybook/src/shared-module/common/services/backend/files.ts create mode 100644 storybook/src/shared-module/common/styles/GlobalStyles.tsx create mode 100644 storybook/src/shared-module/common/styles/constants.ts create mode 100644 storybook/src/shared-module/common/styles/cssReset.ts create mode 100644 storybook/src/shared-module/common/styles/index.ts create mode 100644 storybook/src/shared-module/common/styles/monacoFontFixer.ts create mode 100644 storybook/src/shared-module/common/styles/muiTheme.ts create mode 100644 storybook/src/shared-module/common/styles/respond.ts create mode 100644 storybook/src/shared-module/common/styles/theme.ts create mode 100644 storybook/src/shared-module/common/styles/typography.ts create mode 100644 storybook/src/shared-module/common/types/imageTypes.d.ts create mode 100644 storybook/src/shared-module/common/utils/accessibility.ts create mode 100644 storybook/src/shared-module/common/utils/base-path.ts create mode 100644 storybook/src/shared-module/common/utils/constants.ts create mode 100644 storybook/src/shared-module/common/utils/cookies.ts create mode 100644 storybook/src/shared-module/common/utils/cross-routing.ts create mode 100644 storybook/src/shared-module/common/utils/dateUtil.ts create mode 100644 storybook/src/shared-module/common/utils/dom.ts create mode 100644 storybook/src/shared-module/common/utils/dontRenderUntilQueryParametersReady.tsx create mode 100644 storybook/src/shared-module/common/utils/exerciseServices.ts create mode 100644 storybook/src/shared-module/common/utils/fetching.ts create mode 100644 storybook/src/shared-module/common/utils/files.ts create mode 100644 storybook/src/shared-module/common/utils/generateWebVitalsReporter.ts create mode 100644 storybook/src/shared-module/common/utils/getGuestPseudonymousUserId.ts create mode 100644 storybook/src/shared-module/common/utils/i18next-parser.config.template.js create mode 100644 storybook/src/shared-module/common/utils/ietfLanguageTagToHumanReadableName.ts create mode 100644 storybook/src/shared-module/common/utils/initI18n.ts create mode 100644 storybook/src/shared-module/common/utils/nullability.ts create mode 100644 storybook/src/shared-module/common/utils/numbers.ts create mode 100644 storybook/src/shared-module/common/utils/redirectBackAfterLoginOrSignup.tsx create mode 100644 storybook/src/shared-module/common/utils/responseHeaders.js create mode 100644 storybook/src/shared-module/common/utils/routes.ts create mode 100644 storybook/src/shared-module/common/utils/strings.ts create mode 100644 storybook/src/shared-module/common/utils/styles.ts create mode 100644 storybook/src/shared-module/common/utils/svgoConfig.js create mode 100644 storybook/src/shared-module/common/utils/testing/i18nTest.ts create mode 100644 storybook/src/shared-module/common/utils/testing/replaceUuidsWithPlaceholders.ts create mode 100644 storybook/src/shared-module/common/utils/time.ts create mode 100644 storybook/src/shared-module/common/utils/typeMappter.ts create mode 100644 storybook/src/shared-module/common/utils/urlManipulation.ts create mode 100644 storybook/src/shared-module/common/utils/validation.ts create mode 100644 storybook/src/shared-module/common/utils/withErrorBoundary.tsx create mode 100644 storybook/src/shared-module/common/utils/withNoSsr.tsx create mode 100644 storybook/stories/common/Button.stories.tsx create mode 100644 storybook/stories/common/Dialog.stories.tsx create mode 100644 storybook/stories/common/ErrorBanner.stories.tsx create mode 100644 storybook/stories/common/GenericInfoBox.stories.tsx create mode 100644 storybook/stories/common/Spinner.stories.tsx create mode 100644 storybook/stories/common/inputs/Checkbox.stories.tsx create mode 100644 storybook/stories/common/inputs/DatePickerField.stories.tsx create mode 100644 storybook/stories/common/inputs/DateTimeLocal.stories.tsx create mode 100644 storybook/stories/common/inputs/FileField.stories.tsx create mode 100644 storybook/stories/common/inputs/RadioButton.stories.tsx create mode 100644 storybook/stories/common/inputs/SelectField.stories.tsx create mode 100644 storybook/stories/common/inputs/TextAreaField.stories.tsx create mode 100644 storybook/stories/common/inputs/TextField.stories.tsx create mode 100644 storybook/stories/common/inputs/TimerPickerField.stories.tsx create mode 100644 system-tests/src/shared-module-v2/common/bindings.guard.ts create mode 100644 system-tests/src/shared-module-v2/common/bindings.ts create mode 100644 system-tests/src/shared-module-v2/common/components/Accordion/DetailAccordion.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Accordion/index.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Banner/Banner.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Banner/ContributeBanner.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Banner/ReadOnlyBanner.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/BooleanAsText.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Breadcrumbs.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Button.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Card/CardOpenTextOverlay.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Card/CardOpensText.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Card/IllustrationCard.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Card/SimpleCard.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Card/index.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Centering/BreakFromCentered.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Centering/Centered.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/CircularProgressBar.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/CourseProgress/CircularProgress.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/CourseProgress/ProgressBar.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/CourseProgress/index.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/DebugModal.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Dialog.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/DiffFormatter.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/DropdownMenu/DropdownMenuItem.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/DropdownMenu/index.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/ErrorBanner.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/ExerciseList/ExerciseBox.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/ExerciseList/PageBox.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/FloatingErrorBox.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Footer.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Forum/Forum.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Forum/SideNavigation.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Forum/Thread.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Forum/Threads.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/GenericInfobox.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/HeightTrackingContainer.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/InputFields/CheckBox.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/InputFields/CheckboxFieldWrapper.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/InputFields/DatePickerField.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/InputFields/DateTimeLocal.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/InputFields/EditableComponentTextArea.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/InputFields/FileField.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/InputFields/RadioButton.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/InputFields/SelectField.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/InputFields/TextAreaField.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/InputFields/TextField.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/InputFields/TimePickerField.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/LanguageSelection/Language.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/LanguageSelection/LanguageMenu.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/LanguageSelection/LanguageOption.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/LanguageSelection/index.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/LinkOrNoLink.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/LoginControls.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/MessageChannelIFrame.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Navigation/NavBar/ComplexNav.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Navigation/NavBar/Menu/Hamburger/Hamburger.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Navigation/NavBar/Menu/Hamburger/HamburgerSpring.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Navigation/NavBar/Menu/Menu.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Navigation/NavBar/Menu/MenuItem.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Navigation/NavBar/NavContainer.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Navigation/NavBar/NavItem.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Navigation/NavBar/NavItems.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Navigation/NavBar/NavLink.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Navigation/NavBar/SimpleNav.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Navigation/NavBar/index.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Navigation/TabLinks/TabLink.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Navigation/TabLinks/TabLinkNavigation.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Navigation/TabLinks/TabLinkPanel.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Nested.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/NextSectionLink.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Notifications/Base.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Notifications/Delete.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Notifications/Error.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Notifications/Loading.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Notifications/Success.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Notifications/ToasterNotifications.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/OnlyRenderIfPermissions.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/PagesInChapterBox.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Pagination.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/PaginationItemsPerPage.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/PeerReview/LikertScale.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/PeerReview/Option.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/PeerReview/PeerReviewProgress.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/PeerReview/Review.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Quote.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Reference.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/SelectMenu.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/SkipLink.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/SpeechBalloon.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Spinner.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Sponsor.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Test.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/TimeComponent.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/Title.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/TopLevelPage.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/TopicObjectives.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/layout/PageMarginOffset.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/monaco/MonacoDiffEditor.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/monaco/MonacoEditor.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/monaco/impl/MonacoDiffEditorImpl.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/monaco/impl/MonacoEditorImpl.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/monaco/impl/loader.ts create mode 100644 system-tests/src/shared-module-v2/common/components/system-tests/HideChildrenInSystemTests.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/system-tests/HideTextInSystemTests.tsx create mode 100644 system-tests/src/shared-module-v2/common/components/system-tests/MaskOverThisInSystemTests.tsx create mode 100644 system-tests/src/shared-module-v2/common/contexts/ExerciseServiceContext.tsx create mode 100644 system-tests/src/shared-module-v2/common/contexts/IframeHeightContext.tsx create mode 100644 system-tests/src/shared-module-v2/common/contexts/LoginStateContext.tsx create mode 100644 system-tests/src/shared-module-v2/common/exercise-service-protocol-types-2.ts create mode 100644 system-tests/src/shared-module-v2/common/exercise-service-protocol-types.guard.ts create mode 100644 system-tests/src/shared-module-v2/common/exercise-service-protocol-types.ts create mode 100644 system-tests/src/shared-module-v2/common/hooks/exerciseServiceHooks/useExerciseServiceOutputState.tsx create mode 100644 system-tests/src/shared-module-v2/common/hooks/useAuthorizeMultiple.tsx create mode 100644 system-tests/src/shared-module-v2/common/hooks/useClickOutside.tsx create mode 100644 system-tests/src/shared-module-v2/common/hooks/useDateStringAsDate.tsx create mode 100644 system-tests/src/shared-module-v2/common/hooks/useExerciseServiceParentConnection.tsx create mode 100644 system-tests/src/shared-module-v2/common/hooks/useLanguage.tsx create mode 100644 system-tests/src/shared-module-v2/common/hooks/useMedia.ts create mode 100644 system-tests/src/shared-module-v2/common/hooks/useMessageChannel.tsx create mode 100644 system-tests/src/shared-module-v2/common/hooks/usePaginationInfo.tsx create mode 100644 system-tests/src/shared-module-v2/common/hooks/useQueryParameter.ts create mode 100644 system-tests/src/shared-module-v2/common/hooks/useShouldHideStuffForSystemTestScreenshots.tsx create mode 100644 system-tests/src/shared-module-v2/common/hooks/useShowToastInfinitely.tsx create mode 100644 system-tests/src/shared-module-v2/common/hooks/useStateQuery.ts create mode 100644 system-tests/src/shared-module-v2/common/hooks/useToastMutation.tsx create mode 100644 system-tests/src/shared-module-v2/common/hooks/useUserInfo.tsx create mode 100644 system-tests/src/shared-module-v2/common/img/UHBrandLogo.svg create mode 100644 system-tests/src/shared-module-v2/common/img/accordion-arrow.svg create mode 100644 system-tests/src/shared-module-v2/common/img/arrow.svg create mode 100644 system-tests/src/shared-module-v2/common/img/backarrow.svg create mode 100644 system-tests/src/shared-module-v2/common/img/blackArrow.svg create mode 100644 system-tests/src/shared-module-v2/common/img/bulleye.svg create mode 100644 system-tests/src/shared-module-v2/common/img/card-bg-circle.svg create mode 100644 system-tests/src/shared-module-v2/common/img/card-bg-star.svg create mode 100644 system-tests/src/shared-module-v2/common/img/card-bg-zigzag.svg create mode 100644 system-tests/src/shared-module-v2/common/img/card-defualt-bg/circle.svg create mode 100644 system-tests/src/shared-module-v2/common/img/card-defualt-bg/cross.svg create mode 100644 system-tests/src/shared-module-v2/common/img/card-defualt-bg/dot-circle.svg create mode 100644 system-tests/src/shared-module-v2/common/img/card-defualt-bg/equal.svg create mode 100644 system-tests/src/shared-module-v2/common/img/card-defualt-bg/intersection.svg create mode 100644 system-tests/src/shared-module-v2/common/img/card-defualt-bg/pixel-square.svg create mode 100644 system-tests/src/shared-module-v2/common/img/card-defualt-bg/quadruple-circle.svg create mode 100644 system-tests/src/shared-module-v2/common/img/card-defualt-bg/triangle.svg create mode 100644 system-tests/src/shared-module-v2/common/img/cardNext.svg create mode 100644 system-tests/src/shared-module-v2/common/img/caret-arrow-down.svg create mode 100644 system-tests/src/shared-module-v2/common/img/caret-arrow-left.svg create mode 100644 system-tests/src/shared-module-v2/common/img/caret-arrow-right.svg create mode 100644 system-tests/src/shared-module-v2/common/img/caret-arrow-up.svg create mode 100644 system-tests/src/shared-module-v2/common/img/check.svg create mode 100644 system-tests/src/shared-module-v2/common/img/checkmark.svg create mode 100644 system-tests/src/shared-module-v2/common/img/china.svg create mode 100644 system-tests/src/shared-module-v2/common/img/close.svg create mode 100644 system-tests/src/shared-module-v2/common/img/cross.svg create mode 100644 system-tests/src/shared-module-v2/common/img/diamond.png create mode 100644 system-tests/src/shared-module-v2/common/img/diamond.svg create mode 100644 system-tests/src/shared-module-v2/common/img/exist-icon.svg create mode 100644 system-tests/src/shared-module-v2/common/img/external-link.svg create mode 100644 system-tests/src/shared-module-v2/common/img/flags/Austria.svg create mode 100644 system-tests/src/shared-module-v2/common/img/flags/Belgium.svg create mode 100644 system-tests/src/shared-module-v2/common/img/flags/Bulgaria.svg create mode 100644 system-tests/src/shared-module-v2/common/img/flags/Croatia.svg create mode 100644 system-tests/src/shared-module-v2/common/img/flags/Czech.svg create mode 100644 system-tests/src/shared-module-v2/common/img/flags/Denmark.svg create mode 100644 system-tests/src/shared-module-v2/common/img/flags/Estonia.svg create mode 100644 system-tests/src/shared-module-v2/common/img/flags/Finland.svg create mode 100644 system-tests/src/shared-module-v2/common/img/flags/France.svg create mode 100644 system-tests/src/shared-module-v2/common/img/flags/Germany.svg create mode 100644 system-tests/src/shared-module-v2/common/img/flags/Greece.svg create mode 100644 system-tests/src/shared-module-v2/common/img/flags/Ireland.svg create mode 100644 system-tests/src/shared-module-v2/common/img/flags/Italy.svg create mode 100644 system-tests/src/shared-module-v2/common/img/flags/Latvia.svg create mode 100644 system-tests/src/shared-module-v2/common/img/flags/Lithuania.svg create mode 100644 system-tests/src/shared-module-v2/common/img/flags/Netherlands.svg create mode 100644 system-tests/src/shared-module-v2/common/img/flags/Norway.svg create mode 100644 system-tests/src/shared-module-v2/common/img/flags/Poland.svg create mode 100644 system-tests/src/shared-module-v2/common/img/flags/Portugal.svg create mode 100644 system-tests/src/shared-module-v2/common/img/flags/Romania.svg create mode 100644 system-tests/src/shared-module-v2/common/img/flags/Slovenia.svg create mode 100644 system-tests/src/shared-module-v2/common/img/flags/Spain.svg create mode 100644 system-tests/src/shared-module-v2/common/img/flags/Sweden.svg create mode 100644 system-tests/src/shared-module-v2/common/img/flags/USA.svg create mode 100644 system-tests/src/shared-module-v2/common/img/flags/United_Kingdom.svg create mode 100644 system-tests/src/shared-module-v2/common/img/hero-default-bg-image.svg create mode 100644 system-tests/src/shared-module-v2/common/img/likert/agree.svg create mode 100644 system-tests/src/shared-module-v2/common/img/likert/disagree.svg create mode 100644 system-tests/src/shared-module-v2/common/img/likert/neutral.svg create mode 100644 system-tests/src/shared-module-v2/common/img/likert/stronglyAgree.svg create mode 100644 system-tests/src/shared-module-v2/common/img/likert/stronglyDisagree.svg create mode 100644 system-tests/src/shared-module-v2/common/img/lock.svg create mode 100644 system-tests/src/shared-module-v2/common/img/moocfiLogo.svg create mode 100644 system-tests/src/shared-module-v2/common/img/next.svg create mode 100644 system-tests/src/shared-module-v2/common/img/quote.svg create mode 100644 system-tests/src/shared-module-v2/common/img/score.svg create mode 100644 system-tests/src/shared-module-v2/common/img/screwedArrow.svg create mode 100644 system-tests/src/shared-module-v2/common/img/setting.svg create mode 100644 system-tests/src/shared-module-v2/common/img/swoosh.svg create mode 100644 system-tests/src/shared-module-v2/common/img/tick-03.svg create mode 100644 system-tests/src/shared-module-v2/common/img/tick.svg create mode 100644 system-tests/src/shared-module-v2/common/img/uh_without_background.svg create mode 100644 system-tests/src/shared-module-v2/common/img/unitedStates.svg create mode 100644 system-tests/src/shared-module-v2/common/img/up-arrow.svg create mode 100644 system-tests/src/shared-module-v2/common/locales/en/cms.json create mode 100644 system-tests/src/shared-module-v2/common/locales/en/course-material.json create mode 100644 system-tests/src/shared-module-v2/common/locales/en/example-exercise.json create mode 100644 system-tests/src/shared-module-v2/common/locales/en/main-frontend.json create mode 100644 system-tests/src/shared-module-v2/common/locales/en/quizzes.json create mode 100644 system-tests/src/shared-module-v2/common/locales/en/shared-module.json create mode 100644 system-tests/src/shared-module-v2/common/locales/en/tmc.json create mode 100644 system-tests/src/shared-module-v2/common/locales/fi/cms.json create mode 100644 system-tests/src/shared-module-v2/common/locales/fi/course-material.json create mode 100644 system-tests/src/shared-module-v2/common/locales/fi/example-exercise.json create mode 100644 system-tests/src/shared-module-v2/common/locales/fi/main-frontend.json create mode 100644 system-tests/src/shared-module-v2/common/locales/fi/quizzes.json create mode 100644 system-tests/src/shared-module-v2/common/locales/fi/shared-module.json create mode 100644 system-tests/src/shared-module-v2/common/locales/fi/tmc.json create mode 100644 system-tests/src/shared-module-v2/common/services/appQueryClient.ts create mode 100644 system-tests/src/shared-module-v2/common/services/backend/auth.ts create mode 100644 system-tests/src/shared-module-v2/common/services/backend/files.ts create mode 100644 system-tests/src/shared-module-v2/common/styles/GlobalStyles.tsx create mode 100644 system-tests/src/shared-module-v2/common/styles/constants.ts create mode 100644 system-tests/src/shared-module-v2/common/styles/cssReset.ts create mode 100644 system-tests/src/shared-module-v2/common/styles/index.ts create mode 100644 system-tests/src/shared-module-v2/common/styles/monacoFontFixer.ts create mode 100644 system-tests/src/shared-module-v2/common/styles/muiTheme.ts create mode 100644 system-tests/src/shared-module-v2/common/styles/respond.ts create mode 100644 system-tests/src/shared-module-v2/common/styles/theme.ts create mode 100644 system-tests/src/shared-module-v2/common/styles/typography.ts create mode 100644 system-tests/src/shared-module-v2/common/types/imageTypes.d.ts create mode 100644 system-tests/src/shared-module-v2/common/utils/accessibility.ts create mode 100644 system-tests/src/shared-module-v2/common/utils/base-path.ts create mode 100644 system-tests/src/shared-module-v2/common/utils/constants.ts create mode 100644 system-tests/src/shared-module-v2/common/utils/cookies.ts create mode 100644 system-tests/src/shared-module-v2/common/utils/cross-routing.ts create mode 100644 system-tests/src/shared-module-v2/common/utils/dateUtil.ts create mode 100644 system-tests/src/shared-module-v2/common/utils/dom.ts create mode 100644 system-tests/src/shared-module-v2/common/utils/dontRenderUntilQueryParametersReady.tsx create mode 100644 system-tests/src/shared-module-v2/common/utils/exerciseServices.ts create mode 100644 system-tests/src/shared-module-v2/common/utils/fetching.ts create mode 100644 system-tests/src/shared-module-v2/common/utils/files.ts create mode 100644 system-tests/src/shared-module-v2/common/utils/generateWebVitalsReporter.ts create mode 100644 system-tests/src/shared-module-v2/common/utils/getGuestPseudonymousUserId.ts create mode 100644 system-tests/src/shared-module-v2/common/utils/i18next-parser.config.template.js create mode 100644 system-tests/src/shared-module-v2/common/utils/ietfLanguageTagToHumanReadableName.ts create mode 100644 system-tests/src/shared-module-v2/common/utils/initI18n.ts create mode 100644 system-tests/src/shared-module-v2/common/utils/nullability.ts create mode 100644 system-tests/src/shared-module-v2/common/utils/numbers.ts create mode 100644 system-tests/src/shared-module-v2/common/utils/redirectBackAfterLoginOrSignup.tsx create mode 100644 system-tests/src/shared-module-v2/common/utils/responseHeaders.js create mode 100644 system-tests/src/shared-module-v2/common/utils/routes.ts create mode 100644 system-tests/src/shared-module-v2/common/utils/strings.ts create mode 100644 system-tests/src/shared-module-v2/common/utils/styles.ts create mode 100644 system-tests/src/shared-module-v2/common/utils/svgoConfig.js create mode 100644 system-tests/src/shared-module-v2/common/utils/testing/i18nTest.ts create mode 100644 system-tests/src/shared-module-v2/common/utils/testing/replaceUuidsWithPlaceholders.ts create mode 100644 system-tests/src/shared-module-v2/common/utils/time.ts create mode 100644 system-tests/src/shared-module-v2/common/utils/typeMappter.ts create mode 100644 system-tests/src/shared-module-v2/common/utils/urlManipulation.ts create mode 100644 system-tests/src/shared-module-v2/common/utils/validation.ts create mode 100644 system-tests/src/shared-module-v2/common/utils/withErrorBoundary.tsx create mode 100644 system-tests/src/shared-module-v2/common/utils/withNoSsr.tsx diff --git a/services/cms/src/shared-module-v2/common/bindings.guard.ts b/services/cms/src/shared-module-v2/common/bindings.guard.ts new file mode 100644 index 000000000000..4c323786ad37 --- /dev/null +++ b/services/cms/src/shared-module-v2/common/bindings.guard.ts @@ -0,0 +1,3360 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ + +/* + * Generated type guards for "bindings.ts". + * WARNING: Do not manually change this file. + */ +import { + Action, + ActionOnResource, + ActivityProgress, + AnswerRequiringAttention, + AnswerRequiringAttentionWithTasks, + AnswersRequiringAttention, + AutomaticCompletionRequirements, + BlockProposal, + BlockProposalAction, + BlockProposalInfo, + CertificateAllRequirements, + CertificateConfiguration, + CertificateConfigurationAndRequirements, + CertificateConfigurationUpdate, + CertificateTextAnchor, + Chapter, + ChapterScore, + ChapterStatus, + ChaptersWithStatus, + ChapterUpdate, + ChapterWithStatus, + CmsPageExercise, + CmsPageExerciseSlide, + CmsPageExerciseTask, + CmsPageUpdate, + CmsPeerReviewConfig, + CmsPeerReviewConfiguration, + CmsPeerReviewQuestion, + CompletionPolicy, + CompletionRegistrationLink, + ContentManagementPage, + Course, + CourseBackgroundQuestion, + CourseBackgroundQuestionAnswer, + CourseBackgroundQuestionsAndAnswers, + CourseBackgroundQuestionType, + CourseBreadcrumbInfo, + CourseCount, + CourseExam, + CourseInstance, + CourseInstanceCompletionSummary, + CourseInstanceEnrollment, + CourseInstanceEnrollmentsInfo, + CourseInstanceForm, + CourseMaterialCourseModule, + CourseMaterialExercise, + CourseMaterialExerciseServiceInfo, + CourseMaterialExerciseSlide, + CourseMaterialExerciseTask, + CourseMaterialPeerReviewConfig, + CourseMaterialPeerReviewData, + CourseMaterialPeerReviewDataAnswerToReview, + CourseMaterialPeerReviewDataWithToken, + CourseMaterialPeerReviewQuestionAnswer, + CourseMaterialPeerReviewSubmission, + CourseModule, + CourseModuleCompletion, + CourseModuleCompletionWithRegistrationInfo, + CoursePageWithUserData, + CourseStructure, + CourseUpdate, + CreateAccountDetails, + DatabaseChapter, + EditedBlockNoLongerExistsData, + EditedBlockStillExistsData, + EditProposalInfo, + EmailTemplate, + EmailTemplateNew, + EmailTemplateUpdate, + ErrorData, + ErrorResponse, + Exam, + ExamCourseInfo, + ExamData, + ExamEnrollment, + ExamEnrollmentData, + ExamInstructions, + ExamInstructionsUpdate, + Exercise, + ExerciseAnswersInCourseRequiringAttentionCount, + ExerciseGradingStatus, + ExerciseRepository, + ExerciseRepositoryStatus, + ExerciseService, + ExerciseServiceIframeRenderingInfo, + ExerciseServiceInfoApi, + ExerciseServiceNewOrUpdate, + ExerciseSlide, + ExerciseSlideSubmission, + ExerciseSlideSubmissionCount, + ExerciseSlideSubmissionCountByExercise, + ExerciseSlideSubmissionCountByWeekAndHour, + ExerciseSlideSubmissionInfo, + ExerciseStatus, + ExerciseStatusSummaryForUser, + ExerciseSubmissions, + ExerciseTask, + ExerciseTaskGrading, + ExerciseTaskGradingResult, + ExerciseTaskSubmission, + ExerciseUserCounts, + ExerciseWithExerciseTasks, + Feedback, + FeedbackBlock, + FeedbackCount, + GeneratedCertificate, + GetEditProposalsQuery, + GetFeedbackQuery, + GlobalStatEntry, + GradingProgress, + HistoryChangeReason, + HistoryRestoreData, + IsChapterFrontPage, + Login, + ManualCompletionPreview, + ManualCompletionPreviewUser, + MarkAsRead, + MaterialReference, + ModifiedModule, + ModuleUpdates, + NewChapter, + NewCourse, + NewCourseBackgroundQuestionAnswer, + NewCourseModule, + NewExam, + NewExerciseRepository, + NewFeedback, + NewMaterialReference, + NewModule, + NewPage, + NewProposedBlockEdit, + NewProposedPageEdits, + NewRegrading, + NewResearchForm, + NewResearchFormQuestion, + NewResearchFormQuestionAnswer, + NewTeacherGradingDecision, + OEmbedResponse, + Organization, + OrgExam, + Page, + PageAudioFile, + PageChapterAndCourseInformation, + PageDetailsUpdate, + PageHistory, + PageInfo, + PageNavigationInformation, + PageProposal, + PageRoutingData, + PageSearchResult, + PageVisitDatumSummaryByCourse, + PageVisitDatumSummaryByCourseDeviceTypes, + PageVisitDatumSummaryByCoursesCountries, + PageVisitDatumSummaryByPages, + PageWithExercises, + Pagination, + PaperSize, + PeerReviewAnswer, + PeerReviewConfig, + PeerReviewProcessingStrategy, + PeerReviewQuestion, + PeerReviewQuestionAndAnswer, + PeerReviewQuestionSubmission, + PeerReviewQuestionType, + PeerReviewQueueEntry, + PeerReviewsRecieved, + PeerReviewSubmission, + PeerReviewWithQuestionsAndAnswers, + PendingRole, + PlaygroundExample, + PlaygroundExampleData, + PlaygroundViewsMessage, + PointMap, + Points, + ProposalCount, + ProposalStatus, + Regrading, + RegradingInfo, + RegradingSubmissionInfo, + RepositoryExercise, + ResearchForm, + ResearchFormQuestion, + ResearchFormQuestionAnswer, + Resource, + ReviewingStage, + RoleDomain, + RoleInfo, + RoleQuery, + RoleUser, + SaveCourseSettingsPayload, + SearchRequest, + SpecRequest, + StudentCountry, + StudentExerciseSlideSubmission, + StudentExerciseSlideSubmissionResult, + StudentExerciseTaskSubmission, + StudentExerciseTaskSubmissionResult, + TeacherDecisionType, + TeacherGradingDecision, + TeacherManualCompletion, + TeacherManualCompletionRequest, + Term, + TermUpdate, + UploadResult, + User, + UserCompletionInformation, + UserCourseInstanceChapterExerciseProgress, + UserCourseInstanceChapterProgress, + UserCourseInstanceExerciseServiceVariable, + UserCourseInstanceProgress, + UserCourseModuleCompletion, + UserCourseSettings, + UserDetail, + UserExerciseState, + UserInfo, + UserModuleCompletionStatus, + UserPointsUpdateStrategy, + UserResearchConsent, + UserRole, + UserWithModuleCompletions, +} from "./bindings" + +export function isAction(obj: unknown): obj is Action { + const typedObj = obj as Action + return ( + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "view_material") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "view") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "edit") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "grade") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "teach") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "download") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "duplicate") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "delete_answer") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "edit_role" && + (isUserRole(typedObj["variant"]) as boolean)) || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "create_courses_or_exams") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "usually_unacceptable_deletion") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "upload_file") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "view_user_progress_or_details") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "view_internal_course_structure") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "view_stats") + ) +} + +export function isActionOnResource(obj: unknown): obj is ActionOnResource { + const typedObj = obj as ActionOnResource + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + (isAction(typedObj["action"]) as boolean) && + (isResource(typedObj["resource"]) as boolean) + ) +} + +export function isResource(obj: unknown): obj is Resource { + const typedObj = obj as Resource + return ( + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "global_permissions") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "chapter" && + typeof typedObj["id"] === "string") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "course" && + typeof typedObj["id"] === "string") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "course_instance" && + typeof typedObj["id"] === "string") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "exam" && + typeof typedObj["id"] === "string") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "exercise" && + typeof typedObj["id"] === "string") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "exercise_slide_submission" && + typeof typedObj["id"] === "string") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "exercise_task" && + typeof typedObj["id"] === "string") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "exercise_task_grading" && + typeof typedObj["id"] === "string") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "exercise_task_submission" && + typeof typedObj["id"] === "string") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "organization" && + typeof typedObj["id"] === "string") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "page" && + typeof typedObj["id"] === "string") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "study_registry" && + typeof typedObj["id"] === "string") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "any_course") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "role") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "user") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "playground_example") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "exercise_service") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "material_reference") + ) +} + +export function isErrorData(obj: unknown): obj is ErrorData { + const typedObj = obj as ErrorData + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["block_id"] === "string" + ) +} + +export function isErrorResponse(obj: unknown): obj is ErrorResponse { + const typedObj = obj as ErrorResponse + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["title"] === "string" && + typeof typedObj["message"] === "string" && + (typedObj["source"] === null || typeof typedObj["source"] === "string") && + (typedObj["data"] === null || (isErrorData(typedObj["data"]) as boolean)) + ) +} + +export function isSpecRequest(obj: unknown): obj is SpecRequest { + const typedObj = obj as SpecRequest + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["request_id"] === "string" && + (typedObj["upload_url"] === null || typeof typedObj["upload_url"] === "string") + ) +} + +export function isChapter(obj: unknown): obj is Chapter { + const typedObj = obj as Chapter + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + typeof typedObj["name"] === "string" && + (typedObj["color"] === null || typeof typedObj["color"] === "string") && + typeof typedObj["course_id"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + (typedObj["chapter_image_url"] === null || typeof typedObj["chapter_image_url"] === "string") && + typeof typedObj["chapter_number"] === "number" && + (typedObj["front_page_id"] === null || typeof typedObj["front_page_id"] === "string") && + (typedObj["opens_at"] === null || typeof typedObj["opens_at"] === "string") && + (typedObj["deadline"] === null || typeof typedObj["deadline"] === "string") && + (typedObj["copied_from"] === null || typeof typedObj["copied_from"] === "string") && + typeof typedObj["course_module_id"] === "string" + ) +} + +export function isChapterStatus(obj: unknown): obj is ChapterStatus { + const typedObj = obj as ChapterStatus + return typedObj === "open" || typedObj === "closed" +} + +export function isChapterUpdate(obj: unknown): obj is ChapterUpdate { + const typedObj = obj as ChapterUpdate + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["name"] === "string" && + (typedObj["color"] === null || typeof typedObj["color"] === "string") && + (typedObj["front_page_id"] === null || typeof typedObj["front_page_id"] === "string") && + (typedObj["deadline"] === null || typeof typedObj["deadline"] === "string") && + (typedObj["opens_at"] === null || typeof typedObj["opens_at"] === "string") && + (typedObj["course_module_id"] === null || typeof typedObj["course_module_id"] === "string") + ) +} + +export function isChapterWithStatus(obj: unknown): obj is ChapterWithStatus { + const typedObj = obj as ChapterWithStatus + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + typeof typedObj["name"] === "string" && + (typedObj["color"] === null || typeof typedObj["color"] === "string") && + typeof typedObj["course_id"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + typeof typedObj["chapter_number"] === "number" && + (typedObj["front_page_id"] === null || typeof typedObj["front_page_id"] === "string") && + (typedObj["opens_at"] === null || typeof typedObj["opens_at"] === "string") && + (isChapterStatus(typedObj["status"]) as boolean) && + (typedObj["chapter_image_url"] === null || typeof typedObj["chapter_image_url"] === "string") && + typeof typedObj["course_module_id"] === "string" + ) +} + +export function isDatabaseChapter(obj: unknown): obj is DatabaseChapter { + const typedObj = obj as DatabaseChapter + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + typeof typedObj["name"] === "string" && + (typedObj["color"] === null || typeof typedObj["color"] === "string") && + typeof typedObj["course_id"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + (typedObj["chapter_image_path"] === null || + typeof typedObj["chapter_image_path"] === "string") && + typeof typedObj["chapter_number"] === "number" && + (typedObj["front_page_id"] === null || typeof typedObj["front_page_id"] === "string") && + (typedObj["opens_at"] === null || typeof typedObj["opens_at"] === "string") && + (typedObj["deadline"] === null || typeof typedObj["deadline"] === "string") && + (typedObj["copied_from"] === null || typeof typedObj["copied_from"] === "string") && + typeof typedObj["course_module_id"] === "string" + ) +} + +export function isNewChapter(obj: unknown): obj is NewChapter { + const typedObj = obj as NewChapter + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["name"] === "string" && + (typedObj["color"] === null || typeof typedObj["color"] === "string") && + typeof typedObj["course_id"] === "string" && + typeof typedObj["chapter_number"] === "number" && + (typedObj["front_page_id"] === null || typeof typedObj["front_page_id"] === "string") && + (typedObj["opens_at"] === null || typeof typedObj["opens_at"] === "string") && + (typedObj["deadline"] === null || typeof typedObj["deadline"] === "string") && + (typedObj["course_module_id"] === null || typeof typedObj["course_module_id"] === "string") + ) +} + +export function isUserCourseInstanceChapterProgress( + obj: unknown, +): obj is UserCourseInstanceChapterProgress { + const typedObj = obj as UserCourseInstanceChapterProgress + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["score_given"] === "number" && + typeof typedObj["score_maximum"] === "number" && + (typedObj["total_exercises"] === null || typeof typedObj["total_exercises"] === "number") && + (typedObj["attempted_exercises"] === null || + typeof typedObj["attempted_exercises"] === "number") + ) +} + +export function isCourseBackgroundQuestionAnswer( + obj: unknown, +): obj is CourseBackgroundQuestionAnswer { + const typedObj = obj as CourseBackgroundQuestionAnswer + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + typeof typedObj["course_background_question_id"] === "string" && + (typedObj["answer_value"] === null || typeof typedObj["answer_value"] === "string") && + typeof typedObj["user_id"] === "string" + ) +} + +export function isNewCourseBackgroundQuestionAnswer( + obj: unknown, +): obj is NewCourseBackgroundQuestionAnswer { + const typedObj = obj as NewCourseBackgroundQuestionAnswer + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + (typedObj["answer_value"] === null || typeof typedObj["answer_value"] === "string") && + typeof typedObj["course_background_question_id"] === "string" + ) +} + +export function isCourseBackgroundQuestion(obj: unknown): obj is CourseBackgroundQuestion { + const typedObj = obj as CourseBackgroundQuestion + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + (typedObj["course_instance_id"] === null || + typeof typedObj["course_instance_id"] === "string") && + typeof typedObj["course_id"] === "string" && + typeof typedObj["question_text"] === "string" && + (isCourseBackgroundQuestionType(typedObj["question_type"]) as boolean) + ) +} + +export function isCourseBackgroundQuestionType(obj: unknown): obj is CourseBackgroundQuestionType { + const typedObj = obj as CourseBackgroundQuestionType + return typedObj === "Checkbox" || typedObj === "Text" +} + +export function isCourseBackgroundQuestionsAndAnswers( + obj: unknown, +): obj is CourseBackgroundQuestionsAndAnswers { + const typedObj = obj as CourseBackgroundQuestionsAndAnswers + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + Array.isArray(typedObj["background_questions"]) && + typedObj["background_questions"].every((e: any) => isCourseBackgroundQuestion(e) as boolean) && + Array.isArray(typedObj["answers"]) && + typedObj["answers"].every((e: any) => isCourseBackgroundQuestionAnswer(e) as boolean) + ) +} + +export function isCourseInstanceEnrollment(obj: unknown): obj is CourseInstanceEnrollment { + const typedObj = obj as CourseInstanceEnrollment + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["user_id"] === "string" && + typeof typedObj["course_id"] === "string" && + typeof typedObj["course_instance_id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") + ) +} + +export function isCourseInstanceEnrollmentsInfo( + obj: unknown, +): obj is CourseInstanceEnrollmentsInfo { + const typedObj = obj as CourseInstanceEnrollmentsInfo + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + Array.isArray(typedObj["course_instance_enrollments"]) && + typedObj["course_instance_enrollments"].every( + (e: any) => isCourseInstanceEnrollment(e) as boolean, + ) && + Array.isArray(typedObj["course_instances"]) && + typedObj["course_instances"].every((e: any) => isCourseInstance(e) as boolean) && + Array.isArray(typedObj["courses"]) && + typedObj["courses"].every((e: any) => isCourse(e) as boolean) && + Array.isArray(typedObj["user_course_settings"]) && + typedObj["user_course_settings"].every((e: any) => isUserCourseSettings(e) as boolean) && + Array.isArray(typedObj["course_module_completions"]) && + typedObj["course_module_completions"].every((e: any) => isCourseModuleCompletion(e) as boolean) + ) +} + +export function isChapterScore(obj: unknown): obj is ChapterScore { + const typedObj = obj as ChapterScore + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + typeof typedObj["name"] === "string" && + (typedObj["color"] === null || typeof typedObj["color"] === "string") && + typeof typedObj["course_id"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + (typedObj["chapter_image_path"] === null || + typeof typedObj["chapter_image_path"] === "string") && + typeof typedObj["chapter_number"] === "number" && + (typedObj["front_page_id"] === null || typeof typedObj["front_page_id"] === "string") && + (typedObj["opens_at"] === null || typeof typedObj["opens_at"] === "string") && + (typedObj["deadline"] === null || typeof typedObj["deadline"] === "string") && + (typedObj["copied_from"] === null || typeof typedObj["copied_from"] === "string") && + typeof typedObj["course_module_id"] === "string" && + typeof typedObj["score_given"] === "number" && + typeof typedObj["score_total"] === "number" + ) +} + +export function isCourseInstance(obj: unknown): obj is CourseInstance { + const typedObj = obj as CourseInstance + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + typeof typedObj["course_id"] === "string" && + (typedObj["starts_at"] === null || typeof typedObj["starts_at"] === "string") && + (typedObj["ends_at"] === null || typeof typedObj["ends_at"] === "string") && + (typedObj["name"] === null || typeof typedObj["name"] === "string") && + (typedObj["description"] === null || typeof typedObj["description"] === "string") && + typeof typedObj["teacher_in_charge_name"] === "string" && + typeof typedObj["teacher_in_charge_email"] === "string" && + (typedObj["support_email"] === null || typeof typedObj["support_email"] === "string") + ) +} + +export function isCourseInstanceForm(obj: unknown): obj is CourseInstanceForm { + const typedObj = obj as CourseInstanceForm + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + (typedObj["name"] === null || typeof typedObj["name"] === "string") && + (typedObj["description"] === null || typeof typedObj["description"] === "string") && + typeof typedObj["teacher_in_charge_name"] === "string" && + typeof typedObj["teacher_in_charge_email"] === "string" && + (typedObj["support_email"] === null || typeof typedObj["support_email"] === "string") && + (typedObj["opening_time"] === null || typeof typedObj["opening_time"] === "string") && + (typedObj["closing_time"] === null || typeof typedObj["closing_time"] === "string") + ) +} + +export function isPointMap(obj: unknown): obj is PointMap { + const typedObj = obj as PointMap + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + Object.entries(typedObj).every( + ([key, value]) => typeof value === "number" && typeof key === "string", + ) + ) +} + +export function isPoints(obj: unknown): obj is Points { + const typedObj = obj as Points + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + Array.isArray(typedObj["chapter_points"]) && + typedObj["chapter_points"].every((e: any) => isChapterScore(e) as boolean) && + Array.isArray(typedObj["users"]) && + typedObj["users"].every((e: any) => isUserDetail(e) as boolean) && + ((typedObj["user_chapter_points"] !== null && + typeof typedObj["user_chapter_points"] === "object") || + typeof typedObj["user_chapter_points"] === "function") && + Object.entries(typedObj["user_chapter_points"]).every( + ([key, value]) => (isPointMap(value) as boolean) && typeof key === "string", + ) + ) +} + +export function isGeneratedCertificate(obj: unknown): obj is GeneratedCertificate { + const typedObj = obj as GeneratedCertificate + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + typeof typedObj["user_id"] === "string" && + typeof typedObj["name_on_certificate"] === "string" && + typeof typedObj["verification_id"] === "string" && + typeof typedObj["certificate_configuration_id"] === "string" + ) +} + +export function isCertificateConfiguration(obj: unknown): obj is CertificateConfiguration { + const typedObj = obj as CertificateConfiguration + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + typeof typedObj["certificate_owner_name_y_pos"] === "string" && + typeof typedObj["certificate_owner_name_x_pos"] === "string" && + typeof typedObj["certificate_owner_name_font_size"] === "string" && + typeof typedObj["certificate_owner_name_text_color"] === "string" && + (isCertificateTextAnchor(typedObj["certificate_owner_name_text_anchor"]) as boolean) && + typeof typedObj["certificate_validate_url_y_pos"] === "string" && + typeof typedObj["certificate_validate_url_x_pos"] === "string" && + typeof typedObj["certificate_validate_url_font_size"] === "string" && + typeof typedObj["certificate_validate_url_text_color"] === "string" && + (isCertificateTextAnchor(typedObj["certificate_validate_url_text_anchor"]) as boolean) && + typeof typedObj["certificate_date_y_pos"] === "string" && + typeof typedObj["certificate_date_x_pos"] === "string" && + typeof typedObj["certificate_date_font_size"] === "string" && + typeof typedObj["certificate_date_text_color"] === "string" && + (isCertificateTextAnchor(typedObj["certificate_date_text_anchor"]) as boolean) && + typeof typedObj["certificate_locale"] === "string" && + (isPaperSize(typedObj["paper_size"]) as boolean) && + typeof typedObj["background_svg_path"] === "string" && + typeof typedObj["background_svg_file_upload_id"] === "string" && + (typedObj["overlay_svg_path"] === null || typeof typedObj["overlay_svg_path"] === "string") && + (typedObj["overlay_svg_file_upload_id"] === null || + typeof typedObj["overlay_svg_file_upload_id"] === "string") + ) +} + +export function isCertificateTextAnchor(obj: unknown): obj is CertificateTextAnchor { + const typedObj = obj as CertificateTextAnchor + return typedObj === "start" || typedObj === "middle" || typedObj === "end" +} + +export function isPaperSize(obj: unknown): obj is PaperSize { + const typedObj = obj as PaperSize + return typedObj === "horizontal-a4" || typedObj === "vertical-a4" +} + +export function isCourseModuleCompletionWithRegistrationInfo( + obj: unknown, +): obj is CourseModuleCompletionWithRegistrationInfo { + const typedObj = obj as CourseModuleCompletionWithRegistrationInfo + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + (typedObj["completion_registration_attempt_date"] === null || + typeof typedObj["completion_registration_attempt_date"] === "string") && + typeof typedObj["course_module_id"] === "string" && + typeof typedObj["created_at"] === "string" && + (typedObj["grade"] === null || typeof typedObj["grade"] === "number") && + typeof typedObj["passed"] === "boolean" && + typeof typedObj["prerequisite_modules_completed"] === "boolean" && + typeof typedObj["registered"] === "boolean" && + typeof typedObj["user_id"] === "string" + ) +} + +export function isCourseModuleCompletion(obj: unknown): obj is CourseModuleCompletion { + const typedObj = obj as CourseModuleCompletion + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + typeof typedObj["course_id"] === "string" && + typeof typedObj["course_instance_id"] === "string" && + typeof typedObj["course_module_id"] === "string" && + typeof typedObj["user_id"] === "string" && + typeof typedObj["completion_date"] === "string" && + (typedObj["completion_registration_attempt_date"] === null || + typeof typedObj["completion_registration_attempt_date"] === "string") && + typeof typedObj["completion_language"] === "string" && + typeof typedObj["eligible_for_ects"] === "boolean" && + typeof typedObj["email"] === "string" && + (typedObj["grade"] === null || typeof typedObj["grade"] === "number") && + typeof typedObj["passed"] === "boolean" && + typeof typedObj["prerequisite_modules_completed"] === "boolean" && + (typedObj["completion_granter_user_id"] === null || + typeof typedObj["completion_granter_user_id"] === "string") + ) +} + +export function isAutomaticCompletionRequirements( + obj: unknown, +): obj is AutomaticCompletionRequirements { + const typedObj = obj as AutomaticCompletionRequirements + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["course_module_id"] === "string" && + (typedObj["number_of_exercises_attempted_treshold"] === null || + typeof typedObj["number_of_exercises_attempted_treshold"] === "number") && + (typedObj["number_of_points_treshold"] === null || + typeof typedObj["number_of_points_treshold"] === "number") && + typeof typedObj["requires_exam"] === "boolean" + ) +} + +export function isCompletionPolicy(obj: unknown): obj is CompletionPolicy { + const typedObj = obj as CompletionPolicy + return ( + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["policy"] === "automatic" && + (isAutomaticCompletionRequirements(typedObj) as boolean)) || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["policy"] === "manual") + ) +} + +export function isCourseModule(obj: unknown): obj is CourseModule { + const typedObj = obj as CourseModule + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + (typedObj["name"] === null || typeof typedObj["name"] === "string") && + typeof typedObj["course_id"] === "string" && + typeof typedObj["order_number"] === "number" && + (typedObj["copied_from"] === null || typeof typedObj["copied_from"] === "string") && + (typedObj["uh_course_code"] === null || typeof typedObj["uh_course_code"] === "string") && + (isCompletionPolicy(typedObj["completion_policy"]) as boolean) && + (typedObj["completion_registration_link_override"] === null || + typeof typedObj["completion_registration_link_override"] === "string") && + (typedObj["ects_credits"] === null || typeof typedObj["ects_credits"] === "number") && + typeof typedObj["enable_registering_completion_to_uh_open_university"] === "boolean" && + typeof typedObj["certification_enabled"] === "boolean" + ) +} + +export function isModifiedModule(obj: unknown): obj is ModifiedModule { + const typedObj = obj as ModifiedModule + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + (typedObj["name"] === null || typeof typedObj["name"] === "string") && + typeof typedObj["order_number"] === "number" && + (typedObj["uh_course_code"] === null || typeof typedObj["uh_course_code"] === "string") && + (typedObj["ects_credits"] === null || typeof typedObj["ects_credits"] === "number") && + (isCompletionPolicy(typedObj["completion_policy"]) as boolean) && + (typedObj["completion_registration_link_override"] === null || + typeof typedObj["completion_registration_link_override"] === "string") && + typeof typedObj["enable_registering_completion_to_uh_open_university"] === "boolean" + ) +} + +export function isModuleUpdates(obj: unknown): obj is ModuleUpdates { + const typedObj = obj as ModuleUpdates + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + Array.isArray(typedObj["new_modules"]) && + typedObj["new_modules"].every((e: any) => isNewModule(e) as boolean) && + Array.isArray(typedObj["deleted_modules"]) && + typedObj["deleted_modules"].every((e: any) => typeof e === "string") && + Array.isArray(typedObj["modified_modules"]) && + typedObj["modified_modules"].every((e: any) => isModifiedModule(e) as boolean) && + Array.isArray(typedObj["moved_chapters"]) && + typedObj["moved_chapters"].every( + (e: any) => Array.isArray(e) && typeof e[0] === "string" && typeof e[1] === "string", + ) + ) +} + +export function isNewCourseModule(obj: unknown): obj is NewCourseModule { + const typedObj = obj as NewCourseModule + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + (isCompletionPolicy(typedObj["completion_policy"]) as boolean) && + (typedObj["completion_registration_link_override"] === null || + typeof typedObj["completion_registration_link_override"] === "string") && + typeof typedObj["course_id"] === "string" && + (typedObj["ects_credits"] === null || typeof typedObj["ects_credits"] === "number") && + (typedObj["name"] === null || typeof typedObj["name"] === "string") && + typeof typedObj["order_number"] === "number" && + (typedObj["uh_course_code"] === null || typeof typedObj["uh_course_code"] === "string") && + typeof typedObj["enable_registering_completion_to_uh_open_university"] === "boolean" + ) +} + +export function isNewModule(obj: unknown): obj is NewModule { + const typedObj = obj as NewModule + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["name"] === "string" && + typeof typedObj["order_number"] === "number" && + Array.isArray(typedObj["chapters"]) && + typedObj["chapters"].every((e: any) => typeof e === "string") && + (typedObj["uh_course_code"] === null || typeof typedObj["uh_course_code"] === "string") && + (typedObj["ects_credits"] === null || typeof typedObj["ects_credits"] === "number") && + (isCompletionPolicy(typedObj["completion_policy"]) as boolean) && + (typedObj["completion_registration_link_override"] === null || + typeof typedObj["completion_registration_link_override"] === "string") && + typeof typedObj["enable_registering_completion_to_uh_open_university"] === "boolean" + ) +} + +export function isCourse(obj: unknown): obj is Course { + const typedObj = obj as Course + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["slug"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + typeof typedObj["name"] === "string" && + (typedObj["description"] === null || typeof typedObj["description"] === "string") && + typeof typedObj["organization_id"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + typeof typedObj["language_code"] === "string" && + (typedObj["copied_from"] === null || typeof typedObj["copied_from"] === "string") && + (typedObj["content_search_language"] === null || + typeof typedObj["content_search_language"] === "string") && + typeof typedObj["course_language_group_id"] === "string" && + typeof typedObj["is_draft"] === "boolean" && + typeof typedObj["is_test_mode"] === "boolean" && + typeof typedObj["base_module_completion_requires_n_submodule_completions"] === "number" + ) +} + +export function isCourseCount(obj: unknown): obj is CourseCount { + const typedObj = obj as CourseCount + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["count"] === "number" + ) +} + +export function isCourseStructure(obj: unknown): obj is CourseStructure { + const typedObj = obj as CourseStructure + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + (isCourse(typedObj["course"]) as boolean) && + Array.isArray(typedObj["pages"]) && + typedObj["pages"].every((e: any) => isPage(e) as boolean) && + Array.isArray(typedObj["chapters"]) && + typedObj["chapters"].every((e: any) => isChapter(e) as boolean) && + Array.isArray(typedObj["modules"]) && + typedObj["modules"].every((e: any) => isCourseModule(e) as boolean) + ) +} + +export function isCourseUpdate(obj: unknown): obj is CourseUpdate { + const typedObj = obj as CourseUpdate + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["name"] === "string" && + (typedObj["description"] === null || typeof typedObj["description"] === "string") && + typeof typedObj["is_draft"] === "boolean" && + typeof typedObj["is_test_mode"] === "boolean" + ) +} + +export function isNewCourse(obj: unknown): obj is NewCourse { + const typedObj = obj as NewCourse + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["name"] === "string" && + typeof typedObj["slug"] === "string" && + typeof typedObj["organization_id"] === "string" && + typeof typedObj["language_code"] === "string" && + typeof typedObj["teacher_in_charge_name"] === "string" && + typeof typedObj["teacher_in_charge_email"] === "string" && + typeof typedObj["description"] === "string" && + typeof typedObj["is_draft"] === "boolean" && + typeof typedObj["is_test_mode"] === "boolean" && + typeof typedObj["copy_user_permissions"] === "boolean" + ) +} + +export function isCourseBreadcrumbInfo(obj: unknown): obj is CourseBreadcrumbInfo { + const typedObj = obj as CourseBreadcrumbInfo + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["course_id"] === "string" && + typeof typedObj["course_name"] === "string" && + typeof typedObj["course_slug"] === "string" && + typeof typedObj["organization_slug"] === "string" && + typeof typedObj["organization_name"] === "string" + ) +} + +export function isCertificateConfigurationAndRequirements( + obj: unknown, +): obj is CertificateConfigurationAndRequirements { + const typedObj = obj as CertificateConfigurationAndRequirements + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + (isCertificateConfiguration(typedObj["certificate_configuration"]) as boolean) && + (isCertificateAllRequirements(typedObj["requirements"]) as boolean) + ) +} + +export function isCertificateAllRequirements(obj: unknown): obj is CertificateAllRequirements { + const typedObj = obj as CertificateAllRequirements + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["certificate_configuration_id"] === "string" && + Array.isArray(typedObj["course_module_ids"]) && + typedObj["course_module_ids"].every((e: any) => typeof e === "string") && + Array.isArray(typedObj["course_instance_ids"]) && + typedObj["course_instance_ids"].every((e: any) => typeof e === "string") + ) +} + +export function isEmailTemplate(obj: unknown): obj is EmailTemplate { + const typedObj = obj as EmailTemplate + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + typeof typedObj["name"] === "string" && + (typedObj["subject"] === null || typeof typedObj["subject"] === "string") && + (typedObj["exercise_completions_threshold"] === null || + typeof typedObj["exercise_completions_threshold"] === "number") && + (typedObj["points_threshold"] === null || typeof typedObj["points_threshold"] === "number") && + typeof typedObj["course_instance_id"] === "string" + ) +} + +export function isEmailTemplateNew(obj: unknown): obj is EmailTemplateNew { + const typedObj = obj as EmailTemplateNew + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["name"] === "string" + ) +} + +export function isEmailTemplateUpdate(obj: unknown): obj is EmailTemplateUpdate { + const typedObj = obj as EmailTemplateUpdate + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["name"] === "string" && + typeof typedObj["subject"] === "string" && + (typedObj["exercise_completions_threshold"] === null || + typeof typedObj["exercise_completions_threshold"] === "number") && + (typedObj["points_threshold"] === null || typeof typedObj["points_threshold"] === "number") + ) +} + +export function isCourseExam(obj: unknown): obj is CourseExam { + const typedObj = obj as CourseExam + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["course_id"] === "string" && + typeof typedObj["course_name"] === "string" && + typeof typedObj["name"] === "string" + ) +} + +export function isExam(obj: unknown): obj is Exam { + const typedObj = obj as Exam + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["name"] === "string" && + typeof typedObj["page_id"] === "string" && + Array.isArray(typedObj["courses"]) && + typedObj["courses"].every((e: any) => isCourse(e) as boolean) && + (typedObj["starts_at"] === null || typeof typedObj["starts_at"] === "string") && + (typedObj["ends_at"] === null || typeof typedObj["ends_at"] === "string") && + typeof typedObj["time_minutes"] === "number" && + typeof typedObj["minimum_points_treshold"] === "number" && + typeof typedObj["language"] === "string" + ) +} + +export function isExamEnrollment(obj: unknown): obj is ExamEnrollment { + const typedObj = obj as ExamEnrollment + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["user_id"] === "string" && + typeof typedObj["exam_id"] === "string" && + typeof typedObj["started_at"] === "string" + ) +} + +export function isExamInstructions(obj: unknown): obj is ExamInstructions { + const typedObj = obj as ExamInstructions + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" + ) +} + +export function isExamInstructionsUpdate(obj: unknown): obj is ExamInstructionsUpdate { + const typedObj = obj as ExamInstructionsUpdate + return (typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function" +} + +export function isNewExam(obj: unknown): obj is NewExam { + const typedObj = obj as NewExam + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["name"] === "string" && + (typedObj["starts_at"] === null || typeof typedObj["starts_at"] === "string") && + (typedObj["ends_at"] === null || typeof typedObj["ends_at"] === "string") && + typeof typedObj["time_minutes"] === "number" && + typeof typedObj["organization_id"] === "string" && + typeof typedObj["minimum_points_treshold"] === "number" + ) +} + +export function isOrgExam(obj: unknown): obj is OrgExam { + const typedObj = obj as OrgExam + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["name"] === "string" && + (typedObj["starts_at"] === null || typeof typedObj["starts_at"] === "string") && + (typedObj["ends_at"] === null || typeof typedObj["ends_at"] === "string") && + typeof typedObj["time_minutes"] === "number" && + typeof typedObj["organization_id"] === "string" && + typeof typedObj["minimum_points_treshold"] === "number" + ) +} + +export function isExerciseRepository(obj: unknown): obj is ExerciseRepository { + const typedObj = obj as ExerciseRepository + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["url"] === "string" && + (typedObj["course_id"] === null || typeof typedObj["course_id"] === "string") && + (typedObj["exam_id"] === null || typeof typedObj["exam_id"] === "string") && + (isExerciseRepositoryStatus(typedObj["status"]) as boolean) && + (typedObj["error_message"] === null || typeof typedObj["error_message"] === "string") + ) +} + +export function isExerciseRepositoryStatus(obj: unknown): obj is ExerciseRepositoryStatus { + const typedObj = obj as ExerciseRepositoryStatus + return typedObj === "Pending" || typedObj === "Success" || typedObj === "Failure" +} + +export function isCourseMaterialExerciseServiceInfo( + obj: unknown, +): obj is CourseMaterialExerciseServiceInfo { + const typedObj = obj as CourseMaterialExerciseServiceInfo + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["exercise_iframe_url"] === "string" + ) +} + +export function isExerciseServiceInfoApi(obj: unknown): obj is ExerciseServiceInfoApi { + const typedObj = obj as ExerciseServiceInfoApi + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["service_name"] === "string" && + typeof typedObj["user_interface_iframe_path"] === "string" && + typeof typedObj["grade_endpoint_path"] === "string" && + typeof typedObj["public_spec_endpoint_path"] === "string" && + typeof typedObj["model_solution_spec_endpoint_path"] === "string" + ) +} + +export function isExerciseService(obj: unknown): obj is ExerciseService { + const typedObj = obj as ExerciseService + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + typeof typedObj["name"] === "string" && + typeof typedObj["slug"] === "string" && + typeof typedObj["public_url"] === "string" && + (typedObj["internal_url"] === null || typeof typedObj["internal_url"] === "string") && + typeof typedObj["max_reprocessing_submissions_at_once"] === "number" + ) +} + +export function isExerciseServiceIframeRenderingInfo( + obj: unknown, +): obj is ExerciseServiceIframeRenderingInfo { + const typedObj = obj as ExerciseServiceIframeRenderingInfo + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["name"] === "string" && + typeof typedObj["slug"] === "string" && + typeof typedObj["public_iframe_url"] === "string" + ) +} + +export function isExerciseServiceNewOrUpdate(obj: unknown): obj is ExerciseServiceNewOrUpdate { + const typedObj = obj as ExerciseServiceNewOrUpdate + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["name"] === "string" && + typeof typedObj["slug"] === "string" && + typeof typedObj["public_url"] === "string" && + (typedObj["internal_url"] === null || typeof typedObj["internal_url"] === "string") && + typeof typedObj["max_reprocessing_submissions_at_once"] === "number" + ) +} + +export function isAnswerRequiringAttention(obj: unknown): obj is AnswerRequiringAttention { + const typedObj = obj as AnswerRequiringAttention + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["user_id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + (typedObj["course_instance_id"] === null || + typeof typedObj["course_instance_id"] === "string") && + (isGradingProgress(typedObj["grading_progress"]) as boolean) && + (typedObj["score_given"] === null || typeof typedObj["score_given"] === "number") && + typeof typedObj["submission_id"] === "string" && + typeof typedObj["exercise_id"] === "string" + ) +} + +export function isExerciseAnswersInCourseRequiringAttentionCount( + obj: unknown, +): obj is ExerciseAnswersInCourseRequiringAttentionCount { + const typedObj = obj as ExerciseAnswersInCourseRequiringAttentionCount + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["name"] === "string" && + typeof typedObj["page_id"] === "string" && + (typedObj["chapter_id"] === null || typeof typedObj["chapter_id"] === "string") && + typeof typedObj["order_number"] === "number" && + (typedObj["count"] === null || typeof typedObj["count"] === "number") + ) +} + +export function isExerciseSlideSubmission(obj: unknown): obj is ExerciseSlideSubmission { + const typedObj = obj as ExerciseSlideSubmission + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + typeof typedObj["exercise_slide_id"] === "string" && + (typedObj["course_id"] === null || typeof typedObj["course_id"] === "string") && + (typedObj["course_instance_id"] === null || + typeof typedObj["course_instance_id"] === "string") && + (typedObj["exam_id"] === null || typeof typedObj["exam_id"] === "string") && + typeof typedObj["exercise_id"] === "string" && + typeof typedObj["user_id"] === "string" && + (isUserPointsUpdateStrategy(typedObj["user_points_update_strategy"]) as boolean) + ) +} + +export function isExerciseSlideSubmissionCount(obj: unknown): obj is ExerciseSlideSubmissionCount { + const typedObj = obj as ExerciseSlideSubmissionCount + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + (typedObj["date"] === null || typeof typedObj["date"] === "string") && + (typedObj["count"] === null || typeof typedObj["count"] === "number") + ) +} + +export function isExerciseSlideSubmissionCountByExercise( + obj: unknown, +): obj is ExerciseSlideSubmissionCountByExercise { + const typedObj = obj as ExerciseSlideSubmissionCountByExercise + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["exercise_id"] === "string" && + (typedObj["count"] === null || typeof typedObj["count"] === "number") && + typeof typedObj["exercise_name"] === "string" + ) +} + +export function isExerciseSlideSubmissionCountByWeekAndHour( + obj: unknown, +): obj is ExerciseSlideSubmissionCountByWeekAndHour { + const typedObj = obj as ExerciseSlideSubmissionCountByWeekAndHour + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + (typedObj["isodow"] === null || typeof typedObj["isodow"] === "number") && + (typedObj["hour"] === null || typeof typedObj["hour"] === "number") && + (typedObj["count"] === null || typeof typedObj["count"] === "number") + ) +} + +export function isExerciseSlideSubmissionInfo(obj: unknown): obj is ExerciseSlideSubmissionInfo { + const typedObj = obj as ExerciseSlideSubmissionInfo + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + Array.isArray(typedObj["tasks"]) && + typedObj["tasks"].every((e: any) => isCourseMaterialExerciseTask(e) as boolean) && + (isExercise(typedObj["exercise"]) as boolean) && + (isExerciseSlideSubmission(typedObj["exercise_slide_submission"]) as boolean) + ) +} + +export function isPeerReviewsRecieved(obj: unknown): obj is PeerReviewsRecieved { + const typedObj = obj as PeerReviewsRecieved + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + Array.isArray(typedObj["peer_review_questions"]) && + typedObj["peer_review_questions"].every((e: any) => isPeerReviewQuestion(e) as boolean) && + Array.isArray(typedObj["peer_review_question_submissions"]) && + typedObj["peer_review_question_submissions"].every( + (e: any) => isPeerReviewQuestionSubmission(e) as boolean, + ) + ) +} + +export function isCourseMaterialExerciseSlide(obj: unknown): obj is CourseMaterialExerciseSlide { + const typedObj = obj as CourseMaterialExerciseSlide + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + Array.isArray(typedObj["exercise_tasks"]) && + typedObj["exercise_tasks"].every((e: any) => isCourseMaterialExerciseTask(e) as boolean) + ) +} + +export function isExerciseSlide(obj: unknown): obj is ExerciseSlide { + const typedObj = obj as ExerciseSlide + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + typeof typedObj["exercise_id"] === "string" && + typeof typedObj["order_number"] === "number" + ) +} + +export function isExerciseTaskGrading(obj: unknown): obj is ExerciseTaskGrading { + const typedObj = obj as ExerciseTaskGrading + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + typeof typedObj["exercise_task_submission_id"] === "string" && + (typedObj["course_id"] === null || typeof typedObj["course_id"] === "string") && + (typedObj["exam_id"] === null || typeof typedObj["exam_id"] === "string") && + typeof typedObj["exercise_id"] === "string" && + typeof typedObj["exercise_task_id"] === "string" && + typeof typedObj["grading_priority"] === "number" && + (typedObj["score_given"] === null || typeof typedObj["score_given"] === "number") && + (isGradingProgress(typedObj["grading_progress"]) as boolean) && + (typedObj["unscaled_score_given"] === null || + typeof typedObj["unscaled_score_given"] === "number") && + (typedObj["unscaled_score_maximum"] === null || + typeof typedObj["unscaled_score_maximum"] === "number") && + (typedObj["grading_started_at"] === null || + typeof typedObj["grading_started_at"] === "string") && + (typedObj["grading_completed_at"] === null || + typeof typedObj["grading_completed_at"] === "string") && + (typedObj["feedback_text"] === null || typeof typedObj["feedback_text"] === "string") && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") + ) +} + +export function isExerciseTaskGradingResult(obj: unknown): obj is ExerciseTaskGradingResult { + const typedObj = obj as ExerciseTaskGradingResult + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + (isGradingProgress(typedObj["grading_progress"]) as boolean) && + typeof typedObj["score_given"] === "number" && + typeof typedObj["score_maximum"] === "number" && + (typedObj["feedback_text"] === null || typeof typedObj["feedback_text"] === "string") && + (typeof typedObj["set_user_variables"] === "undefined" || + (((typedObj["set_user_variables"] !== null && + typeof typedObj["set_user_variables"] === "object") || + typeof typedObj["set_user_variables"] === "function") && + Object.entries(typedObj["set_user_variables"]).every( + ([key, _value]) => typeof key === "string", + ))) + ) +} + +export function isUserPointsUpdateStrategy(obj: unknown): obj is UserPointsUpdateStrategy { + const typedObj = obj as UserPointsUpdateStrategy + return ( + typedObj === "CanAddPointsButCannotRemovePoints" || + typedObj === "CanAddPointsAndCanRemovePoints" + ) +} + +export function isExerciseTaskSubmission(obj: unknown): obj is ExerciseTaskSubmission { + const typedObj = obj as ExerciseTaskSubmission + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + typeof typedObj["exercise_slide_submission_id"] === "string" && + typeof typedObj["exercise_task_id"] === "string" && + typeof typedObj["exercise_slide_id"] === "string" && + (typedObj["exercise_task_grading_id"] === null || + typeof typedObj["exercise_task_grading_id"] === "string") + ) +} + +export function isCourseMaterialExerciseTask(obj: unknown): obj is CourseMaterialExerciseTask { + const typedObj = obj as CourseMaterialExerciseTask + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["exercise_service_slug"] === "string" && + typeof typedObj["exercise_slide_id"] === "string" && + (typedObj["exercise_iframe_url"] === null || + typeof typedObj["exercise_iframe_url"] === "string") && + (typedObj["pseudonumous_user_id"] === null || + typeof typedObj["pseudonumous_user_id"] === "string") && + (typedObj["previous_submission"] === null || + (isExerciseTaskSubmission(typedObj["previous_submission"]) as boolean)) && + (typedObj["previous_submission_grading"] === null || + (isExerciseTaskGrading(typedObj["previous_submission_grading"]) as boolean)) && + typeof typedObj["order_number"] === "number" + ) +} + +export function isExerciseTask(obj: unknown): obj is ExerciseTask { + const typedObj = obj as ExerciseTask + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + typeof typedObj["exercise_slide_id"] === "string" && + typeof typedObj["exercise_type"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + (typedObj["copied_from"] === null || typeof typedObj["copied_from"] === "string") && + typeof typedObj["order_number"] === "number" + ) +} + +export function isActivityProgress(obj: unknown): obj is ActivityProgress { + const typedObj = obj as ActivityProgress + return ( + typedObj === "Initialized" || + typedObj === "Started" || + typedObj === "InProgress" || + typedObj === "Submitted" || + typedObj === "Completed" + ) +} + +export function isCourseMaterialExercise(obj: unknown): obj is CourseMaterialExercise { + const typedObj = obj as CourseMaterialExercise + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + (isExercise(typedObj["exercise"]) as boolean) && + typeof typedObj["can_post_submission"] === "boolean" && + (isCourseMaterialExerciseSlide(typedObj["current_exercise_slide"]) as boolean) && + (typedObj["exercise_status"] === null || + (isExerciseStatus(typedObj["exercise_status"]) as boolean)) && + ((typedObj["exercise_slide_submission_counts"] !== null && + typeof typedObj["exercise_slide_submission_counts"] === "object") || + typeof typedObj["exercise_slide_submission_counts"] === "function") && + Object.entries(typedObj["exercise_slide_submission_counts"]).every( + ([key, value]) => typeof value === "number" && typeof key === "string", + ) && + (typedObj["peer_review_config"] === null || + (isCourseMaterialPeerReviewConfig(typedObj["peer_review_config"]) as boolean)) && + (typedObj["previous_exercise_slide_submission"] === null || + (isExerciseSlideSubmission(typedObj["previous_exercise_slide_submission"]) as boolean)) && + Array.isArray(typedObj["user_course_instance_exercise_service_variables"]) && + typedObj["user_course_instance_exercise_service_variables"].every( + (e: any) => isUserCourseInstanceExerciseServiceVariable(e) as boolean, + ) + ) +} + +export function isExercise(obj: unknown): obj is Exercise { + const typedObj = obj as Exercise + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + typeof typedObj["name"] === "string" && + (typedObj["course_id"] === null || typeof typedObj["course_id"] === "string") && + (typedObj["exam_id"] === null || typeof typedObj["exam_id"] === "string") && + typeof typedObj["page_id"] === "string" && + (typedObj["chapter_id"] === null || typeof typedObj["chapter_id"] === "string") && + (typedObj["deadline"] === null || typeof typedObj["deadline"] === "string") && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + typeof typedObj["score_maximum"] === "number" && + typeof typedObj["order_number"] === "number" && + (typedObj["copied_from"] === null || typeof typedObj["copied_from"] === "string") && + (typedObj["max_tries_per_slide"] === null || + typeof typedObj["max_tries_per_slide"] === "number") && + typeof typedObj["limit_number_of_tries"] === "boolean" && + typeof typedObj["needs_peer_review"] === "boolean" && + typeof typedObj["use_course_default_peer_review_config"] === "boolean" && + (typedObj["exercise_language_group_id"] === null || + typeof typedObj["exercise_language_group_id"] === "string") + ) +} + +export function isExerciseStatus(obj: unknown): obj is ExerciseStatus { + const typedObj = obj as ExerciseStatus + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + (typedObj["score_given"] === null || typeof typedObj["score_given"] === "number") && + (isActivityProgress(typedObj["activity_progress"]) as boolean) && + (isGradingProgress(typedObj["grading_progress"]) as boolean) && + (isReviewingStage(typedObj["reviewing_stage"]) as boolean) + ) +} + +export function isExerciseStatusSummaryForUser(obj: unknown): obj is ExerciseStatusSummaryForUser { + const typedObj = obj as ExerciseStatusSummaryForUser + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + (isExercise(typedObj["exercise"]) as boolean) && + (typedObj["user_exercise_state"] === null || + (isUserExerciseState(typedObj["user_exercise_state"]) as boolean)) && + Array.isArray(typedObj["exercise_slide_submissions"]) && + typedObj["exercise_slide_submissions"].every( + (e: any) => isExerciseSlideSubmission(e) as boolean, + ) && + Array.isArray(typedObj["given_peer_review_submissions"]) && + typedObj["given_peer_review_submissions"].every( + (e: any) => isPeerReviewSubmission(e) as boolean, + ) && + Array.isArray(typedObj["given_peer_review_question_submissions"]) && + typedObj["given_peer_review_question_submissions"].every( + (e: any) => isPeerReviewQuestionSubmission(e) as boolean, + ) && + Array.isArray(typedObj["received_peer_review_submissions"]) && + typedObj["received_peer_review_submissions"].every( + (e: any) => isPeerReviewSubmission(e) as boolean, + ) && + Array.isArray(typedObj["received_peer_review_question_submissions"]) && + typedObj["received_peer_review_question_submissions"].every( + (e: any) => isPeerReviewQuestionSubmission(e) as boolean, + ) && + (typedObj["peer_review_queue_entry"] === null || + (isPeerReviewQueueEntry(typedObj["peer_review_queue_entry"]) as boolean)) && + (typedObj["teacher_grading_decision"] === null || + (isTeacherGradingDecision(typedObj["teacher_grading_decision"]) as boolean)) && + Array.isArray(typedObj["peer_review_questions"]) && + typedObj["peer_review_questions"].every((e: any) => isPeerReviewQuestion(e) as boolean) + ) +} + +export function isGlobalStatEntry(obj: unknown): obj is GlobalStatEntry { + const typedObj = obj as GlobalStatEntry + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["name"] === "string" && + typeof typedObj["course_id"] === "string" && + typeof typedObj["organization_id"] === "string" && + typeof typedObj["organization_name"] === "string" && + typeof typedObj["year"] === "string" && + typeof typedObj["value"] === "number" + ) +} + +export function isExerciseGradingStatus(obj: unknown): obj is ExerciseGradingStatus { + const typedObj = obj as ExerciseGradingStatus + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["exercise_id"] === "string" && + typeof typedObj["exercise_name"] === "string" && + typeof typedObj["score_maximum"] === "number" && + (typedObj["score_given"] === null || typeof typedObj["score_given"] === "number") && + (typedObj["teacher_decision"] === null || + typedObj["teacher_decision"] === "FullPoints" || + typedObj["teacher_decision"] === "ZeroPoints" || + typedObj["teacher_decision"] === "CustomPoints" || + typedObj["teacher_decision"] === "SuspectedPlagiarism") && + typeof typedObj["submission_id"] === "string" && + typeof typedObj["updated_at"] === "string" + ) +} + +export function isGradingProgress(obj: unknown): obj is GradingProgress { + const typedObj = obj as GradingProgress + return ( + typedObj === "Pending" || + typedObj === "Failed" || + typedObj === "NotReady" || + typedObj === "PendingManual" || + typedObj === "FullyGraded" + ) +} + +export function isFeedback(obj: unknown): obj is Feedback { + const typedObj = obj as Feedback + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + (typedObj["user_id"] === null || typeof typedObj["user_id"] === "string") && + typeof typedObj["course_id"] === "string" && + (typedObj["page_id"] === null || typeof typedObj["page_id"] === "string") && + typeof typedObj["feedback_given"] === "string" && + (typedObj["selected_text"] === null || typeof typedObj["selected_text"] === "string") && + typeof typedObj["marked_as_read"] === "boolean" && + typeof typedObj["created_at"] === "string" && + Array.isArray(typedObj["blocks"]) && + typedObj["blocks"].every((e: any) => isFeedbackBlock(e) as boolean) && + typeof typedObj["page_title"] === "string" && + typeof typedObj["page_url_path"] === "string" + ) +} + +export function isFeedbackBlock(obj: unknown): obj is FeedbackBlock { + const typedObj = obj as FeedbackBlock + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + (typedObj["text"] === null || typeof typedObj["text"] === "string") && + (typedObj["order_number"] === null || typeof typedObj["order_number"] === "number") + ) +} + +export function isFeedbackCount(obj: unknown): obj is FeedbackCount { + const typedObj = obj as FeedbackCount + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["read"] === "number" && + typeof typedObj["unread"] === "number" + ) +} + +export function isNewFeedback(obj: unknown): obj is NewFeedback { + const typedObj = obj as NewFeedback + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["feedback_given"] === "string" && + (typedObj["selected_text"] === null || typeof typedObj["selected_text"] === "string") && + Array.isArray(typedObj["related_blocks"]) && + typedObj["related_blocks"].every((e: any) => isFeedbackBlock(e) as boolean) && + typeof typedObj["page_id"] === "string" + ) +} + +export function isTerm(obj: unknown): obj is Term { + const typedObj = obj as Term + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["term"] === "string" && + typeof typedObj["definition"] === "string" + ) +} + +export function isTermUpdate(obj: unknown): obj is TermUpdate { + const typedObj = obj as TermUpdate + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["term"] === "string" && + typeof typedObj["definition"] === "string" + ) +} + +export function isAnswerRequiringAttentionWithTasks( + obj: unknown, +): obj is AnswerRequiringAttentionWithTasks { + const typedObj = obj as AnswerRequiringAttentionWithTasks + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["user_id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + (isGradingProgress(typedObj["grading_progress"]) as boolean) && + (typedObj["score_given"] === null || typeof typedObj["score_given"] === "number") && + typeof typedObj["submission_id"] === "string" && + typeof typedObj["exercise_id"] === "string" && + Array.isArray(typedObj["tasks"]) && + typedObj["tasks"].every((e: any) => isCourseMaterialExerciseTask(e) as boolean) && + Array.isArray(typedObj["given_peer_reviews"]) && + typedObj["given_peer_reviews"].every( + (e: any) => isPeerReviewWithQuestionsAndAnswers(e) as boolean, + ) && + Array.isArray(typedObj["received_peer_reviews"]) && + typedObj["received_peer_reviews"].every( + (e: any) => isPeerReviewWithQuestionsAndAnswers(e) as boolean, + ) + ) +} + +export function isAnswersRequiringAttention(obj: unknown): obj is AnswersRequiringAttention { + const typedObj = obj as AnswersRequiringAttention + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["exercise_max_points"] === "number" && + Array.isArray(typedObj["data"]) && + typedObj["data"].every((e: any) => isAnswerRequiringAttentionWithTasks(e) as boolean) && + typeof typedObj["total_pages"] === "number" + ) +} + +export function isStudentExerciseSlideSubmission( + obj: unknown, +): obj is StudentExerciseSlideSubmission { + const typedObj = obj as StudentExerciseSlideSubmission + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["exercise_slide_id"] === "string" && + Array.isArray(typedObj["exercise_task_submissions"]) && + typedObj["exercise_task_submissions"].every( + (e: any) => isStudentExerciseTaskSubmission(e) as boolean, + ) + ) +} + +export function isStudentExerciseSlideSubmissionResult( + obj: unknown, +): obj is StudentExerciseSlideSubmissionResult { + const typedObj = obj as StudentExerciseSlideSubmissionResult + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + (typedObj["exercise_status"] === null || + (isExerciseStatus(typedObj["exercise_status"]) as boolean)) && + Array.isArray(typedObj["exercise_task_submission_results"]) && + typedObj["exercise_task_submission_results"].every( + (e: any) => isStudentExerciseTaskSubmissionResult(e) as boolean, + ) && + Array.isArray(typedObj["user_course_instance_exercise_service_variables"]) && + typedObj["user_course_instance_exercise_service_variables"].every( + (e: any) => isUserCourseInstanceExerciseServiceVariable(e) as boolean, + ) + ) +} + +export function isStudentExerciseTaskSubmission( + obj: unknown, +): obj is StudentExerciseTaskSubmission { + const typedObj = obj as StudentExerciseTaskSubmission + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["exercise_task_id"] === "string" + ) +} + +export function isStudentExerciseTaskSubmissionResult( + obj: unknown, +): obj is StudentExerciseTaskSubmissionResult { + const typedObj = obj as StudentExerciseTaskSubmissionResult + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + (isExerciseTaskSubmission(typedObj["submission"]) as boolean) && + (typedObj["grading"] === null || (isExerciseTaskGrading(typedObj["grading"]) as boolean)) && + typeof typedObj["exercise_task_exercise_service_slug"] === "string" + ) +} + +export function isCourseMaterialPeerReviewData(obj: unknown): obj is CourseMaterialPeerReviewData { + const typedObj = obj as CourseMaterialPeerReviewData + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + (typedObj["answer_to_review"] === null || + (isCourseMaterialPeerReviewDataAnswerToReview(typedObj["answer_to_review"]) as boolean)) && + (isPeerReviewConfig(typedObj["peer_review_config"]) as boolean) && + Array.isArray(typedObj["peer_review_questions"]) && + typedObj["peer_review_questions"].every((e: any) => isPeerReviewQuestion(e) as boolean) && + typeof typedObj["num_peer_reviews_given"] === "number" + ) +} + +export function isCourseMaterialPeerReviewDataAnswerToReview( + obj: unknown, +): obj is CourseMaterialPeerReviewDataAnswerToReview { + const typedObj = obj as CourseMaterialPeerReviewDataAnswerToReview + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["exercise_slide_submission_id"] === "string" && + Array.isArray(typedObj["course_material_exercise_tasks"]) && + typedObj["course_material_exercise_tasks"].every( + (e: any) => isCourseMaterialExerciseTask(e) as boolean, + ) + ) +} + +export function isCourseMaterialPeerReviewQuestionAnswer( + obj: unknown, +): obj is CourseMaterialPeerReviewQuestionAnswer { + const typedObj = obj as CourseMaterialPeerReviewQuestionAnswer + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["peer_review_question_id"] === "string" && + (typedObj["text_data"] === null || typeof typedObj["text_data"] === "string") && + (typedObj["number_data"] === null || typeof typedObj["number_data"] === "number") + ) +} + +export function isCourseMaterialPeerReviewSubmission( + obj: unknown, +): obj is CourseMaterialPeerReviewSubmission { + const typedObj = obj as CourseMaterialPeerReviewSubmission + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["exercise_slide_submission_id"] === "string" && + typeof typedObj["peer_review_config_id"] === "string" && + Array.isArray(typedObj["peer_review_question_answers"]) && + typedObj["peer_review_question_answers"].every( + (e: any) => isCourseMaterialPeerReviewQuestionAnswer(e) as boolean, + ) && + typeof typedObj["token"] === "string" + ) +} + +export function isCompletionRegistrationLink(obj: unknown): obj is CompletionRegistrationLink { + const typedObj = obj as CompletionRegistrationLink + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["url"] === "string" + ) +} + +export function isCourseInstanceCompletionSummary( + obj: unknown, +): obj is CourseInstanceCompletionSummary { + const typedObj = obj as CourseInstanceCompletionSummary + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + Array.isArray(typedObj["course_modules"]) && + typedObj["course_modules"].every((e: any) => isCourseModule(e) as boolean) && + Array.isArray(typedObj["users_with_course_module_completions"]) && + typedObj["users_with_course_module_completions"].every( + (e: any) => isUserWithModuleCompletions(e) as boolean, + ) + ) +} + +export function isManualCompletionPreview(obj: unknown): obj is ManualCompletionPreview { + const typedObj = obj as ManualCompletionPreview + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + Array.isArray(typedObj["already_completed_users"]) && + typedObj["already_completed_users"].every( + (e: any) => isManualCompletionPreviewUser(e) as boolean, + ) && + Array.isArray(typedObj["first_time_completing_users"]) && + typedObj["first_time_completing_users"].every( + (e: any) => isManualCompletionPreviewUser(e) as boolean, + ) && + Array.isArray(typedObj["non_enrolled_users"]) && + typedObj["non_enrolled_users"].every((e: any) => isManualCompletionPreviewUser(e) as boolean) + ) +} + +export function isManualCompletionPreviewUser(obj: unknown): obj is ManualCompletionPreviewUser { + const typedObj = obj as ManualCompletionPreviewUser + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["user_id"] === "string" && + (typedObj["first_name"] === null || typeof typedObj["first_name"] === "string") && + (typedObj["last_name"] === null || typeof typedObj["last_name"] === "string") && + (typedObj["grade"] === null || typeof typedObj["grade"] === "number") && + typeof typedObj["passed"] === "boolean" + ) +} + +export function isTeacherManualCompletion(obj: unknown): obj is TeacherManualCompletion { + const typedObj = obj as TeacherManualCompletion + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["user_id"] === "string" && + (typedObj["grade"] === null || typeof typedObj["grade"] === "number") && + (typedObj["completion_date"] === null || typeof typedObj["completion_date"] === "string") + ) +} + +export function isTeacherManualCompletionRequest( + obj: unknown, +): obj is TeacherManualCompletionRequest { + const typedObj = obj as TeacherManualCompletionRequest + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["course_module_id"] === "string" && + Array.isArray(typedObj["new_completions"]) && + typedObj["new_completions"].every((e: any) => isTeacherManualCompletion(e) as boolean) && + typeof typedObj["skip_duplicate_completions"] === "boolean" + ) +} + +export function isUserCompletionInformation(obj: unknown): obj is UserCompletionInformation { + const typedObj = obj as UserCompletionInformation + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["course_module_completion_id"] === "string" && + typeof typedObj["course_name"] === "string" && + typeof typedObj["uh_course_code"] === "string" && + typeof typedObj["email"] === "string" && + (typedObj["ects_credits"] === null || typeof typedObj["ects_credits"] === "number") && + typeof typedObj["enable_registering_completion_to_uh_open_university"] === "boolean" + ) +} + +export function isUserCourseModuleCompletion(obj: unknown): obj is UserCourseModuleCompletion { + const typedObj = obj as UserCourseModuleCompletion + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["course_module_id"] === "string" && + (typedObj["grade"] === null || typeof typedObj["grade"] === "number") && + typeof typedObj["passed"] === "boolean" + ) +} + +export function isUserModuleCompletionStatus(obj: unknown): obj is UserModuleCompletionStatus { + const typedObj = obj as UserModuleCompletionStatus + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["completed"] === "boolean" && + typeof typedObj["default"] === "boolean" && + typeof typedObj["module_id"] === "string" && + typeof typedObj["name"] === "string" && + typeof typedObj["order_number"] === "number" && + typeof typedObj["prerequisite_modules_completed"] === "boolean" && + (typedObj["grade"] === null || typeof typedObj["grade"] === "number") && + (typedObj["passed"] === null || typedObj["passed"] === false || typedObj["passed"] === true) && + typeof typedObj["enable_registering_completion_to_uh_open_university"] === "boolean" && + typeof typedObj["certification_enabled"] === "boolean" && + (typedObj["certificate_configuration_id"] === null || + typeof typedObj["certificate_configuration_id"] === "string") + ) +} + +export function isUserWithModuleCompletions(obj: unknown): obj is UserWithModuleCompletions { + const typedObj = obj as UserWithModuleCompletions + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + Array.isArray(typedObj["completed_modules"]) && + typedObj["completed_modules"].every( + (e: any) => isCourseModuleCompletionWithRegistrationInfo(e) as boolean, + ) && + typeof typedObj["email"] === "string" && + (typedObj["first_name"] === null || typeof typedObj["first_name"] === "string") && + (typedObj["last_name"] === null || typeof typedObj["last_name"] === "string") && + typeof typedObj["user_id"] === "string" + ) +} + +export function isMaterialReference(obj: unknown): obj is MaterialReference { + const typedObj = obj as MaterialReference + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["course_id"] === "string" && + typeof typedObj["citation_key"] === "string" && + typeof typedObj["reference"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") + ) +} + +export function isNewMaterialReference(obj: unknown): obj is NewMaterialReference { + const typedObj = obj as NewMaterialReference + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["citation_key"] === "string" && + typeof typedObj["reference"] === "string" + ) +} + +export function isOrganization(obj: unknown): obj is Organization { + const typedObj = obj as Organization + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["slug"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + typeof typedObj["name"] === "string" && + (typedObj["description"] === null || typeof typedObj["description"] === "string") && + (typedObj["organization_image_url"] === null || + typeof typedObj["organization_image_url"] === "string") && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") + ) +} + +export function isHistoryChangeReason(obj: unknown): obj is HistoryChangeReason { + const typedObj = obj as HistoryChangeReason + return typedObj === "PageSaved" || typedObj === "HistoryRestored" +} + +export function isPageHistory(obj: unknown): obj is PageHistory { + const typedObj = obj as PageHistory + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["title"] === "string" && + (isHistoryChangeReason(typedObj["history_change_reason"]) as boolean) && + (typedObj["restored_from_id"] === null || typeof typedObj["restored_from_id"] === "string") && + typeof typedObj["author_user_id"] === "string" + ) +} + +export function isCmsPageExercise(obj: unknown): obj is CmsPageExercise { + const typedObj = obj as CmsPageExercise + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["name"] === "string" && + typeof typedObj["order_number"] === "number" && + typeof typedObj["score_maximum"] === "number" && + (typedObj["max_tries_per_slide"] === null || + typeof typedObj["max_tries_per_slide"] === "number") && + typeof typedObj["limit_number_of_tries"] === "boolean" && + (typedObj["deadline"] === null || typeof typedObj["deadline"] === "string") && + typeof typedObj["needs_peer_review"] === "boolean" && + (typedObj["peer_review_config"] === null || + (isCmsPeerReviewConfig(typedObj["peer_review_config"]) as boolean)) && + (typedObj["peer_review_questions"] === null || + (Array.isArray(typedObj["peer_review_questions"]) && + typedObj["peer_review_questions"].every( + (e: any) => isCmsPeerReviewQuestion(e) as boolean, + ))) && + typeof typedObj["use_course_default_peer_review_config"] === "boolean" + ) +} + +export function isCmsPageExerciseSlide(obj: unknown): obj is CmsPageExerciseSlide { + const typedObj = obj as CmsPageExerciseSlide + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["exercise_id"] === "string" && + typeof typedObj["order_number"] === "number" + ) +} + +export function isCmsPageExerciseTask(obj: unknown): obj is CmsPageExerciseTask { + const typedObj = obj as CmsPageExerciseTask + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["exercise_slide_id"] === "string" && + typeof typedObj["exercise_type"] === "string" && + typeof typedObj["order_number"] === "number" + ) +} + +export function isCmsPageUpdate(obj: unknown): obj is CmsPageUpdate { + const typedObj = obj as CmsPageUpdate + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + Array.isArray(typedObj["exercises"]) && + typedObj["exercises"].every((e: any) => isCmsPageExercise(e) as boolean) && + Array.isArray(typedObj["exercise_slides"]) && + typedObj["exercise_slides"].every((e: any) => isCmsPageExerciseSlide(e) as boolean) && + Array.isArray(typedObj["exercise_tasks"]) && + typedObj["exercise_tasks"].every((e: any) => isCmsPageExerciseTask(e) as boolean) && + typeof typedObj["url_path"] === "string" && + typeof typedObj["title"] === "string" && + (typedObj["chapter_id"] === null || typeof typedObj["chapter_id"] === "string") + ) +} + +export function isContentManagementPage(obj: unknown): obj is ContentManagementPage { + const typedObj = obj as ContentManagementPage + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + (isPage(typedObj["page"]) as boolean) && + Array.isArray(typedObj["exercises"]) && + typedObj["exercises"].every((e: any) => isCmsPageExercise(e) as boolean) && + Array.isArray(typedObj["exercise_slides"]) && + typedObj["exercise_slides"].every((e: any) => isCmsPageExerciseSlide(e) as boolean) && + Array.isArray(typedObj["exercise_tasks"]) && + typedObj["exercise_tasks"].every((e: any) => isCmsPageExerciseTask(e) as boolean) && + Array.isArray(typedObj["peer_review_configs"]) && + typedObj["peer_review_configs"].every((e: any) => isCmsPeerReviewConfig(e) as boolean) && + Array.isArray(typedObj["peer_review_questions"]) && + typedObj["peer_review_questions"].every((e: any) => isCmsPeerReviewQuestion(e) as boolean) && + typeof typedObj["organization_id"] === "string" + ) +} + +export function isCoursePageWithUserData(obj: unknown): obj is CoursePageWithUserData { + const typedObj = obj as CoursePageWithUserData + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + (isPage(typedObj["page"]) as boolean) && + (typedObj["instance"] === null || (isCourseInstance(typedObj["instance"]) as boolean)) && + (typedObj["settings"] === null || (isUserCourseSettings(typedObj["settings"]) as boolean)) && + typeof typedObj["was_redirected"] === "boolean" && + typeof typedObj["is_test_mode"] === "boolean" + ) +} + +export function isExerciseWithExerciseTasks(obj: unknown): obj is ExerciseWithExerciseTasks { + const typedObj = obj as ExerciseWithExerciseTasks + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + typeof typedObj["course_id"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + typeof typedObj["name"] === "string" && + (typedObj["deadline"] === null || typeof typedObj["deadline"] === "string") && + typeof typedObj["page_id"] === "string" && + Array.isArray(typedObj["exercise_tasks"]) && + typedObj["exercise_tasks"].every((e: any) => isExerciseTask(e) as boolean) && + typeof typedObj["score_maximum"] === "number" + ) +} + +export function isHistoryRestoreData(obj: unknown): obj is HistoryRestoreData { + const typedObj = obj as HistoryRestoreData + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["history_id"] === "string" + ) +} + +export function isIsChapterFrontPage(obj: unknown): obj is IsChapterFrontPage { + const typedObj = obj as IsChapterFrontPage + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["is_chapter_front_page"] === "boolean" + ) +} + +export function isNewPage(obj: unknown): obj is NewPage { + const typedObj = obj as NewPage + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + Array.isArray(typedObj["exercises"]) && + typedObj["exercises"].every((e: any) => isCmsPageExercise(e) as boolean) && + Array.isArray(typedObj["exercise_slides"]) && + typedObj["exercise_slides"].every((e: any) => isCmsPageExerciseSlide(e) as boolean) && + Array.isArray(typedObj["exercise_tasks"]) && + typedObj["exercise_tasks"].every((e: any) => isCmsPageExerciseTask(e) as boolean) && + typeof typedObj["url_path"] === "string" && + typeof typedObj["title"] === "string" && + (typedObj["course_id"] === null || typeof typedObj["course_id"] === "string") && + (typedObj["exam_id"] === null || typeof typedObj["exam_id"] === "string") && + (typedObj["chapter_id"] === null || typeof typedObj["chapter_id"] === "string") && + (typedObj["front_page_of_chapter_id"] === null || + typeof typedObj["front_page_of_chapter_id"] === "string") && + (typedObj["content_search_language"] === null || + typeof typedObj["content_search_language"] === "string") + ) +} + +export function isPage(obj: unknown): obj is Page { + const typedObj = obj as Page + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["course_id"] === null || typeof typedObj["course_id"] === "string") && + (typedObj["exam_id"] === null || typeof typedObj["exam_id"] === "string") && + (typedObj["chapter_id"] === null || typeof typedObj["chapter_id"] === "string") && + typeof typedObj["url_path"] === "string" && + typeof typedObj["title"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + typeof typedObj["order_number"] === "number" && + (typedObj["copied_from"] === null || typeof typedObj["copied_from"] === "string") && + typeof typedObj["hidden"] === "boolean" && + (typedObj["page_language_group_id"] === null || + typeof typedObj["page_language_group_id"] === "string") + ) +} + +export function isPageChapterAndCourseInformation( + obj: unknown, +): obj is PageChapterAndCourseInformation { + const typedObj = obj as PageChapterAndCourseInformation + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + (typedObj["chapter_name"] === null || typeof typedObj["chapter_name"] === "string") && + (typedObj["chapter_number"] === null || typeof typedObj["chapter_number"] === "number") && + (typedObj["course_name"] === null || typeof typedObj["course_name"] === "string") && + (typedObj["course_slug"] === null || typeof typedObj["course_slug"] === "string") && + (typedObj["chapter_front_page_id"] === null || + typeof typedObj["chapter_front_page_id"] === "string") && + (typedObj["chapter_front_page_url_path"] === null || + typeof typedObj["chapter_front_page_url_path"] === "string") && + typeof typedObj["organization_slug"] === "string" + ) +} + +export function isPageInfo(obj: unknown): obj is PageInfo { + const typedObj = obj as PageInfo + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["page_id"] === "string" && + typeof typedObj["page_title"] === "string" && + (typedObj["course_id"] === null || typeof typedObj["course_id"] === "string") && + (typedObj["course_name"] === null || typeof typedObj["course_name"] === "string") && + (typedObj["course_slug"] === null || typeof typedObj["course_slug"] === "string") && + (typedObj["organization_slug"] === null || typeof typedObj["organization_slug"] === "string") + ) +} + +export function isPageNavigationInformation(obj: unknown): obj is PageNavigationInformation { + const typedObj = obj as PageNavigationInformation + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + (typedObj["chapter_front_page"] === null || + (isPageRoutingData(typedObj["chapter_front_page"]) as boolean)) && + (typedObj["next_page"] === null || (isPageRoutingData(typedObj["next_page"]) as boolean)) && + (typedObj["previous_page"] === null || + (isPageRoutingData(typedObj["previous_page"]) as boolean)) + ) +} + +export function isPageRoutingData(obj: unknown): obj is PageRoutingData { + const typedObj = obj as PageRoutingData + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["url_path"] === "string" && + typeof typedObj["title"] === "string" && + typeof typedObj["page_id"] === "string" && + typeof typedObj["chapter_number"] === "number" && + typeof typedObj["chapter_id"] === "string" && + (typedObj["chapter_opens_at"] === null || typeof typedObj["chapter_opens_at"] === "string") && + (typedObj["chapter_front_page_id"] === null || + typeof typedObj["chapter_front_page_id"] === "string") + ) +} + +export function isSearchRequest(obj: unknown): obj is SearchRequest { + const typedObj = obj as SearchRequest + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["query"] === "string" + ) +} + +export function isPageSearchResult(obj: unknown): obj is PageSearchResult { + const typedObj = obj as PageSearchResult + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + (typedObj["title_headline"] === null || typeof typedObj["title_headline"] === "string") && + (typedObj["rank"] === null || typeof typedObj["rank"] === "number") && + (typedObj["content_headline"] === null || typeof typedObj["content_headline"] === "string") && + typeof typedObj["url_path"] === "string" + ) +} + +export function isPageWithExercises(obj: unknown): obj is PageWithExercises { + const typedObj = obj as PageWithExercises + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["course_id"] === null || typeof typedObj["course_id"] === "string") && + (typedObj["exam_id"] === null || typeof typedObj["exam_id"] === "string") && + (typedObj["chapter_id"] === null || typeof typedObj["chapter_id"] === "string") && + typeof typedObj["url_path"] === "string" && + typeof typedObj["title"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + typeof typedObj["order_number"] === "number" && + (typedObj["copied_from"] === null || typeof typedObj["copied_from"] === "string") && + typeof typedObj["hidden"] === "boolean" && + (typedObj["page_language_group_id"] === null || + typeof typedObj["page_language_group_id"] === "string") && + Array.isArray(typedObj["exercises"]) && + typedObj["exercises"].every((e: any) => isExercise(e) as boolean) + ) +} + +export function isPageDetailsUpdate(obj: unknown): obj is PageDetailsUpdate { + const typedObj = obj as PageDetailsUpdate + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["title"] === "string" && + typeof typedObj["url_path"] === "string" + ) +} + +export function isCmsPeerReviewConfig(obj: unknown): obj is CmsPeerReviewConfig { + const typedObj = obj as CmsPeerReviewConfig + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["course_id"] === "string" && + (typedObj["exercise_id"] === null || typeof typedObj["exercise_id"] === "string") && + typeof typedObj["peer_reviews_to_give"] === "number" && + typeof typedObj["peer_reviews_to_receive"] === "number" && + typeof typedObj["accepting_threshold"] === "number" && + (isPeerReviewProcessingStrategy(typedObj["processing_strategy"]) as boolean) && + typeof typedObj["points_are_all_or_nothing"] === "boolean" + ) +} + +export function isCmsPeerReviewConfiguration(obj: unknown): obj is CmsPeerReviewConfiguration { + const typedObj = obj as CmsPeerReviewConfiguration + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + (isCmsPeerReviewConfig(typedObj["peer_review_config"]) as boolean) && + Array.isArray(typedObj["peer_review_questions"]) && + typedObj["peer_review_questions"].every((e: any) => isCmsPeerReviewQuestion(e) as boolean) + ) +} + +export function isCourseMaterialPeerReviewConfig( + obj: unknown, +): obj is CourseMaterialPeerReviewConfig { + const typedObj = obj as CourseMaterialPeerReviewConfig + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["course_id"] === "string" && + (typedObj["exercise_id"] === null || typeof typedObj["exercise_id"] === "string") && + typeof typedObj["peer_reviews_to_give"] === "number" && + typeof typedObj["peer_reviews_to_receive"] === "number" + ) +} + +export function isPeerReviewProcessingStrategy(obj: unknown): obj is PeerReviewProcessingStrategy { + const typedObj = obj as PeerReviewProcessingStrategy + return ( + typedObj === "AutomaticallyGradeByAverage" || + typedObj === "AutomaticallyGradeOrManualReviewByAverage" || + typedObj === "ManualReviewEverything" + ) +} + +export function isPeerReviewConfig(obj: unknown): obj is PeerReviewConfig { + const typedObj = obj as PeerReviewConfig + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + typeof typedObj["course_id"] === "string" && + (typedObj["exercise_id"] === null || typeof typedObj["exercise_id"] === "string") && + typeof typedObj["peer_reviews_to_give"] === "number" && + typeof typedObj["peer_reviews_to_receive"] === "number" && + typeof typedObj["accepting_threshold"] === "number" && + (isPeerReviewProcessingStrategy(typedObj["processing_strategy"]) as boolean) && + typeof typedObj["manual_review_cutoff_in_days"] === "number" && + typeof typedObj["points_are_all_or_nothing"] === "boolean" + ) +} + +export function isPeerReviewSubmission(obj: unknown): obj is PeerReviewSubmission { + const typedObj = obj as PeerReviewSubmission + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + typeof typedObj["user_id"] === "string" && + typeof typedObj["exercise_id"] === "string" && + typeof typedObj["course_instance_id"] === "string" && + typeof typedObj["peer_review_config_id"] === "string" && + typeof typedObj["exercise_slide_submission_id"] === "string" + ) +} + +export function isPeerReviewAnswer(obj: unknown): obj is PeerReviewAnswer { + const typedObj = obj as PeerReviewAnswer + return ( + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "no-answer") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "essay" && + typeof typedObj["value"] === "string") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "scale" && + typeof typedObj["value"] === "number") + ) +} + +export function isPeerReviewQuestionAndAnswer(obj: unknown): obj is PeerReviewQuestionAndAnswer { + const typedObj = obj as PeerReviewQuestionAndAnswer + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["peer_review_config_id"] === "string" && + typeof typedObj["peer_review_question_id"] === "string" && + typeof typedObj["peer_review_submission_id"] === "string" && + typeof typedObj["peer_review_question_submission_id"] === "string" && + typeof typedObj["order_number"] === "number" && + typeof typedObj["question"] === "string" && + (isPeerReviewAnswer(typedObj["answer"]) as boolean) && + typeof typedObj["answer_required"] === "boolean" + ) +} + +export function isPeerReviewQuestionSubmission(obj: unknown): obj is PeerReviewQuestionSubmission { + const typedObj = obj as PeerReviewQuestionSubmission + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + typeof typedObj["peer_review_question_id"] === "string" && + typeof typedObj["peer_review_submission_id"] === "string" && + (typedObj["text_data"] === null || typeof typedObj["text_data"] === "string") && + (typedObj["number_data"] === null || typeof typedObj["number_data"] === "number") + ) +} + +export function isPeerReviewQueueEntry(obj: unknown): obj is PeerReviewQueueEntry { + const typedObj = obj as PeerReviewQueueEntry + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + typeof typedObj["user_id"] === "string" && + typeof typedObj["exercise_id"] === "string" && + typeof typedObj["course_instance_id"] === "string" && + typeof typedObj["receiving_peer_reviews_exercise_slide_submission_id"] === "string" && + typeof typedObj["received_enough_peer_reviews"] === "boolean" && + typeof typedObj["peer_review_priority"] === "number" && + typeof typedObj["removed_from_queue_for_unusual_reason"] === "boolean" + ) +} + +export function isPeerReviewWithQuestionsAndAnswers( + obj: unknown, +): obj is PeerReviewWithQuestionsAndAnswers { + const typedObj = obj as PeerReviewWithQuestionsAndAnswers + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["peer_review_submission_id"] === "string" && + Array.isArray(typedObj["questions_and_answers"]) && + typedObj["questions_and_answers"].every((e: any) => isPeerReviewQuestionAndAnswer(e) as boolean) + ) +} + +export function isCmsPeerReviewQuestion(obj: unknown): obj is CmsPeerReviewQuestion { + const typedObj = obj as CmsPeerReviewQuestion + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["peer_review_config_id"] === "string" && + typeof typedObj["order_number"] === "number" && + typeof typedObj["question"] === "string" && + (isPeerReviewQuestionType(typedObj["question_type"]) as boolean) && + typeof typedObj["answer_required"] === "boolean" && + typeof typedObj["weight"] === "number" + ) +} + +export function isPeerReviewQuestion(obj: unknown): obj is PeerReviewQuestion { + const typedObj = obj as PeerReviewQuestion + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + typeof typedObj["peer_review_config_id"] === "string" && + typeof typedObj["order_number"] === "number" && + typeof typedObj["question"] === "string" && + (isPeerReviewQuestionType(typedObj["question_type"]) as boolean) && + typeof typedObj["answer_required"] === "boolean" && + typeof typedObj["weight"] === "number" + ) +} + +export function isPeerReviewQuestionType(obj: unknown): obj is PeerReviewQuestionType { + const typedObj = obj as PeerReviewQuestionType + return typedObj === "Essay" || typedObj === "Scale" +} + +export function isPendingRole(obj: unknown): obj is PendingRole { + const typedObj = obj as PendingRole + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["user_email"] === "string" && + (isUserRole(typedObj["role"]) as boolean) && + typeof typedObj["expires_at"] === "string" + ) +} + +export function isPlaygroundExample(obj: unknown): obj is PlaygroundExample { + const typedObj = obj as PlaygroundExample + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + typeof typedObj["name"] === "string" && + typeof typedObj["url"] === "string" && + typeof typedObj["width"] === "number" + ) +} + +export function isPlaygroundExampleData(obj: unknown): obj is PlaygroundExampleData { + const typedObj = obj as PlaygroundExampleData + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["name"] === "string" && + typeof typedObj["url"] === "string" && + typeof typedObj["width"] === "number" + ) +} + +export function isBlockProposal(obj: unknown): obj is BlockProposal { + const typedObj = obj as BlockProposal + return ( + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "edited-block-still-exists" && + (isEditedBlockStillExistsData(typedObj) as boolean)) || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["type"] === "edited-block-no-longer-exists" && + (isEditedBlockNoLongerExistsData(typedObj) as boolean)) + ) +} + +export function isEditedBlockStillExistsData(obj: unknown): obj is EditedBlockStillExistsData { + const typedObj = obj as EditedBlockStillExistsData + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["block_id"] === "string" && + typeof typedObj["current_text"] === "string" && + typeof typedObj["changed_text"] === "string" && + typeof typedObj["original_text"] === "string" && + (isProposalStatus(typedObj["status"]) as boolean) && + (typedObj["accept_preview"] === null || typeof typedObj["accept_preview"] === "string") + ) +} + +export function isEditedBlockNoLongerExistsData( + obj: unknown, +): obj is EditedBlockNoLongerExistsData { + const typedObj = obj as EditedBlockNoLongerExistsData + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["block_id"] === "string" && + typeof typedObj["changed_text"] === "string" && + typeof typedObj["original_text"] === "string" && + (isProposalStatus(typedObj["status"]) as boolean) + ) +} + +export function isBlockProposalAction(obj: unknown): obj is BlockProposalAction { + const typedObj = obj as BlockProposalAction + return ( + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["tag"] === "Accept" && + typeof typedObj["data"] === "string") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["tag"] === "Reject") + ) +} + +export function isBlockProposalInfo(obj: unknown): obj is BlockProposalInfo { + const typedObj = obj as BlockProposalInfo + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + (isBlockProposalAction(typedObj["action"]) as boolean) + ) +} + +export function isNewProposedBlockEdit(obj: unknown): obj is NewProposedBlockEdit { + const typedObj = obj as NewProposedBlockEdit + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["block_id"] === "string" && + typeof typedObj["block_attribute"] === "string" && + typeof typedObj["original_text"] === "string" && + typeof typedObj["changed_text"] === "string" + ) +} + +export function isProposalStatus(obj: unknown): obj is ProposalStatus { + const typedObj = obj as ProposalStatus + return typedObj === "Pending" || typedObj === "Accepted" || typedObj === "Rejected" +} + +export function isEditProposalInfo(obj: unknown): obj is EditProposalInfo { + const typedObj = obj as EditProposalInfo + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["page_id"] === "string" && + typeof typedObj["page_proposal_id"] === "string" && + Array.isArray(typedObj["block_proposals"]) && + typedObj["block_proposals"].every((e: any) => isBlockProposalInfo(e) as boolean) + ) +} + +export function isNewProposedPageEdits(obj: unknown): obj is NewProposedPageEdits { + const typedObj = obj as NewProposedPageEdits + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["page_id"] === "string" && + Array.isArray(typedObj["block_edits"]) && + typedObj["block_edits"].every((e: any) => isNewProposedBlockEdit(e) as boolean) + ) +} + +export function isPageProposal(obj: unknown): obj is PageProposal { + const typedObj = obj as PageProposal + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["page_id"] === "string" && + (typedObj["user_id"] === null || typeof typedObj["user_id"] === "string") && + typeof typedObj["pending"] === "boolean" && + typeof typedObj["created_at"] === "string" && + Array.isArray(typedObj["block_proposals"]) && + typedObj["block_proposals"].every((e: any) => isBlockProposal(e) as boolean) && + typeof typedObj["page_title"] === "string" && + typeof typedObj["page_url_path"] === "string" + ) +} + +export function isProposalCount(obj: unknown): obj is ProposalCount { + const typedObj = obj as ProposalCount + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["pending"] === "number" && + typeof typedObj["handled"] === "number" + ) +} + +export function isPageAudioFile(obj: unknown): obj is PageAudioFile { + const typedObj = obj as PageAudioFile + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["page_id"] === "string" && + typeof typedObj["created_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + typeof typedObj["path"] === "string" && + typeof typedObj["mime_type"] === "string" + ) +} + +export function isNewRegrading(obj: unknown): obj is NewRegrading { + const typedObj = obj as NewRegrading + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + (isUserPointsUpdateStrategy(typedObj["user_points_update_strategy"]) as boolean) && + Array.isArray(typedObj["exercise_task_submission_ids"]) && + typedObj["exercise_task_submission_ids"].every((e: any) => typeof e === "string") + ) +} + +export function isRegrading(obj: unknown): obj is Regrading { + const typedObj = obj as Regrading + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["regrading_started_at"] === null || + typeof typedObj["regrading_started_at"] === "string") && + (typedObj["regrading_completed_at"] === null || + typeof typedObj["regrading_completed_at"] === "string") && + (isGradingProgress(typedObj["total_grading_progress"]) as boolean) && + (isUserPointsUpdateStrategy(typedObj["user_points_update_strategy"]) as boolean) && + (typedObj["user_id"] === null || typeof typedObj["user_id"] === "string") + ) +} + +export function isRegradingInfo(obj: unknown): obj is RegradingInfo { + const typedObj = obj as RegradingInfo + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + (isRegrading(typedObj["regrading"]) as boolean) && + Array.isArray(typedObj["submission_infos"]) && + typedObj["submission_infos"].every((e: any) => isRegradingSubmissionInfo(e) as boolean) + ) +} + +export function isRegradingSubmissionInfo(obj: unknown): obj is RegradingSubmissionInfo { + const typedObj = obj as RegradingSubmissionInfo + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["exercise_task_submission_id"] === "string" && + (isExerciseTaskGrading(typedObj["grading_before_regrading"]) as boolean) && + (typedObj["grading_after_regrading"] === null || + (isExerciseTaskGrading(typedObj["grading_after_regrading"]) as boolean)) + ) +} + +export function isRepositoryExercise(obj: unknown): obj is RepositoryExercise { + const typedObj = obj as RepositoryExercise + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["repository_id"] === "string" && + typeof typedObj["part"] === "string" && + typeof typedObj["name"] === "string" && + typeof typedObj["repository_url"] === "string" && + Array.isArray(typedObj["checksum"]) && + typedObj["checksum"].every((e: any) => typeof e === "number") && + typeof typedObj["download_url"] === "string" + ) +} + +export function isNewResearchForm(obj: unknown): obj is NewResearchForm { + const typedObj = obj as NewResearchForm + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["course_id"] === "string" + ) +} + +export function isNewResearchFormQuestion(obj: unknown): obj is NewResearchFormQuestion { + const typedObj = obj as NewResearchFormQuestion + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["question_id"] === "string" && + typeof typedObj["course_id"] === "string" && + typeof typedObj["research_consent_form_id"] === "string" && + typeof typedObj["question"] === "string" + ) +} + +export function isResearchFormQuestion(obj: unknown): obj is ResearchFormQuestion { + const typedObj = obj as ResearchFormQuestion + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["course_id"] === "string" && + typeof typedObj["research_consent_form_id"] === "string" && + typeof typedObj["question"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") + ) +} + +export function isResearchForm(obj: unknown): obj is ResearchForm { + const typedObj = obj as ResearchForm + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["course_id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") + ) +} + +export function isNewResearchFormQuestionAnswer( + obj: unknown, +): obj is NewResearchFormQuestionAnswer { + const typedObj = obj as NewResearchFormQuestionAnswer + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["user_id"] === "string" && + typeof typedObj["research_form_question_id"] === "string" && + typeof typedObj["research_consent"] === "boolean" + ) +} + +export function isResearchFormQuestionAnswer(obj: unknown): obj is ResearchFormQuestionAnswer { + const typedObj = obj as ResearchFormQuestionAnswer + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["user_id"] === "string" && + typeof typedObj["course_id"] === "string" && + typeof typedObj["research_form_question_id"] === "string" && + typeof typedObj["research_consent"] === "boolean" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") + ) +} + +export function isRoleDomain(obj: unknown): obj is RoleDomain { + const typedObj = obj as RoleDomain + return ( + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["tag"] === "Global") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["tag"] === "Organization" && + typeof typedObj["id"] === "string") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["tag"] === "Course" && + typeof typedObj["id"] === "string") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["tag"] === "CourseInstance" && + typeof typedObj["id"] === "string") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["tag"] === "Exam" && + typeof typedObj["id"] === "string") + ) +} + +export function isRoleInfo(obj: unknown): obj is RoleInfo { + const typedObj = obj as RoleInfo + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["email"] === "string" && + (isUserRole(typedObj["role"]) as boolean) && + (isRoleDomain(typedObj["domain"]) as boolean) + ) +} + +export function isRoleUser(obj: unknown): obj is RoleUser { + const typedObj = obj as RoleUser + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + (typedObj["first_name"] === null || typeof typedObj["first_name"] === "string") && + (typedObj["last_name"] === null || typeof typedObj["last_name"] === "string") && + typeof typedObj["email"] === "string" && + (isUserRole(typedObj["role"]) as boolean) + ) +} + +export function isUserRole(obj: unknown): obj is UserRole { + const typedObj = obj as UserRole + return ( + typedObj === "Reviewer" || + typedObj === "Assistant" || + typedObj === "Teacher" || + typedObj === "Admin" || + typedObj === "CourseOrExamCreator" || + typedObj === "MaterialViewer" || + typedObj === "TeachingAndLearningServices" + ) +} + +export function isStudentCountry(obj: unknown): obj is StudentCountry { + const typedObj = obj as StudentCountry + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["user_id"] === "string" && + typeof typedObj["course_id"] === "string" && + typeof typedObj["course_instance_id"] === "string" && + typeof typedObj["country_code"] === "string" && + typeof typedObj["created_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") + ) +} + +export function isNewTeacherGradingDecision(obj: unknown): obj is NewTeacherGradingDecision { + const typedObj = obj as NewTeacherGradingDecision + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["user_exercise_state_id"] === "string" && + typeof typedObj["exercise_id"] === "string" && + (isTeacherDecisionType(typedObj["action"]) as boolean) && + (typedObj["manual_points"] === null || typeof typedObj["manual_points"] === "number") + ) +} + +export function isTeacherDecisionType(obj: unknown): obj is TeacherDecisionType { + const typedObj = obj as TeacherDecisionType + return ( + typedObj === "FullPoints" || + typedObj === "ZeroPoints" || + typedObj === "CustomPoints" || + typedObj === "SuspectedPlagiarism" + ) +} + +export function isTeacherGradingDecision(obj: unknown): obj is TeacherGradingDecision { + const typedObj = obj as TeacherGradingDecision + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["user_exercise_state_id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + typeof typedObj["score_given"] === "number" && + (isTeacherDecisionType(typedObj["teacher_decision"]) as boolean) + ) +} + +export function isUserCourseInstanceExerciseServiceVariable( + obj: unknown, +): obj is UserCourseInstanceExerciseServiceVariable { + const typedObj = obj as UserCourseInstanceExerciseServiceVariable + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + typeof typedObj["exercise_service_slug"] === "string" && + typeof typedObj["user_id"] === "string" && + (typedObj["course_instance_id"] === null || + typeof typedObj["course_instance_id"] === "string") && + (typedObj["exam_id"] === null || typeof typedObj["exam_id"] === "string") && + typeof typedObj["variable_key"] === "string" + ) +} + +export function isUserCourseSettings(obj: unknown): obj is UserCourseSettings { + const typedObj = obj as UserCourseSettings + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["user_id"] === "string" && + typeof typedObj["course_language_group_id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + typeof typedObj["current_course_id"] === "string" && + typeof typedObj["current_course_instance_id"] === "string" + ) +} + +export function isUserDetail(obj: unknown): obj is UserDetail { + const typedObj = obj as UserDetail + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["user_id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + typeof typedObj["email"] === "string" && + (typedObj["first_name"] === null || typeof typedObj["first_name"] === "string") && + (typedObj["last_name"] === null || typeof typedObj["last_name"] === "string") && + (typedObj["search_helper"] === null || typeof typedObj["search_helper"] === "string") + ) +} + +export function isExerciseUserCounts(obj: unknown): obj is ExerciseUserCounts { + const typedObj = obj as ExerciseUserCounts + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["exercise_name"] === "string" && + typeof typedObj["exercise_order_number"] === "number" && + typeof typedObj["page_order_number"] === "number" && + typeof typedObj["chapter_number"] === "number" && + typeof typedObj["exercise_id"] === "string" && + typeof typedObj["n_users_attempted"] === "number" && + typeof typedObj["n_users_with_some_points"] === "number" && + typeof typedObj["n_users_with_max_points"] === "number" + ) +} + +export function isReviewingStage(obj: unknown): obj is ReviewingStage { + const typedObj = obj as ReviewingStage + return ( + typedObj === "NotStarted" || + typedObj === "PeerReview" || + typedObj === "SelfReview" || + typedObj === "WaitingForPeerReviews" || + typedObj === "WaitingForManualGrading" || + typedObj === "ReviewedAndLocked" + ) +} + +export function isUserCourseInstanceChapterExerciseProgress( + obj: unknown, +): obj is UserCourseInstanceChapterExerciseProgress { + const typedObj = obj as UserCourseInstanceChapterExerciseProgress + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["exercise_id"] === "string" && + typeof typedObj["score_given"] === "number" + ) +} + +export function isUserCourseInstanceProgress(obj: unknown): obj is UserCourseInstanceProgress { + const typedObj = obj as UserCourseInstanceProgress + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["course_module_id"] === "string" && + typeof typedObj["course_module_name"] === "string" && + typeof typedObj["course_module_order_number"] === "number" && + typeof typedObj["score_given"] === "number" && + (typedObj["score_required"] === null || typeof typedObj["score_required"] === "number") && + (typedObj["score_maximum"] === null || typeof typedObj["score_maximum"] === "number") && + (typedObj["total_exercises"] === null || typeof typedObj["total_exercises"] === "number") && + (typedObj["attempted_exercises"] === null || + typeof typedObj["attempted_exercises"] === "number") && + (typedObj["attempted_exercises_required"] === null || + typeof typedObj["attempted_exercises_required"] === "number") + ) +} + +export function isUserExerciseState(obj: unknown): obj is UserExerciseState { + const typedObj = obj as UserExerciseState + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["user_id"] === "string" && + typeof typedObj["exercise_id"] === "string" && + (typedObj["course_instance_id"] === null || + typeof typedObj["course_instance_id"] === "string") && + (typedObj["exam_id"] === null || typeof typedObj["exam_id"] === "string") && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + (typedObj["score_given"] === null || typeof typedObj["score_given"] === "number") && + (isGradingProgress(typedObj["grading_progress"]) as boolean) && + (isActivityProgress(typedObj["activity_progress"]) as boolean) && + (isReviewingStage(typedObj["reviewing_stage"]) as boolean) && + (typedObj["selected_exercise_slide_id"] === null || + typeof typedObj["selected_exercise_slide_id"] === "string") + ) +} + +export function isUserResearchConsent(obj: unknown): obj is UserResearchConsent { + const typedObj = obj as UserResearchConsent + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["user_id"] === "string" && + typeof typedObj["research_consent"] === "boolean" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") + ) +} + +export function isUser(obj: unknown): obj is User { + const typedObj = obj as User + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + (typedObj["upstream_id"] === null || typeof typedObj["upstream_id"] === "number") && + (typedObj["email_domain"] === null || typeof typedObj["email_domain"] === "string") + ) +} + +export function isPageVisitDatumSummaryByCourse( + obj: unknown, +): obj is PageVisitDatumSummaryByCourse { + const typedObj = obj as PageVisitDatumSummaryByCourse + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + (typedObj["course_id"] === null || typeof typedObj["course_id"] === "string") && + (typedObj["exam_id"] === null || typeof typedObj["exam_id"] === "string") && + (typedObj["referrer"] === null || typeof typedObj["referrer"] === "string") && + (typedObj["utm_source"] === null || typeof typedObj["utm_source"] === "string") && + (typedObj["utm_medium"] === null || typeof typedObj["utm_medium"] === "string") && + (typedObj["utm_campaign"] === null || typeof typedObj["utm_campaign"] === "string") && + (typedObj["utm_term"] === null || typeof typedObj["utm_term"] === "string") && + (typedObj["utm_content"] === null || typeof typedObj["utm_content"] === "string") && + typeof typedObj["num_visitors"] === "number" && + typeof typedObj["visit_date"] === "string" + ) +} + +export function isPageVisitDatumSummaryByCourseDeviceTypes( + obj: unknown, +): obj is PageVisitDatumSummaryByCourseDeviceTypes { + const typedObj = obj as PageVisitDatumSummaryByCourseDeviceTypes + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + (typedObj["browser"] === null || typeof typedObj["browser"] === "string") && + (typedObj["browser_version"] === null || typeof typedObj["browser_version"] === "string") && + (typedObj["operating_system"] === null || typeof typedObj["operating_system"] === "string") && + (typedObj["device_type"] === null || typeof typedObj["device_type"] === "string") && + (typedObj["course_id"] === null || typeof typedObj["course_id"] === "string") && + (typedObj["exam_id"] === null || typeof typedObj["exam_id"] === "string") && + typeof typedObj["num_visitors"] === "number" && + typeof typedObj["visit_date"] === "string" + ) +} + +export function isPageVisitDatumSummaryByPages(obj: unknown): obj is PageVisitDatumSummaryByPages { + const typedObj = obj as PageVisitDatumSummaryByPages + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + (typedObj["exam_id"] === null || typeof typedObj["exam_id"] === "string") && + (typedObj["course_id"] === null || typeof typedObj["course_id"] === "string") && + typeof typedObj["page_id"] === "string" && + typeof typedObj["num_visitors"] === "number" && + typeof typedObj["visit_date"] === "string" + ) +} + +export function isPageVisitDatumSummaryByCoursesCountries( + obj: unknown, +): obj is PageVisitDatumSummaryByCoursesCountries { + const typedObj = obj as PageVisitDatumSummaryByCoursesCountries + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["created_at"] === "string" && + typeof typedObj["updated_at"] === "string" && + (typedObj["deleted_at"] === null || typeof typedObj["deleted_at"] === "string") && + (typedObj["country"] === null || typeof typedObj["country"] === "string") && + (typedObj["course_id"] === null || typeof typedObj["course_id"] === "string") && + (typedObj["exam_id"] === null || typeof typedObj["exam_id"] === "string") && + typeof typedObj["num_visitors"] === "number" && + typeof typedObj["visit_date"] === "string" + ) +} + +export function isUploadResult(obj: unknown): obj is UploadResult { + const typedObj = obj as UploadResult + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["url"] === "string" + ) +} + +export function isCreateAccountDetails(obj: unknown): obj is CreateAccountDetails { + const typedObj = obj as CreateAccountDetails + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["email"] === "string" && + typeof typedObj["first_name"] === "string" && + typeof typedObj["last_name"] === "string" && + typeof typedObj["language"] === "string" && + typeof typedObj["password"] === "string" && + typeof typedObj["password_confirmation"] === "string" + ) +} + +export function isLogin(obj: unknown): obj is Login { + const typedObj = obj as Login + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["email"] === "string" && + typeof typedObj["password"] === "string" + ) +} + +export function isUserInfo(obj: unknown): obj is UserInfo { + const typedObj = obj as UserInfo + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["user_id"] === "string" && + (typedObj["first_name"] === null || typeof typedObj["first_name"] === "string") && + (typedObj["last_name"] === null || typeof typedObj["last_name"] === "string") + ) +} + +export function isSaveCourseSettingsPayload(obj: unknown): obj is SaveCourseSettingsPayload { + const typedObj = obj as SaveCourseSettingsPayload + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + Array.isArray(typedObj["background_question_answers"]) && + typedObj["background_question_answers"].every( + (e: any) => isNewCourseBackgroundQuestionAnswer(e) as boolean, + ) + ) +} + +export function isChaptersWithStatus(obj: unknown): obj is ChaptersWithStatus { + const typedObj = obj as ChaptersWithStatus + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["is_previewable"] === "boolean" && + Array.isArray(typedObj["modules"]) && + typedObj["modules"].every((e: any) => isCourseMaterialCourseModule(e) as boolean) + ) +} + +export function isCourseMaterialCourseModule(obj: unknown): obj is CourseMaterialCourseModule { + const typedObj = obj as CourseMaterialCourseModule + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + Array.isArray(typedObj["chapters"]) && + typedObj["chapters"].every((e: any) => isChapterWithStatus(e) as boolean) && + typeof typedObj["id"] === "string" && + typeof typedObj["is_default"] === "boolean" && + (typedObj["name"] === null || typeof typedObj["name"] === "string") && + typeof typedObj["order_number"] === "number" + ) +} + +export function isExamData(obj: unknown): obj is ExamData { + const typedObj = obj as ExamData + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["id"] === "string" && + typeof typedObj["name"] === "string" && + typeof typedObj["starts_at"] === "string" && + typeof typedObj["ends_at"] === "string" && + typeof typedObj["ended"] === "boolean" && + typeof typedObj["time_minutes"] === "number" && + (isExamEnrollmentData(typedObj["enrollment_data"]) as boolean) && + typeof typedObj["language"] === "string" + ) +} + +export function isExamEnrollmentData(obj: unknown): obj is ExamEnrollmentData { + const typedObj = obj as ExamEnrollmentData + return ( + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["tag"] === "EnrolledAndStarted" && + typeof typedObj["page_id"] === "string" && + (isPage(typedObj["page"]) as boolean) && + (isExamEnrollment(typedObj["enrollment"]) as boolean)) || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["tag"] === "NotEnrolled" && + typeof typedObj["can_enroll"] === "boolean") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["tag"] === "NotYetStarted") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["tag"] === "StudentTimeUp") + ) +} + +export function isCourseMaterialPeerReviewDataWithToken( + obj: unknown, +): obj is CourseMaterialPeerReviewDataWithToken { + const typedObj = obj as CourseMaterialPeerReviewDataWithToken + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + (isCourseMaterialPeerReviewData(typedObj["course_material_peer_review_data"]) as boolean) && + (typedObj["token"] === null || typeof typedObj["token"] === "string") + ) +} + +export function isCertificateConfigurationUpdate( + obj: unknown, +): obj is CertificateConfigurationUpdate { + const typedObj = obj as CertificateConfigurationUpdate + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["course_module_id"] === "string" && + (typedObj["course_instance_id"] === null || + typeof typedObj["course_instance_id"] === "string") && + (typedObj["certificate_owner_name_y_pos"] === null || + typeof typedObj["certificate_owner_name_y_pos"] === "string") && + (typedObj["certificate_owner_name_x_pos"] === null || + typeof typedObj["certificate_owner_name_x_pos"] === "string") && + (typedObj["certificate_owner_name_font_size"] === null || + typeof typedObj["certificate_owner_name_font_size"] === "string") && + (typedObj["certificate_owner_name_text_color"] === null || + typeof typedObj["certificate_owner_name_text_color"] === "string") && + (typedObj["certificate_owner_name_text_anchor"] === null || + typedObj["certificate_owner_name_text_anchor"] === "start" || + typedObj["certificate_owner_name_text_anchor"] === "middle" || + typedObj["certificate_owner_name_text_anchor"] === "end") && + (typedObj["certificate_validate_url_y_pos"] === null || + typeof typedObj["certificate_validate_url_y_pos"] === "string") && + (typedObj["certificate_validate_url_x_pos"] === null || + typeof typedObj["certificate_validate_url_x_pos"] === "string") && + (typedObj["certificate_validate_url_font_size"] === null || + typeof typedObj["certificate_validate_url_font_size"] === "string") && + (typedObj["certificate_validate_url_text_color"] === null || + typeof typedObj["certificate_validate_url_text_color"] === "string") && + (typedObj["certificate_validate_url_text_anchor"] === null || + typedObj["certificate_validate_url_text_anchor"] === "start" || + typedObj["certificate_validate_url_text_anchor"] === "middle" || + typedObj["certificate_validate_url_text_anchor"] === "end") && + (typedObj["certificate_date_y_pos"] === null || + typeof typedObj["certificate_date_y_pos"] === "string") && + (typedObj["certificate_date_x_pos"] === null || + typeof typedObj["certificate_date_x_pos"] === "string") && + (typedObj["certificate_date_font_size"] === null || + typeof typedObj["certificate_date_font_size"] === "string") && + (typedObj["certificate_date_text_color"] === null || + typeof typedObj["certificate_date_text_color"] === "string") && + (typedObj["certificate_date_text_anchor"] === null || + typedObj["certificate_date_text_anchor"] === "start" || + typedObj["certificate_date_text_anchor"] === "middle" || + typedObj["certificate_date_text_anchor"] === "end") && + (typedObj["certificate_locale"] === null || + typeof typedObj["certificate_locale"] === "string") && + (typedObj["paper_size"] === null || + typedObj["paper_size"] === "horizontal-a4" || + typedObj["paper_size"] === "vertical-a4") && + (typedObj["background_svg_file_name"] === null || + typeof typedObj["background_svg_file_name"] === "string") && + (typedObj["overlay_svg_file_name"] === null || + typeof typedObj["overlay_svg_file_name"] === "string") && + typeof typedObj["clear_overlay_svg_file"] === "boolean" + ) +} + +export function isGetFeedbackQuery(obj: unknown): obj is GetFeedbackQuery { + const typedObj = obj as GetFeedbackQuery + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["read"] === "boolean" && + (typeof typedObj["page"] === "undefined" || typeof typedObj["page"] === "number") && + (typeof typedObj["limit"] === "undefined" || typeof typedObj["limit"] === "number") + ) +} + +export function isExamCourseInfo(obj: unknown): obj is ExamCourseInfo { + const typedObj = obj as ExamCourseInfo + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["course_id"] === "string" + ) +} + +export function isNewExerciseRepository(obj: unknown): obj is NewExerciseRepository { + const typedObj = obj as NewExerciseRepository + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + (typedObj["course_id"] === null || typeof typedObj["course_id"] === "string") && + (typedObj["exam_id"] === null || typeof typedObj["exam_id"] === "string") && + typeof typedObj["git_url"] === "string" && + (typedObj["deploy_key"] === null || typeof typedObj["deploy_key"] === "string") + ) +} + +export function isExerciseSubmissions(obj: unknown): obj is ExerciseSubmissions { + const typedObj = obj as ExerciseSubmissions + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + Array.isArray(typedObj["data"]) && + typedObj["data"].every((e: any) => isExerciseSlideSubmission(e) as boolean) && + typeof typedObj["total_pages"] === "number" + ) +} + +export function isMarkAsRead(obj: unknown): obj is MarkAsRead { + const typedObj = obj as MarkAsRead + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["read"] === "boolean" + ) +} + +export function isPlaygroundViewsMessage(obj: unknown): obj is PlaygroundViewsMessage { + const typedObj = obj as PlaygroundViewsMessage + return ( + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["tag"] === "TimedOut") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["tag"] === "Registered" && + typeof typedObj["data"] === "string") || + (((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typedObj["tag"] === "ExerciseTaskGradingResult" && + (isExerciseTaskGradingResult(typedObj["data"]) as boolean)) + ) +} + +export function isGetEditProposalsQuery(obj: unknown): obj is GetEditProposalsQuery { + const typedObj = obj as GetEditProposalsQuery + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["pending"] === "boolean" && + (typeof typedObj["page"] === "undefined" || typeof typedObj["page"] === "number") && + (typeof typedObj["limit"] === "undefined" || typeof typedObj["limit"] === "number") + ) +} + +export function isRoleQuery(obj: unknown): obj is RoleQuery { + const typedObj = obj as RoleQuery + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + (typeof typedObj["global"] === "undefined" || + typedObj["global"] === false || + typedObj["global"] === true) && + (typeof typedObj["organization_id"] === "undefined" || + typeof typedObj["organization_id"] === "string") && + (typeof typedObj["course_id"] === "undefined" || typeof typedObj["course_id"] === "string") && + (typeof typedObj["course_instance_id"] === "undefined" || + typeof typedObj["course_instance_id"] === "string") && + (typeof typedObj["exam_id"] === "undefined" || typeof typedObj["exam_id"] === "string") + ) +} + +export function isPagination(obj: unknown): obj is Pagination { + const typedObj = obj as Pagination + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + (typeof typedObj["page"] === "undefined" || typeof typedObj["page"] === "number") && + (typeof typedObj["limit"] === "undefined" || typeof typedObj["limit"] === "number") + ) +} + +export function isOEmbedResponse(obj: unknown): obj is OEmbedResponse { + const typedObj = obj as OEmbedResponse + return ( + ((typedObj !== null && typeof typedObj === "object") || typeof typedObj === "function") && + typeof typedObj["author_name"] === "string" && + typeof typedObj["author_url"] === "string" && + typeof typedObj["html"] === "string" && + typeof typedObj["provider_name"] === "string" && + typeof typedObj["provider_url"] === "string" && + typeof typedObj["title"] === "string" && + typeof typedObj["version"] === "string" + ) +} diff --git a/services/cms/src/shared-module-v2/common/bindings.ts b/services/cms/src/shared-module-v2/common/bindings.ts new file mode 100644 index 000000000000..f21eda71e52d --- /dev/null +++ b/services/cms/src/shared-module-v2/common/bindings.ts @@ -0,0 +1,1900 @@ +// ########################################### +// ## This file is autogenerated by running ## +// ## "bin/generate-bindings" in the root ## +// ## folder of this repo ## +// ## ## +// ## Do not edit this file by hand. ## +// ########################################### + +export type Action = + | { type: "view_material" } + | { type: "view" } + | { type: "edit" } + | { type: "grade" } + | { type: "teach" } + | { type: "download" } + | { type: "duplicate" } + | { type: "delete_answer" } + | { type: "edit_role"; variant: UserRole } + | { type: "create_courses_or_exams" } + | { type: "usually_unacceptable_deletion" } + | { type: "upload_file" } + | { type: "view_user_progress_or_details" } + | { type: "view_internal_course_structure" } + | { type: "view_stats" } + +export interface ActionOnResource { + action: Action + resource: Resource +} + +export type Resource = + | { type: "global_permissions" } + | { type: "chapter"; id: string } + | { type: "course"; id: string } + | { type: "course_instance"; id: string } + | { type: "exam"; id: string } + | { type: "exercise"; id: string } + | { type: "exercise_slide_submission"; id: string } + | { type: "exercise_task"; id: string } + | { type: "exercise_task_grading"; id: string } + | { type: "exercise_task_submission"; id: string } + | { type: "organization"; id: string } + | { type: "page"; id: string } + | { type: "study_registry"; id: string } + | { type: "any_course" } + | { type: "role" } + | { type: "user" } + | { type: "playground_example" } + | { type: "exercise_service" } + | { type: "material_reference" } + +export type ErrorData = { block_id: string } + +export interface ErrorResponse { + title: string + message: string + source: string | null + data: ErrorData | null +} + +export interface SpecRequest { + request_id: string + private_spec: unknown | null + upload_url: string | null +} + +export interface Chapter { + id: string + created_at: string + updated_at: string + name: string + color: string | null + course_id: string + deleted_at: string | null + chapter_image_url: string | null + chapter_number: number + front_page_id: string | null + opens_at: string | null + deadline: string | null + copied_from: string | null + course_module_id: string +} + +export type ChapterStatus = "open" | "closed" + +export interface ChapterUpdate { + name: string + color: string | null + front_page_id: string | null + deadline: string | null + opens_at: string | null + course_module_id: string | null +} + +export interface ChapterWithStatus { + id: string + created_at: string + updated_at: string + name: string + color: string | null + course_id: string + deleted_at: string | null + chapter_number: number + front_page_id: string | null + opens_at: string | null + status: ChapterStatus + chapter_image_url: string | null + course_module_id: string +} + +export interface DatabaseChapter { + id: string + created_at: string + updated_at: string + name: string + color: string | null + course_id: string + deleted_at: string | null + chapter_image_path: string | null + chapter_number: number + front_page_id: string | null + opens_at: string | null + deadline: string | null + copied_from: string | null + course_module_id: string +} + +export interface NewChapter { + name: string + color: string | null + course_id: string + chapter_number: number + front_page_id: string | null + opens_at: string | null + deadline: string | null + course_module_id: string | null +} + +export interface UserCourseInstanceChapterProgress { + score_given: number + score_maximum: number + total_exercises: number | null + attempted_exercises: number | null +} + +export interface CourseBackgroundQuestionAnswer { + id: string + created_at: string + updated_at: string + deleted_at: string | null + course_background_question_id: string + answer_value: string | null + user_id: string +} + +export interface NewCourseBackgroundQuestionAnswer { + answer_value: string | null + course_background_question_id: string +} + +export interface CourseBackgroundQuestion { + id: string + created_at: string + updated_at: string + deleted_at: string | null + course_instance_id: string | null + course_id: string + question_text: string + question_type: CourseBackgroundQuestionType +} + +export type CourseBackgroundQuestionType = "Checkbox" | "Text" + +export interface CourseBackgroundQuestionsAndAnswers { + background_questions: Array + answers: Array +} + +export interface CourseInstanceEnrollment { + user_id: string + course_id: string + course_instance_id: string + created_at: string + updated_at: string + deleted_at: string | null +} + +export interface CourseInstanceEnrollmentsInfo { + course_instance_enrollments: Array + course_instances: Array + courses: Array + user_course_settings: Array + course_module_completions: Array +} + +export interface ChapterScore { + id: string + created_at: string + updated_at: string + name: string + color: string | null + course_id: string + deleted_at: string | null + chapter_image_path: string | null + chapter_number: number + front_page_id: string | null + opens_at: string | null + deadline: string | null + copied_from: string | null + course_module_id: string + score_given: number + score_total: number +} + +export interface CourseInstance { + id: string + created_at: string + updated_at: string + deleted_at: string | null + course_id: string + starts_at: string | null + ends_at: string | null + name: string | null + description: string | null + teacher_in_charge_name: string + teacher_in_charge_email: string + support_email: string | null +} + +export interface CourseInstanceForm { + name: string | null + description: string | null + teacher_in_charge_name: string + teacher_in_charge_email: string + support_email: string | null + opening_time: string | null + closing_time: string | null +} + +export type PointMap = Record + +export interface Points { + chapter_points: Array + users: Array + user_chapter_points: Record +} + +export interface GeneratedCertificate { + id: string + created_at: string + updated_at: string + deleted_at: string | null + user_id: string + name_on_certificate: string + verification_id: string + certificate_configuration_id: string +} + +export interface CertificateConfiguration { + id: string + created_at: string + updated_at: string + deleted_at: string | null + certificate_owner_name_y_pos: string + certificate_owner_name_x_pos: string + certificate_owner_name_font_size: string + certificate_owner_name_text_color: string + certificate_owner_name_text_anchor: CertificateTextAnchor + certificate_validate_url_y_pos: string + certificate_validate_url_x_pos: string + certificate_validate_url_font_size: string + certificate_validate_url_text_color: string + certificate_validate_url_text_anchor: CertificateTextAnchor + certificate_date_y_pos: string + certificate_date_x_pos: string + certificate_date_font_size: string + certificate_date_text_color: string + certificate_date_text_anchor: CertificateTextAnchor + certificate_locale: string + paper_size: PaperSize + background_svg_path: string + background_svg_file_upload_id: string + overlay_svg_path: string | null + overlay_svg_file_upload_id: string | null +} + +export type CertificateTextAnchor = "start" | "middle" | "end" + +export type PaperSize = "horizontal-a4" | "vertical-a4" + +export interface CourseModuleCompletionWithRegistrationInfo { + completion_registration_attempt_date: string | null + course_module_id: string + created_at: string + grade: number | null + passed: boolean + prerequisite_modules_completed: boolean + registered: boolean + user_id: string +} + +export interface CourseModuleCompletion { + id: string + created_at: string + updated_at: string + deleted_at: string | null + course_id: string + course_instance_id: string + course_module_id: string + user_id: string + completion_date: string + completion_registration_attempt_date: string | null + completion_language: string + eligible_for_ects: boolean + email: string + grade: number | null + passed: boolean + prerequisite_modules_completed: boolean + completion_granter_user_id: string | null +} + +export interface AutomaticCompletionRequirements { + course_module_id: string + number_of_exercises_attempted_treshold: number | null + number_of_points_treshold: number | null + requires_exam: boolean +} + +export type CompletionPolicy = + | ({ policy: "automatic" } & AutomaticCompletionRequirements) + | { policy: "manual" } + +export interface CourseModule { + id: string + created_at: string + updated_at: string + deleted_at: string | null + name: string | null + course_id: string + order_number: number + copied_from: string | null + uh_course_code: string | null + completion_policy: CompletionPolicy + completion_registration_link_override: string | null + ects_credits: number | null + enable_registering_completion_to_uh_open_university: boolean + certification_enabled: boolean +} + +export interface ModifiedModule { + id: string + name: string | null + order_number: number + uh_course_code: string | null + ects_credits: number | null + completion_policy: CompletionPolicy + completion_registration_link_override: string | null + enable_registering_completion_to_uh_open_university: boolean +} + +export interface ModuleUpdates { + new_modules: Array + deleted_modules: Array + modified_modules: Array + moved_chapters: Array<[string, string]> +} + +export interface NewCourseModule { + completion_policy: CompletionPolicy + completion_registration_link_override: string | null + course_id: string + ects_credits: number | null + name: string | null + order_number: number + uh_course_code: string | null + enable_registering_completion_to_uh_open_university: boolean +} + +export interface NewModule { + name: string + order_number: number + chapters: Array + uh_course_code: string | null + ects_credits: number | null + completion_policy: CompletionPolicy + completion_registration_link_override: string | null + enable_registering_completion_to_uh_open_university: boolean +} + +export interface Course { + id: string + slug: string + created_at: string + updated_at: string + name: string + description: string | null + organization_id: string + deleted_at: string | null + language_code: string + copied_from: string | null + content_search_language: string | null + course_language_group_id: string + is_draft: boolean + is_test_mode: boolean + base_module_completion_requires_n_submodule_completions: number +} + +export interface CourseCount { + count: number +} + +export interface CourseStructure { + course: Course + pages: Array + chapters: Array + modules: Array +} + +export interface CourseUpdate { + name: string + description: string | null + is_draft: boolean + is_test_mode: boolean +} + +export interface NewCourse { + name: string + slug: string + organization_id: string + language_code: string + teacher_in_charge_name: string + teacher_in_charge_email: string + description: string + is_draft: boolean + is_test_mode: boolean + copy_user_permissions: boolean +} + +export interface CourseBreadcrumbInfo { + course_id: string + course_name: string + course_slug: string + organization_slug: string + organization_name: string +} + +export interface CertificateConfigurationAndRequirements { + certificate_configuration: CertificateConfiguration + requirements: CertificateAllRequirements +} + +export interface CertificateAllRequirements { + certificate_configuration_id: string + course_module_ids: Array + course_instance_ids: Array +} + +export interface EmailTemplate { + id: string + created_at: string + updated_at: string + deleted_at: string | null + content: unknown | null + name: string + subject: string | null + exercise_completions_threshold: number | null + points_threshold: number | null + course_instance_id: string +} + +export interface EmailTemplateNew { + name: string +} + +export interface EmailTemplateUpdate { + name: string + subject: string + content: unknown + exercise_completions_threshold: number | null + points_threshold: number | null +} + +export interface CourseExam { + id: string + course_id: string + course_name: string + name: string +} + +export interface Exam { + id: string + name: string + instructions: unknown + page_id: string + courses: Array + starts_at: string | null + ends_at: string | null + time_minutes: number + minimum_points_treshold: number + language: string +} + +export interface ExamEnrollment { + user_id: string + exam_id: string + started_at: string +} + +export interface ExamInstructions { + id: string + instructions: unknown +} + +export interface ExamInstructionsUpdate { + instructions: unknown +} + +export interface NewExam { + name: string + starts_at: string | null + ends_at: string | null + time_minutes: number + organization_id: string + minimum_points_treshold: number +} + +export interface OrgExam { + id: string + name: string + instructions: unknown + starts_at: string | null + ends_at: string | null + time_minutes: number + organization_id: string + minimum_points_treshold: number +} + +export interface ExerciseRepository { + id: string + url: string + course_id: string | null + exam_id: string | null + status: ExerciseRepositoryStatus + error_message: string | null +} + +export type ExerciseRepositoryStatus = "Pending" | "Success" | "Failure" + +export interface CourseMaterialExerciseServiceInfo { + exercise_iframe_url: string +} + +export interface ExerciseServiceInfoApi { + service_name: string + user_interface_iframe_path: string + grade_endpoint_path: string + public_spec_endpoint_path: string + model_solution_spec_endpoint_path: string +} + +export interface ExerciseService { + id: string + created_at: string + updated_at: string + deleted_at: string | null + name: string + slug: string + public_url: string + internal_url: string | null + max_reprocessing_submissions_at_once: number +} + +export interface ExerciseServiceIframeRenderingInfo { + id: string + name: string + slug: string + public_iframe_url: string +} + +export interface ExerciseServiceNewOrUpdate { + name: string + slug: string + public_url: string + internal_url: string | null + max_reprocessing_submissions_at_once: number +} + +export interface AnswerRequiringAttention { + id: string + user_id: string + created_at: string + updated_at: string + deleted_at: string | null + data_json: unknown | null + course_instance_id: string | null + grading_progress: GradingProgress + score_given: number | null + submission_id: string + exercise_id: string +} + +export interface ExerciseAnswersInCourseRequiringAttentionCount { + id: string + name: string + page_id: string + chapter_id: string | null + order_number: number + count: number | null +} + +export interface ExerciseSlideSubmission { + id: string + created_at: string + updated_at: string + deleted_at: string | null + exercise_slide_id: string + course_id: string | null + course_instance_id: string | null + exam_id: string | null + exercise_id: string + user_id: string + user_points_update_strategy: UserPointsUpdateStrategy +} + +export interface ExerciseSlideSubmissionCount { + date: string | null + count: number | null +} + +export interface ExerciseSlideSubmissionCountByExercise { + exercise_id: string + count: number | null + exercise_name: string +} + +export interface ExerciseSlideSubmissionCountByWeekAndHour { + isodow: number | null + hour: number | null + count: number | null +} + +export interface ExerciseSlideSubmissionInfo { + tasks: Array + exercise: Exercise + exercise_slide_submission: ExerciseSlideSubmission +} + +export interface PeerReviewsRecieved { + peer_review_questions: Array + peer_review_question_submissions: Array +} + +export interface CourseMaterialExerciseSlide { + id: string + exercise_tasks: Array +} + +export interface ExerciseSlide { + id: string + created_at: string + updated_at: string + deleted_at: string | null + exercise_id: string + order_number: number +} + +export interface ExerciseTaskGrading { + id: string + created_at: string + updated_at: string + exercise_task_submission_id: string + course_id: string | null + exam_id: string | null + exercise_id: string + exercise_task_id: string + grading_priority: number + score_given: number | null + grading_progress: GradingProgress + unscaled_score_given: number | null + unscaled_score_maximum: number | null + grading_started_at: string | null + grading_completed_at: string | null + feedback_json: unknown | null + feedback_text: string | null + deleted_at: string | null +} + +export interface ExerciseTaskGradingResult { + grading_progress: GradingProgress + score_given: number + score_maximum: number + feedback_text: string | null + feedback_json: unknown | null + set_user_variables?: Record +} + +export type UserPointsUpdateStrategy = + | "CanAddPointsButCannotRemovePoints" + | "CanAddPointsAndCanRemovePoints" + +export interface ExerciseTaskSubmission { + id: string + created_at: string + updated_at: string + deleted_at: string | null + exercise_slide_submission_id: string + exercise_task_id: string + exercise_slide_id: string + data_json: unknown | null + exercise_task_grading_id: string | null + metadata: unknown | null +} + +export interface CourseMaterialExerciseTask { + id: string + exercise_service_slug: string + exercise_slide_id: string + exercise_iframe_url: string | null + pseudonumous_user_id: string | null + assignment: unknown + public_spec: unknown | null + model_solution_spec: unknown | null + previous_submission: ExerciseTaskSubmission | null + previous_submission_grading: ExerciseTaskGrading | null + order_number: number +} + +export interface ExerciseTask { + id: string + created_at: string + updated_at: string + exercise_slide_id: string + exercise_type: string + assignment: unknown + deleted_at: string | null + public_spec: unknown | null + private_spec: unknown | null + model_solution_spec: unknown | null + copied_from: string | null + order_number: number +} + +export type ActivityProgress = "Initialized" | "Started" | "InProgress" | "Submitted" | "Completed" + +export interface CourseMaterialExercise { + exercise: Exercise + can_post_submission: boolean + current_exercise_slide: CourseMaterialExerciseSlide + exercise_status: ExerciseStatus | null + exercise_slide_submission_counts: Record + peer_review_config: CourseMaterialPeerReviewConfig | null + previous_exercise_slide_submission: ExerciseSlideSubmission | null + user_course_instance_exercise_service_variables: Array +} + +export interface Exercise { + id: string + created_at: string + updated_at: string + name: string + course_id: string | null + exam_id: string | null + page_id: string + chapter_id: string | null + deadline: string | null + deleted_at: string | null + score_maximum: number + order_number: number + copied_from: string | null + max_tries_per_slide: number | null + limit_number_of_tries: boolean + needs_peer_review: boolean + use_course_default_peer_review_config: boolean + exercise_language_group_id: string | null +} + +export interface ExerciseStatus { + score_given: number | null + activity_progress: ActivityProgress + grading_progress: GradingProgress + reviewing_stage: ReviewingStage +} + +export interface ExerciseStatusSummaryForUser { + exercise: Exercise + user_exercise_state: UserExerciseState | null + exercise_slide_submissions: Array + given_peer_review_submissions: Array + given_peer_review_question_submissions: Array + received_peer_review_submissions: Array + received_peer_review_question_submissions: Array + peer_review_queue_entry: PeerReviewQueueEntry | null + teacher_grading_decision: TeacherGradingDecision | null + peer_review_questions: Array +} + +export interface GlobalStatEntry { + name: string + course_id: string + organization_id: string + organization_name: string + year: string + value: number +} + +export interface ExerciseGradingStatus { + exercise_id: string + exercise_name: string + score_maximum: number + score_given: number | null + teacher_decision: TeacherDecisionType | null + submission_id: string + updated_at: string +} + +export type GradingProgress = "Failed" | "NotReady" | "PendingManual" | "Pending" | "FullyGraded" + +export interface Feedback { + id: string + user_id: string | null + course_id: string + page_id: string | null + feedback_given: string + selected_text: string | null + marked_as_read: boolean + created_at: string + blocks: Array + page_title: string + page_url_path: string +} + +export interface FeedbackBlock { + id: string + text: string | null + order_number: number | null +} + +export interface FeedbackCount { + read: number + unread: number +} + +export interface NewFeedback { + feedback_given: string + selected_text: string | null + related_blocks: Array + page_id: string +} + +export interface Term { + id: string + term: string + definition: string +} + +export interface TermUpdate { + term: string + definition: string +} + +export interface AnswerRequiringAttentionWithTasks { + id: string + user_id: string + created_at: string + updated_at: string + deleted_at: string | null + data_json: unknown | null + grading_progress: GradingProgress + score_given: number | null + submission_id: string + exercise_id: string + tasks: Array + given_peer_reviews: Array + received_peer_reviews: Array +} + +export interface AnswersRequiringAttention { + exercise_max_points: number + data: Array + total_pages: number +} + +export interface StudentExerciseSlideSubmission { + exercise_slide_id: string + exercise_task_submissions: Array +} + +export interface StudentExerciseSlideSubmissionResult { + exercise_status: ExerciseStatus | null + exercise_task_submission_results: Array + user_course_instance_exercise_service_variables: Array +} + +export interface StudentExerciseTaskSubmission { + exercise_task_id: string + data_json: unknown +} + +export interface StudentExerciseTaskSubmissionResult { + submission: ExerciseTaskSubmission + grading: ExerciseTaskGrading | null + model_solution_spec: unknown | null + exercise_task_exercise_service_slug: string +} + +export interface CourseMaterialPeerReviewData { + answer_to_review: CourseMaterialPeerReviewDataAnswerToReview | null + peer_review_config: PeerReviewConfig + peer_review_questions: Array + num_peer_reviews_given: number +} + +export interface CourseMaterialPeerReviewDataAnswerToReview { + exercise_slide_submission_id: string + course_material_exercise_tasks: Array +} + +export interface CourseMaterialPeerReviewQuestionAnswer { + peer_review_question_id: string + text_data: string | null + number_data: number | null +} + +export interface CourseMaterialPeerReviewSubmission { + exercise_slide_submission_id: string + peer_review_config_id: string + peer_review_question_answers: Array + token: string +} + +export interface CompletionRegistrationLink { + url: string +} + +export interface CourseInstanceCompletionSummary { + course_modules: Array + users_with_course_module_completions: Array +} + +export interface ManualCompletionPreview { + already_completed_users: Array + first_time_completing_users: Array + non_enrolled_users: Array +} + +export interface ManualCompletionPreviewUser { + user_id: string + first_name: string | null + last_name: string | null + grade: number | null + passed: boolean +} + +export interface TeacherManualCompletion { + user_id: string + grade: number | null + completion_date: string | null +} + +export interface TeacherManualCompletionRequest { + course_module_id: string + new_completions: Array + skip_duplicate_completions: boolean +} + +export interface UserCompletionInformation { + course_module_completion_id: string + course_name: string + uh_course_code: string + email: string + ects_credits: number | null + enable_registering_completion_to_uh_open_university: boolean +} + +export interface UserCourseModuleCompletion { + course_module_id: string + grade: number | null + passed: boolean +} + +export interface UserModuleCompletionStatus { + completed: boolean + default: boolean + module_id: string + name: string + order_number: number + prerequisite_modules_completed: boolean + grade: number | null + passed: boolean | null + enable_registering_completion_to_uh_open_university: boolean + certification_enabled: boolean + certificate_configuration_id: string | null +} + +export interface UserWithModuleCompletions { + completed_modules: Array + email: string + first_name: string | null + last_name: string | null + user_id: string +} + +export interface MaterialReference { + id: string + course_id: string + citation_key: string + reference: string + created_at: string + updated_at: string + deleted_at: string | null +} + +export interface NewMaterialReference { + citation_key: string + reference: string +} + +export interface Organization { + id: string + slug: string + created_at: string + updated_at: string + name: string + description: string | null + organization_image_url: string | null + deleted_at: string | null +} + +export type HistoryChangeReason = "PageSaved" | "HistoryRestored" + +export interface PageHistory { + id: string + created_at: string + title: string + content: unknown + history_change_reason: HistoryChangeReason + restored_from_id: string | null + author_user_id: string +} + +export interface CmsPageExercise { + id: string + name: string + order_number: number + score_maximum: number + max_tries_per_slide: number | null + limit_number_of_tries: boolean + deadline: string | null + needs_peer_review: boolean + peer_review_config: CmsPeerReviewConfig | null + peer_review_questions: Array | null + use_course_default_peer_review_config: boolean +} + +export interface CmsPageExerciseSlide { + id: string + exercise_id: string + order_number: number +} + +export interface CmsPageExerciseTask { + id: string + exercise_slide_id: string + assignment: unknown + exercise_type: string + private_spec: unknown | null + order_number: number +} + +export interface CmsPageUpdate { + content: unknown + exercises: Array + exercise_slides: Array + exercise_tasks: Array + url_path: string + title: string + chapter_id: string | null +} + +export interface ContentManagementPage { + page: Page + exercises: Array + exercise_slides: Array + exercise_tasks: Array + peer_review_configs: Array + peer_review_questions: Array + organization_id: string +} + +export interface CoursePageWithUserData { + page: Page + instance: CourseInstance | null + settings: UserCourseSettings | null + was_redirected: boolean + is_test_mode: boolean +} + +export interface ExerciseWithExerciseTasks { + id: string + created_at: string + updated_at: string + course_id: string + deleted_at: string | null + name: string + deadline: string | null + page_id: string + exercise_tasks: Array + score_maximum: number +} + +export interface HistoryRestoreData { + history_id: string +} + +export interface IsChapterFrontPage { + is_chapter_front_page: boolean +} + +export interface NewPage { + exercises: Array + exercise_slides: Array + exercise_tasks: Array + content: unknown + url_path: string + title: string + course_id: string | null + exam_id: string | null + chapter_id: string | null + front_page_of_chapter_id: string | null + content_search_language: string | null +} + +export interface Page { + id: string + created_at: string + updated_at: string + course_id: string | null + exam_id: string | null + chapter_id: string | null + url_path: string + title: string + deleted_at: string | null + content: unknown + order_number: number + copied_from: string | null + hidden: boolean + page_language_group_id: string | null +} + +export interface PageChapterAndCourseInformation { + chapter_name: string | null + chapter_number: number | null + course_name: string | null + course_slug: string | null + chapter_front_page_id: string | null + chapter_front_page_url_path: string | null + organization_slug: string +} + +export interface PageInfo { + page_id: string + page_title: string + course_id: string | null + course_name: string | null + course_slug: string | null + organization_slug: string | null +} + +export interface PageNavigationInformation { + chapter_front_page: PageRoutingData | null + next_page: PageRoutingData | null + previous_page: PageRoutingData | null +} + +export interface PageRoutingData { + url_path: string + title: string + page_id: string + chapter_number: number + chapter_id: string + chapter_opens_at: string | null + chapter_front_page_id: string | null +} + +export interface SearchRequest { + query: string +} + +export interface PageSearchResult { + id: string + title_headline: string | null + rank: number | null + content_headline: string | null + url_path: string +} + +export interface PageWithExercises { + id: string + created_at: string + updated_at: string + course_id: string | null + exam_id: string | null + chapter_id: string | null + url_path: string + title: string + deleted_at: string | null + content: unknown + order_number: number + copied_from: string | null + hidden: boolean + page_language_group_id: string | null + exercises: Array +} + +export interface PageDetailsUpdate { + title: string + url_path: string +} + +export interface CmsPeerReviewConfig { + id: string + course_id: string + exercise_id: string | null + peer_reviews_to_give: number + peer_reviews_to_receive: number + accepting_threshold: number + processing_strategy: PeerReviewProcessingStrategy + points_are_all_or_nothing: boolean +} + +export interface CmsPeerReviewConfiguration { + peer_review_config: CmsPeerReviewConfig + peer_review_questions: Array +} + +export interface CourseMaterialPeerReviewConfig { + id: string + course_id: string + exercise_id: string | null + peer_reviews_to_give: number + peer_reviews_to_receive: number +} + +export type PeerReviewProcessingStrategy = + | "AutomaticallyGradeByAverage" + | "AutomaticallyGradeOrManualReviewByAverage" + | "ManualReviewEverything" + +export interface PeerReviewConfig { + id: string + created_at: string + updated_at: string + deleted_at: string | null + course_id: string + exercise_id: string | null + peer_reviews_to_give: number + peer_reviews_to_receive: number + accepting_threshold: number + processing_strategy: PeerReviewProcessingStrategy + manual_review_cutoff_in_days: number + points_are_all_or_nothing: boolean +} + +export interface PeerReviewSubmission { + id: string + created_at: string + updated_at: string + deleted_at: string | null + user_id: string + exercise_id: string + course_instance_id: string + peer_review_config_id: string + exercise_slide_submission_id: string +} + +export type PeerReviewAnswer = + | { type: "no-answer" } + | { type: "essay"; value: string } + | { type: "scale"; value: number } + +export interface PeerReviewQuestionAndAnswer { + peer_review_config_id: string + peer_review_question_id: string + peer_review_submission_id: string + peer_review_question_submission_id: string + order_number: number + question: string + answer: PeerReviewAnswer + answer_required: boolean +} + +export interface PeerReviewQuestionSubmission { + id: string + created_at: string + updated_at: string + deleted_at: string | null + peer_review_question_id: string + peer_review_submission_id: string + text_data: string | null + number_data: number | null +} + +export interface PeerReviewQueueEntry { + id: string + created_at: string + updated_at: string + deleted_at: string | null + user_id: string + exercise_id: string + course_instance_id: string + receiving_peer_reviews_exercise_slide_submission_id: string + received_enough_peer_reviews: boolean + peer_review_priority: number + removed_from_queue_for_unusual_reason: boolean +} + +export interface PeerReviewWithQuestionsAndAnswers { + peer_review_submission_id: string + questions_and_answers: Array +} + +export interface CmsPeerReviewQuestion { + id: string + peer_review_config_id: string + order_number: number + question: string + question_type: PeerReviewQuestionType + answer_required: boolean + weight: number +} + +export interface PeerReviewQuestion { + id: string + created_at: string + updated_at: string + deleted_at: string | null + peer_review_config_id: string + order_number: number + question: string + question_type: PeerReviewQuestionType + answer_required: boolean + weight: number +} + +export type PeerReviewQuestionType = "Essay" | "Scale" + +export interface PendingRole { + id: string + user_email: string + role: UserRole + expires_at: string +} + +export interface PlaygroundExample { + id: string + created_at: string + updated_at: string + deleted_at: string | null + name: string + url: string + width: number + data: unknown +} + +export interface PlaygroundExampleData { + name: string + url: string + width: number + data: unknown +} + +export type BlockProposal = + | ({ type: "edited-block-still-exists" } & EditedBlockStillExistsData) + | ({ type: "edited-block-no-longer-exists" } & EditedBlockNoLongerExistsData) + +export interface EditedBlockStillExistsData { + id: string + block_id: string + current_text: string + changed_text: string + original_text: string + status: ProposalStatus + accept_preview: string | null +} + +export interface EditedBlockNoLongerExistsData { + id: string + block_id: string + changed_text: string + original_text: string + status: ProposalStatus +} + +export type BlockProposalAction = { tag: "Accept"; data: string } | { tag: "Reject" } + +export interface BlockProposalInfo { + id: string + action: BlockProposalAction +} + +export interface NewProposedBlockEdit { + block_id: string + block_attribute: string + original_text: string + changed_text: string +} + +export type ProposalStatus = "Pending" | "Accepted" | "Rejected" + +export interface EditProposalInfo { + page_id: string + page_proposal_id: string + block_proposals: Array +} + +export interface NewProposedPageEdits { + page_id: string + block_edits: Array +} + +export interface PageProposal { + id: string + page_id: string + user_id: string | null + pending: boolean + created_at: string + block_proposals: Array + page_title: string + page_url_path: string +} + +export interface ProposalCount { + pending: number + handled: number +} + +export interface PageAudioFile { + id: string + page_id: string + created_at: string + deleted_at: string | null + path: string + mime_type: string +} + +export interface NewRegrading { + user_points_update_strategy: UserPointsUpdateStrategy + exercise_task_submission_ids: Array +} + +export interface Regrading { + id: string + created_at: string + updated_at: string + regrading_started_at: string | null + regrading_completed_at: string | null + total_grading_progress: GradingProgress + user_points_update_strategy: UserPointsUpdateStrategy + user_id: string | null +} + +export interface RegradingInfo { + regrading: Regrading + submission_infos: Array +} + +export interface RegradingSubmissionInfo { + exercise_task_submission_id: string + grading_before_regrading: ExerciseTaskGrading + grading_after_regrading: ExerciseTaskGrading | null +} + +export interface RepositoryExercise { + id: string + repository_id: string + part: string + name: string + repository_url: string + checksum: Array + download_url: string +} + +export interface NewResearchForm { + course_id: string + content: unknown +} + +export interface NewResearchFormQuestion { + question_id: string + course_id: string + research_consent_form_id: string + question: string +} + +export interface ResearchFormQuestion { + id: string + course_id: string + research_consent_form_id: string + question: string + created_at: string + updated_at: string + deleted_at: string | null +} + +export interface ResearchForm { + id: string + course_id: string + content: unknown + created_at: string + updated_at: string + deleted_at: string | null +} + +export interface NewResearchFormQuestionAnswer { + user_id: string + research_form_question_id: string + research_consent: boolean +} + +export interface ResearchFormQuestionAnswer { + id: string + user_id: string + course_id: string + research_form_question_id: string + research_consent: boolean + created_at: string + updated_at: string + deleted_at: string | null +} + +export type RoleDomain = + | { tag: "Global" } + | { tag: "Organization"; id: string } + | { tag: "Course"; id: string } + | { tag: "CourseInstance"; id: string } + | { tag: "Exam"; id: string } + +export interface RoleInfo { + email: string + role: UserRole + domain: RoleDomain +} + +export interface RoleUser { + id: string + first_name: string | null + last_name: string | null + email: string + role: UserRole +} + +export type UserRole = + | "Reviewer" + | "Assistant" + | "Teacher" + | "Admin" + | "CourseOrExamCreator" + | "MaterialViewer" + | "TeachingAndLearningServices" + +export interface StudentCountry { + id: string + user_id: string + course_id: string + course_instance_id: string + country_code: string + created_at: string + deleted_at: string | null +} + +export interface NewTeacherGradingDecision { + user_exercise_state_id: string + exercise_id: string + action: TeacherDecisionType + manual_points: number | null +} + +export type TeacherDecisionType = + | "FullPoints" + | "ZeroPoints" + | "CustomPoints" + | "SuspectedPlagiarism" + +export interface TeacherGradingDecision { + id: string + user_exercise_state_id: string + created_at: string + updated_at: string + deleted_at: string | null + score_given: number + teacher_decision: TeacherDecisionType +} + +export interface UserCourseInstanceExerciseServiceVariable { + id: string + created_at: string + updated_at: string + deleted_at: string | null + exercise_service_slug: string + user_id: string + course_instance_id: string | null + exam_id: string | null + variable_key: string + variable_value: unknown +} + +export interface UserCourseSettings { + user_id: string + course_language_group_id: string + created_at: string + updated_at: string + deleted_at: string | null + current_course_id: string + current_course_instance_id: string +} + +export interface UserDetail { + user_id: string + created_at: string + updated_at: string + email: string + first_name: string | null + last_name: string | null + search_helper: string | null +} + +export interface ExerciseUserCounts { + exercise_name: string + exercise_order_number: number + page_order_number: number + chapter_number: number + exercise_id: string + n_users_attempted: number + n_users_with_some_points: number + n_users_with_max_points: number +} + +export type ReviewingStage = + | "NotStarted" + | "PeerReview" + | "SelfReview" + | "WaitingForPeerReviews" + | "WaitingForManualGrading" + | "ReviewedAndLocked" + +export interface UserCourseInstanceChapterExerciseProgress { + exercise_id: string + score_given: number +} + +export interface UserCourseInstanceProgress { + course_module_id: string + course_module_name: string + course_module_order_number: number + score_given: number + score_required: number | null + score_maximum: number | null + total_exercises: number | null + attempted_exercises: number | null + attempted_exercises_required: number | null +} + +export interface UserExerciseState { + id: string + user_id: string + exercise_id: string + course_instance_id: string | null + exam_id: string | null + created_at: string + updated_at: string + deleted_at: string | null + score_given: number | null + grading_progress: GradingProgress + activity_progress: ActivityProgress + reviewing_stage: ReviewingStage + selected_exercise_slide_id: string | null +} + +export interface UserResearchConsent { + id: string + user_id: string + research_consent: boolean + created_at: string + updated_at: string + deleted_at: string | null +} + +export interface User { + id: string + created_at: string + updated_at: string + deleted_at: string | null + upstream_id: number | null + email_domain: string | null +} + +export interface PageVisitDatumSummaryByCourse { + id: string + created_at: string + updated_at: string + deleted_at: string | null + course_id: string | null + exam_id: string | null + referrer: string | null + utm_source: string | null + utm_medium: string | null + utm_campaign: string | null + utm_term: string | null + utm_content: string | null + num_visitors: number + visit_date: string +} + +export interface PageVisitDatumSummaryByCourseDeviceTypes { + id: string + created_at: string + updated_at: string + deleted_at: string | null + browser: string | null + browser_version: string | null + operating_system: string | null + device_type: string | null + course_id: string | null + exam_id: string | null + num_visitors: number + visit_date: string +} + +export interface PageVisitDatumSummaryByPages { + id: string + created_at: string + updated_at: string + deleted_at: string | null + exam_id: string | null + course_id: string | null + page_id: string + num_visitors: number + visit_date: string +} + +export interface PageVisitDatumSummaryByCoursesCountries { + id: string + created_at: string + updated_at: string + deleted_at: string | null + country: string | null + course_id: string | null + exam_id: string | null + num_visitors: number + visit_date: string +} + +export interface UploadResult { + url: string +} + +export interface CreateAccountDetails { + email: string + first_name: string + last_name: string + language: string + password: string + password_confirmation: string +} + +export interface Login { + email: string + password: string +} + +export interface UserInfo { + user_id: string + first_name: string | null + last_name: string | null +} + +export interface SaveCourseSettingsPayload { + background_question_answers: Array +} + +export interface ChaptersWithStatus { + is_previewable: boolean + modules: Array +} + +export interface CourseMaterialCourseModule { + chapters: Array + id: string + is_default: boolean + name: string | null + order_number: number +} + +export interface ExamData { + id: string + name: string + instructions: unknown + starts_at: string + ends_at: string + ended: boolean + time_minutes: number + enrollment_data: ExamEnrollmentData + language: string +} + +export type ExamEnrollmentData = + | { tag: "EnrolledAndStarted"; page_id: string; page: Page; enrollment: ExamEnrollment } + | { tag: "NotEnrolled"; can_enroll: boolean } + | { tag: "NotYetStarted" } + | { tag: "StudentTimeUp" } + +export interface CourseMaterialPeerReviewDataWithToken { + course_material_peer_review_data: CourseMaterialPeerReviewData + token: string | null +} + +export interface CertificateConfigurationUpdate { + course_module_id: string + course_instance_id: string | null + certificate_owner_name_y_pos: string | null + certificate_owner_name_x_pos: string | null + certificate_owner_name_font_size: string | null + certificate_owner_name_text_color: string | null + certificate_owner_name_text_anchor: CertificateTextAnchor | null + certificate_validate_url_y_pos: string | null + certificate_validate_url_x_pos: string | null + certificate_validate_url_font_size: string | null + certificate_validate_url_text_color: string | null + certificate_validate_url_text_anchor: CertificateTextAnchor | null + certificate_date_y_pos: string | null + certificate_date_x_pos: string | null + certificate_date_font_size: string | null + certificate_date_text_color: string | null + certificate_date_text_anchor: CertificateTextAnchor | null + certificate_locale: string | null + paper_size: PaperSize | null + background_svg_file_name: string | null + overlay_svg_file_name: string | null + clear_overlay_svg_file: boolean +} + +export interface GetFeedbackQuery { + read: boolean + page: number | undefined + limit: number | undefined +} + +export interface ExamCourseInfo { + course_id: string +} + +export interface NewExerciseRepository { + course_id: string | null + exam_id: string | null + git_url: string + deploy_key: string | null +} + +export interface ExerciseSubmissions { + data: Array + total_pages: number +} + +export interface MarkAsRead { + read: boolean +} + +export type PlaygroundViewsMessage = + | { tag: "TimedOut" } + | { tag: "Registered"; data: string } + | { tag: "ExerciseTaskGradingResult"; data: ExerciseTaskGradingResult } + +export interface GetEditProposalsQuery { + pending: boolean + page: number | undefined + limit: number | undefined +} + +export interface RoleQuery { + global?: boolean + organization_id?: string + course_id?: string + course_instance_id?: string + exam_id?: string +} + +export interface Pagination { + page: number | undefined + limit: number | undefined +} + +export interface OEmbedResponse { + author_name: string + author_url: string + html: string + provider_name: string + provider_url: string + title: string + version: string +} diff --git a/services/cms/src/shared-module-v2/common/components/Accordion/DetailAccordion.tsx b/services/cms/src/shared-module-v2/common/components/Accordion/DetailAccordion.tsx new file mode 100644 index 000000000000..325a8bffbe86 --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/Accordion/DetailAccordion.tsx @@ -0,0 +1,132 @@ +import { keyframes } from "@emotion/css" +import styled from "@emotion/styled" +import React from "react" + +import { baseTheme, secondaryFont } from "../../styles" +import { respondToOrLarger } from "../../styles/respond" + +const openAnimation = keyframes` +0% { opacity: 0; } +100% { opacity: 1; } +` +const slideDown = keyframes` +from { opacity: 0; height: 0; padding: 0;} +to { opacity: 1; height: 100%; padding: 10px;} +` + +// eslint-disable-next-line i18next/no-literal-string +const TextWrapper = styled.div` + padding: 0; + margin: 0; + font-family: ${secondaryFont}; + + details { + border: 1px solid rgba(0, 0, 0, 0.2); + transition: all 0.3s ease-in-out; + } + + details[open] summary ~ * { + animation: ${openAnimation} 0.3s ease-in-out; + color: ${baseTheme.colors.gray[700]}; + } + + details[open] > div { + animation-name: ${slideDown}; + animation-duration: 0.3s; + animation-fill-mode: forwards; + padding: 1rem 1rem 1rem 2rem; + } + + details summary { + padding: 1rem; + position: relative; + cursor: pointer; + font-weight: medium; + list-style: none; + color: ${baseTheme.colors.gray[700]}; + outline: 0; + background: ${baseTheme.colors.clear[100]}; + ${respondToOrLarger.sm} { + padding: 1rem 1rem 1rem 2rem; + } + } + + details summary::-webkit-details-marker { + display: none; + } + + details[open] > summary { + color: ${baseTheme.colors.gray[700]}; + } + + details summary:after { + content: "+"; + position: absolute; + font-size: 2.4rem; + color: ${baseTheme.colors.gray[700]}; + line-height: 0; + margin-top: 0.75rem; + top: 14px; + right: 4%; + font-weight: 200; + transform-origin: center; + transition: all 200ms linear; + } + details[open] summary:after { + transform: rotate(45deg); + font-size: 2.4rem; + } + details[open] summary { + font-weight: 600; + opacity: 0.9; + } + + ul { + padding: 14px; + margin: 0; + + ${respondToOrLarger.sm} { + background: #f9f9f9; + padding: 25px 35px 30px 35px; + } + } + + ul li { + font-size: 1.1rem; + margin: 0 0 0.2rem; + line-height: 1.7; + list-style: none; + } +` + +const PLACEHOLDER_HEADING = "This is a heading:" +const PLACEHOLDER_TEXT = `Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown +printer took a galley of type and scrambled it to make a type specimen book. It has +survived not only five centuries, but also the leap into electronic typesetting, +remaining essentially unchanged. It was popularised in the 1960s with the release of +Letraset sheets containing Lorem Ipsum passages, and more recently with desktop +publishing software like Aldus PageMaker including versions of Lorem Ipsum` + +export type AccordionProps = React.DetailsHTMLAttributes + +const DetailAccordion: React.FC< + React.PropsWithChildren> +> = (props) => { + if (props.children) { + return {props.children} + } + return ( +
+ +
+ {PLACEHOLDER_HEADING} +
    +
  • {PLACEHOLDER_TEXT}
  • +
+
+
+
+ ) +} + +export default DetailAccordion diff --git a/services/cms/src/shared-module-v2/common/components/Accordion/index.tsx b/services/cms/src/shared-module-v2/common/components/Accordion/index.tsx new file mode 100644 index 000000000000..6def19cf99a3 --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/Accordion/index.tsx @@ -0,0 +1,148 @@ +import { keyframes } from "@emotion/css" +import styled from "@emotion/styled" +import React from "react" + +import { baseTheme } from "../../styles" + +import DetailAccordion from "./DetailAccordion" + +const openAnimation = keyframes` +0% { opacity: 0; } +100% { opacity: 1; } +` + +const slideDown = keyframes` +from { opacity: 0; height: 0; padding: 0;} +to { opacity: 1; height: 100%; padding: 10px;} +` + +// eslint-disable-next-line i18next/no-literal-string +const TextWrapper = styled.div` + padding: 0; + margin: 0; + + details[open] summary ~ * { + animation: ${openAnimation} 0.3s ease-in-out; + color: ${baseTheme.colors.gray[700]}; + } + + details[open] > div { + animation-name: ${slideDown}; + animation-duration: 0.3s; + animation-fill-mode: forwards; + } + + details summary { + padding: 1rem 0; + border-bottom: 1px solid ${baseTheme.colors.gray[700]}; + position: relative; + cursor: pointer; + font-size: 1.25rem; + font-weight: medium; + list-style: none; + outline: 0; + color: ${baseTheme.colors.gray[700]}; + } + + details summary::-webkit-details-marker { + display: none; + } + + details[open] > summary { + color: #1c1c1c; + } + + details summary:after { + content: "+"; + color: black; + position: absolute; + font-size: 1.75rem; + line-height: 0; + margin-top: 0.75rem; + right: 0; + font-weight: 200; + transform-origin: center; + transition: all 200ms linear; + } + details[open] summary:after { + transform: rotate(45deg); + font-size: 2rem; + } + details[open] summary { + font-weight: 600; + opacity: 0.9; + } + + ul { + padding: 0 0 0 0.6rem; + } + + details ul li { + font-size: 1.1rem; + line-height: 1.6; + margin: 0 0 0.2rem; + padding-left: 8px; + list-style-position: outside; + } + + ul li::marker { + content: "☉"; + text-align: center; + margin-left: 2rem !important; + } +` + +const PLACEHOLDER_HEADING = "This is a heading:" +const PLACEHOLDER_LIST_ITEM = "This is a list item" +export interface AccordionExtraProps { + variant: "simple" | "detail" +} + +export type AccordionProps = React.DetailsHTMLAttributes & AccordionExtraProps + +const Accordion: React.FC>> = ( + props, +) => { + if (props.variant === "detail") { + return + } + + if (props.children) { + return {props.children} + } + return ( +
+ +
+ {PLACEHOLDER_HEADING} +
    +
  • {PLACEHOLDER_LIST_ITEM}
  • +
  • {PLACEHOLDER_LIST_ITEM}
  • +
  • {PLACEHOLDER_LIST_ITEM}
  • +
  • {PLACEHOLDER_LIST_ITEM}
  • +
+
+
+ {PLACEHOLDER_HEADING} +
    +
  • {PLACEHOLDER_LIST_ITEM}
  • +
  • {PLACEHOLDER_LIST_ITEM}
  • +
  • {PLACEHOLDER_LIST_ITEM}
  • +
  • {PLACEHOLDER_LIST_ITEM}
  • +
+
+
+ {PLACEHOLDER_HEADING} +
    +
  • {PLACEHOLDER_LIST_ITEM}
  • +
  • {PLACEHOLDER_LIST_ITEM}
  • +
  • {PLACEHOLDER_LIST_ITEM}
  • +
  • {PLACEHOLDER_LIST_ITEM}
  • +
+
+
+
+ ) +} + +export default Accordion diff --git a/services/cms/src/shared-module-v2/common/components/Banner/Banner.tsx b/services/cms/src/shared-module-v2/common/components/Banner/Banner.tsx new file mode 100644 index 000000000000..64fef4c61d59 --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/Banner/Banner.tsx @@ -0,0 +1,110 @@ +import styled from "@emotion/styled" +import React from "react" + +import Next from "../../img/next.svg" +import { respondToOrLarger } from "../../styles/respond" + +import ReadOnlyBanner from "./ReadOnlyBanner" + +const BannerWrapper = styled.div` + background: rgba(212, 212, 217, 1); + width: 100%; + position: relative; + margin: 0 auto; + display: block; + + ${respondToOrLarger.sm} { + max-width: 1984px; + } + + &:before { + content: "+"; + color: black; + position: absolute; + font-size: 2.4rem; + line-height: 0; + margin-top: 0.75rem; + top: 18px; + right: 2rem; + font-weight: 200; + transform-origin: center; + transition: all 200ms linear; + transform: rotate(45deg); + + ${respondToOrLarger.sm} { + top: 30px; + right: 4rem; + } + } +` + +const Content = styled.div` + padding: 3.5rem 1.4rem 2rem 1.4rem; + max-width: 1760px; + font-weight: 500; + font-size: 1rem; + line-height: 1.4; + display: grid; + grid-template-columns: repeat(6, 1fr); + gap: 2rem; + + ${respondToOrLarger.sm} { + padding: 2rem 4rem 2.5rem 4rem; + grid-template-columns: repeat(12, 1fr); + } + + a { + text-decoration: none; + max-width: 100%; + cursor: pointer; + display: flex; + height: 1rem; + line-height: 1rem; + margin-top: 1rem; + + span { + display: flex; + align-items: center; + margin-left: 0.5rem; + } + } +` +const Text = styled.div` + grid-column: span 8 / auto; +` + +export interface BannerExtraProps { + variant: "text" | "link" | "readOnly" + linkHref?: string + linkText?: string +} + +export type BannerProps = React.HTMLAttributes & BannerExtraProps + +const Banner: React.FC>> = ( + { children, variant, linkHref, linkText }, + props, +) => { + if (variant === "readOnly") { + return {children} + } + return ( + + + +
{children}
+ {variant === "link" && ( + +
{linkText}
+ + + +
+ )} +
+
+
+ ) +} + +export default Banner diff --git a/services/cms/src/shared-module-v2/common/components/Banner/ContributeBanner.tsx b/services/cms/src/shared-module-v2/common/components/Banner/ContributeBanner.tsx new file mode 100644 index 000000000000..bf7e487cb05d --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/Banner/ContributeBanner.tsx @@ -0,0 +1,110 @@ +import styled from "@emotion/styled" +import React from "react" +import { useTranslation } from "react-i18next" + +import { baseTheme, headingFont } from "../../styles" + +// eslint-disable-next-line i18next/no-literal-string +const BannerWrapper = styled.div` + height: 300px; + position: relative; + display: grid; + justify-content: center; + align-items: center; + background: #f6f8fa; + margin-top: 5rem; + + .svgwrapper { + display: flex; + position: absolute; + right: 0; + top: 0; + width: 100%; + height: 250px; + z-index: -1; + } + + .cover { + width: 100%; + height: 100%; + } +` +const Content = styled.div` + font-weight: 500; + font-size: 1.2rem; + line-height: 1.4; + margin: 0 auto; + max-width: 700px; + text-align: center; + + h2 { + font-size: clamp(35px, 4vw, 56px); + font-family: ${headingFont}; + font-weight: 700; + text-align: center; + margin-bottom: 5px !important; + + background: -webkit-linear-gradient(-70deg, #020344 0%, #28b8d5 100%); + -webkit-background-clip: text; + background-clip: text; + -webkit-text-fill-color: transparent; + } +` +const Text = styled.div` + text-align: center; + font-size: 18px; + margin-bottom: 10px; + + div { + color: ${baseTheme.colors.gray[700]}; + opacity: 0.8; + } +` +// eslint-disable-next-line i18next/no-literal-string +const StyledLink = styled.a` + font-family: ${headingFont}; + font-size: 20px; + color: #1f6964; + text-decoration: none; + + span { + padding-bottom: 10px; + position: relative; + margin-right: 10px; + } + + span::after { + content: ""; + + width: 100%; + position: absolute; + left: 0; + bottom: 5px; + + border-width: 0 0 3px; + border-style: solid; + } +` +export type ContributeProps = React.HTMLAttributes + +const Contribute: React.FC< + React.PropsWithChildren> +> = () => { + const { t } = useTranslation() + return ( + +
+ +

{t("about-this-project")}

+ +
{t("about-this-project-description")}
+
+ + {t("project-github")} + +
+
+ ) +} + +export default Contribute diff --git a/services/cms/src/shared-module-v2/common/components/Banner/ReadOnlyBanner.tsx b/services/cms/src/shared-module-v2/common/components/Banner/ReadOnlyBanner.tsx new file mode 100644 index 000000000000..bddf7ba06d2b --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/Banner/ReadOnlyBanner.tsx @@ -0,0 +1,51 @@ +import styled from "@emotion/styled" +import React from "react" + +import { baseTheme } from "../../styles" + +// eslint-disable-next-line i18next/no-literal-string +const BannerWrapper = styled.div` + background: ${baseTheme.colors.clear[100]}; + width: 100%; + position: relative; + padding: 3rem 2rem; + margin: 0 auto; + display: block; +` + +const Content = styled.div` + font-weight: 500; + font-size: 1.2rem; + line-height: 1.4; + display: grid; + grid-template-columns: 1fr; + gap: 2rem; +` +const Text = styled.div` + text-align: center; + + div { + color: #3b4754; + } +` + +export interface BannerExtraProps { + variant: "text" | "link" | "read-only" + content: string +} + +export type BannerProps = React.HTMLAttributes & BannerExtraProps + +const Quote: React.FC>> = (props) => { + return ( + + + +
{props.children}
+
+
+
+ ) +} + +export default Quote diff --git a/services/cms/src/shared-module-v2/common/components/BooleanAsText.tsx b/services/cms/src/shared-module-v2/common/components/BooleanAsText.tsx new file mode 100644 index 000000000000..4d723707f031 --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/BooleanAsText.tsx @@ -0,0 +1,8 @@ +import { useTranslation } from "react-i18next" + +const BooleanAsText = ({ value }: { value: boolean }) => { + const { t } = useTranslation() + return <>{value ? t("label-true") : t("label-false")} +} + +export default BooleanAsText diff --git a/services/cms/src/shared-module-v2/common/components/Breadcrumbs.tsx b/services/cms/src/shared-module-v2/common/components/Breadcrumbs.tsx new file mode 100644 index 000000000000..71a287120a96 --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/Breadcrumbs.tsx @@ -0,0 +1,108 @@ +import { css, cx } from "@emotion/css" +import styled from "@emotion/styled" +import Link from "next/link" +import { useTranslation } from "react-i18next" + +const StyledBreadcrumb = styled.div` + font-size: 1rem; + margin: 0; + + .breadcrumb { + font-size: 16px; + .list { + margin: 0.5rem 0; + display: flex; + flex-wrap: wrap; + gap: 0.75rem; + } + + .group { + display: inline-flex; + align-items: center; + } + + .arrow { + margin-left: 0.75rem; + color: #333; + } + } +` + +const wrapper = css` + padding: 1rem 2rem; + color: #fff; + border-radius: 2px; + + &:nth-of-type(n + 2) { + margin-top: 2.5rem; + } +` + +const link = css` + color: #696e77; + text-decoration: none !important; + + &:hover { + color: #1a2333; + } +` +const breadCrumbText = css` + color: #1a2333; + font-size: 16px; +` + +export interface BreakcrumbProps { + pieces: BreadcrumbPiece[] +} + +export interface BreadcrumbPiece { + text: string + url: string + externalLink?: boolean +} + +const MARKER = "›" + +const Breadcrumbs: React.FC>> = ({ + pieces, +}) => { + const { t } = useTranslation() + + return ( + +
+ +
+
+ ) +} + +export default Breadcrumbs diff --git a/services/cms/src/shared-module-v2/common/components/Button.tsx b/services/cms/src/shared-module-v2/common/components/Button.tsx new file mode 100644 index 000000000000..aa708bcc560a --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/Button.tsx @@ -0,0 +1,323 @@ +import styled from "@emotion/styled" +import React, { forwardRef, Ref } from "react" + +import { baseTheme, fontWeights, headingFont, theme } from "../styles" +import { defaultFontSizePx } from "../styles/constants" +import { respondToOrLarger } from "../styles/respond" + +export interface ButtonProps extends React.ButtonHTMLAttributes { + variant: "primary" | "secondary" | "reject" | "tertiary" | "outlined" | "blue" | "white" | "icon" + size: "small" | "medium" | "large" + transform?: "capitalize" | "uppercase" | "none" | "lowercase" + children?: React.ReactNode +} + +// BaseButtonStyles is the primary button +export const BASE_BUTTON_STYLES = ` + position: relative; + display: inline-block; + padding: ${theme.buttonSizes["large"].padding}; + font-family: ${headingFont}; + font-weight: ${fontWeights.normal}; + font-size: ${defaultFontSizePx}px; + line-height: normal; + vertical-align: baseline; + cursor: pointer; + user-select: none; + text-decoration: none; + text-align: center; + justify-content: center; + text-transform: uppercase; + letter-spacing: 0.02em; + transition: all 150ms linear; + border: 2.5px solid transparent; + z-index: 1; + white-space: nowrap; + + color: ${theme.primary.text}; + background-color: ${theme.primary.bg}; + border-color: ${theme.primary.border}; + + &:hover { + color: ${theme.primary.hoverBorder}; + background-color: ${theme.primary.hoverBg}; + border-color: ${theme.primary.hoverBorder}; + text-decoration: none; + } + + &:active { + color: ${theme.primary.hoverText}; + background-color: ${theme.primary.activeBg}; + border-color: ${theme.primary.hoverBorder}; + } + + &:disabled { + color: ${theme.primary.disabledText}; + background-color: ${theme.primary.disabledBg}; + border-color: ${theme.primary.disabledBorder}; + cursor: not-allowed; + } + + &:focus { + text-decoration: none; + } + + + ${respondToOrLarger.sm} { + white-space: nowrap; + } +` + +export const PrimaryButtonStyles = (props: ButtonProps) => { + const PRIMARY_BUTTON_STYLES = ` + text-transform: ${props.transform}; + padding: ${theme.buttonSizes[props.size].padding}; + ` + return PRIMARY_BUTTON_STYLES +} + +export const WhiteButtonStyles = (props: ButtonProps) => { + const WHITE_BUTTON_STYLES = ` + text-transform: ${props.transform}; + padding: ${theme.buttonSizes[props.size].padding}; + + color: ${theme.white.text}; + background: #FCFCFC; + border: 1.5px solid #DEDEDE; + + ` + return WHITE_BUTTON_STYLES +} + +export const IconButtonStyles = (props: ButtonProps) => { + const ICON_BUTTON_STYLES = ` + text-transform: ${props.transform}; + padding: ${theme.buttonSizes[props.size].padding}; + color: black; + background: none; + border: 0px; + + &:hover, &:active, &:disabled { + background: none; + } + + ` + return ICON_BUTTON_STYLES +} + +export const SecondaryButtonStyles = (props: ButtonProps) => { + const SECONDARY_BUTTON_STYLES = ` + text-transform: ${props.transform}; + padding: ${theme.buttonSizes[props.size].padding}; + + color: ${theme.secondary.text}; + background: ${theme.secondary.bg}; + border: 1.5px solid ${theme.secondary.border}; + + &:hover, + &:focus { + color: ${theme.secondary.hoverText}; + box-shadow: 0 0 0 1px ${theme.secondary.text}; + border: 1.5px solid ${theme.secondary.text}; + } + + &:active { + color: ${theme.secondary.hoverText}; + background-color: ${theme.secondary.activeBg}; + } + + &:disabled { + color: ${theme.secondary.disabledText}; + background-color: ${theme.secondary.disabledBg}; + border-color: ${theme.secondary.disabledBorder}; + } + ` + return SECONDARY_BUTTON_STYLES +} + +export const RejectButtonStyles = (props: ButtonProps) => { + const REJECT_BUTTON_STYLES = ` + text-transform: ${props.transform}; + padding: ${theme.buttonSizes[props.size].padding}; + + color: ${theme.reject.text}; + background: ${theme.reject.bg}; + border: 1.5px solid ${theme.reject.border}; + + &:hover, + &:focus { + color: ${theme.reject.hoverText}; + box-shadow: 0 0 0 1px ${theme.reject.text}; + border: 1.5px solid ${theme.reject.text}; + } + + &:active { + color: ${theme.reject.hoverText}; + background-color: ${theme.reject.activeBg}; + } + + &:disabled { + color: ${theme.reject.disabledText}; + background-color: ${theme.reject.disabledBg}; + border-color: ${theme.reject.disabledBorder}; + } + ` + return REJECT_BUTTON_STYLES +} + +export const TertiaryButtonStyles = (props: ButtonProps) => { + const TERTIARY_BUTTON_STYLES = ` + text-transform: ${props.transform}; + padding: ${theme.buttonSizes[props.size].padding}; + + color: ${theme.tertiary.text}; + background-color: ${theme.tertiary.bg}; + border: unset; + + &:hover { + color: ${theme.tertiary.hoverText}; + background-color: ${theme.tertiary.hoverBg}; + } + + &:active { + color: ${theme.tertiary.hoverText}; + background-color: ${theme.tertiary.activeBg}; + } + + &:disabled { + color: ${theme.tertiary.disabledText}; + background-color: ${theme.tertiary.disabledBg}; + border-color: ${theme.tertiary.disabledBorder}; + } + ` + return TERTIARY_BUTTON_STYLES +} + +export const BlueButtonStyles = (props: ButtonProps) => { + const BLUE_BUTTON_STYLES = ` + text-transform: ${props.transform}; + padding: ${theme.buttonSizes[props.size].padding}; + + color: ${theme.tertiary.text}; + background-color: ${baseTheme.colors.blue[500]}; + border: unset; + border: 2px solid ${theme.secondary.border}; + + &:hover { + border: 2px solid ${baseTheme.colors.blue[600]}; + color: ${baseTheme.colors.blue[700]}; + } + + &:active { + border: 2px solid ${baseTheme.colors.blue[400]}; + } + + &:disabled { + color: ${theme.secondary.disabledText}; + background-color: ${theme.secondary.disabledBg}; + border-color: ${theme.secondary.disabledBorder}; + } + ` + return BLUE_BUTTON_STYLES +} + +const PrimaryButton = styled.button` + ${BASE_BUTTON_STYLES} + ${PrimaryButtonStyles} +` + +const SecondaryButton = styled.button` + ${BASE_BUTTON_STYLES} + ${SecondaryButtonStyles} +` + +const RejectButton = styled.button` + ${BASE_BUTTON_STYLES} + ${RejectButtonStyles} +` + +const TertiaryButton = styled.button` + ${BASE_BUTTON_STYLES} + ${TertiaryButtonStyles} +` + +const BlueButton = styled.button` + ${BASE_BUTTON_STYLES} + ${BlueButtonStyles} +` + +const WhiteButton = styled.button` + ${BASE_BUTTON_STYLES} + ${WhiteButtonStyles} +` +const IconButton = styled.button` + ${BASE_BUTTON_STYLES} + ${IconButtonStyles} +` + +export const LabelButton = styled.label` + ${BASE_BUTTON_STYLES} +` + +const Button: React.FC = forwardRef( + ( + { variant = "primary", size = "medium", transform = "uppercase", ...rest }, + ref?: Ref, + ) => { + switch (variant) { + case "primary": + return ( + + ) + case "secondary": + return ( + + ) + case "reject": + return ( + + ) + case "tertiary": + return ( + + ) + case "outlined": + return ( + + ) + case "blue": + return ( + + ) + case "white": + return ( + + ) + case "icon": + return ( + + ) + default: + return ( + + ) + } + }, +) + +// eslint-disable-next-line i18next/no-literal-string +Button.displayName = "Button" + +export default Button diff --git a/services/cms/src/shared-module-v2/common/components/Card/CardOpenTextOverlay.tsx b/services/cms/src/shared-module-v2/common/components/Card/CardOpenTextOverlay.tsx new file mode 100644 index 000000000000..7862266505f7 --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/Card/CardOpenTextOverlay.tsx @@ -0,0 +1,50 @@ +import { css } from "@emotion/css" + +import { respondToOrLarger } from "../../styles/respond" + +import CardOpensText from "./CardOpensText" + +interface CardOpensTextProps { + open: boolean | undefined + date: string | undefined + time: string | undefined +} + +const CardOpensTextOverlay: React.FC< + React.PropsWithChildren> +> = ({ open, date, time }) => { + return ( +
+ {!open && ( +
+ +
+ )} +
+ ) +} + +export default CardOpensTextOverlay diff --git a/services/cms/src/shared-module-v2/common/components/Card/CardOpensText.tsx b/services/cms/src/shared-module-v2/common/components/Card/CardOpensText.tsx new file mode 100644 index 000000000000..1b1e9b9db5e6 --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/Card/CardOpensText.tsx @@ -0,0 +1,47 @@ +import { css, cx } from "@emotion/css" +import { useTranslation } from "react-i18next" + +import { secondaryFont } from "../../styles" + +interface CardOpensTextProps { + open: boolean | undefined + date: string | undefined + time: string | undefined +} + +// eslint-disable-next-line i18next/no-literal-string + +// eslint-disable-next-line i18next/no-literal-string +const styledspan = css` + font-family: ${secondaryFont} !important; + font-size: 0.9rem; + opacity: 0.8; + text-transform: uppercase; +` + +const CardOpensText: React.FC< + React.PropsWithChildren> +> = ({ open, date, time }) => { + const { t } = useTranslation() + if (date && time) { + return ( + <> +
{t("available")}
+
{t("on-date-at-time", { date, time })}
+ + ) + } else if (time) { + return ( + <> +
{t("opens-in")}
+
{time}
+ + ) + } else if (open) { + return {t("opens-now")} + } else { + return {t("closed")} + } +} + +export default CardOpensText diff --git a/services/cms/src/shared-module-v2/common/components/Card/IllustrationCard.tsx b/services/cms/src/shared-module-v2/common/components/Card/IllustrationCard.tsx new file mode 100644 index 000000000000..4c5b0ececc63 --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/Card/IllustrationCard.tsx @@ -0,0 +1,142 @@ +import { css } from "@emotion/css" +import styled from "@emotion/styled" +import React from "react" +import { useTranslation } from "react-i18next" + +import { baseTheme, headingFont } from "../../styles" +import { cardMaxWidth } from "../../styles/constants" +import { respondToOrLarger } from "../../styles/respond" + +import CardOpensTextOverlay from "./CardOpenTextOverlay" + +import { CardExtraProps } from "." + +export interface BackgroundProps { + bg: string | undefined + backgroundImage?: string +} + +export const BackgroundStyles = ({ bg }: BackgroundProps) => { + const CARD_BACKGROUND_STYLES = ` + background-color: ${bg ? bg : "#fff"}; + ` + return CARD_BACKGROUND_STYLES +} + +// eslint-disable-next-line i18next/no-literal-string +const CardContentWrapper = styled.div` + display: flex; + height: 100%; + text-align: left; + flex-direction: column; + overflow: hidden; + overflow-wrap: break-word; + ${BackgroundStyles} + + h2 { + font-weight: 600; + z-index: 20; + line-height: 1.2; + color: ${baseTheme.colors.gray[700]}; + margin-top: 5px; + font-size: clamp(26px, 2.2vw, 30px); + opacity: 0.9; + } +` + +export type CardProps = React.HTMLAttributes & CardExtraProps + +const IllustrationCard: React.FC>> = ({ + title, + chapterNumber, + bg, + backgroundImage, + open, + date, + time, +}) => { + const { t } = useTranslation() + + return ( +
+ + +
+
+
+ + {t("chapter-chapter-number", { number: chapterNumber })} + +
+ +

{title}

+
+
+
+ ) +} + +export default IllustrationCard diff --git a/services/cms/src/shared-module-v2/common/components/Card/SimpleCard.tsx b/services/cms/src/shared-module-v2/common/components/Card/SimpleCard.tsx new file mode 100644 index 000000000000..097fe6ec17dc --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/Card/SimpleCard.tsx @@ -0,0 +1,161 @@ +import { css } from "@emotion/css" +import styled from "@emotion/styled" +import React from "react" +import { useTranslation } from "react-i18next" + +import CardSVG from "../../img/cardNext.svg" +import { headingFont } from "../../styles" +import { cardMaxWidth } from "../../styles/constants" +import { respondToOrLarger } from "../../styles/respond" + +import CardOpensTextOverlay from "./CardOpenTextOverlay" + +import { CardExtraProps } from "." + +export interface BackgroundProps { + bg: string | undefined +} + +export const BackgroundStyles = ({ bg }: BackgroundProps) => { + const CARD_BACKGROUND_STYLES = ` + background-color: ${bg ? bg : "#fff"}; + ` + return CARD_BACKGROUND_STYLES +} +const StCardSvg = styled(CardSVG)` + width: 40px; + opacity: 0.8; + color: #fff; +` + +// eslint-disable-next-line i18next/no-literal-string +const CardContentWrapper = styled.div` + display: flex; + height: 100%; + text-align: left; + flex-direction: column; + overflow-wrap: break-word; + position: relative; + ${BackgroundStyles} + + &:hover { + filter: brightness(1.1) contrast(0.9); + } + + h2 { + z-index: 20; + color: #fff; + font-weight: 500; + line-height: 100%; + font-size: clamp(28px, 2.7rem, 46px); + } + + span { + color: #f5f6f7; + font-size: clamp(16px, 1em, 20px); + opacity: 0.9; + z-index: 20; + font-weight: 500; + width: 50%; + line-height: 2.5em; + } +` +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export const StyledSVG = (Image: any) => { + return ( + + ) +} + +export type CardProps = React.HTMLAttributes & CardExtraProps + +const SimpleCard: React.FC>> = ({ + title, + chapterNumber, + open, + date, + time, + bg, + backgroundImage, +}) => { + const { t } = useTranslation() + + return ( +
+ + {backgroundImage && StyledSVG(backgroundImage)} + + {open && ( +
+ +
+ )} + +
+ +
+
+
+ + {t("chapter-chapter-number", { number: chapterNumber })} + +

{title}

+
+
+
+
+
+ ) +} + +export default SimpleCard diff --git a/services/cms/src/shared-module-v2/common/components/Card/index.tsx b/services/cms/src/shared-module-v2/common/components/Card/index.tsx new file mode 100644 index 000000000000..4b433e776fd7 --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/Card/index.tsx @@ -0,0 +1,68 @@ +import { css } from "@emotion/css" +import React from "react" + +import { baseTheme } from "../../styles" +import basePath from "../../utils/base-path" + +import IllustrationCard from "./IllustrationCard" +import SimpleCard from "./SimpleCard" + +// type CourseCardProps = { +// title: string +// description: string +// languages: string +// } + +export interface CardExtraProps { + variant: "simple" | "illustration" | "course" + title: string + chapterNumber: number + url?: string + bg?: string + open?: boolean + allowedToPreview?: boolean + date?: string + time?: string + description?: string + languages?: string + backgroundImage?: string | null +} + +export type CardProps = React.ButtonHTMLAttributes & CardExtraProps + +const variantToComponent = { + simple: SimpleCard, + course: SimpleCard, + illustration: IllustrationCard, +} + +const Card: React.FC>> = (props) => { + const Component = variantToComponent[props.variant] + + if (props.url && (props.open || props.allowedToPreview)) { + return ( + // This should be a next/link but there's a weird problem in firefox if you this when it's next/link + // and navigate back straight away, if you click this the click won't register but will just scroll the + // page up + + + + ) + } + + return +} + +export default Card diff --git a/services/cms/src/shared-module-v2/common/components/Centering/BreakFromCentered.tsx b/services/cms/src/shared-module-v2/common/components/Centering/BreakFromCentered.tsx new file mode 100644 index 000000000000..20800602a273 --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/Centering/BreakFromCentered.tsx @@ -0,0 +1,80 @@ +import { css } from "@emotion/css" +import React from "react" + +interface NoSidebar { + sidebar: false +} + +export interface WithSidebar { + sidebar: true + sidebarPosition: "left" | "right" + sidebarWidth: string + sidebarThreshold?: string +} + +export type BreakFromCenteredProps = NoSidebar | WithSidebar + +const BreakFromCentered: React.FC< + React.PropsWithChildren> +> = (props) => { + // 100vw unfortunately does not take into account the scrollbar width, so we need to calculate its width and substract it from the width of the page + let scrollbarWidth = 0 + if (typeof window !== "undefined") { + scrollbarWidth = Math.abs(window.innerWidth - document.documentElement.clientWidth) / 2 + } + if (props.sidebar) { + if (props.sidebarThreshold) { + return ( +
+ {props.children} +
+ ) + } else { + return ( +
+ {props.children} +
+ ) + } + } + return ( +
+ {props.children} +
+ ) +} + +export default BreakFromCentered diff --git a/services/cms/src/shared-module-v2/common/components/Centering/Centered.tsx b/services/cms/src/shared-module-v2/common/components/Centering/Centered.tsx new file mode 100644 index 000000000000..d035c8a24a77 --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/Centering/Centered.tsx @@ -0,0 +1,46 @@ +import { css } from "@emotion/css" +import React from "react" + +import { narrowContainerWidthRem, normalContainerWidthRem } from "../../styles/constants" +import { respondToOrLarger } from "../../styles/respond" + +// eslint-disable-next-line i18next/no-literal-string +export const defaultWidthCenteredComponentStyles = css` + max-width: ${normalContainerWidthRem}rem; + margin-left: auto; + margin-right: auto; + padding: 0rem 1.375rem; + margin-bottom: 1.25rem; + ${respondToOrLarger.xl} { + padding: 0rem; + } +` + +// eslint-disable-next-line i18next/no-literal-string +export const narrowWidthCenteredComponentStyles = css` + max-width: ${narrowContainerWidthRem}rem; + margin-left: auto; + margin-right: auto; + padding: 0rem 1.375rem; + margin-bottom: 1.25rem; + ${respondToOrLarger.md} { + padding: 0rem; + } +` + +export interface CenteredProps { + variant: "default" | "narrow" +} + +const Centered: React.FC>> = ({ + children, + variant, +}) => { + if (variant === "narrow") { + return
{children}
+ } else { + return
{children}
+ } +} + +export default Centered diff --git a/services/cms/src/shared-module-v2/common/components/CircularProgressBar.tsx b/services/cms/src/shared-module-v2/common/components/CircularProgressBar.tsx new file mode 100644 index 000000000000..9cb455878b88 --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/CircularProgressBar.tsx @@ -0,0 +1,86 @@ +import styled from "@emotion/styled" +import React from "react" + +import { baseTheme, headingFont } from "../styles" + +export interface CircularProgressBarExtraProps { + scoreMaximum: number + userPoints: number +} + +interface CircleBoxProps { + point: number +} + +export type CircularProgressBarProps = React.HTMLAttributes & + CircularProgressBarExtraProps + +// eslint-disable-next-line i18next/no-literal-string +const CircleBox = styled.div` + width: 60px; + height: 60px; + margin: 0.2rem !important; + display: inline-block; + padding: 0; + .progress { + position: absolute; + height: 60px; + width: 60px; + cursor: pointer; + } + + .progress-circle { + transform: rotate(-90deg); + } + + .progress-circle-bg { + fill: none; + stroke: ${baseTheme.colors.green[200]}; + stroke-width: 7px; + stroke-linecap: round; + } + .progress-circle-value { + fill: none; + stroke: ${baseTheme.colors.green[600]}; + stroke-width: 7px; + stroke-linecap: round; + stroke-dasharray: 131 131; + stroke-dashoffset: ${({ point }: CircleBoxProps) => 131 - point * 131}; + transition: stroke-dashoffset 0.7s ease-in-out; + } + .progress-text { + position: absolute; + top: 48%; + left: 50%; + transform: translate(-50%, -50%); + font-size: 12px; + font-family: ${headingFont}; + } +` +// To get the appropriate stroke-dasharray; It is 2 * PI * radius = 131 + +const CircularProgressBar: React.FC< + React.PropsWithChildren> +> = ({ scoreMaximum, userPoints }) => { + const complete = userPoints / scoreMaximum + return ( + +
+ + + + +
+ {userPoints}/{scoreMaximum} +
+
+
+ ) +} + +export default CircularProgressBar diff --git a/services/cms/src/shared-module-v2/common/components/CourseProgress/CircularProgress.tsx b/services/cms/src/shared-module-v2/common/components/CourseProgress/CircularProgress.tsx new file mode 100644 index 000000000000..971f66f948de --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/CourseProgress/CircularProgress.tsx @@ -0,0 +1,185 @@ +import { css, cx } from "@emotion/css" +import styled from "@emotion/styled" +import { useLayoutEffect, useState } from "react" +import { useTranslation } from "react-i18next" +import { useSpring } from "react-spring" + +import { baseTheme, headingFont, secondaryFont } from "../../styles" +import { respondToOrLarger } from "../../styles/respond" +import { INCLUDE_THIS_HEADING_IN_HEADINGS_NAVIGATION_CLASS } from "../../utils/constants" + +import { CircularProgressExtraProps } from "." + +const StyledSVG = styled.div` + position: relative; + width: 100%; + text-align: center; + height: auto; + + svg { + margin: 0 auto; + width: 16rem; + transform: rotate(-90deg); + transform-origin: 50% 50%; + + ${respondToOrLarger.sm} { + width: 25rem; + } + } + + svg circle { + width: 100%; + height: 100%; + fill: none; + stroke: #b4cdcb; + stroke-width: 40px; + transition: stroke-dashoffset 0.35s; + transform: rotate(0deg); + } + + svg circle:nth-of-type(2) { + stroke: #b4cdcb; + } + + svg circle:nth-of-type(3) { + stroke: #1f6964; + } + + p { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + font-size: 2rem; + line-height: 1.1; + font-weight: 600; + opacity: 0.9; + font-family: ${headingFont}; + ${respondToOrLarger.sm} { + font-size: 3rem; + } + span { + opacity: 0.4; + } + } + + .points { + font-size: 1.4rem; + text-transform: uppercase; + font-weight: 600; + opacity: 0.5; + font-family: ${secondaryFont}; + + @media (max-width: 767.98px) { + font-size: 1rem; + } + } +` +const CircularProgress: React.FC = ({ + label, + given, + max, + required, +}) => { + const [willAnimate, setWillAnimate] = useState(false) + const { t } = useTranslation() + + const givenScore = given ?? 0 + const maximum = max ?? 0 + + const radius = 160 + const circumference = 2 * Math.PI * radius + const receivedPointsRatio = givenScore / maximum + const requiredForCompletionRatio = required && required > 0 && max && max > 0 ? required / max : 0 + + const receivedPointsStrokeDashOffset = (1 - receivedPointsRatio) * circumference + const requiredForCompletionStrokeDashOffset = (1 - requiredForCompletionRatio) * circumference + + useLayoutEffect(() => { + const onScroll = () => { + const scrollPosition = window.scrollY + window.innerHeight + if (scrollPosition > 1700) { + setWillAnimate(true) + } + } + + window.addEventListener("scroll", onScroll) + return () => window.removeEventListener("scroll", onScroll) + }, []) + + useSpring({ + number: !willAnimate ? 0 : givenScore, + config: { duration: 1000 }, + }) + return ( + <> +

+ {label} +

+ + + + + + + + + + + + + + +

+ {givenScore} + {"/"} + {maximum} +
+ {t("points")} +

+
+ + ) +} + +export default CircularProgress diff --git a/services/cms/src/shared-module-v2/common/components/CourseProgress/ProgressBar.tsx b/services/cms/src/shared-module-v2/common/components/CourseProgress/ProgressBar.tsx new file mode 100644 index 000000000000..8166ed7788e6 --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/CourseProgress/ProgressBar.tsx @@ -0,0 +1,132 @@ +import { css } from "@emotion/css" +import styled from "@emotion/styled" +import { useEffect, useState } from "react" + +import { baseTheme, headingFont } from "../../styles" +import { respondToOrLarger } from "../../styles/respond" + +import { ProgressBarExtraProps } from "." + +// eslint-disable-next-line i18next/no-literal-string +const LinearProgress = styled.div` + display: flex; + background: ${baseTheme.colors.green[100]}; + border-radius: 100px; + overflow: hidden; + align-items: center; + height: ${({ height }) => (height === "small" ? "16px" : "20px")}; + width: 290px; + + ${respondToOrLarger.sm} { + height: ${({ height }) => (height === "small" ? "16px" : "28px")}; + width: 100%; + } +` +interface LinearProgressFillProps { + percentage: number + height: string + light?: boolean +} +interface LinearProgressProps { + height: string +} +// eslint-disable-next-line i18next/no-literal-string +const LinearProgressFill = styled.div` + height: ${({ height }) => (height === "small" ? "16px" : "20px")}; + position: absolute; + top: 0; + left: 0; + transition: 1.5s ease-in-out; + border-radius: 50px; + width: ${(props) => props.percentage}%; + background: ${(props) => + props.light ? baseTheme.colors.yellow[200] : baseTheme.colors.green[600]}; + justify-content: end; + + ${respondToOrLarger.sm} { + height: ${({ height }) => (height === "small" ? "16px" : "28px")}; + } +` + +const Label = styled.div` + min-width: 100%; + font-weight: 500; + margin-right: 1rem; + margin-bottom: 0.5rem; + text-align: center; + padding-left: 10px; + + span:first-of-type { + font-size: 0.8em; + font-weight: 500; + font-family: ${headingFont}; + color: #313947; + } + ${respondToOrLarger.sm} { + span:first-of-type { + font-size: 1.1em; + } + } +` + +const ProgressBar: React.FC< + React.PropsWithChildren> +> = ({ + showAsPercentage = false, + exercisesAttempted, + exercisesTotal, + height = "medium", + label, + required, +}) => { + const ratio = (exercisesTotal ?? 0) > 0 ? (exercisesAttempted ?? 0) / (exercisesTotal ?? 0) : 0 + const requiredRatio = (exercisesTotal ?? 0) > 0 ? (required ?? 0) / (exercisesTotal ?? 0) : 0 + + const percentage = ratio * 100 + const requiredPercentage = requiredRatio * 100 + // Make the progress bar animate from 0 when the page loads + const [visualPercentage, setVisualPercentage] = useState(0) + useEffect(() => { + setTimeout(() => { + setVisualPercentage(percentage) + }, 100) + }, [percentage]) + + return ( + <> +
+ {label && ( + + )} + +
+ + +
+
+
+ + ) +} + +export default ProgressBar diff --git a/services/cms/src/shared-module-v2/common/components/CourseProgress/index.tsx b/services/cms/src/shared-module-v2/common/components/CourseProgress/index.tsx new file mode 100644 index 000000000000..73a95fe368f7 --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/CourseProgress/index.tsx @@ -0,0 +1,35 @@ +import React from "react" + +import CircularProgress from "./CircularProgress" +import ProgressBar from "./ProgressBar" +export interface CircularProgressExtraProps { + variant: "circle" + size?: "medium" | "large" + max: number | null + given: number | null + label: string + required?: number +} +export interface ProgressBarExtraProps { + variant: "bar" + showAsPercentage?: boolean + exercisesAttempted: number | null + exercisesTotal: number | null + height?: string + label: string + required?: number +} + +type ProgressExtraProps = CircularProgressExtraProps | ProgressBarExtraProps + +type ProgressProps = React.HTMLAttributes & ProgressExtraProps + +const Progress: React.FC>> = ( + props, +) => { + return ( + <>{props.variant === "circle" ? : } + ) +} + +export default Progress diff --git a/services/cms/src/shared-module-v2/common/components/DebugModal.tsx b/services/cms/src/shared-module-v2/common/components/DebugModal.tsx new file mode 100644 index 000000000000..9d8110ad3ce8 --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/DebugModal.tsx @@ -0,0 +1,107 @@ +import { css } from "@emotion/css" +import styled from "@emotion/styled" +import { BugInsect } from "@vectopus/atlas-icons-react" +import { Dispatch, useState } from "react" +import { useTranslation } from "react-i18next" + +import Button from "./Button" +import Dialog from "./Dialog" +import MonacoEditor from "./monaco/MonacoEditor" + +export interface DebugModalProps { + data: unknown + readOnly?: boolean + // eslint-disable-next-line @typescript-eslint/no-explicit-any + updateDataOnClose?: Dispatch + buttonSize?: "small" | "medium" | "large" +} + +const HeaderBar = styled.div` + display: flex; + padding: 0.5rem; + align-items: center; + h1 { + font-size: 1.25rem; + margin-bottom: 0; + } +` + +const DebugModal: React.FC>> = ({ + data, + readOnly = true, + updateDataOnClose, + buttonSize = "medium", +}) => { + const { t } = useTranslation() + const [open, setOpen] = useState(false) + const [editedContent, setEditedContent] = useState(null) + + const closeModal = () => { + setOpen(false) + if (updateDataOnClose) { + let parsed = null + if (typeof editedContent === "string") { + parsed = JSON.parse(editedContent) + } + updateDataOnClose(parsed) + } + } + + const openModal = () => { + setEditedContent(JSON.stringify(data, undefined, 2)) + setOpen(true) + } + + const readOnlySpecifier = readOnly ? t("read-only") : t("editable") + + return ( + <> + + + +

+ {t("title-debug-view")} ({readOnlySpecifier}) +

+
+ + + value && setEditedContent(value)} + /> +
+ + ) +} + +export default DebugModal diff --git a/services/cms/src/shared-module-v2/common/components/Dialog.tsx b/services/cms/src/shared-module-v2/common/components/Dialog.tsx new file mode 100644 index 000000000000..4a4cdfc91835 --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/Dialog.tsx @@ -0,0 +1,132 @@ +import { css } from "@emotion/css" +import React, { useEffect, useRef } from "react" + +import useClickOutside from "../hooks/useClickOutside" +import { typography } from "../styles" + +interface DialogProps extends React.HTMLAttributes { + open: boolean + onClose?: () => void + closeable?: boolean + noPadding?: boolean + width?: "normal" | "wide" +} + +const Dialog: React.FC = ({ + children, + open, + onClose, + closeable = true, + noPadding = false, + width = "normal", + ...rest +}) => { + const ref = useRef(null) + const dialogContentRef = useRef(null) + + useEffect(() => { + const current = ref.current + const closeCallback = () => { + if (onClose) { + onClose() + } + } + current?.addEventListener("close", closeCallback) + return () => { + current?.removeEventListener("close", closeCallback) + } + }, [onClose]) + + useEffect(() => { + if (!ref.current) { + return + } + if (open && !ref.current.open) { + ref.current.showModal() + } else if (ref.current.open) { + ref.current.close() + } + }, [open]) + + // Make non-closable dialogs not closable + useEffect(() => { + if (!ref.current || closeable) { + return + } + const eventHandler = (event: Event) => { + if (!event.cancelable) { + ref.current?.showModal() + } + event.preventDefault() + } + const element = ref.current + element.addEventListener("close", eventHandler) + element.addEventListener("cancel", eventHandler) + return () => { + element?.removeEventListener("close", eventHandler) + element?.removeEventListener("cancel", eventHandler) + } + }, [closeable]) + + useClickOutside( + dialogContentRef, + () => { + if (closeable) { + ref.current?.close() + } + }, + open, + ) + + return ( + + {open && ( +
+ {children} +
+ )} +
+ ) +} + +export default Dialog diff --git a/services/cms/src/shared-module-v2/common/components/DiffFormatter.tsx b/services/cms/src/shared-module-v2/common/components/DiffFormatter.tsx new file mode 100644 index 000000000000..d100aed792b5 --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/DiffFormatter.tsx @@ -0,0 +1,73 @@ +import { css } from "@emotion/css" +import { useTranslation } from "react-i18next" + +/** + * Matches the diff object from the diff npm package. Reimplemented here so that we don't have to depend on diff in shared-module + */ +interface DiffChange { + count?: number | undefined + value: string + added?: boolean | undefined + removed?: boolean | undefined +} + +interface DiffFormatterProps { + changes: DiffChange[] + dontShowAdded?: boolean + dontShowRemoved?: boolean +} + +/** + * Formats the diff object from the diff npm package. Remember to wrap this inside a container like a div or a p. + */ +const DiffFormatter: React.FC< + React.PropsWithChildren> +> = ({ changes, dontShowAdded, dontShowRemoved }) => { + const { t } = useTranslation() + + return ( + <> + {changes.map((change) => { + if (change.added) { + if (dontShowAdded) { + return null + } + return ( + + {change.value} + + ) + } else if (change.removed) { + if (dontShowRemoved) { + return null + } + return ( + + {change.value} + + ) + } else { + return {change.value} + } + })} + + ) +} + +export default DiffFormatter diff --git a/services/cms/src/shared-module-v2/common/components/DropdownMenu/DropdownMenuItem.tsx b/services/cms/src/shared-module-v2/common/components/DropdownMenu/DropdownMenuItem.tsx new file mode 100644 index 000000000000..75985bba7472 --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/DropdownMenu/DropdownMenuItem.tsx @@ -0,0 +1,77 @@ +import { css } from "@emotion/css" +import Link from "next/link" +import React from "react" + +import { baseTheme } from "../../styles" + +interface DropdownMenuItemWithOnClick { + label: string + href?: undefined + onClick: () => void +} + +interface DropdownMenuItemWithHref { + label: string + href: string + onClick?: undefined +} + +export type DropdownMenuItemType = DropdownMenuItemWithOnClick | DropdownMenuItemWithHref + +interface DropdownMenuProps { + item: DropdownMenuItemType + closeMenu: () => void +} + +const itemInnerStyles = css` + border: none; + padding: 0.5rem 1.5rem; + background-color: white; + cursor: pointer; + display: block; + color: ${baseTheme.colors.gray[500]}; + font-weight: 600; + text-decoration: none; + width: 100%; + white-space: nowrap; + text-align: left; + &:focus { + filter: brightness(92%) contrast(110%); + border: 2px solid black; + outline: none; + } +` + +const DropdownMenuItem: React.FC< + React.PropsWithChildren> +> = ({ item, closeMenu }) => { + if (item.href) { + return ( +
  • + + {item.label} + +
  • + ) + } + return ( +
  • + +
  • + ) +} + +export default DropdownMenuItem diff --git a/services/cms/src/shared-module-v2/common/components/DropdownMenu/index.tsx b/services/cms/src/shared-module-v2/common/components/DropdownMenu/index.tsx new file mode 100644 index 000000000000..340e0ac84939 --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/DropdownMenu/index.tsx @@ -0,0 +1,154 @@ +import { css } from "@emotion/css" +import { DotsVertical } from "@vectopus/atlas-icons-react" +import React, { useCallback, useEffect, useState } from "react" +import { useTranslation } from "react-i18next" +import { usePopper } from "react-popper" + +import { baseTheme } from "../../styles" + +import DropdownMenuItem, { DropdownMenuItemType } from "./DropdownMenuItem" + +export interface DropdownMenuProps { + items: (DropdownMenuItemType | null)[] +} + +const DropdownMenu: React.FC< + React.PropsWithChildren> +> = ({ items }) => { + const { t } = useTranslation() + const [expanded, setExpanded] = useState(false) + + // This is the right way according to popper.js docs + const [referenceElement, setReferenceElement] = useState(null) + const [popperElement, setPopperElement] = useState(null) + + const { styles, attributes } = usePopper(referenceElement, popperElement, { + placement: "bottom-start", + strategy: "fixed", + modifiers: [ + { + name: "offset", + enabled: true, + options: { + offset: [0, 5], + }, + }, + { + name: "preventOverflow", + enabled: true, + options: { + padding: 8, + }, + }, + { + name: "flip", + enabled: true, + }, + ], + }) + + const handleOutsideClick = useCallback( + (event: MouseEvent) => { + if (!expanded) { + return + } + if ( + referenceElement && + (referenceElement.contains(event.target as Node) || referenceElement === event.target) + ) { + return + } + setExpanded(false) + }, + [expanded, referenceElement], + ) + + useEffect(() => { + document.addEventListener("click", handleOutsideClick) + return () => { + document.removeEventListener("click", handleOutsideClick) + } + }, [handleOutsideClick]) + + return ( +
    + + {expanded && ( +
    +
      + {items + .filter((item) => item !== null) + .map((item) => { + if (item === null) { + return null + } + return ( + { + setExpanded(false) + }} + /> + ) + })} +
    +
    + )} +
    + ) +} + +export default DropdownMenu diff --git a/services/cms/src/shared-module-v2/common/components/ErrorBanner.tsx b/services/cms/src/shared-module-v2/common/components/ErrorBanner.tsx new file mode 100644 index 000000000000..25e1f3cb1c76 --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/ErrorBanner.tsx @@ -0,0 +1,304 @@ +import styled from "@emotion/styled" +import { AxiosError } from "axios" +import React, { useEffect, useState } from "react" +import { useTranslation } from "react-i18next" + +import { ErrorResponse } from "../bindings" +import { isErrorData, isErrorResponse } from "../bindings.guard" +import { baseTheme } from "../styles" + +import Spinner from "./Spinner" + +const BannerWrapper = styled.div` + background: #f1f1f1; + width: 100%; + position: relative; + margin: 0 auto; + display: block; + border-left: 4px solid #da4453; +` + +const Content = styled.div` + padding-top: 3rem; + padding-bottom: 3rem; + max-width: 100%; + font-weight: 500; + font-size: 1rem; + line-height: 1.4; + display: grid; + grid-template-columns: 1fr; + gap: 0.5rem; + + a { + text-decoration: none; + max-width: 100%; + cursor: pointer; + display: flex; + height: 1rem; + line-height: 1rem; + margin-top: 1rem; + + span { + display: flex; + align-items: center; + margin-left: 0.5rem; + } + } +` +const Text = styled.div` + padding: 0 2rem; +` +const DetailTag = styled.div` + background: #e1e1e1; + details { + padding: 0 2rem; + } + + details[open] summary ~ * { + color: ${baseTheme.colors.gray[700]}; + } + + details[open] > div { + animation-duration: 0.3s; + animation-fill-mode: forwards; + } + + details summary { + padding: 1rem 0; + position: relative; + cursor: pointer; + font-size: 1.1rem; + font-weight: medium; + list-style: none; + color: ${baseTheme.colors.gray[700]}; + outline: 0; + ::-webkit-details-marker { + display: none; + } + &:hover { + text-decoration: underline; + } + } + + details[open] > summary { + color: #1c1c1c; + } + + details[open] summary { + opacity: 0.9; + } + + ul { + padding: 0; + margin: 0; + padding-bottom: 2rem; + } + + ul li { + font-size: 1.1rem; + margin: 0 0 0.2rem; + padding: 15px 30px; + line-height: 1.7; + list-style: none; + background: #e3e3e3; + border: 2px solid #c1c1c1; + border-radius: 10px; + } + + ul li pre { + white-space: pre-line; + } +` + +export interface ErrorBannerProps extends React.HTMLAttributes { + error: unknown | string +} + +const ErrorBanner: React.FC = ({ error: unknownError }) => { + const { t } = useTranslation() + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const anyError = unknownError as any + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const [error, setError] = useState(undefined) + useEffect(() => { + if (typeof anyError === "object" && anyError !== null && anyError.data instanceof Blob) { + const blob: Blob = anyError.data + blob.text().then((text) => { + try { + const parsed = JSON.parse(text) + setError({ ...anyError, data: parsed }) + } catch { + setError({ ...anyError, data: text }) + } + }) + } else if (anyError === undefined) { + throw new Error("Invalid input") + } else { + setError(anyError) + } + }, [anyError]) + + if (error === undefined) { + // error data is blob and haven't read it yet, this should practically never be shown + return + } + + if (typeof error === "string") { + return ( + + + +

    {t("error-title")}

    +

    {error}

    +
    +
    +
    + ) + } else if (typeof error === "object" && error !== null) { + if (isErrorResponse(error.data)) { + // response data contains an error response + const data: ErrorResponse = error.data + const errorData = data.data + let linkComponent = <> + if (isErrorData(errorData)) { + const url = window.location.href.replace(location.hash, "") + // eslint-disable-next-line i18next/no-literal-string + linkComponent = Go to error + } + + return ( + + + +

    + {t("error-title")} {error.status}: {data.title} +

    +

    {data.message}

    +
    + + {data.source && ( +
    + {t("show-error-source")} +
      +
    • +
      {data.source}
      +
    • +
    +
    + )} +
    + {data.data && {linkComponent}} +
    +
    + ) + } else if (error.isAxiosError) { + const axiosError = error as AxiosError + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const responseMessage = (axiosError.response?.data as any)?.message + return ( + + + +

    + {t("error-title")}: {axiosError.message} +

    + {responseMessage &&

    {responseMessage}

    } +
    + + {Boolean(axiosError.response?.data) && ( +
    + {t("show-error-source")} +
      +
    • +
      {JSON.stringify(axiosError.response?.data, undefined, 2)}
      +
    • +
    +
    + )} +
    +
    +
    + ) + } else if ( + error.status !== undefined && + error.statusText !== undefined && + typeof error.request === "object" && + error.request.responseURL !== undefined + ) { + // error contains a response but no ErrorResponse + return ( + + + +

    + {t("error-title")} {error.status}: {error.statusText} +

    +

    {error.request.responseURL}

    +
    + + {error.data && ( +
    + {t("show-error-source")} +
      +
    • +
      {JSON.stringify(error.data, undefined, 2)}
      +
    • +
    +
    + )} +
    +
    +
    + ) + } else if (error instanceof Error) { + // caught error from somewhere (JSON.stringifying an error returns {}) + return ( + + + +

    {t("error-title")}

    +
    + +
    + {t("show-error-source")} +
      +
    • +
      +                      {error.toString()}
      +                      
      + {error.stack} +
      +
    • +
    +
    +
    +
    +
    + ) + } + } + + // Error very much unknown + return ( + + + +

    {t("error-title")}

    +
    + +
    + {t("show-error-source")} +
      +
    • +
      {JSON.stringify(error, undefined, 2)}
      +
    • +
    +
    +
    +
    +
    + ) +} + +export default ErrorBanner diff --git a/services/cms/src/shared-module-v2/common/components/ExerciseList/ExerciseBox.tsx b/services/cms/src/shared-module-v2/common/components/ExerciseList/ExerciseBox.tsx new file mode 100644 index 000000000000..aeec982c9cec --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/ExerciseList/ExerciseBox.tsx @@ -0,0 +1,166 @@ +import { css } from "@emotion/css" +import styled from "@emotion/styled" +import Link from "next/link" +import React from "react" + +import { baseTheme, headingFont, monospaceFont, secondaryFont } from "../../styles" +import CircularProgressBar from "../CircularProgressBar" + +const Wrapper = styled.div` + border-radius: 10px; + position: relative; + width: 100%; + margin-bottom: 5px; + + h2 { + text-align: center; + color: #3b4754; + font-family: ${secondaryFont}; + text-transform: uppercase; + font-size: 1.6rem; + margin-bottom: 2rem; + } +` + +const StyledLink = styled.div` + :hover { + cursor: pointer; + } +` + +// eslint-disable-next-line i18next/no-literal-string +const ImageBox = styled.div` + width: auto; + height: 40px; + padding: 0 6px; + position: relative; + vertical-align: middle; + display: flex; + align-items: center; + + div { + z-index: 2; + text-align: center; + align-content: center; + width: 24px; + height: 24px; + border-radius: 50%; + background: ${baseTheme.colors.blue[200]}; + opacity: 0.8; + } + + p { + text-align: center; + z-index: 3; + font-family: ${monospaceFont}; + color: ${baseTheme.colors.gray[700]}; + font-weight: 600; + line-height: 1.8; + font-size: 12px; + margin-bottom: 0; + } +` + +// eslint-disable-next-line i18next/no-literal-string +const ExercisePart = styled.div` + position: relative; + margin-left: 0em; + padding-left: 1em; + list-style-type: none; + color: ${baseTheme.colors.gray[700]}; + text-decoration: none; + background: ${({ bg }) => bg && bg}; + display: flex; + align-items: center; + + :hover { + background-color: rgb(235, 239, 242); + } + + span { + vertical-align: top; + padding: 0.6em 0; + font-size: 18px; + display: inline-block; + width: 80%; + margin: 0.4em 0 0.4em 0.2em; + font-family: ${headingFont}; + font-weight: 400; + } + + div:last-of-type { + margin-left: auto; + } +` +export interface ExerciseBoxExtraProps { + exerciseIndex: number + exerciseTitle: string + url: string + scoreMaximum: number + /// The caller will set this to null if the user is not logged in + userPoints: number | null + bg?: string +} +export interface StyledProps { + bg?: string +} + +export type ExerciseBox = React.HTMLAttributes & ExerciseBoxExtraProps + +const ExerciseBox: React.FC>> = ({ + exerciseIndex, + exerciseTitle, + url, + scoreMaximum, + userPoints, + bg, +}) => { + return ( + + + div { + background-color: ${baseTheme.colors.gray[500]}; + color: ${baseTheme.colors.clear[100]}; + } + } + `} + > + + +
    +

    {exerciseIndex}

    +
    +
    + {exerciseTitle} +
    + {userPoints !== null ? ( + + ) : ( + + )} +
    +
    + +
    +
    + ) +} + +export default ExerciseBox diff --git a/services/cms/src/shared-module-v2/common/components/ExerciseList/PageBox.tsx b/services/cms/src/shared-module-v2/common/components/ExerciseList/PageBox.tsx new file mode 100644 index 000000000000..b70ffdebe63e --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/ExerciseList/PageBox.tsx @@ -0,0 +1,55 @@ +import styled from "@emotion/styled" +import React from "react" + +import { baseTheme, headingFont } from "../../styles" + +const Wrapper = styled.div` + border-radius: 10px; + position: relative; + width: 100%; + margin-top: 5px; +` + +// eslint-disable-next-line i18next/no-literal-string +const PageBoxRow = styled.div` + position: relative; + padding: 0.6em 1em; + list-style-type: none; + color: ${baseTheme.colors.gray[600]}; + text-decoration: none; + border-radius: 2px; + background: #f2f5f7; + margin: 5px 0 5px 0; + display: flex; + justify-content: center; + + span { + vertical-align: top; + font-family: ${headingFont}; + font-size: clamp(16px, 1vw, 18px); + font-weight: 600; + display: inline-block; + width: 100%; + margin: 0.4em 0 0.4em 0.2em; + } +` + +export interface PageBoxExtraProps { + pageTitle: string +} + +export type PageBoxProps = React.HTMLAttributes & PageBoxExtraProps + +const PageBox: React.FC>> = ( + props, +) => { + return ( + + + {props.pageTitle} + + + ) +} + +export default PageBox diff --git a/services/cms/src/shared-module-v2/common/components/FloatingErrorBox.tsx b/services/cms/src/shared-module-v2/common/components/FloatingErrorBox.tsx new file mode 100644 index 000000000000..cb6da3e99f80 --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/FloatingErrorBox.tsx @@ -0,0 +1,77 @@ +import styled from "@emotion/styled" +import React from "react" + +import Tick from "../img/tick.svg" +import { headingFont } from "../styles" + +import Button from "./Button" + +const ErrorWrapper = styled.div` + max-width: 460px; + height: 163px; + border-radius: 1px; + transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); + background: #f5f5f5; + display: grid; + justify-content: center; + align-items: center; + position: relative; +` +const ButtonWrapper = styled.div` + display: flex; + gap: 26px; +` +const Message = styled.div` + position: absolute; + bottom: 0; + right: 0; + width: 100%; + height: 30px; + background: #e2efec; + display: flex; + justify-content: center; + gap: 5px; + + span { + display: inline-block; + font-family: ${headingFont}; + color: #37bc9b; + align-self: center; + } +` + +export interface ErrorExtraProps { + variant: "success" | "error" + content: string +} + +export type ErrorProps = React.HTMLAttributes & ErrorExtraProps + +const PLACEHOLDER_TEXT_ONE = "Reset" +const PLACEHOLDER_TEXT_TWO = "Your edit has been saved!" + +const FloatingErrorBox: React.FC< + React.PropsWithChildren> +> = () => { + // If URL defined, the chapter is open + + return ( + + + + + + + + + {PLACEHOLDER_TEXT_TWO} + + + ) +} + +export default FloatingErrorBox diff --git a/services/cms/src/shared-module-v2/common/components/Footer.tsx b/services/cms/src/shared-module-v2/common/components/Footer.tsx new file mode 100644 index 000000000000..71cf4d7b01c6 --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/Footer.tsx @@ -0,0 +1,205 @@ +import { css } from "@emotion/css" +import styled from "@emotion/styled" +import React from "react" +import { useTranslation } from "react-i18next" + +import UHLogo from "../img/UHBrandLogo.svg" +import MOOCfi from "../img/moocfiLogo.svg" +import { baseTheme, headingFont } from "../styles" +import { respondToOrLarger } from "../styles/respond" + +const PRIVACY_LINK = "https://www.mooc.fi/faq/tietosuojaseloste/" + +// To be link in the future +// const CREATORS_LINK = "https://www.mooc.fi/en/" + +// eslint-disable-next-line i18next/no-literal-string +const Container = styled.div` + margin-top: 5em; + padding: 1rem; + background: #f7f8f9; + + ${respondToOrLarger.sm} { + padding: 4rem; + } + + ${respondToOrLarger.lg} { + padding: 5rem 3rem; + } + + h1 { + margin-bottom: 0.8rem; + line-height: 1; + font-weight: 600; + font-size: clamp(24px, 2vw, 30px); + color: ${baseTheme.colors.gray[700]}; + padding: 0; + + ${respondToOrLarger.sm} { + padding: 0 2rem 0 0; + } + ${respondToOrLarger.lg} { + padding: 0 2rem 0 3rem; + } + } +` +const Wrapper = styled.div` + display: grid; + grid-template-rows: 1fr; + color: #231f20; + position: relative; + row-gap: 20px; + + ${respondToOrLarger.sm} { + grid-template-columns: 1fr; + gap: 20px; + row-gap: 20px; + } + + ${respondToOrLarger.lg} { + grid-template-columns: 0.9fr 0.2fr; + gap: 20px; + row-gap: 20px; + } +` + +const StyledLink = styled.a` + text-decoration: none; + color: ${baseTheme.colors.gray[700]}; + font-size: 18px; + font-weight: 500; + opacity: 0.8; + transition: opacity 0.2s ease-in; + margin-bottom: 5px; + font-family: ${headingFont}; + padding-left: 0; + + ${respondToOrLarger.lg} { + margin-bottom: 10px; + padding-left: 3rem; + } + + :hover { + text-decoration: none; + opacity: 1; + } +` +const Text = styled.div` + width: 100%; + padding: 0; + + ${respondToOrLarger.sm} { + padding: 0 2rem 0 0; + } + + ${respondToOrLarger.md} { + width: 90%; + } + + ${respondToOrLarger.lg} { + width: 90%; + padding: 0 5rem 0 3rem; + } + + p { + font-size: 18px; + padding-right: 0; + color: ${baseTheme.colors.gray[600]}; + } + + .mooc-description { + display: inline-block; + padding-top: 10px; + opacity: 0.8; + } +` +const Links = styled.div` + display: flex; + flex-direction: column; +` + +const LogoA = styled.a` + filter: brightness(100%) contrast(100%); + transition: filter 0.2s; + max-height: 98px; + &:hover { + filter: brightness(34%) contrast(40%); + } + + &:first-of-type { + margin-right: 1.5rem; + } +` + +export type FooterProps = React.HTMLAttributes + +const Footer: React.FC>> = () => { + const { t, i18n } = useTranslation() + const useFinnishLinks = i18n.language === "fi" || i18n.language === "fi-FI" + return ( +
    + +

    {t("about")}

    + + +

    {t("about-mooc-center-description")}

    +

    + {t("mooc-project-description")} {t("star-the-project-on-github")}:{" "} + {t("project-github")}. +

    +
    + + {t("privacy")} + {/* {t("accessibility")} */} + +
    + + + + + + +
    +
    +
    +
    + ) +} + +export default Footer diff --git a/services/cms/src/shared-module-v2/common/components/Forum/Forum.tsx b/services/cms/src/shared-module-v2/common/components/Forum/Forum.tsx new file mode 100644 index 000000000000..5803e2279441 --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/Forum/Forum.tsx @@ -0,0 +1,187 @@ +/* eslint-disable i18next/no-literal-string */ +import styled from "@emotion/styled" +import React, { useRef, useState } from "react" +import { useTranslation } from "react-i18next" + +import RadioButton from "../InputFields/RadioButton" +import TextAreaField from "../InputFields/TextAreaField" + +import Thread from "./Thread" + +const placeholder = `Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has +been the industry's standard dummy text ever since the 1500s, when an unknown printer took +a galley of type and scrambled it to make a type specimen book. It has survived not only +five centuries, but also the leap into electronic typesetting, remaining essentially +unchanged.` + +const authorObject = { + id: "1001", + text: placeholder, + time: "12hr ago", +} +const Wrapper = styled.div` + background: #fff; + width: 60%; + height: auto; + border: 2px solid rgba(205, 205, 205, 0.8); + border-radius: 4px; +` +const Head = styled.div` + border-bottom: 1px solid rgba(205, 205, 205, 0.6); +` +const CommentSection = styled.form` + width: 100%; + height: auto; + border-top: 1px solid rgba(205, 205, 205, 0.6); + padding: 2rem; +` +const Label = styled.span` + color: #333; + opacity: 0.5; + font-size: 16px; +` +const RadioSection = styled.div` + display: flex; + margin-top: 0.2rem; + margin-bottom: 1rem; +` + +const StyledButton = styled.input` + display: flex; + border: none; + align-self: end; + padding: 0.5rem 2rem; + font-size: 18px; + color: #313947; + margin-top: 1.5rem; +` + +const StRadio = styled(RadioButton)` + margin-right: 1rem !important; +` +export interface Item { + id: string + text: string + time: string + author: string +} + +export interface Thread { + id: string + text: string + time: string + items?: Item[] +} + +const Forum = () => { + const [state, setState] = useState([]) + const [visibility, setVisibility] = useState("hide") + const [clicked, setClicked] = useState(false) + const selectedId = useRef("") + + const current = new Date() + + const { t } = useTranslation() + + const handleClick = (event: React.MouseEvent) => { + setClicked(!clicked) + const target = event.target as HTMLInputElement + selectedId.current = target.id + } + + const handleReply = (e: React.SyntheticEvent) => { + e.preventDefault() + const target = e.target as typeof e.target & { + reply: { value: string } + } + + const reply = target.reply.value + + setState((prevState) => { + return prevState.map((item) => { + const { items } = item + return item.id === selectedId.current + ? { + ...item, + items: [ + { + id: current.toLocaleString(), + text: reply, + time: current.toLocaleString(), + author: "Anonymous", + }, + ...(items ? items : []), + ], + } + : item + }) + }) + setClicked(false) + target.reply.value = "" + } + + return ( + + + + + {state?.map((obj) => ( + + ))} + { + e.preventDefault() + const target = e.target as typeof e.target & { + comment: { value: string } + visibility: { value: string } + } + + const comment = target.comment.value + const visible = target.visibility.value + + setState((state) => [ + ...state, + { + id: String(current.toLocaleTimeString()), + text: comment, + time: current.toLocaleString(), + item: [], + }, + ]) + setVisibility(visible) + target.comment.value = "" + }} + > + + + setVisibility("show")} + /> + setVisibility("hide")} + checked={visibility === "hide"} + /> + + null} /> + + + + ) +} + +export default Forum diff --git a/services/cms/src/shared-module-v2/common/components/Forum/SideNavigation.tsx b/services/cms/src/shared-module-v2/common/components/Forum/SideNavigation.tsx new file mode 100644 index 000000000000..a10c33445089 --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/Forum/SideNavigation.tsx @@ -0,0 +1,176 @@ +/* eslint-disable i18next/no-literal-string */ +import styled from "@emotion/styled" +import { useState } from "react" + +import { headingFont } from "../../styles" + +const arr = [ + { text: "Home", path: "/" }, + { text: "Your threads", path: "/" }, + { text: "Saved", path: "/" }, +] +const currentCourse = [ + { id: "001", text: "Computer science", path: "/" }, + { id: "002", text: "Biology", path: "/" }, + { + id: "003", + text: "Chemistry", + path: "/", + items: [ + { text: "Subtopic", path: "/" }, + { text: "Subtopic threads", path: "/" }, + ], + }, + { + id: "004", + text: "Economics", + path: "/", + items: [ + { text: "Subtopic I", path: "/" }, + { text: "Subtopic threads IV", path: "/" }, + ], + }, + { id: "005", text: "Physics", path: "/" }, + { id: "006", text: "Computer science II", path: "/" }, +] + +const Wrapper = styled.div` + display: block; + position: sticky; + top: 24px; + max-width: 450px; + height: 100vh; + overflow: auto; + border-right: 2px solid #cfcfcf; + padding-left: 2rem; + background: #f8f8f9; + + h2 { + color: #989ca3; + font-size: 30px; + font-weight: 400; + padding-left: 1rem; + } + + ol { + text-decoration: none; + list-style: none; + padding-left: 0; + + li { + display: flex; + color: #767b85; + margin-bottom: 0.8rem; + margin-right: 4rem; + padding: 0.8rem 0; + align-items: center; + padding-left: 1rem; + position: relative; + + &:hover { + background: #fff; + + &:before { + content: ""; + background: #44827e; + width: 4px; + height: 20px; + position: absolute; + border-radius: 1px; + left: 0; + } + } + + a { + text-decoration: none; + color: #767b85; + font-weight: 400; + font-size: 22px; + font-family: ${headingFont}; + line-height: 1; + align-self: center; + } + } + } + + ol:first-of-type { + margin-bottom: 4rem; + } + ol:last-of-type { + margin-bottom: 3rem; + } +` + +const PlaceholderAvatar = styled.div` + background: #dddee0; + border-radius: 100%; + height: 34px; + width: 34px; + margin-right: 15px; +` + +const StyledButton = styled.button` + display: flex; + border: none; + justify-content: center; + padding: 1rem 2rem; + margin-left: 1rem; + font-size: 18px; + color: #313947; + width: 21rem; +` +const ListItem = styled.li` + margin-left: 2rem; +` + +const SideNavigation = () => { + const [active, setActive] = useState() + + return ( + +
      + {arr.map(({ text, path }) => ( +
    1. + + {text} +
    2. + ))} +
    + +

    Current course

    +
      + {currentCourse.map(({ text, items, id, path }, index) => ( +
      { + const activeId = active !== id && items ? id : "" + setActive(activeId) + }} + onKeyDown={() => { + const activeId = active !== id && items ? id : "" + setActive(activeId) + }} + role="button" + tabIndex={index} + > +
    1. + + {text} +
    2. + {active === id && + items?.map(({ text, path }) => ( + + + {text} + + ))} +
      + ))} +
    + + Join new course +
    + ) +} + +export default SideNavigation diff --git a/services/cms/src/shared-module-v2/common/components/Forum/Thread.tsx b/services/cms/src/shared-module-v2/common/components/Forum/Thread.tsx new file mode 100644 index 000000000000..34e8effaa77a --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/Forum/Thread.tsx @@ -0,0 +1,207 @@ +import { css } from "@emotion/css" +import styled from "@emotion/styled" +import React, { Fragment } from "react" +import { useTranslation } from "react-i18next" + +import TextAreaField from "../InputFields/TextAreaField" + +import { Item, Thread as StateProps } from "./Forum" + +const Wrapper = styled.div` + width: 100%; + height: auto; +` +const Header = styled.div` + display: flex; + justify-content: space-between; + padding: 2rem 2rem 1.6rem 2rem; + + h2 { + align-self: end; + } +` +const Content = styled.div` + padding: 0 2rem; +` +const Text = styled.p` + font-size: 20px; + line-height: 140%; + font-weight: 500; + padding-bottom: 0rem; +` +const Footer = styled.div` + display: flex; + justify-content: space-between; + padding: 1.5rem 0 3rem 0; + align-items: center; +` +const Author = styled.div` + display: flex; + + span { + margin-right: 10px; + color: #535a66; + font-size: 20px; + align-self: center; + } +` +const ActionTab = styled.div` + display: flex; +` +const ChatIcon = styled.div` + display: flex; +` +const PlaceholderAvatar = styled.div` + background: #f3f3f3; + border-radius: 100%; + height: 35px; + width: 35px; + margin-right: 10px; +` +const PlaceholderIcon = styled.div` + background: #f3f3f3; + border-radius: 100%; + height: 30px; + width: 30px; + margin-right: 10px; +` +const StyledReplyIcon = styled.div` + display: flex; + margin: 0 1.5rem; + cursor: pointer; + + span { + color: #535a66; + } +` +const StyledReportIcon = styled.span` + color: #b66757; +` +const TimeLabel = styled.span` + color: #535a66; +` +const StyledButton = styled.input` + display: flex; + border: none; + align-self: end; + padding: 0.5rem 2rem; + font-size: 18px; + color: #313947; + margin: 1rem 0; +` + +interface ThreadProps { + state: StateProps + author: string + handleReply?: (e: React.SyntheticEvent) => void + clicked?: boolean + selectedId?: string + handleClick?: (event: React.MouseEvent) => void +} + +const REPLY = "reply" +const SUBMIT = "submit" + +const Thread: React.FC>> = (props) => { + const { + state: { items }, + } = props + + return ( + + {GetThread(props)} + {items?.map((item) => GetNestedThread(item))} + + ) +} + +const GetThread = (props: ThreadProps) => { + const { t } = useTranslation() + const { state, author, handleReply, handleClick, clicked, selectedId } = props + + const { id, text, time } = state + return ( + text && ( + +
    + + + {author} + + {time} +
    + + {text} +
    + + + + + + + {t("reply")} + + {t("report")} + + + + +
    + {clicked && selectedId === id && ( +
    + null} + /> + + + )} +
    +
    + ) + ) +} + +const GetNestedThread = (item: Item) => { + const { t } = useTranslation() + const { text, time, author } = item + return ( + text && ( + +
    + + + {author} + + {time} +
    + + {text} +
    + + + + + {t("report")} + + + + +
    +
    +
    + ) + ) +} + +export default Thread diff --git a/services/cms/src/shared-module-v2/common/components/Forum/Threads.tsx b/services/cms/src/shared-module-v2/common/components/Forum/Threads.tsx new file mode 100644 index 000000000000..e82e5fb7cbb6 --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/Forum/Threads.tsx @@ -0,0 +1,98 @@ +/* eslint-disable i18next/no-literal-string */ +import styled from "@emotion/styled" + +const Wrapper = styled.div` + background: #fff; + width: 60%; + height: auto; + border: 2px solid rgba(205, 205, 205, 0.8); + border-radius: 4px; +` +const Header = styled.div` + display: flex; + justify-content: space-between; + padding: 2rem 2rem 2rem 2rem; + + h2 { + align-self: end; + } +` +const Tag = styled.div` + background: #ececec; + width: auto; + padding: 1rem; + text-transform: uppercase; +` +const Content = styled.div` + padding: 0 2rem; +` +const Text = styled.p` + font-size: 20px; + line-height: 140%; + font-weight: 500; + padding-bottom: 3rem; + border-bottom: 2px solid rgba(197, 197, 197, 0.8); +` +const Footer = styled.div` + display: flex; + justify-content: space-between; + padding: 1.5rem 0 3rem 0; + align-items: center; +` +const Author = styled.div` + display: flex; + + p { + margin-right: 10px; + color: #b2b2b2; + span { + color: #32bea6; + margin: 0 10px; + } + } +` +const ChatIcon = styled.div` + display: flex; +` +const PlaceholderAvatar = styled.div` + background: #f3f3f3; + border-radius: 100%; + height: 30px; + width: 30px; + margin-right: 10px; +` + +const Threads = () => { + return ( + +
    +

    New date for final exams

    + Computer science +
    + + + Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has + been the industrys standard dummy text ever since the 1500s, when an unknown printer took + a galley of type and scrambled it to make a type specimen book. It has survived not only + five centuries, but also the leap into electronic typesetting, remaining essentially + unchanged. + +
    + + +

    + Posted by Henrik Nygren +

    + 12hr ago +
    + + + 50+ + +
    +
    +
    + ) +} + +export default Threads diff --git a/services/cms/src/shared-module-v2/common/components/GenericInfobox.tsx b/services/cms/src/shared-module-v2/common/components/GenericInfobox.tsx new file mode 100644 index 000000000000..394f64472b1a --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/GenericInfobox.tsx @@ -0,0 +1,36 @@ +import { css } from "@emotion/css" +import { InfoCircle } from "@vectopus/atlas-icons-react" + +import { baseTheme } from "../styles" + +const GenericInfobox: React.FC>> = ({ + children, +}) => { + return ( +
    + +
    + {children} +
    +
    + ) +} + +export default GenericInfobox diff --git a/services/cms/src/shared-module-v2/common/components/HeightTrackingContainer.tsx b/services/cms/src/shared-module-v2/common/components/HeightTrackingContainer.tsx new file mode 100644 index 000000000000..7b36b78f2d17 --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/HeightTrackingContainer.tsx @@ -0,0 +1,106 @@ +import { css } from "@emotion/css" +import React, { ReactNode, useEffect, useRef, useState } from "react" + +import IframeHeightContext from "../contexts/IframeHeightContext" + +interface Props { + port: MessagePort | null + children?: ReactNode +} + +const HeightTrackingContainer: React.FC< + React.PropsWithChildren> +> = ({ port, children }) => { + const contentRef = useRef(null) + const [height, setHeight] = useState(0) + const previouslySentHeightRef = useRef(0) + + useEffect(() => { + const onResize = () => { + const ref = contentRef.current + if (!ref) { + return + } + setHeight(ref.getBoundingClientRect().height) + } + window.addEventListener("resize", onResize) + return () => { + window.removeEventListener("resize", onResize) + } + }, []) + + // resize observer, catches whenever an element resizes + useEffect(() => { + const ref = contentRef.current + if (!ref) { + return + } + const onResize = () => { + const ref = contentRef.current + if (!ref) { + return + } + setHeight(ref.getBoundingClientRect().height) + } + const observer = new ResizeObserver(onResize) + observer.observe(ref) + return () => { + observer.disconnect() + } + }, [contentRef]) + + useEffect(() => { + // To be safe, we'll check periodically whether the sent height matches the height in the document. + const intervalId = setInterval(() => { + if (!port) { + return + } + const ref = contentRef.current + if (!ref) { + return + } + const currentHeight = ref.getBoundingClientRect().height + if (currentHeight !== previouslySentHeightRef.current) { + setHeight(currentHeight) + } + return () => { + clearInterval(intervalId) + } + }, 5000) + }, [port]) + + useEffect(() => { + // Send the updates to the parent + if (!port || height === previouslySentHeightRef.current) { + return + } + onHeightChange(height, port) + previouslySentHeightRef.current = height + }, [height, port]) + + return ( + + + + ) +} + +function onHeightChange(newHeight: number, port: MessagePort) { + if (!port) { + return + } + port.postMessage({ + message: "height-changed", + data: newHeight, + }) +} + +export default HeightTrackingContainer diff --git a/services/cms/src/shared-module-v2/common/components/InputFields/CheckBox.tsx b/services/cms/src/shared-module-v2/common/components/InputFields/CheckBox.tsx new file mode 100644 index 000000000000..a7d7ffd583f8 --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/InputFields/CheckBox.tsx @@ -0,0 +1,140 @@ +import { css, cx } from "@emotion/css" +import styled from "@emotion/styled" +import React, { forwardRef, InputHTMLAttributes } from "react" + +import { baseTheme, primaryFont } from "../../styles" + +const ERRORCOLOR = "#F76D82" +const DEFAULTCOLOR = "#787878" + +interface LabelExtraProps { + error?: boolean +} + +// eslint-disable-next-line i18next/no-literal-string +const Label = styled.label` + font-family: ${primaryFont}; + font-size: 1.1rem; + line-height: 1.1; + display: grid; + grid-template-columns: 1em auto; + gap: 0.5em; + color: ${baseTheme.colors.gray[600]}; + + input[type="checkbox"] { + appearance: none; + background-color: #fff; + margin: 0; + font: inherit; + width: 1.15em; + height: 1.1em; + border: 2px solid ${({ error }) => (error ? ERRORCOLOR : DEFAULTCOLOR)}; + transform: translateY(-0.075em); + display: grid; + place-content: center; + } + + input[type="checkbox"]:hover { + background: #f9f9f9; + } + + input[type="checkbox"]:before { + content: ""; + width: 0.65em; + height: 0.65em; + transform: scale(0); + transition: 120ms transform ease-in-out; + box-shadow: inset 1em 1em #fff; + clip-path: polygon(28% 38%, 41% 53%, 75% 24%, 86% 38%, 40% 78%, 15% 50%); + } + + input[type="checkbox"]:checked { + border-color: #37bc9b; + background: #37bc9b; + } + input[type="checkbox"]:checked::before { + transform: scale(1); + } + + input[type="checkbox"]:disabled { + color: #959495; + cursor: not-allowed; + } +` + +const error = css` + color: #f76d82; + font-size: 14px; + display: inline-block; + margin-top: -15px; +` + +// Error string might change in the future + +const ERROR = "Please check the secret box" + +export interface CheckboxProps extends InputHTMLAttributes { + label: string + error?: boolean + checked?: boolean + onChangeByValue?: (checked: boolean, name?: string) => void +} + +const CheckBox: React.FC = forwardRef( + ({ onChangeByValue, onChange, className, checked, ...rest }, ref) => { + const handleOnChange = (event: React.ChangeEvent) => { + if (onChangeByValue) { + const { + target: { checked }, + } = event + onChangeByValue(checked) + } + if (onChange) { + onChange(event) + } + } + return ( +
    + + {rest.error && ( + + {ERROR} + + )} +
    + ) + }, +) + +CheckBox.displayName = "CheckBox" +export default CheckBox diff --git a/services/cms/src/shared-module-v2/common/components/InputFields/CheckboxFieldWrapper.tsx b/services/cms/src/shared-module-v2/common/components/InputFields/CheckboxFieldWrapper.tsx new file mode 100644 index 000000000000..bb710a037c44 --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/InputFields/CheckboxFieldWrapper.tsx @@ -0,0 +1,44 @@ +import { css, cx } from "@emotion/css" +import React, { InputHTMLAttributes, useState } from "react" +import { useTranslation } from "react-i18next" + +import CheckBox from "./CheckBox" + +export interface CheckboxFieldWrapperProps extends InputHTMLAttributes { + fieldName: string + onUncheck: () => void + initialChecked?: boolean +} + +const CheckboxFieldWrapper: React.FC< + React.PropsWithChildren> +> = ({ fieldName, className, children, onUncheck, initialChecked }) => { + const { t } = useTranslation() + const [checked, setChecked] = useState(initialChecked ?? false) + return ( +
    + { + if (!checked) { + onUncheck() + } + setChecked(checked) + }} + className={css` + ${checked && `margin-bottom: 0.2rem;`} + `} + /> +
    + {children} +
    +
    + ) +} + +export default CheckboxFieldWrapper diff --git a/services/cms/src/shared-module-v2/common/components/InputFields/DatePickerField.tsx b/services/cms/src/shared-module-v2/common/components/InputFields/DatePickerField.tsx new file mode 100644 index 000000000000..c39f89b7873c --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/InputFields/DatePickerField.tsx @@ -0,0 +1,67 @@ +import { css, cx } from "@emotion/css" +import { InputHTMLAttributes } from "react" + +export interface DatePickerProps extends InputHTMLAttributes { + label: string + hint?: string + onChangeByValue: (value: string, name?: string) => void +} + +const DatePicker = ({ onChange, onChangeByValue, className, ...rest }: DatePickerProps) => { + const handleOnChange = (event: React.ChangeEvent) => { + if (onChangeByValue) { + const { + target: { value }, + } = event + onChangeByValue(value) + } + if (onChange) { + onChange(event) + } + } + return ( +
    + +
    + ) +} + +export default DatePicker diff --git a/services/cms/src/shared-module-v2/common/components/InputFields/DateTimeLocal.tsx b/services/cms/src/shared-module-v2/common/components/InputFields/DateTimeLocal.tsx new file mode 100644 index 000000000000..80eaf256027f --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/InputFields/DateTimeLocal.tsx @@ -0,0 +1,116 @@ +import { css, cx } from "@emotion/css" +import React, { forwardRef, InputHTMLAttributes, useState } from "react" + +import { baseTheme } from "../../styles" +import { dateToString } from "../../utils/time" + +const error = css` + color: #f76d82; + font-size: 14px; + display: inline-block; + margin-top: -15px; +` + +export interface TimePickerProps extends InputHTMLAttributes { + label: string + onChangeByValue?: (value: string, name?: string) => void + error?: string + defaultValue?: string + className?: string +} + +const DateTimeLocal: React.FC = forwardRef( + ({ onChangeByValue, onChange, className, defaultValue, ...rest }, ref) => { + const [value, setValue] = useState(defaultValue ?? "") + const handleOnChange = (event: React.ChangeEvent) => { + if (onChangeByValue) { + const { + target: { value }, + } = event + onChangeByValue(value) + } + if (onChange) { + onChange(event) + } + setValue(event.target.value) + } + return ( +
    + + + {value && ( + + {dateToString(new Date(value))} + + )} + + {rest.error && ( + + {rest.error} + + )} +
    + ) + }, +) +DateTimeLocal.displayName = "DateTimeLocal" + +export default DateTimeLocal diff --git a/services/cms/src/shared-module-v2/common/components/InputFields/EditableComponentTextArea.tsx b/services/cms/src/shared-module-v2/common/components/InputFields/EditableComponentTextArea.tsx new file mode 100644 index 000000000000..6cb6cb5a71cc --- /dev/null +++ b/services/cms/src/shared-module-v2/common/components/InputFields/EditableComponentTextArea.tsx @@ -0,0 +1,93 @@ +import { css, cx } from "@emotion/css" +import React, { TextareaHTMLAttributes, useEffect, useRef } from "react" + +export interface TextFieldProps extends TextareaHTMLAttributes { + label?: string + errorMessage?: string + autoResize?: boolean + onChangeByValue: (value: string, name?: string) => void +} + +function updateHeight(ref: React.RefObject) { + if (ref.current) { + // eslint-disable-next-line i18next/no-literal-string + ref.current.style.height = "20px" + // eslint-disable-next-line i18next/no-literal-string + ref.current.style.height = `${ref.current.scrollHeight /* + 5 */}px` + } +} + +const EditableComponentTextArea = ({ + onChangeByValue, + onChange, + className, + autoResize, + ...rest +}: TextFieldProps) => { + const textareaRef = useRef(null) + + useEffect(() => { + // This auto-resizes the textarea if the feature is enabled + if (!autoResize || !textareaRef.current) { + return + } + updateHeight(textareaRef) + }, [rest.value, autoResize]) + + const handleOnChange = (event: React.ChangeEvent) => { + if (onChangeByValue) { + const { + target: { value }, + } = event + onChangeByValue(value) + } + if (onChange) { + onChange(event) + } + if (autoResize) { + updateHeight(textareaRef) + } + } + return ( +
    +