diff --git a/.coderabbit.yaml b/.coderabbit.yaml
index 2561dae05690..08e009547a4a 100644
--- a/.coderabbit.yaml
+++ b/.coderabbit.yaml
@@ -9,7 +9,7 @@ tone_instructions: ''
early_access: true
enable_free_tier: true
reviews:
- profile: assertive
+ profile: chill
request_changes_workflow: true
high_level_summary: true
high_level_summary_placeholder: '@coderabbitai summary'
@@ -192,7 +192,7 @@ reviews:
- TYPOGRAPHY
- CASING
enabled_only: false
- level: picky
+ level: default
enabled_rules: []
enabled_categories: []
biome:
diff --git a/.github/workflows/check-translation-keys.yml b/.github/workflows/check-translation-keys.yml
index a14ed3f43b9a..02dbe17f2955 100644
--- a/.github/workflows/check-translation-keys.yml
+++ b/.github/workflows/check-translation-keys.yml
@@ -18,7 +18,4 @@ jobs:
with:
python-version: "3.12"
- name: Check if translation keys match
- run: >
- python .ci/translation-file-checker/translation_file_checker.py
- --german-files src/main/webapp/i18n/de/
- --english-files src/main/webapp/i18n/en/
+ run: python .ci/translation-file-checker/translation_file_checker.py --german-files src/main/webapp/i18n/de/ --english-files src/main/webapp/i18n/en/
diff --git a/.github/workflows/validate-pr-title.yml b/.github/workflows/validate-pr-title.yml
new file mode 100644
index 000000000000..37e280ee2017
--- /dev/null
+++ b/.github/workflows/validate-pr-title.yml
@@ -0,0 +1,14 @@
+name: Validate PR Title
+
+on:
+ pull_request:
+ types: [opened, synchronize, reopened, ready_for_review, edited]
+
+jobs:
+ validate-pr-title:
+ runs-on: ubuntu-latest
+ timeout-minutes: 1
+ steps:
+ - uses: Slashgear/action-check-pr-title@v4.3.0
+ with:
+ regexp: '^`(Programming exercises|Integrated code lifecycle|Quiz exercises|Modeling exercises|Text exercises|File upload exercises|Exam mode|Grading|Assessment|Communication|Notifications|Team exercises|Lectures|Integrated markdown editor|Plagiarism checks|Learning analytics|Adaptive learning|Learning path|Tutorial groups|Iris|Scalability|Usability|Performance|Infrastructure|Mobile apps|Development|General)`:\s[A-Z].*$'
\ No newline at end of file
diff --git a/.idea/runConfigurations/_template__of_Gradle.xml b/.idea/runConfigurations/_template__of_Gradle.xml
index 0d7f0a89449e..7c6cecee1dad 100644
--- a/.idea/runConfigurations/_template__of_Gradle.xml
+++ b/.idea/runConfigurations/_template__of_Gradle.xml
@@ -4,7 +4,7 @@
-
+
diff --git a/README.md b/README.md
index 9b6118e0fe28..a982be2c6bba 100644
--- a/README.md
+++ b/README.md
@@ -193,7 +193,7 @@ Refer to [Using JHipster in production](http://www.jhipster.tech/production) for
The following command can automate the deployment to a server. The example shows the deployment to the main Artemis test server (which runs a virtual machine):
```shell
-./artemis-server-cli deploy username@artemistest.ase.in.tum.de -w build/libs/Artemis-7.5.6.war
+./artemis-server-cli deploy username@artemistest.ase.in.tum.de -w build/libs/Artemis-7.6.1.war
```
## Architecture
diff --git a/angular.json b/angular.json
index e5543ff2ce60..008ac75d13bf 100644
--- a/angular.json
+++ b/angular.json
@@ -113,7 +113,7 @@
},
{
"glob": "**/*",
- "input": "./node_modules/monaco-editor/min/vs",
+ "input": "./node_modules/monaco-editor/bundles/vs",
"output": "vs"
}
],
diff --git a/build.gradle b/build.gradle
index 1375d3298583..a1388862f5a6 100644
--- a/build.gradle
+++ b/build.gradle
@@ -25,7 +25,7 @@ plugins {
}
group = "de.tum.cit.aet.artemis"
-version = "7.5.6"
+version = "7.6.1"
description = "Interactive Learning with Individual Feedback"
java {
@@ -246,12 +246,15 @@ dependencies {
implementation "org.gitlab4j:gitlab4j-api:6.0.0-rc.5"
implementation "de.jplag:jplag:${jplag_version}"
- implementation "de.jplag:java:${jplag_version}"
- implementation "de.jplag:kotlin:${jplag_version}"
+
implementation "de.jplag:c:${jplag_version}"
- implementation "de.jplag:swift:${jplag_version}"
implementation "de.jplag:java:${jplag_version}"
+ implementation "de.jplag:javascript:${jplag_version}"
+ implementation "de.jplag:kotlin:${jplag_version}"
implementation "de.jplag:python-3:${jplag_version}"
+ implementation "de.jplag:rlang:${jplag_version}"
+ implementation "de.jplag:rust:${jplag_version}"
+ implementation "de.jplag:swift:${jplag_version}"
implementation "de.jplag:text:${jplag_version}"
// those are transitive dependencies of JPlag Text --> Stanford NLP
@@ -270,7 +273,7 @@ dependencies {
}
}
- implementation "org.apache.logging.log4j:log4j-to-slf4j:2.24.0"
+ implementation "org.apache.logging.log4j:log4j-to-slf4j:2.24.1"
// Note: spring-security-lti13 does not work with jakarta yet, so we built our own custom version and declare its transitive dependencies below
// implementation "uk.ac.ox.ctl:spring-security-lti13:0.1.11"
@@ -342,7 +345,7 @@ dependencies {
implementation "tech.jhipster:jhipster-framework:${jhipster_dependencies_version}"
implementation "org.springframework.boot:spring-boot-starter-cache:${spring_boot_version}"
- implementation "io.micrometer:micrometer-registry-prometheus:1.13.4"
+ implementation "io.micrometer:micrometer-registry-prometheus:1.13.5"
implementation "net.logstash.logback:logstash-logback-encoder:8.0"
// Defines low-level streaming API, and includes JSON-specific implementations
@@ -405,7 +408,7 @@ dependencies {
implementation "org.springframework.cloud:spring-cloud-starter-config:4.1.3"
implementation "org.springframework.cloud:spring-cloud-commons:4.1.4"
- implementation "io.netty:netty-all:4.1.113.Final"
+ implementation "io.netty:netty-all:4.1.114.Final"
implementation "io.projectreactor.netty:reactor-netty:1.1.22"
implementation "org.springframework:spring-messaging:6.1.13"
implementation "org.springframework.retry:spring-retry:2.0.9"
@@ -416,7 +419,7 @@ dependencies {
implementation "org.springframework.security:spring-security-oauth2-core:${spring_security_version}"
implementation "org.springframework.security:spring-security-oauth2-client:${spring_security_version}"
// use newest version of nimbus-jose-jwt to avoid security issues through outdated dependencies
- implementation "com.nimbusds:nimbus-jose-jwt:9.41.1"
+ implementation "com.nimbusds:nimbus-jose-jwt:9.41.2"
implementation "org.springframework.security:spring-security-oauth2-jose:${spring_security_version}"
implementation "org.springframework.security:spring-security-crypto:${spring_security_version}"
@@ -445,8 +448,7 @@ dependencies {
implementation "com.ibm.icu:icu4j-charset:75.1"
implementation "com.github.seancfoley:ipaddress:5.5.1"
implementation "org.apache.maven:maven-model:3.9.9"
- // NOTE: 3.0.2 is broken for splitting lecture specific PDFs
- implementation "org.apache.pdfbox:pdfbox:3.0.1"
+ implementation "org.apache.pdfbox:pdfbox:3.0.3"
implementation "org.apache.commons:commons-csv:1.12.0"
implementation "org.commonmark:commonmark:0.23.0"
implementation "commons-fileupload:commons-fileupload:1.5"
@@ -464,7 +466,7 @@ dependencies {
implementation "com.google.code.gson:gson:2.11.0"
- implementation "com.google.errorprone:error_prone_annotations:2.32.0"
+ implementation "com.google.errorprone:error_prone_annotations:2.33.0"
// NOTE: we want to keep the same unique version for all configurations, implementation and annotationProcessor
implementation("net.bytebuddy:byte-buddy") {
@@ -528,11 +530,11 @@ dependencies {
testImplementation "org.mockito:mockito-core:${mockito_version}"
testImplementation "org.mockito:mockito-junit-jupiter:${mockito_version}"
- testImplementation "io.github.classgraph:classgraph:4.8.176"
+ testImplementation "io.github.classgraph:classgraph:4.8.177"
testImplementation "org.awaitility:awaitility:4.2.2"
testImplementation "org.apache.maven.shared:maven-invoker:3.3.0"
testImplementation "org.gradle:gradle-tooling-api:8.10.2"
- testImplementation "org.apache.maven.surefire:surefire-report-parser:3.5.0"
+ testImplementation "org.apache.maven.surefire:surefire-report-parser:3.5.1"
testImplementation "com.opencsv:opencsv:5.9"
testImplementation("io.zonky.test:embedded-database-spring-test:2.5.1") {
exclude group: "org.testcontainers", module: "mariadb"
diff --git a/docs/dev/guidelines/database.rst b/docs/dev/guidelines/database.rst
index 65365549f10a..ea4e436b53d4 100644
--- a/docs/dev/guidelines/database.rst
+++ b/docs/dev/guidelines/database.rst
@@ -295,7 +295,7 @@ Best Practices
// IrisSubSettings.java
@Column(name = "allowed_models")
@Convert(converter = IrisModelListConverter.class)
- private TreeSet allowedModels = new TreeSet<>();
+ private TreeSet allowedVariants = new TreeSet<>();
* **Ordered Collection with duplicates**: When you want to order the collection of (potentially duplicated) objects of the relationship, then always use a ``List``. It is important to note here that there is no inherent order in a database table. One could argue that you can use the ``id`` field for the ordering, but there are edge cases where this can lead to problems. Therefore, for an ordered collection with duplicates, **always** annotate it with ``@OrderColumn``. An order column indicates to Hibernate that we want to order our collection based on a specific column of our data table. By default, the column name it expects is *tablenameS\_order*. For ordered collections, we also recommend that you annotate them with ``cascade = CascadeType.ALL`` and ``orphanRemoval = true``. E.g.:
diff --git a/docs/index.rst b/docs/index.rst
index 32c130434e4f..f4a7bc4cf449 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -37,6 +37,7 @@ All these exercises are supposed to be run either live in the lecture with insta
user/grading
user/courses/customizable
user/markdown-support
+ user/integrated-code-lifecycle
user/exports
user/mobile-applications
user/lti
diff --git a/docs/user/exercises/programming-exercise-features.inc b/docs/user/exercises/programming-exercise-features.inc
index 6d0b257dd96e..660e2bd4bf02 100644
--- a/docs/user/exercises/programming-exercise-features.inc
+++ b/docs/user/exercises/programming-exercise-features.inc
@@ -37,6 +37,8 @@ Instructors can still use those templates to generate programming exercises and
+----------------------+----------+---------+
| JavaScript | yes | yes |
+----------------------+----------+---------+
+ | R | yes | yes |
+ +----------------------+----------+---------+
- Not all ``templates`` support the same feature set and supported features can also change depending on the continuous integration system setup.
Depending on the feature set, some options might not be available during the creation of the programming exercise.
@@ -67,9 +69,11 @@ Instructors can still use those templates to generate programming exercises and
+----------------------+----------------------+----------------------+---------------------+--------------+------------------------------------------+------------------------------+----------------------------+------------------------+
| OCaml | no | no | no | no | n/a | yes | no | L: yes, J: no |
+----------------------+----------------------+----------------------+---------------------+--------------+------------------------------------------+------------------------------+----------------------------+------------------------+
- | Rust | no | no | no | no | n/a | no | no | L: yes, J: no |
+ | Rust | no | no | yes | no | n/a | no | no | L: yes, J: no |
+ +----------------------+----------------------+----------------------+---------------------+--------------+------------------------------------------+------------------------------+----------------------------+------------------------+
+ | JavaScript | no | no | yes | no | n/a | no | no | L: yes, J: no |
+----------------------+----------------------+----------------------+---------------------+--------------+------------------------------------------+------------------------------+----------------------------+------------------------+
- | JavaScript | no | no | no | no | n/a | no | no | L: yes, J: no |
+ | R | no | no | yes | no | n/a | no | no | L: yes, J: no |
+----------------------+----------------------+----------------------+---------------------+--------------+------------------------------------------+------------------------------+----------------------------+------------------------+
- *Sequential Test Runs*: ``Artemis`` can generate a build plan which first executes structural and then behavioral tests. This feature can help students to better concentrate on the immediate challenge at hand.
diff --git a/docs/user/exercises/programming-repository-access.inc b/docs/user/exercises/programming-repository-access.inc
index 45323fced7dd..c4e201d0f4b6 100644
--- a/docs/user/exercises/programming-repository-access.inc
+++ b/docs/user/exercises/programming-repository-access.inc
@@ -1,3 +1,5 @@
+If you are a student, and want to know how to use the Artemis Version Control for checking out repositories locally, :ref:`checkout this guide.`
+
The following tables lists the different types of repositories and gives an overview of the access rights different users have.
To gain these access rights, a user must assume the indicated role in the course the repository belongs to.
diff --git a/docs/user/exercises/programming.rst b/docs/user/exercises/programming.rst
index 6f8a8e00782c..61f1731c4dff 100644
--- a/docs/user/exercises/programming.rst
+++ b/docs/user/exercises/programming.rst
@@ -224,19 +224,5 @@ Each one represents a single test case feedback and should have the format:
Integrated Code Lifecycle
-------------------------
-The following sections describe programming exercise features that are part of the integrated code lifecycle system.
-
-Repository View
-^^^^^^^^^^^^^^^
-
-.. include:: programming-integrated-code-lifecycle-repository-view.inc
-
-Build Agent View
-^^^^^^^^^^^^^^^^
-
-.. include:: programming-integrated-code-lifecycle-build-agent-view.inc
-
-Build Overview View
-^^^^^^^^^^^^^^^^^^^
-
-.. include:: programming-integrated-code-lifecycle-build-queue-view.inc
+The Artemis Integrated Code Lifecycle system allows you to use programming exercises fully integrated within Artemis, without the need of any external tools.
+Find more information on it :ref:`here`.
diff --git a/docs/user/exercises/programming/build-agent-details.png b/docs/user/exercises/programming/build-agent-details.png
deleted file mode 100644
index ae9d8f2561f4..000000000000
Binary files a/docs/user/exercises/programming/build-agent-details.png and /dev/null differ
diff --git a/docs/user/exercises/programming/build-agent-summary.png b/docs/user/exercises/programming/build-agent-summary.png
deleted file mode 100644
index 414451407f71..000000000000
Binary files a/docs/user/exercises/programming/build-agent-summary.png and /dev/null differ
diff --git a/docs/user/exercises/programming/buildQueueCourseManagement.png b/docs/user/exercises/programming/buildQueueCourseManagement.png
deleted file mode 100644
index dc16f6dd6a32..000000000000
Binary files a/docs/user/exercises/programming/buildQueueCourseManagement.png and /dev/null differ
diff --git a/docs/user/exercises/programming/buildQueueSystemAdministration.png b/docs/user/exercises/programming/buildQueueSystemAdministration.png
deleted file mode 100644
index 1a18244e443a..000000000000
Binary files a/docs/user/exercises/programming/buildQueueSystemAdministration.png and /dev/null differ
diff --git a/docs/user/exercises/programming/commit-diff-view.png b/docs/user/exercises/programming/commit-diff-view.png
deleted file mode 100644
index cfd5cda349cc..000000000000
Binary files a/docs/user/exercises/programming/commit-diff-view.png and /dev/null differ
diff --git a/docs/user/exercises/programming/commit-history-view.png b/docs/user/exercises/programming/commit-history-view.png
deleted file mode 100644
index ac691c9c3a60..000000000000
Binary files a/docs/user/exercises/programming/commit-history-view.png and /dev/null differ
diff --git a/docs/user/exercises/programming/course-management-repositories.png b/docs/user/exercises/programming/course-management-repositories.png
deleted file mode 100644
index 47e842da25a5..000000000000
Binary files a/docs/user/exercises/programming/course-management-repositories.png and /dev/null differ
diff --git a/docs/user/exercises/programming/current-repository-content-view.png b/docs/user/exercises/programming/current-repository-content-view.png
deleted file mode 100644
index 041b6411f6a1..000000000000
Binary files a/docs/user/exercises/programming/current-repository-content-view.png and /dev/null differ
diff --git a/docs/user/exercises/programming/finished-build-jobs.png b/docs/user/exercises/programming/finished-build-jobs.png
deleted file mode 100644
index 149a7f98819b..000000000000
Binary files a/docs/user/exercises/programming/finished-build-jobs.png and /dev/null differ
diff --git a/docs/user/exercises/programming/open-repository-button.png b/docs/user/exercises/programming/open-repository-button.png
deleted file mode 100644
index a758454dead7..000000000000
Binary files a/docs/user/exercises/programming/open-repository-button.png and /dev/null differ
diff --git a/docs/user/exercises/programming/open-repository-instructor-participations.png b/docs/user/exercises/programming/open-repository-instructor-participations.png
deleted file mode 100644
index 03e9e66e3910..000000000000
Binary files a/docs/user/exercises/programming/open-repository-instructor-participations.png and /dev/null differ
diff --git a/docs/user/exercises/programming/open-repository-student.png b/docs/user/exercises/programming/open-repository-student.png
deleted file mode 100644
index 5685e134d177..000000000000
Binary files a/docs/user/exercises/programming/open-repository-student.png and /dev/null differ
diff --git a/docs/user/exercises/programming/queued-build-jobs.png b/docs/user/exercises/programming/queued-build-jobs.png
deleted file mode 100644
index eb7165c01436..000000000000
Binary files a/docs/user/exercises/programming/queued-build-jobs.png and /dev/null differ
diff --git a/docs/user/exercises/programming/running-build-jobs.png b/docs/user/exercises/programming/running-build-jobs.png
deleted file mode 100644
index 08ccfa8856fd..000000000000
Binary files a/docs/user/exercises/programming/running-build-jobs.png and /dev/null differ
diff --git a/docs/user/icl/general.rst b/docs/user/icl/general.rst
new file mode 100644
index 000000000000..bf0132e6d20e
--- /dev/null
+++ b/docs/user/icl/general.rst
@@ -0,0 +1,12 @@
+.. _icl-general-information:
+
+General Information
+===================
+
+Artemis offers the Integrated Code Lifecycle (ICL), a comprehensive feature designed to streamline the development process for programming exercises.
+ICL combines version control, secure communication, and continuous integration to provide a seamless experience for students and instructors.
+Understanding these components is crucial for effectively using Artemis, especially if you're new to concepts like SSH and Git. The key components of ICL are:
+
+- :ref:`Local Version Control`: Use the Local Version Control to interact with the repositories of programming exercises.
+- :ref:`SSH`: Use SSH to perform Git operations on repositories.
+- :ref:`Local Continuous Integration`: Exercise submissions are built and tested by the Local CI system.
diff --git a/docs/user/exercises/programming-integrated-code-lifecycle-build-agent-view.inc b/docs/user/icl/local-ci-build-agent-view.inc
similarity index 95%
rename from docs/user/exercises/programming-integrated-code-lifecycle-build-agent-view.inc
rename to docs/user/icl/local-ci-build-agent-view.inc
index a59068be8589..b211e879b252 100644
--- a/docs/user/exercises/programming-integrated-code-lifecycle-build-agent-view.inc
+++ b/docs/user/icl/local-ci-build-agent-view.inc
@@ -5,7 +5,7 @@ The build agent view consists of two parts: the *Build Agent Summary View* and t
The **Build Agent Summary View** shows a list of all build agents in the system, along with their status (idle and running), maximum number of concurrent builds, and running builds.
The running builds can be canceled individually by clicking the red cancellation button next to the build. An Administrator can also cancel all running builds on a build agent by clicking the '*Cancel All*' button.
-.. figure:: programming/build-agent-summary.png
+.. figure:: local-ci/build-agent-summary.png
:alt: Build Agent Summary View
:align: center
@@ -20,7 +20,7 @@ the submission time, start time, end time, the duration of the build job, the co
The administrator can click on the participation ID to navigate to the participation's submission page.
The administrator can also click on the commit hash to navigate to the commits details page and the course ID to navigate to the course management page.
-.. figure:: programming/build-agent-details.png
+.. figure:: local-ci/build-agent-details.png
:alt: Build Agent Details
:align: center
diff --git a/docs/user/exercises/programming-integrated-code-lifecycle-build-queue-view.inc b/docs/user/icl/local-ci-build-queue-view.inc
similarity index 90%
rename from docs/user/exercises/programming-integrated-code-lifecycle-build-queue-view.inc
rename to docs/user/icl/local-ci-build-queue-view.inc
index 2c2470d9561a..7c865758f98c 100644
--- a/docs/user/exercises/programming-integrated-code-lifecycle-build-queue-view.inc
+++ b/docs/user/icl/local-ci-build-queue-view.inc
@@ -1,7 +1,7 @@
Artemis provides a build overview view that displays all queued, running, and finished build jobs. Access to the system-wide build overview is
exclusively available to **Administrators** through the *System Administration* menu.
-.. figure:: programming/buildQueueSystemAdministration.png
+.. figure:: local-ci/buildQueueSystemAdministration.png
:alt: Build Overview System Administration
:align: center
@@ -10,7 +10,7 @@ exclusively available to **Administrators** through the *System Administration*
**Instructors** can access the build overview for a specific course through the *Build Overview* button located in *Course Management*.
This view displays only the queued, running, and finished build jobs associated with the selected course.
-.. figure:: programming/buildQueueCourseManagement.png
+.. figure:: local-ci/buildQueueCourseManagement.png
:alt: Build Overview Course Management
:align: center
@@ -27,7 +27,7 @@ Jobs are dynamically added to and removed from the queue in real-time.
Users have the ability to cancel any job in progress. The table provides the following information:
-.. figure:: programming/running-build-jobs.png
+.. figure:: local-ci/running-build-jobs.png
:alt: Running Build Jobs
:align: center
@@ -43,7 +43,7 @@ Users also have the option to cancel any job that is queued.
The table below displays the following information:
-.. figure:: programming/queued-build-jobs.png
+.. figure:: local-ci/queued-build-jobs.png
:alt: Queued Build Jobs
:align: center
@@ -59,7 +59,7 @@ Instructors can also access build logs with detailed information about the build
The table provides the following information:
-.. figure:: programming/finished-build-jobs.png
+.. figure:: local-ci/finished-build-jobs.png
:alt: Finished Build Jobs
:align: center
diff --git a/docs/user/icl/local-ci/build-agent-details.png b/docs/user/icl/local-ci/build-agent-details.png
new file mode 100644
index 000000000000..4b5b8474781a
Binary files /dev/null and b/docs/user/icl/local-ci/build-agent-details.png differ
diff --git a/docs/user/icl/local-ci/build-agent-summary.png b/docs/user/icl/local-ci/build-agent-summary.png
new file mode 100644
index 000000000000..ec11e28a0d1d
Binary files /dev/null and b/docs/user/icl/local-ci/build-agent-summary.png differ
diff --git a/docs/user/icl/local-ci/buildQueueCourseManagement.png b/docs/user/icl/local-ci/buildQueueCourseManagement.png
new file mode 100644
index 000000000000..d4e255f39988
Binary files /dev/null and b/docs/user/icl/local-ci/buildQueueCourseManagement.png differ
diff --git a/docs/user/icl/local-ci/buildQueueSystemAdministration.png b/docs/user/icl/local-ci/buildQueueSystemAdministration.png
new file mode 100644
index 000000000000..9a857a317ce8
Binary files /dev/null and b/docs/user/icl/local-ci/buildQueueSystemAdministration.png differ
diff --git a/docs/user/icl/local-ci/finished-build-jobs.png b/docs/user/icl/local-ci/finished-build-jobs.png
new file mode 100644
index 000000000000..eb7b3dda190d
Binary files /dev/null and b/docs/user/icl/local-ci/finished-build-jobs.png differ
diff --git a/docs/user/icl/local-ci/queued-build-jobs.png b/docs/user/icl/local-ci/queued-build-jobs.png
new file mode 100644
index 000000000000..acd382dfe1f8
Binary files /dev/null and b/docs/user/icl/local-ci/queued-build-jobs.png differ
diff --git a/docs/user/icl/local-ci/running-build-jobs.png b/docs/user/icl/local-ci/running-build-jobs.png
new file mode 100644
index 000000000000..8cc66a2e5c63
Binary files /dev/null and b/docs/user/icl/local-ci/running-build-jobs.png differ
diff --git a/docs/user/icl/local-continuous-integration.rst b/docs/user/icl/local-continuous-integration.rst
new file mode 100644
index 000000000000..6c3cdd9b8e65
--- /dev/null
+++ b/docs/user/icl/local-continuous-integration.rst
@@ -0,0 +1,27 @@
+.. _local-ci:
+
+Continuous Integration
+======================
+
+Continuous Integration (CI) is a software development practice where developers frequently merge their code changes into a shared repository. Each change is automatically built and tested, which helps to:
+
+- Detect and address integration issues early
+- Ensure code quality and consistency
+- Streamline the development process
+
+Artemis Local CI is our implementation of these CI principles, tailored to support the Artemis learning platform.
+It provides tools and views to help users build and test in programming exercises effectively.
+
+This document will introduce you to the key components of Artemis Local CI: the Build Agent View and the Build Overview View.
+These tools will assist you throughout your development workflow on the Artemis platform.
+
+Build Agent View
+^^^^^^^^^^^^^^^^
+
+.. include:: local-ci-build-agent-view.inc
+
+
+Build Overview View
+^^^^^^^^^^^^^^^^^^^
+
+.. include:: local-ci-build-queue-view.inc
diff --git a/docs/user/icl/local-vc-authentication.inc b/docs/user/icl/local-vc-authentication.inc
new file mode 100644
index 000000000000..6735cd2743df
--- /dev/null
+++ b/docs/user/icl/local-vc-authentication.inc
@@ -0,0 +1,67 @@
+Cloning a repository
+^^^^^^^^^^^^^^^^^^^^
+
+You can use Sourcetree, git from the terminal, or any client you like to clone your Git repository.
+These instructions show you how to clone your repository using Git from the terminal.
+
+From the exercise view, click the code button to display the Clone dialog.
+Copy the clone URL (either the SSH format or the HTTPS, with or without token).
+If you are using the SSH protocol, ensure your public key is stored in your Artemis account settings and loaded on the local system to which you are cloning.
+From a terminal window, change to the local directory where you want to clone your repository.
+
+Paste the command you copied from Bitbucket, for example:
+
+Clone over HTTPS:
+
+.. code-block:: bash
+
+ git clone https://username@artemis.cit.tum.de/course/documentation-tests.git
+
+
+Clone over HTTPS with access token:
+
+.. code-block:: bash
+
+ git clone https://username:accessToken@artemis.cit.tum.de/course/documentation-tests.git
+
+
+Clone over SSH:
+
+.. code-block:: bash
+
+ git clone ssh://git@artemis.cit.tum.de/course/documentation-tests.git
+
+
+If the clone was successful, a new sub-directory appears on your local drive.
+This directory has the same name as the repository that you cloned.
+The clone contains the files and metadata that Git requires to maintain the changes you make to the source files.
+
+Choosing between HTTPS and SSH:
+
+- HTTPS: Easier to set up initially, works through firewalls, but requires entering credentials more frequently.
+- SSH: More secure, doesn't require entering passwords for each operation once set up, but initial setup can be more complex.
+
+Choose HTTPS if you're new to Git or working in an environment with strict firewall rules.
+Choose SSH for enhanced security and convenience in long-term development.
+
+HTTPS access tokens
+^^^^^^^^^^^^^^^^^^^
+
+Instructors can create HTTP access tokens for repository access in Artemis.
+They are created in the account settings and are used in place of passwords for Git over HTTPS.
+For every student's exercise, Artemis automatically generates an access token, only associated with the repository of this particular exercise.
+You can use these to authenticate to the Artemis Local Version Control.
+
+Token Creation
+""""""""""""""
+
+1. Go to Profile > Settings > VCS token.
+2. Create a new token
+
+Using SSH keys to secure Git operations
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Artemis provides a simple way for users to connect securely to repositories, using SSH to perform Git operations.
+Next is a :ref:`small and basic introduction to SSH`, and if you already know it, :ref:`here is a guide on how to create SSH keys`.
+If you already have an SSH key, :ref:`learn how to add it to your Artemis account here`.
+
diff --git a/docs/user/exercises/programming-integrated-code-lifecycle-repository-view.inc b/docs/user/icl/local-vc-repository-view.inc
similarity index 88%
rename from docs/user/exercises/programming-integrated-code-lifecycle-repository-view.inc
rename to docs/user/icl/local-vc-repository-view.inc
index 5273befacd08..aef46936e99a 100644
--- a/docs/user/exercises/programming-integrated-code-lifecycle-repository-view.inc
+++ b/docs/user/icl/local-vc-repository-view.inc
@@ -3,13 +3,13 @@ These changes are stored in a repository. A repository is a collection of files
How to navigate through the repository and view the code is explained in the following sections. This guide is divided into two parts: one for students and one for instructors.
It is demonstrated using course programming exercises, but the same principles apply to exams as well.
-For Students
-""""""""""""
+Access Repositories as a Student
+""""""""""""""""""""""""""""""""
As a student, you can use the repository to view your course submissions.
To access your submissions, you need to navigate to the exercise, press the '*Code*' button, and click on |open-repository-button|.
-.. figure:: programming/open-repository-student.png
+.. figure:: local-vc/open-repository-student.png
:alt: Opening the repository in the student view
:align: center
@@ -22,7 +22,7 @@ To the right side of the screen, above the problem statement, you can see the re
the '*Code*' button to clone the repository to your local machine and see the full commit history by pressing the '*Open Commit History*' button. Finally, you can
download the repository as a ZIP file by pressing the '*Download Repository*' button.
-.. figure:: programming/current-repository-content-view.png
+.. figure:: local-vc/current-repository-content-view.png
:alt: Current Repository Content
:align: center
@@ -33,7 +33,7 @@ You can see the commit message, the author of the commit, the date of the commit
If you created a submission with multiple commits, you can see all of them here but only the last commit has the result of the submission.
Lastly, you can also view the code of the commit by pressing on the commit hash.
-.. figure:: programming/commit-history-view.png
+.. figure:: local-vc/commit-history-view.png
:alt: Commit History View
:align: center
@@ -44,20 +44,20 @@ You can see the changes in the code, the files that have been added, the files t
Green color indicates the lines that have been added and red color indicates the lines that have been deleted.
You can also see the commit message, the author of the commit, the date of the commit and the commit hash.
-.. figure:: programming/commit-diff-view.png
+.. figure:: local-vc/commit-diff-view.png
:alt: Commit Diff View
:align: center
Commit Diff View
-For Instructors
-"""""""""""""""
+Access Repositories as an Instructor
+""""""""""""""""""""""""""""""""""""
As an instructor, you can use the repository to view the submissions of your students. For this purpose, you need to navigate to the exercise participations page.
Here you can see all the students’ participations for the exercise and navigate to the repository of a student by pressing the '*Code*' button and clicking on |open-repository-button|.
This will show the repository of the student just like it is shown to the student.
-.. figure:: programming/open-repository-instructor-participations.png
+.. figure:: local-vc/open-repository-instructor-participations.png
:alt: Open Repository Button in Participations Page
:align: center
@@ -66,11 +66,11 @@ This will show the repository of the student just like it is shown to the studen
You can also see the repositories for an exercises **solution**, **template** and **test** repositories on the exercise management page.
You can navigate to these repositories by pressing the '*Code*' button and clicking |open-repository-button| as described above.
-.. figure:: programming/course-management-repositories.png
+.. figure:: local-vc/course-management-repositories.png
:alt: Solution, Template and Test Repositories in Exercise Management Page
:align: center
Solution, Template and Test Repositories in Exercise Management Page
-.. |open-repository-button| image:: programming/open-repository-button.png
+.. |open-repository-button| image:: local-vc/open-repository-button.png
:scale: 50%
diff --git a/docs/user/icl/local-vc/commit-diff-view.png b/docs/user/icl/local-vc/commit-diff-view.png
new file mode 100644
index 000000000000..19ebb58be3ab
Binary files /dev/null and b/docs/user/icl/local-vc/commit-diff-view.png differ
diff --git a/docs/user/icl/local-vc/commit-history-view.png b/docs/user/icl/local-vc/commit-history-view.png
new file mode 100644
index 000000000000..2dd208d0de16
Binary files /dev/null and b/docs/user/icl/local-vc/commit-history-view.png differ
diff --git a/docs/user/icl/local-vc/course-management-repositories.png b/docs/user/icl/local-vc/course-management-repositories.png
new file mode 100644
index 000000000000..ab0af10e9103
Binary files /dev/null and b/docs/user/icl/local-vc/course-management-repositories.png differ
diff --git a/docs/user/icl/local-vc/current-repository-content-view.png b/docs/user/icl/local-vc/current-repository-content-view.png
new file mode 100644
index 000000000000..961e9f17889b
Binary files /dev/null and b/docs/user/icl/local-vc/current-repository-content-view.png differ
diff --git a/docs/user/icl/local-vc/open-repository-button.png b/docs/user/icl/local-vc/open-repository-button.png
new file mode 100644
index 000000000000..b1b4d60873cd
Binary files /dev/null and b/docs/user/icl/local-vc/open-repository-button.png differ
diff --git a/docs/user/icl/local-vc/open-repository-instructor-participations.png b/docs/user/icl/local-vc/open-repository-instructor-participations.png
new file mode 100644
index 000000000000..bf051e6d644d
Binary files /dev/null and b/docs/user/icl/local-vc/open-repository-instructor-participations.png differ
diff --git a/docs/user/icl/local-vc/open-repository-student.png b/docs/user/icl/local-vc/open-repository-student.png
new file mode 100644
index 000000000000..93312d1cab27
Binary files /dev/null and b/docs/user/icl/local-vc/open-repository-student.png differ
diff --git a/docs/user/icl/local-vc/open-settings.png b/docs/user/icl/local-vc/open-settings.png
new file mode 100644
index 000000000000..84c13407ab74
Binary files /dev/null and b/docs/user/icl/local-vc/open-settings.png differ
diff --git a/docs/user/icl/local-vc/ssh-add-public-key.png b/docs/user/icl/local-vc/ssh-add-public-key.png
new file mode 100644
index 000000000000..3e4683c09b7e
Binary files /dev/null and b/docs/user/icl/local-vc/ssh-add-public-key.png differ
diff --git a/docs/user/icl/local-version-control.rst b/docs/user/icl/local-version-control.rst
new file mode 100644
index 000000000000..1ca1c1c2c31c
--- /dev/null
+++ b/docs/user/icl/local-version-control.rst
@@ -0,0 +1,16 @@
+.. _local-vc:
+
+Local Version Control
+=====================
+
+.. contents:: Content of this document
+ :local:
+ :depth: 2
+
+
+Repository View
+^^^^^^^^^^^^^^^
+
+.. include:: local-vc-repository-view.inc
+
+.. include:: local-vc-authentication.inc
diff --git a/docs/user/icl/ssh-add-key-to-artemis.rst b/docs/user/icl/ssh-add-key-to-artemis.rst
new file mode 100644
index 000000000000..0e3425faa501
--- /dev/null
+++ b/docs/user/icl/ssh-add-key-to-artemis.rst
@@ -0,0 +1,68 @@
+.. _use ssh key:
+
+Using SSH with Artemis
+^^^^^^^^^^^^^^^^^^^^^^
+
+.. contents:: Content of this document
+ :local:
+ :depth: 1
+
+You can use SSH keys to establish a secure connection between your computer and Artemis when you are performing Git operations (pull, clone, push) from your local machine.
+Personal keys are linked to your Artemis account, inheriting its permissions and operating under its unique identity.
+To use your generated SSH keys with Artemis, you need to add it in the account settings.
+
+
+Add an SSH key to your Artemis account
+""""""""""""""""""""""""""""""""""""""
+
+**1. Copy your public key**
+
+On Windows in your command prompt, change directory to your `.ssh` directory, and copy the public key file to your clipboard by running:
+
+.. code-block:: bash
+
+ cd %userprofile%/.ssh
+ clip < id_ed25519.pub
+
+On macOS or Linux simply run the following in a terminal:
+
+.. _xclip: https://wiki.ubuntuusers.de/xclip/
+
+.. code-block:: bash
+
+ pbcopy < ~/.ssh/id_ed25519.pub
+
+If `pbcopy` isn't working, locate the hidden `.ssh` folder, open the file in a text editor, and copy it to your clipboard.
+Note that on Linux, you may need to download and install `xclip`_, then use that, as shown in this code snippet:
+
+.. code-block:: bash
+
+ sudo apt-get install xclip
+ xclip -sel clip < ~/.ssh/id_ed25519.pub
+
+Note that the key's name is not necessarily **id_ed25519.pub**, but can be arbitrary, and depends on how you saved it.
+
+
+**2. Add the key to your Artemis account**
+
+Open the settings, go to the SSH tab, and select 'New Key'.
+Then paste the copied SSH key into the text box.
+
++---------------------------------------------------+--------------------------------------------------------------+
+|.. figure:: local-vc/open-settings.png | .. figure:: local-vc/ssh-add-public-key.png |
+| :alt: Open account settings | :alt: Add public SSH key to account |
+| :align: center | :align: center |
+| | |
+| Open you Artemis account settings | Add public SSH key to account in account settings |
++---------------------------------------------------+--------------------------------------------------------------+
+
+**3. Save the key. You're done!**
+
+Use SSH to connect to Artemis repositories
+""""""""""""""""""""""""""""""""""""""""""
+
+After everything is set up, you can go to a programming exercise, and use the SSH clone URL with git to access the repository locally, like this, for example:
+
+.. code-block:: bash
+
+ git clone ssh://git@artemis.cit.tum.de:7921/git/COURSE/exercise-user_1.git
diff --git a/docs/user/icl/ssh-intro.rst b/docs/user/icl/ssh-intro.rst
new file mode 100644
index 000000000000..fd41034ebe5d
--- /dev/null
+++ b/docs/user/icl/ssh-intro.rst
@@ -0,0 +1,67 @@
+.. _basic SSH introduction:
+
+SSH
+^^^
+
+.. contents:: Content of this document
+ :local:
+ :depth: 2
+
+Artemis uses SSH as a simple way for users to connect securely to repositories to perform Git operations.
+
+What is SSH?
+""""""""""""
+
+.. _SSH (Secure Shell): https://en.wikipedia.org/wiki/Secure_Shell
+
+`SSH (Secure Shell)`_ is a protocol that allows you to securely connect to another computer over a network.
+It’s mostly used by system administrators, developers, and IT professionals to remotely manage servers or computers.
+SSH provides a secure and encrypted communication channel between your computer and a remote machine, so any data passed (like passwords or commands) is protected from eavesdropping.
+In Artemis you an use SSH to access your repositories with Git.
+
+Why use SSH?
+""""""""""""
+
+The main advantage of SSH is security.
+When you connect to a remote machine using SSH, all the data exchanged between your computer and the server is encrypted.
+This means if someone tries to intercept the communication, they can't read it. It's like sending messages through a locked box that only you and the server can open.
+
+How does SSH work?
+""""""""""""""""""
+
+SSH works by using two components:
+
+- Client: The computer you are using to connect.
+- Server: The machine you want to connect to.
+
+When you want to connect, your SSH client sends a request to the server.
+If the connection is successful, you can log in to the server and start working as if you were sitting in front of it.
+The connection uses SSH keys for authentication. Although it is also possible to use username and password to connect over SSH, this is discouraged.
+
+What are SSH Keys?
+""""""""""""""""""
+
+.. _public-key cryptography: https://en.wikipedia.org/wiki/Public-key_cryptography
+
+
+SSH keys are a more secure alternative to passwords for logging into a server.
+They are based on `public-key cryptography`_ and come in pairs: a public key and a private key.
+
+- Public Key: This key is stored on the server. Think of it like a lock that only you can open.
+- Private Key: This key stays on your local machine (never shared!). It’s like the key to that lock.
+
+When you try to connect to the server, your computer proves it has the private key that matches the server's public key, granting you access.
+You can add a personal SSH key to your user account to easily authenticate when performing read operations from your local machine.
+An Artemis user can currently add one key to their account.
+For instructions on how to add your SSH key to your Artemis account, please refer to :ref:`the relevant documentation`.
+
+Before you can use SSH keys to secure a connection with Artemis the following must have already been done:
+
+- SSH is enabled on your university's Artemis instance
+- You need an SSH key! See :ref:`Creating SSH keys`.
+
+.. note::
+
+ - You can use the same SSH key for multiple repositories or projects.
+ - An Artemis user can currently only add one key to their account.
+ - Artemis supports ECDSA, RSA2, and Ed25519 key types.
diff --git a/docs/user/icl/ssh-key-creation.rst b/docs/user/icl/ssh-key-creation.rst
new file mode 100644
index 000000000000..58e7b01f5a4d
--- /dev/null
+++ b/docs/user/icl/ssh-key-creation.rst
@@ -0,0 +1,161 @@
+.. _create ssh key:
+
+Creating SSH keys
+^^^^^^^^^^^^^^^^^
+
+.. contents:: Content of this document
+ :local:
+ :depth: 2
+
+SSH keys can be used to establish a secure connection with the Artemis Local Version Control, where you are performing Git operations from your local machine.
+The SSH key needs to be added to Artemis before you can make use of the key.
+
+Creating an SSH key on Windows
+""""""""""""""""""""""""""""""
+
+**1. Check for existing keys**
+
+You should check for existing SSH keys on your local computer. Open a command prompt, and run:
+
+.. code-block:: bash
+
+ cd %userprofile%/.ssh
+
+- If you see "No such file or directory", then there aren't any existing keys: go to step 3.
+
+- Check to see if you have a key already:
+
+.. code-block:: bash
+
+ dir id_*
+
+If there are existing keys, you may want to use those: :ref:`Add your key to Artemis`.
+
+**2. Back up old SSH keys**
+
+If you have existing SSH keys, but you don't want to use them when connecting to Bitbucket, you should back those up.
+In a command prompt on your local computer, run:
+
+.. code-block:: bash
+
+ mkdir key_backup
+ copy * key_backup
+
+**3. Generate a new SSH key**
+
+If you don't have an existing SSH key that you wish to use, generate one as follows:
+1. Log in to your local computer as an administrator.
+2. In a command prompt, run:
+
+.. _Git (with Git Bash): https://gitforwindows.org/
+
+
+.. code-block:: bash
+
+ ssh-keygen -t ed25519 -C "your_email@example.com"
+
+Associating the key with your email address helps you to identify the key later on.
+Note that the `ssh-keygen` command is only available if you have already installed `Git (with Git Bash)`_.
+You'll see a response similar to this:
+
+.. code-block:: bash
+
+ C:\Users\artemis>ssh-keygen -t ed25519 -C "your_email@example.com"
+ Generating public/private ed25519 key pair.
+ Enter file in which to save the key (/c/Users/artemis/.ssh/id_ed25519):
+
+3. Just press to accept the default location and file name. If the .ssh directory doesn't exist, the system creates one for you.
+4. Enter, and re-enter, a passphrase when prompted. The whole interaction will look similar to this:
+
+.. code-block:: bash
+
+ C:\Users\artemis>ssh-keygen -t ed25519 -C "your_email@example.com"
+ Generating public/private ed25519 key pair.
+ Enter file in which to save the key (/c/Users/artemis/.ssh/id_ed25519):
+ Created directory '/c/Users/artemis/.ssh'.
+ Enter passphrase (empty for no passphrase):
+ Enter same passphrase again:
+ Your identification has been saved in c/Users/artemis/.ssh/id_ed25519.
+ Your public key has been saved in c/Users/artemis/.ssh/id_ed25519.pub.
+ The key fingerprint is:
+ SHA256:wvaHYeLtY6+DlvV5sFZgDi3abcdefghijklmnopqrstuvw your_email@example.com
+
+5. You're done and you can now :ref:`add your key to Artemis`.
+
+Creating an SSH key on Linux & macOS
+""""""""""""""""""""""""""""""""""""
+
+**1. Check for existing SSH keys**
+
+You should check for existing SSH keys on your local computer. Open a terminal and run:
+
+.. code-block:: bash
+
+ cd ~/.ssh
+
+If you see "No such file or directory, then there aren't any existing keys: go to step 3.
+Check to see if you have a key already:
+
+.. code-block:: bash
+
+ ls id_*
+
+If there are existing keys, you may want to use those: :ref:`Add your key to Artemis`.
+
+**2. Back up old SSH keys**
+
+If you have existing SSH keys, but you don't want to use them when connecting to Bitbucket, you should back those up.
+In a command prompt on your local computer, run:
+
+.. code-block:: bash
+
+ mkdir key_backup
+ cp * key_backup
+
+**3. Generate a new SSH key**
+
+If you don't have an existing SSH key that you wish to use, generate one as follows:
+
+1. Open a terminal on your local computer and enter the following:
+
+.. code-block:: bash
+
+ ssh-keygen -t ed25519 -C "your_email@example.com"
+
+Associating the key with your email address helps you to identify the key later on. You'll see a response similar to this:
+
+.. code-block:: bash
+
+ artemis@homemac ~ % ssh-keygen -t ed25519 -C artemis@email.com
+ Generating public/private ed25519 key pair.
+ Enter file in which to save the key (/Users/artemis/.ssh/id_ed25519):
+
+2. Just press to accept the default location and file name. If the .ssh directory doesn't exist, the system creates one for you.
+3. Enter, and re-enter, a passphrase when prompted. The whole interaction will look similar to this:
+
+.. code-block:: bash
+
+ artemis@homemac ~ % ssh-keygen -t ed25519 -C artemis@email.com
+ Generating public/private ed25519 key pair.
+ Enter file in which to save the key (/Users/artemis/.ssh/id_ed25519):
+ Enter passphrase (empty for no passphrase):
+ Enter same passphrase again:
+ Your identification has been saved in /Users/artemis/.ssh/id_ed25519.
+ Your public key has been saved in /Users/artemis/.ssh/id_ed25519.pub.
+ The key fingerprint is:
+ SHA256:gTVWKbn41z6JgBNu3wYjLC4abcdefghijklmnopqrstuvwxy artemis@email.com
+ The keys randomart image is:
+ +--[ED25519 256]--+
+ |==+. +o.. |
+ |.oE. +o.. |
+ | . ...o |
+ | .o... |
+ | oo+S . |
+ | + ..B = . . |
+ |.+.+.oo+ * o . |
+ |o++.o+ . + + |
+ |B+ o. . . |
+ +----[SHA256]-----+
+ artemis@homemac ~ %
+
+4. You're done and you can now :ref:`add your key to Artemis`.
diff --git a/docs/user/integrated-code-lifecycle.rst b/docs/user/integrated-code-lifecycle.rst
new file mode 100644
index 000000000000..9e5ab5231ef0
--- /dev/null
+++ b/docs/user/integrated-code-lifecycle.rst
@@ -0,0 +1,15 @@
+.. _integrated code lifecycle:
+
+Integrated Code Lifecycle
+=========================
+
+Artemis' Integrated Code Lifecycle consists of two main components: Local Version Control and Local Continuous Integration.
+
+.. toctree::
+
+ icl/general
+ icl/local-version-control
+ icl/ssh-intro
+ icl/ssh-key-creation
+ icl/ssh-add-key-to-artemis
+ icl/local-continuous-integration
diff --git a/gradle.properties b/gradle.properties
index fc54fad2849b..07ee79d07d25 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -18,29 +18,29 @@ jaxb_runtime_version=4.0.5
hazelcast_version=5.5.0
fasterxml_version=2.18.0
jgit_version=7.0.0.202409031743-r
-sshd_version=2.13.2
-checkstyle_version=10.18.1
+sshd_version=2.14.0
+checkstyle_version=10.18.2
jplag_version=5.1.0
# not really used in Artemis, nor Jplag, nor the used version of Stanford CoreNLP, but we use the latest to avoid security vulnerabilities
# NOTE: we do not need to use the latest version 9.x here as long as Stanford CoreNLP does not reference it
lucene_version=8.11.4
slf4j_version=2.0.16
-sentry_version=7.14.0
+sentry_version=7.15.0
liquibase_version=4.29.2
docker_java_version=3.4.0
-logback_version=1.5.8
+logback_version=1.5.10
java_parser_version=3.26.2
-byte_buddy_version=1.15.3
+byte_buddy_version=1.15.4
# testing
# make sure both versions are compatible
junit_version=5.11.0
-junit_platform_version=1.11.1
-mockito_version=5.13.0
+junit_platform_version=1.11.2
+mockito_version=5.14.1
# gradle plugin version
-gradle_node_plugin_version=7.0.2
+gradle_node_plugin_version=7.1.0
apt_plugin_version=0.21
liquibase_plugin_version=2.1.1
modernizer_plugin_version=1.9.3
diff --git a/jest.config.js b/jest.config.js
index 41354957ab0d..9855e511a99a 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -102,10 +102,10 @@ module.exports = {
coverageThreshold: {
global: {
// TODO: in the future, the following values should increase to at least 90%
- statements: 87.35,
- branches: 73.57,
- functions: 81.91,
- lines: 87.41,
+ statements: 87.39,
+ branches: 73.60,
+ functions: 81.97,
+ lines: 87.45,
},
},
coverageReporters: ['clover', 'json', 'lcov', 'text-summary'],
diff --git a/package-lock.json b/package-lock.json
index bc1d3b7dff03..4737065d0233 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,27 +1,27 @@
{
"name": "artemis",
- "version": "7.5.6",
+ "version": "7.6.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "artemis",
- "version": "7.5.6",
+ "version": "7.6.1",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
- "@angular/animations": "18.2.6",
- "@angular/cdk": "18.2.6",
- "@angular/common": "18.2.6",
- "@angular/compiler": "18.2.6",
- "@angular/core": "18.2.6",
- "@angular/forms": "18.2.6",
- "@angular/localize": "18.2.6",
- "@angular/material": "18.2.6",
- "@angular/platform-browser": "18.2.6",
- "@angular/platform-browser-dynamic": "18.2.6",
- "@angular/router": "18.2.6",
- "@angular/service-worker": "18.2.6",
+ "@angular/animations": "18.2.8",
+ "@angular/cdk": "18.2.8",
+ "@angular/common": "18.2.8",
+ "@angular/compiler": "18.2.8",
+ "@angular/core": "18.2.8",
+ "@angular/forms": "18.2.8",
+ "@angular/localize": "18.2.8",
+ "@angular/material": "18.2.8",
+ "@angular/platform-browser": "18.2.8",
+ "@angular/platform-browser-dynamic": "18.2.8",
+ "@angular/router": "18.2.8",
+ "@angular/service-worker": "18.2.8",
"@ctrl/ngx-emoji-mart": "9.2.0",
"@danielmoncada/angular-datetime-picker": "18.1.0",
"@fingerprintjs/fingerprintjs": "4.5.0",
@@ -33,7 +33,7 @@
"@ng-bootstrap/ng-bootstrap": "17.0.1",
"@ngx-translate/core": "15.0.0",
"@ngx-translate/http-loader": "8.0.0",
- "@sentry/angular": "8.32.0",
+ "@sentry/angular": "8.34.0",
"@siemens/ngx-datatable": "22.4.1",
"@swimlane/ngx-charts": "20.5.0",
"@swimlane/ngx-graph": "8.4.0",
@@ -55,12 +55,12 @@
"jszip": "3.10.1",
"lodash-es": "4.17.21",
"mobile-drag-drop": "3.0.0-rc.0",
- "monaco-editor": "0.51.0",
+ "monaco-editor": "0.52.0",
"ngx-infinite-scroll": "18.0.0",
"ngx-webstorage": "18.0.0",
"papaparse": "5.4.1",
- "pdfjs-dist": "4.6.82",
- "posthog-js": "1.165.0",
+ "pdfjs-dist": "4.7.76",
+ "posthog-js": "1.167.0",
"rxjs": "7.8.1",
"showdown": "2.1.0",
"showdown-highlight": "3.1.0",
@@ -78,30 +78,30 @@
},
"devDependencies": {
"@angular-builders/jest": "18.0.0",
- "@angular-devkit/build-angular": "18.2.6",
+ "@angular-devkit/build-angular": "18.2.8",
"@angular-eslint/builder": "18.3.1",
"@angular-eslint/eslint-plugin": "18.3.1",
"@angular-eslint/eslint-plugin-template": "18.3.1",
"@angular-eslint/schematics": "18.3.1",
"@angular-eslint/template-parser": "18.3.1",
- "@angular/cli": "18.2.6",
- "@angular/compiler-cli": "18.2.6",
- "@angular/language-service": "18.2.6",
- "@sentry/types": "8.32.0",
+ "@angular/cli": "18.2.8",
+ "@angular/compiler-cli": "18.2.8",
+ "@angular/language-service": "18.2.8",
+ "@sentry/types": "8.34.0",
"@types/crypto-js": "4.2.2",
"@types/d3-shape": "3.1.6",
"@types/dompurify": "3.0.5",
"@types/jest": "29.5.13",
"@types/lodash-es": "4.17.12",
- "@types/node": "22.7.3",
+ "@types/node": "22.7.5",
"@types/papaparse": "5.3.14",
"@types/showdown": "2.0.6",
"@types/smoothscroll-polyfill": "0.3.4",
"@types/sockjs-client": "1.5.4",
"@types/uuid": "10.0.0",
- "@typescript-eslint/eslint-plugin": "8.7.0",
- "@typescript-eslint/parser": "8.7.0",
- "eslint": "9.11.1",
+ "@typescript-eslint/eslint-plugin": "8.8.1",
+ "@typescript-eslint/parser": "8.8.1",
+ "eslint": "9.12.0",
"eslint-config-prettier": "9.1.0",
"eslint-plugin-deprecation": "3.0.0",
"eslint-plugin-jest": "28.8.3",
@@ -113,7 +113,7 @@
"jest-canvas-mock": "2.5.2",
"jest-date-mock": "1.0.10",
"jest-extended": "4.0.2",
- "jest-fail-on-console": "3.3.0",
+ "jest-fail-on-console": "3.3.1",
"jest-junit": "16.0.0",
"jest-preset-angular": "14.2.4",
"lint-staged": "15.2.10",
@@ -121,7 +121,7 @@
"ngxtension": "4.0.0",
"prettier": "3.3.3",
"rimraf": "6.0.1",
- "sass": "1.79.3",
+ "sass": "1.79.5",
"ts-jest": "29.2.5",
"typescript": "5.5.4",
"weak-napi": "2.0.2"
@@ -212,13 +212,13 @@
}
},
"node_modules/@angular-devkit/architect": {
- "version": "0.1802.6",
- "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1802.6.tgz",
- "integrity": "sha512-oF7cPFdTLxeuvXkK/opSdIxZ1E4LrBbmuytQ/nCoAGOaKBWdqvwagRZ6jVhaI0Gwu48rkcV7Zhesg/ESNnROdw==",
+ "version": "0.1802.8",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1802.8.tgz",
+ "integrity": "sha512-/rtFQEKgS7LlB9oHr4NCBSdKnvP5kr8L5Hbd3Vl8hZOYK9QWjxKPEXnryA2d5+PCE98bBzZswCNXqELZCPTgIQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@angular-devkit/core": "18.2.6",
+ "@angular-devkit/core": "18.2.8",
"rxjs": "7.8.1"
},
"engines": {
@@ -228,17 +228,17 @@
}
},
"node_modules/@angular-devkit/build-angular": {
- "version": "18.2.6",
- "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-18.2.6.tgz",
- "integrity": "sha512-u12cJZttgs5j7gICHWSmcaTCu0EFXEzKqI8nkYCwq2MtuJlAXiMQSXYuEP9OU3Go4vMAPtQh2kShyOWCX5b4EQ==",
+ "version": "18.2.8",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-18.2.8.tgz",
+ "integrity": "sha512-qK/iLk7A8vQp1CyiJV4DpwfLjPKoiOlTtFqoO5vD8Tyxmc+R06FQp6GJTsZ7JtrTLYSiH+QAWiY6NgF/Rj/hHg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@ampproject/remapping": "2.3.0",
- "@angular-devkit/architect": "0.1802.6",
- "@angular-devkit/build-webpack": "0.1802.6",
- "@angular-devkit/core": "18.2.6",
- "@angular/build": "18.2.6",
+ "@angular-devkit/architect": "0.1802.8",
+ "@angular-devkit/build-webpack": "0.1802.8",
+ "@angular-devkit/core": "18.2.8",
+ "@angular/build": "18.2.8",
"@babel/core": "7.25.2",
"@babel/generator": "7.25.0",
"@babel/helper-annotate-as-pure": "7.24.7",
@@ -249,7 +249,7 @@
"@babel/preset-env": "7.25.3",
"@babel/runtime": "7.25.0",
"@discoveryjs/json-ext": "0.6.1",
- "@ngtools/webpack": "18.2.6",
+ "@ngtools/webpack": "18.2.8",
"@vitejs/plugin-basic-ssl": "1.1.0",
"ansi-colors": "4.1.3",
"autoprefixer": "10.4.20",
@@ -382,13 +382,13 @@
"license": "0BSD"
},
"node_modules/@angular-devkit/build-webpack": {
- "version": "0.1802.6",
- "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1802.6.tgz",
- "integrity": "sha512-JMLcXFaitJplwZMKkqhbYirINCRD6eOPZuIGaIOVynXYGWgvJkLT9t5C2wm9HqSLtp1K7NcYG2Y7PtTVR4krnQ==",
+ "version": "0.1802.8",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1802.8.tgz",
+ "integrity": "sha512-uPpopkXkO66SSdjtVr7xCyQCPs/x6KUC76xkDc4j0b8EEHifTbi/fNpbkcZ6wBmoAfjKLWXfKvtkh0TqKK5Hkw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@angular-devkit/architect": "0.1802.6",
+ "@angular-devkit/architect": "0.1802.8",
"rxjs": "7.8.1"
},
"engines": {
@@ -402,9 +402,9 @@
}
},
"node_modules/@angular-devkit/core": {
- "version": "18.2.6",
- "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.2.6.tgz",
- "integrity": "sha512-la4CFvs5PcRWSkQ/H7TB5cPZirFVA9GoWk5LzIk8si6VjWBJRm8b3keKJoC9LlNeABRUIR5z0ocYkyQQUhdMfg==",
+ "version": "18.2.8",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.2.8.tgz",
+ "integrity": "sha512-4o2T6wsmXGE/v53+F8L7kGoN2+qzt03C9rtjLVQpOljzpJVttQ8bhvfWxyYLWwcl04RWqRa+82fpIZtBkOlZJw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -430,13 +430,13 @@
}
},
"node_modules/@angular-devkit/schematics": {
- "version": "18.2.6",
- "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-18.2.6.tgz",
- "integrity": "sha512-uIttrQ2cQ2PWAFFVPeCoNR8xvs7tPJ2i8gzqsIwYdge107xDC6u9CqfgmBqPDSFpWj+IiC2Jwcm8Z4HYKU4+7A==",
+ "version": "18.2.8",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-18.2.8.tgz",
+ "integrity": "sha512-i/h2Oji5FhJMC7wDSnIl5XUe/qym+C1ZwScaATJwDyRLCUIynZkj5rLgdG/uK6l+H0PgvxigkF+akWpokkwW6w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@angular-devkit/core": "18.2.6",
+ "@angular-devkit/core": "18.2.8",
"jsonc-parser": "3.3.1",
"magic-string": "0.30.11",
"ora": "5.4.1",
@@ -549,9 +549,9 @@
}
},
"node_modules/@angular/animations": {
- "version": "18.2.6",
- "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-18.2.6.tgz",
- "integrity": "sha512-vy9wy+Q9beiRxkEO8wNxFQ63AqAujGvk8AUHepxxIT7QNNc512TNKz8uH+feWDPO38Dm2obwYQHMGzs3WO7pUA==",
+ "version": "18.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-18.2.8.tgz",
+ "integrity": "sha512-dMSn2hg70siv3lhP+vqhMbgc923xw6XBUvnpCPEzhZqFHvPXfh/LubmsD5RtqHmjWebXtgVcgS+zg3Gq3jB2lg==",
"license": "MIT",
"dependencies": {
"tslib": "^2.3.0"
@@ -560,18 +560,18 @@
"node": "^18.19.1 || ^20.11.1 || >=22.0.0"
},
"peerDependencies": {
- "@angular/core": "18.2.6"
+ "@angular/core": "18.2.8"
}
},
"node_modules/@angular/build": {
- "version": "18.2.6",
- "resolved": "https://registry.npmjs.org/@angular/build/-/build-18.2.6.tgz",
- "integrity": "sha512-TQzX6Mi7uXFvmz7+OVl4Za7WawYPcx+B5Ewm6IY/DdMyB9P/Z4tbKb1LO+ynWUXYwm7avXo6XQQ4m5ArDY5F/A==",
+ "version": "18.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/build/-/build-18.2.8.tgz",
+ "integrity": "sha512-ufuA4vHJSrL9SQW7bKV61DOoN1mm0t0ILTHaxSoCG3YF70cZJOX7+HNp3cK2uoldRMwbTOKSvCWBw54KKDRd5Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"@ampproject/remapping": "2.3.0",
- "@angular-devkit/architect": "0.1802.6",
+ "@angular-devkit/architect": "0.1802.8",
"@babel/core": "7.25.2",
"@babel/helper-annotate-as-pure": "7.24.7",
"@babel/helper-split-export-declaration": "7.24.7",
@@ -651,9 +651,9 @@
}
},
"node_modules/@angular/cdk": {
- "version": "18.2.6",
- "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-18.2.6.tgz",
- "integrity": "sha512-Gfq/iv4zhlKYpdQkDaBRwxI71NHNUHM1Cs1XhnZ0/oFct5HXvSv1RHRGTKqBJLLACaAPzZKXJ/UglLoyO5CNiQ==",
+ "version": "18.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-18.2.8.tgz",
+ "integrity": "sha512-J8A2FkwTBzLleAEWz6EgW73dEoeq87GREBPjTv8+2JV09LX+V3hnbgNk6zWq5k4OXtQNg9WrWP9QyRbUyA597g==",
"license": "MIT",
"dependencies": {
"tslib": "^2.3.0"
@@ -668,18 +668,18 @@
}
},
"node_modules/@angular/cli": {
- "version": "18.2.6",
- "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-18.2.6.tgz",
- "integrity": "sha512-tdXsnV/w+Rgu8q0zFsLU5L9ImTVqrTol1vppHaQkJ/vuoHy+s8ZEbBqhVrO/ffosNb2xseUybGYvqMS4zkNQjg==",
+ "version": "18.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-18.2.8.tgz",
+ "integrity": "sha512-GKXG7F7z5rxwZ8/bnW/Bp8/zsfE/BpHmIP/icLfUIOwv2kaY5OD2tfQssWXPEuqZzYq2AYz+wjVSbWjxGoja8A==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@angular-devkit/architect": "0.1802.6",
- "@angular-devkit/core": "18.2.6",
- "@angular-devkit/schematics": "18.2.6",
+ "@angular-devkit/architect": "0.1802.8",
+ "@angular-devkit/core": "18.2.8",
+ "@angular-devkit/schematics": "18.2.8",
"@inquirer/prompts": "5.3.8",
"@listr2/prompt-adapter-inquirer": "2.0.15",
- "@schematics/angular": "18.2.6",
+ "@schematics/angular": "18.2.8",
"@yarnpkg/lockfile": "1.1.0",
"ini": "4.1.3",
"jsonc-parser": "3.3.1",
@@ -702,9 +702,9 @@
}
},
"node_modules/@angular/common": {
- "version": "18.2.6",
- "resolved": "https://registry.npmjs.org/@angular/common/-/common-18.2.6.tgz",
- "integrity": "sha512-89793ow+wrI1c7C6kyMbnweLNIZHzXthosxAEjipRZGBrqBYjvTtkE45Fl+5yBa3JO7bAhyGkUnEoyvWtZIAEA==",
+ "version": "18.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/common/-/common-18.2.8.tgz",
+ "integrity": "sha512-TYsKtE5nVaIScWSLGSO34Skc+s3hB/BujSddnfQHoNFvPT/WR0dfmdlpVCTeLj+f50htFoMhW11tW99PbK+whQ==",
"license": "MIT",
"dependencies": {
"tslib": "^2.3.0"
@@ -713,14 +713,14 @@
"node": "^18.19.1 || ^20.11.1 || >=22.0.0"
},
"peerDependencies": {
- "@angular/core": "18.2.6",
+ "@angular/core": "18.2.8",
"rxjs": "^6.5.3 || ^7.4.0"
}
},
"node_modules/@angular/compiler": {
- "version": "18.2.6",
- "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-18.2.6.tgz",
- "integrity": "sha512-3tX2/Qw+bZ8XzKitviH8jzNGyY0uohhehhBB57OJOCc+yr4ojy/7SYFnun1lSsRnDztdCE461641X4iQLCQ94w==",
+ "version": "18.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-18.2.8.tgz",
+ "integrity": "sha512-JRedHNfK1CCPVyeGQB5w3WBYqMA6X8Q240CkvjlGfn0pVXihf9DWk3nkSQJVgYxpvpHfxdgjaYZ5IpMzlkmkhw==",
"license": "MIT",
"dependencies": {
"tslib": "^2.3.0"
@@ -729,7 +729,7 @@
"node": "^18.19.1 || ^20.11.1 || >=22.0.0"
},
"peerDependencies": {
- "@angular/core": "18.2.6"
+ "@angular/core": "18.2.8"
},
"peerDependenciesMeta": {
"@angular/core": {
@@ -738,14 +738,14 @@
}
},
"node_modules/@angular/compiler-cli": {
- "version": "18.2.6",
- "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-18.2.6.tgz",
- "integrity": "sha512-b5x9STfjNiNM/S0D+CnqRP9UOxPtSz1+RlCH5WdOMiW/p8j5p6dBix8YYgTe6Wg3OD7eItD2pnFQKgF/dWiopA==",
+ "version": "18.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-18.2.8.tgz",
+ "integrity": "sha512-OksDE4LWQUCcIvMjtZF7eiDCdIMrcMMpC1+Q0PIYi7KmnqXFGs4/Y0NdJvtn/LrQznzz5WaKM3ZDVNZTRX4wmw==",
"license": "MIT",
"dependencies": {
"@babel/core": "7.25.2",
"@jridgewell/sourcemap-codec": "^1.4.14",
- "chokidar": "^3.0.0",
+ "chokidar": "^4.0.0",
"convert-source-map": "^1.5.1",
"reflect-metadata": "^0.2.0",
"semver": "^7.0.0",
@@ -761,14 +761,42 @@
"node": "^18.19.1 || ^20.11.1 || >=22.0.0"
},
"peerDependencies": {
- "@angular/compiler": "18.2.6",
+ "@angular/compiler": "18.2.8",
"typescript": ">=5.4 <5.6"
}
},
+ "node_modules/@angular/compiler-cli/node_modules/chokidar": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz",
+ "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==",
+ "license": "MIT",
+ "dependencies": {
+ "readdirp": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 14.16.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@angular/compiler-cli/node_modules/readdirp": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz",
+ "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14.16.0"
+ },
+ "funding": {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
"node_modules/@angular/core": {
- "version": "18.2.6",
- "resolved": "https://registry.npmjs.org/@angular/core/-/core-18.2.6.tgz",
- "integrity": "sha512-PjFad2j4YBwLVTw+0Te8CJCa/tV0W8caTHG8aOjj3ObdL6ihGI+FKnwerLc9RVzDFd14BOO4C6/+LbOQAh3Ltw==",
+ "version": "18.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/core/-/core-18.2.8.tgz",
+ "integrity": "sha512-NwIuX/Iby1jT6Iv1/s6S3wOFf8xfuQR3MPGvKhGgNtjXLbHG+TXceK9+QPZC0s9/Z8JR/hz+li34B79GrIKgUg==",
"license": "MIT",
"dependencies": {
"tslib": "^2.3.0"
@@ -782,9 +810,9 @@
}
},
"node_modules/@angular/forms": {
- "version": "18.2.6",
- "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-18.2.6.tgz",
- "integrity": "sha512-quGkUqTxlBaLB8C/RnpfFG57fdmNF5RQ+368N89Ma++2lpIsVAHaGZZn4yOyo3wNYaM2jBxNqaYxOzZNUl5Tig==",
+ "version": "18.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-18.2.8.tgz",
+ "integrity": "sha512-JCLki7KC6D5vF6dE6yGlBmW33khIgpHs8N9SzuiJtkQqNDTIQA8cPsGV6qpLpxflxASynQOX5lDkWYdQyfm77Q==",
"license": "MIT",
"dependencies": {
"tslib": "^2.3.0"
@@ -793,16 +821,16 @@
"node": "^18.19.1 || ^20.11.1 || >=22.0.0"
},
"peerDependencies": {
- "@angular/common": "18.2.6",
- "@angular/core": "18.2.6",
- "@angular/platform-browser": "18.2.6",
+ "@angular/common": "18.2.8",
+ "@angular/core": "18.2.8",
+ "@angular/platform-browser": "18.2.8",
"rxjs": "^6.5.3 || ^7.4.0"
}
},
"node_modules/@angular/language-service": {
- "version": "18.2.6",
- "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-18.2.6.tgz",
- "integrity": "sha512-GBvBvS2llh+/l2YhO7UO5o3GftlvQQoXnw3v0hcNoHKwcnvqXV4CCi+T2WOaZyK0iB8Is4QRbMrpJUC66HokZg==",
+ "version": "18.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-18.2.8.tgz",
+ "integrity": "sha512-IueQ57CPP0Dt0z2n8B1A6JTwTq6m/AJVObZzrkSfXlzY1rY2qRuTJmAbZpTJ3iAxVzNYoaGh+NFHmJL8fRiXKQ==",
"dev": true,
"license": "MIT",
"engines": {
@@ -810,9 +838,9 @@
}
},
"node_modules/@angular/localize": {
- "version": "18.2.6",
- "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-18.2.6.tgz",
- "integrity": "sha512-4NZwh5EAyXItmwv6hqilV+JyN8DT+d+S1rW+M1IwJqC9asCDfpFqipKpuQF81LQKeLH0mn/phNfVbnJCLP0Tkw==",
+ "version": "18.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-18.2.8.tgz",
+ "integrity": "sha512-1T7aXEdgVyeYnHOfQUuIDO8Lsamg1ZLrJrA5zUv61asPJp6HCcMjXy9vDQ1XvHm5+CdDjKk/rczlN4lSMZ0QRw==",
"license": "MIT",
"dependencies": {
"@babel/core": "7.25.2",
@@ -829,21 +857,21 @@
"node": "^18.19.1 || ^20.11.1 || >=22.0.0"
},
"peerDependencies": {
- "@angular/compiler": "18.2.6",
- "@angular/compiler-cli": "18.2.6"
+ "@angular/compiler": "18.2.8",
+ "@angular/compiler-cli": "18.2.8"
}
},
"node_modules/@angular/material": {
- "version": "18.2.6",
- "resolved": "https://registry.npmjs.org/@angular/material/-/material-18.2.6.tgz",
- "integrity": "sha512-ObxC/vomSb9QF3vIztuiInQzws+D6u09Dhfx6uNFjtyICqxEFpF7+Qx7QVDWrsuXOgxZTKgacK8f46iV8hWUfg==",
+ "version": "18.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/material/-/material-18.2.8.tgz",
+ "integrity": "sha512-wQGMVsfQ9lQfih2VsWAvV4z3S3uBxrxc61owlE+K0T1BxH9u/jo3A/rnRitIdvR/L4NnYlfhCnmrW9K+Pl+WCg==",
"license": "MIT",
"dependencies": {
"tslib": "^2.3.0"
},
"peerDependencies": {
"@angular/animations": "^18.0.0 || ^19.0.0",
- "@angular/cdk": "18.2.6",
+ "@angular/cdk": "18.2.8",
"@angular/common": "^18.0.0 || ^19.0.0",
"@angular/core": "^18.0.0 || ^19.0.0",
"@angular/forms": "^18.0.0 || ^19.0.0",
@@ -852,9 +880,9 @@
}
},
"node_modules/@angular/platform-browser": {
- "version": "18.2.6",
- "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-18.2.6.tgz",
- "integrity": "sha512-RA8UMiYNLga+QMwpKcDw1357gYPfPyY/rmLeezMak//BbsENFYQOJ4Z6DBOBNiPlHxmBsUJMGaKdlpQhfCROyQ==",
+ "version": "18.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-18.2.8.tgz",
+ "integrity": "sha512-EPai4ZPqSq3ilLJUC85kPi9wo5j5suQovwtgRyjM/75D9Qy4TV19g8hkVM5Co/zrltO8a2G6vDscCNI5BeGw2A==",
"license": "MIT",
"dependencies": {
"tslib": "^2.3.0"
@@ -863,9 +891,9 @@
"node": "^18.19.1 || ^20.11.1 || >=22.0.0"
},
"peerDependencies": {
- "@angular/animations": "18.2.6",
- "@angular/common": "18.2.6",
- "@angular/core": "18.2.6"
+ "@angular/animations": "18.2.8",
+ "@angular/common": "18.2.8",
+ "@angular/core": "18.2.8"
},
"peerDependenciesMeta": {
"@angular/animations": {
@@ -874,9 +902,9 @@
}
},
"node_modules/@angular/platform-browser-dynamic": {
- "version": "18.2.6",
- "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-18.2.6.tgz",
- "integrity": "sha512-kGBU3FNc+DF9r33hwHZqiWoZgQbCDdEIucU0NCLCIg0Hw6/Q9Hr2ndjxQI+WynCPg0JeBn34jpouvpeJer3YDQ==",
+ "version": "18.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-18.2.8.tgz",
+ "integrity": "sha512-poZoapDqyN/rxGKQ3C6esdPiPLMkSpP2v12hoEa12KHgfPk7T1e+a+NMyJjV8HeOY3WyvL7tGRhW0NPTajTkhw==",
"license": "MIT",
"dependencies": {
"tslib": "^2.3.0"
@@ -885,16 +913,16 @@
"node": "^18.19.1 || ^20.11.1 || >=22.0.0"
},
"peerDependencies": {
- "@angular/common": "18.2.6",
- "@angular/compiler": "18.2.6",
- "@angular/core": "18.2.6",
- "@angular/platform-browser": "18.2.6"
+ "@angular/common": "18.2.8",
+ "@angular/compiler": "18.2.8",
+ "@angular/core": "18.2.8",
+ "@angular/platform-browser": "18.2.8"
}
},
"node_modules/@angular/router": {
- "version": "18.2.6",
- "resolved": "https://registry.npmjs.org/@angular/router/-/router-18.2.6.tgz",
- "integrity": "sha512-t57Sqja8unHhZlPr+4CWnQacuox2M4p2pMHps+31wt337qH6mKf4jqDmK0dE/MFdRyKjT2a2E/2NwtxXxcWNuw==",
+ "version": "18.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/router/-/router-18.2.8.tgz",
+ "integrity": "sha512-L+olYgxIiBq+tbfayVI0cv1yOuymsw33msnGC2l/vpc9sSVfqGzESFnB4yMVU3vHtE9v6v2Y6O+iV44/b79W/g==",
"license": "MIT",
"dependencies": {
"tslib": "^2.3.0"
@@ -903,16 +931,16 @@
"node": "^18.19.1 || ^20.11.1 || >=22.0.0"
},
"peerDependencies": {
- "@angular/common": "18.2.6",
- "@angular/core": "18.2.6",
- "@angular/platform-browser": "18.2.6",
+ "@angular/common": "18.2.8",
+ "@angular/core": "18.2.8",
+ "@angular/platform-browser": "18.2.8",
"rxjs": "^6.5.3 || ^7.4.0"
}
},
"node_modules/@angular/service-worker": {
- "version": "18.2.6",
- "resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-18.2.6.tgz",
- "integrity": "sha512-KNqRAunG0yj3jVA/YYKH9wbAe261gAIwKeQsJyeMHGR48H88tSKdcstttNZZ3S6wdhp7tcyUC526Fc4phXnSJw==",
+ "version": "18.2.8",
+ "resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-18.2.8.tgz",
+ "integrity": "sha512-LQktgS2Hn845ASWNyjde18V+CHkkPeCzORfh0ChYKiOmXYFtj/myEik5o/QI/G13Kaymy+vcuwQKiUuZjZiD1w==",
"license": "MIT",
"dependencies": {
"tslib": "^2.3.0"
@@ -924,17 +952,17 @@
"node": "^18.19.1 || ^20.11.1 || >=22.0.0"
},
"peerDependencies": {
- "@angular/common": "18.2.6",
- "@angular/core": "18.2.6"
+ "@angular/common": "18.2.8",
+ "@angular/core": "18.2.8"
}
},
"node_modules/@babel/code-frame": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz",
- "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.7.tgz",
+ "integrity": "sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==",
"license": "MIT",
"dependencies": {
- "@babel/highlight": "^7.24.7",
+ "@babel/highlight": "^7.25.7",
"picocolors": "^1.0.0"
},
"engines": {
@@ -942,9 +970,9 @@
}
},
"node_modules/@babel/compat-data": {
- "version": "7.25.4",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.4.tgz",
- "integrity": "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==",
+ "version": "7.25.8",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.8.tgz",
+ "integrity": "sha512-ZsysZyXY4Tlx+Q53XdnOFmqwfB9QDTHYxaZYajWRoBLuLEAwI2UIbtxOjWh/cFaa9IKUlcB+DDuoskLuKu56JA==",
"license": "MIT",
"engines": {
"node": ">=6.9.0"
@@ -1014,28 +1042,28 @@
}
},
"node_modules/@babel/helper-builder-binary-assignment-operator-visitor": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz",
- "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.25.7.tgz",
+ "integrity": "sha512-12xfNeKNH7jubQNm7PAkzlLwEmCs1tfuX3UjIw6vP6QXi+leKh6+LyC/+Ed4EIQermwd58wsyh070yjDHFlNGg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/traverse": "^7.24.7",
- "@babel/types": "^7.24.7"
+ "@babel/traverse": "^7.25.7",
+ "@babel/types": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-compilation-targets": {
- "version": "7.25.2",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz",
- "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.7.tgz",
+ "integrity": "sha512-DniTEax0sv6isaw6qSQSfV4gVRNtw2rte8HHM45t9ZR0xILaufBRNkpMifCRiAPyvL4ACD6v0gfCwCmtOQaV4A==",
"license": "MIT",
"dependencies": {
- "@babel/compat-data": "^7.25.2",
- "@babel/helper-validator-option": "^7.24.8",
- "browserslist": "^4.23.1",
+ "@babel/compat-data": "^7.25.7",
+ "@babel/helper-validator-option": "^7.25.7",
+ "browserslist": "^4.24.0",
"lru-cache": "^5.1.1",
"semver": "^6.3.1"
},
@@ -1044,18 +1072,18 @@
}
},
"node_modules/@babel/helper-create-class-features-plugin": {
- "version": "7.25.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.4.tgz",
- "integrity": "sha512-ro/bFs3/84MDgDmMwbcHgDa8/E6J3QKNTk4xJJnVeFtGE+tL0K26E3pNxhYz2b67fJpt7Aphw5XcploKXuCvCQ==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.7.tgz",
+ "integrity": "sha512-bD4WQhbkx80mAyj/WCm4ZHcF4rDxkoLFO6ph8/5/mQ3z4vAzltQXAmbc7GvVJx5H+lk5Mi5EmbTeox5nMGCsbw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-annotate-as-pure": "^7.24.7",
- "@babel/helper-member-expression-to-functions": "^7.24.8",
- "@babel/helper-optimise-call-expression": "^7.24.7",
- "@babel/helper-replace-supers": "^7.25.0",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7",
- "@babel/traverse": "^7.25.4",
+ "@babel/helper-annotate-as-pure": "^7.25.7",
+ "@babel/helper-member-expression-to-functions": "^7.25.7",
+ "@babel/helper-optimise-call-expression": "^7.25.7",
+ "@babel/helper-replace-supers": "^7.25.7",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7",
+ "@babel/traverse": "^7.25.7",
"semver": "^6.3.1"
},
"engines": {
@@ -1065,15 +1093,28 @@
"@babel/core": "^7.0.0"
}
},
+ "node_modules/@babel/helper-create-class-features-plugin/node_modules/@babel/helper-annotate-as-pure": {
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.7.tgz",
+ "integrity": "sha512-4xwU8StnqnlIhhioZf1tqnVWeQ9pvH/ujS8hRfw/WOza+/a+1qv69BWNy+oY231maTCWgKWhfBU7kDpsds6zAA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.25.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/@babel/helper-create-regexp-features-plugin": {
- "version": "7.25.2",
- "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.2.tgz",
- "integrity": "sha512-+wqVGP+DFmqwFD3EH6TMTfUNeqDehV3E/dl+Sd54eaXqm17tEUNbEIn4sVivVowbvUpOtIGxdo3GoXyDH9N/9g==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.7.tgz",
+ "integrity": "sha512-byHhumTj/X47wJ6C6eLpK7wW/WBEcnUeb7D0FNc/jFQnQVw7DOso3Zz5u9x/zLrFVkHa89ZGDbkAa1D54NdrCQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-annotate-as-pure": "^7.24.7",
- "regexpu-core": "^5.3.1",
+ "@babel/helper-annotate-as-pure": "^7.25.7",
+ "regexpu-core": "^6.1.1",
"semver": "^6.3.1"
},
"engines": {
@@ -1083,6 +1124,19 @@
"@babel/core": "^7.0.0"
}
},
+ "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/@babel/helper-annotate-as-pure": {
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.7.tgz",
+ "integrity": "sha512-4xwU8StnqnlIhhioZf1tqnVWeQ9pvH/ujS8hRfw/WOza+/a+1qv69BWNy+oY231maTCWgKWhfBU7kDpsds6zAA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.25.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/@babel/helper-define-polyfill-provider": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz",
@@ -1101,42 +1155,42 @@
}
},
"node_modules/@babel/helper-member-expression-to-functions": {
- "version": "7.24.8",
- "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz",
- "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.7.tgz",
+ "integrity": "sha512-O31Ssjd5K6lPbTX9AAYpSKrZmLeagt9uwschJd+Ixo6QiRyfpvgtVQp8qrDR9UNFjZ8+DO34ZkdrN+BnPXemeA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/traverse": "^7.24.8",
- "@babel/types": "^7.24.8"
+ "@babel/traverse": "^7.25.7",
+ "@babel/types": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-module-imports": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz",
- "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.7.tgz",
+ "integrity": "sha512-o0xCgpNmRohmnoWKQ0Ij8IdddjyBFE4T2kagL/x6M3+4zUgc+4qTOUBoNe4XxDskt1HPKO007ZPiMgLDq2s7Kw==",
"license": "MIT",
"dependencies": {
- "@babel/traverse": "^7.24.7",
- "@babel/types": "^7.24.7"
+ "@babel/traverse": "^7.25.7",
+ "@babel/types": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-module-transforms": {
- "version": "7.25.2",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz",
- "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.7.tgz",
+ "integrity": "sha512-k/6f8dKG3yDz/qCwSM+RKovjMix563SLxQFo0UhRNo239SP6n9u5/eLtKD6EAjwta2JHJ49CsD8pms2HdNiMMQ==",
"license": "MIT",
"dependencies": {
- "@babel/helper-module-imports": "^7.24.7",
- "@babel/helper-simple-access": "^7.24.7",
- "@babel/helper-validator-identifier": "^7.24.7",
- "@babel/traverse": "^7.25.2"
+ "@babel/helper-module-imports": "^7.25.7",
+ "@babel/helper-simple-access": "^7.25.7",
+ "@babel/helper-validator-identifier": "^7.25.7",
+ "@babel/traverse": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -1146,37 +1200,37 @@
}
},
"node_modules/@babel/helper-optimise-call-expression": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz",
- "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.7.tgz",
+ "integrity": "sha512-VAwcwuYhv/AT+Vfr28c9y6SHzTan1ryqrydSTFGjU0uDJHw3uZ+PduI8plCLkRsDnqK2DMEDmwrOQRsK/Ykjng==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.24.7"
+ "@babel/types": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-plugin-utils": {
- "version": "7.24.8",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz",
- "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.7.tgz",
+ "integrity": "sha512-eaPZai0PiqCi09pPs3pAFfl/zYgGaE6IdXtYvmf0qlcDTd3WCtO7JWCcRd64e0EQrcYgiHibEZnOGsSY4QSgaw==",
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-remap-async-to-generator": {
- "version": "7.25.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.0.tgz",
- "integrity": "sha512-NhavI2eWEIz/H9dbrG0TuOicDhNexze43i5z7lEqwYm0WEZVTwnPpA0EafUTP7+6/W79HWIP2cTe3Z5NiSTVpw==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.7.tgz",
+ "integrity": "sha512-kRGE89hLnPfcz6fTrlNU+uhgcwv0mBE4Gv3P9Ke9kLVJYpi4AMVVEElXvB5CabrPZW4nCM8P8UyyjrzCM0O2sw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-annotate-as-pure": "^7.24.7",
- "@babel/helper-wrap-function": "^7.25.0",
- "@babel/traverse": "^7.25.0"
+ "@babel/helper-annotate-as-pure": "^7.25.7",
+ "@babel/helper-wrap-function": "^7.25.7",
+ "@babel/traverse": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -1185,16 +1239,29 @@
"@babel/core": "^7.0.0"
}
},
+ "node_modules/@babel/helper-remap-async-to-generator/node_modules/@babel/helper-annotate-as-pure": {
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.7.tgz",
+ "integrity": "sha512-4xwU8StnqnlIhhioZf1tqnVWeQ9pvH/ujS8hRfw/WOza+/a+1qv69BWNy+oY231maTCWgKWhfBU7kDpsds6zAA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.25.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/@babel/helper-replace-supers": {
- "version": "7.25.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.0.tgz",
- "integrity": "sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.7.tgz",
+ "integrity": "sha512-iy8JhqlUW9PtZkd4pHM96v6BdJ66Ba9yWSE4z0W4TvSZwLBPkyDsiIU3ENe4SmrzRBs76F7rQXTy1lYC49n6Lw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-member-expression-to-functions": "^7.24.8",
- "@babel/helper-optimise-call-expression": "^7.24.7",
- "@babel/traverse": "^7.25.0"
+ "@babel/helper-member-expression-to-functions": "^7.25.7",
+ "@babel/helper-optimise-call-expression": "^7.25.7",
+ "@babel/traverse": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -1204,27 +1271,27 @@
}
},
"node_modules/@babel/helper-simple-access": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz",
- "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.7.tgz",
+ "integrity": "sha512-FPGAkJmyoChQeM+ruBGIDyrT2tKfZJO8NcxdC+CWNJi7N8/rZpSxK7yvBJ5O/nF1gfu5KzN7VKG3YVSLFfRSxQ==",
"license": "MIT",
"dependencies": {
- "@babel/traverse": "^7.24.7",
- "@babel/types": "^7.24.7"
+ "@babel/traverse": "^7.25.7",
+ "@babel/types": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-skip-transparent-expression-wrappers": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz",
- "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.7.tgz",
+ "integrity": "sha512-pPbNbchZBkPMD50K0p3JGcFMNLVUCuU/ABybm/PGNj4JiHrpmNyqqCphBk4i19xXtNV0JhldQJJtbSW5aUvbyA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/traverse": "^7.24.7",
- "@babel/types": "^7.24.7"
+ "@babel/traverse": "^7.25.7",
+ "@babel/types": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -1244,67 +1311,67 @@
}
},
"node_modules/@babel/helper-string-parser": {
- "version": "7.24.8",
- "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz",
- "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz",
+ "integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==",
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-identifier": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz",
- "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz",
+ "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==",
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-option": {
- "version": "7.24.8",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz",
- "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.7.tgz",
+ "integrity": "sha512-ytbPLsm+GjArDYXJ8Ydr1c/KJuutjF2besPNbIZnZ6MKUxi/uTA22t2ymmA4WFjZFpjiAMO0xuuJPqK2nvDVfQ==",
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-wrap-function": {
- "version": "7.25.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.0.tgz",
- "integrity": "sha512-s6Q1ebqutSiZnEjaofc/UKDyC4SbzV5n5SrA2Gq8UawLycr3i04f1dX4OzoQVnexm6aOCh37SQNYlJ/8Ku+PMQ==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.7.tgz",
+ "integrity": "sha512-MA0roW3JF2bD1ptAaJnvcabsVlNQShUaThyJbCDD4bCp8NEgiFvpoqRI2YS22hHlc2thjO/fTg2ShLMC3jygAg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/template": "^7.25.0",
- "@babel/traverse": "^7.25.0",
- "@babel/types": "^7.25.0"
+ "@babel/template": "^7.25.7",
+ "@babel/traverse": "^7.25.7",
+ "@babel/types": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helpers": {
- "version": "7.25.6",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.6.tgz",
- "integrity": "sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.7.tgz",
+ "integrity": "sha512-Sv6pASx7Esm38KQpF/U/OXLwPPrdGHNKoeblRxgZRLXnAtnkEe4ptJPDtAZM7fBLadbc1Q07kQpSiGQ0Jg6tRA==",
"license": "MIT",
"dependencies": {
- "@babel/template": "^7.25.0",
- "@babel/types": "^7.25.6"
+ "@babel/template": "^7.25.7",
+ "@babel/types": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/highlight": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz",
- "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.7.tgz",
+ "integrity": "sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==",
"license": "MIT",
"dependencies": {
- "@babel/helper-validator-identifier": "^7.24.7",
+ "@babel/helper-validator-identifier": "^7.25.7",
"chalk": "^2.4.2",
"js-tokens": "^4.0.0",
"picocolors": "^1.0.0"
@@ -1314,12 +1381,12 @@
}
},
"node_modules/@babel/parser": {
- "version": "7.25.6",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz",
- "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==",
+ "version": "7.25.8",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.8.tgz",
+ "integrity": "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ==",
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.25.6"
+ "@babel/types": "^7.25.8"
},
"bin": {
"parser": "bin/babel-parser.js"
@@ -1329,14 +1396,14 @@
}
},
"node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": {
- "version": "7.25.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.3.tgz",
- "integrity": "sha512-wUrcsxZg6rqBXG05HG1FPYgsP6EvwF4WpBbxIpWIIYnH8wG0gzx3yZY3dtEHas4sTAOGkbTsc9EGPxwff8lRoA==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.7.tgz",
+ "integrity": "sha512-UV9Lg53zyebzD1DwQoT9mzkEKa922LNUp5YkTJ6Uta0RbyXaQNUgcvSt7qIu1PpPzVb6rd10OVNTzkyBGeVmxQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.8",
- "@babel/traverse": "^7.25.3"
+ "@babel/helper-plugin-utils": "^7.25.7",
+ "@babel/traverse": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -1346,13 +1413,13 @@
}
},
"node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": {
- "version": "7.25.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.0.tgz",
- "integrity": "sha512-Bm4bH2qsX880b/3ziJ8KD711LT7z4u8CFudmjqle65AZj/HNUFhEf90dqYv6O86buWvSBmeQDjv0Tn2aF/bIBA==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.7.tgz",
+ "integrity": "sha512-GDDWeVLNxRIkQTnJn2pDOM1pkCgYdSqPeT1a9vh9yIqu2uzzgw1zcqEb+IJOhy+dTBMlNdThrDIksr2o09qrrQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.8"
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -1362,13 +1429,13 @@
}
},
"node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
- "version": "7.25.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.0.tgz",
- "integrity": "sha512-lXwdNZtTmeVOOFtwM/WDe7yg1PL8sYhRk/XH0FzbR2HDQ0xC+EnQ/JHeoMYSavtU115tnUk0q9CDyq8si+LMAA==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.7.tgz",
+ "integrity": "sha512-wxyWg2RYaSUYgmd9MR0FyRGyeOMQE/Uzr1wzd/g5cf5bwi9A4v6HFdDm7y1MgDtod/fLOSTZY6jDgV0xU9d5bA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.8"
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -1378,15 +1445,15 @@
}
},
"node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz",
- "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.7.tgz",
+ "integrity": "sha512-Xwg6tZpLxc4iQjorYsyGMyfJE7nP5MV8t/Ka58BgiA7Jw0fRqQNcANlLfdJ/yvBt9z9LD2We+BEkT7vLqZRWng==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.7",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7",
- "@babel/plugin-transform-optional-chaining": "^7.24.7"
+ "@babel/helper-plugin-utils": "^7.25.7",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7",
+ "@babel/plugin-transform-optional-chaining": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -1396,14 +1463,14 @@
}
},
"node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": {
- "version": "7.25.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.0.tgz",
- "integrity": "sha512-tggFrk1AIShG/RUQbEwt2Tr/E+ObkfwrPjR6BjbRvsx24+PSjK8zrq0GWPNCjo8qpRx4DuJzlcvWJqlm+0h3kw==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.7.tgz",
+ "integrity": "sha512-UVATLMidXrnH+GMUIuxq55nejlj02HP7F5ETyBONzP6G87fPBogG4CH6kxrSrdIuAjdwNO9VzyaYsrZPscWUrw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.8",
- "@babel/traverse": "^7.25.0"
+ "@babel/helper-plugin-utils": "^7.25.7",
+ "@babel/traverse": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -1507,13 +1574,13 @@
}
},
"node_modules/@babel/plugin-syntax-import-assertions": {
- "version": "7.25.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.25.6.tgz",
- "integrity": "sha512-aABl0jHw9bZ2karQ/uUD6XP4u0SG22SJrOHFoL6XB1R7dTovOP4TzTlsxOYC5yQ1pdscVK2JTUnF6QL3ARoAiQ==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.25.7.tgz",
+ "integrity": "sha512-ZvZQRmME0zfJnDQnVBKYzHxXT7lYBB3Revz1GuS7oLXWMgqUPX4G+DDbT30ICClht9WKV34QVrZhSw6WdklwZQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.8"
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -1565,12 +1632,12 @@
}
},
"node_modules/@babel/plugin-syntax-jsx": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz",
- "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.7.tgz",
+ "integrity": "sha512-ruZOnKO+ajVL/MVx+PwNBPOkrnXTXoWMtte1MBpegfCArhqOe3Bj52avVj1huLLxNKYKXYaSxZ2F+woK1ekXfw==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -1690,13 +1757,13 @@
}
},
"node_modules/@babel/plugin-syntax-typescript": {
- "version": "7.25.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.4.tgz",
- "integrity": "sha512-uMOCoHVU52BsSWxPOMVv5qKRdeSlPuImUCB2dlPuBSU+W2/ROE7/Zg8F2Kepbk+8yBa68LlRKxO+xgEVWorsDg==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.7.tgz",
+ "integrity": "sha512-rR+5FDjpCHqqZN2bzZm18bVYGaejGq5ZkpVCJLXor/+zlSrSoc4KWcHI0URVWjl/68Dyr1uwZUz/1njycEAv9g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.8"
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -1723,13 +1790,13 @@
}
},
"node_modules/@babel/plugin-transform-arrow-functions": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz",
- "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.7.tgz",
+ "integrity": "sha512-EJN2mKxDwfOUCPxMO6MUI58RN3ganiRAG/MS/S3HfB6QFNjroAMelQo/gybyYq97WerCBAZoyrAoW8Tzdq2jWg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -1776,13 +1843,13 @@
}
},
"node_modules/@babel/plugin-transform-block-scoped-functions": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz",
- "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.25.7.tgz",
+ "integrity": "sha512-xHttvIM9fvqW+0a3tZlYcZYSBpSWzGBFIt/sYG3tcdSzBB8ZeVgz2gBP7Df+sM0N1850jrviYSSeUuc+135dmQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -1792,13 +1859,13 @@
}
},
"node_modules/@babel/plugin-transform-block-scoping": {
- "version": "7.25.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.0.tgz",
- "integrity": "sha512-yBQjYoOjXlFv9nlXb3f1casSHOZkWr29NX+zChVanLg5Nc157CrbEX9D7hxxtTpuFy7Q0YzmmWfJxzvps4kXrQ==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.7.tgz",
+ "integrity": "sha512-ZEPJSkVZaeTFG/m2PARwLZQ+OG0vFIhPlKHK/JdIMy8DbRJ/htz6LRrTFtdzxi9EHmcwbNPAKDnadpNSIW+Aow==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.8"
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -1808,14 +1875,14 @@
}
},
"node_modules/@babel/plugin-transform-class-properties": {
- "version": "7.25.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.4.tgz",
- "integrity": "sha512-nZeZHyCWPfjkdU5pA/uHiTaDAFUEqkpzf1YoQT2NeSynCGYq9rxfyI3XpQbfx/a0hSnFH6TGlEXvae5Vi7GD8g==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.7.tgz",
+ "integrity": "sha512-mhyfEW4gufjIqYFo9krXHJ3ElbFLIze5IDp+wQTxoPd+mwFb1NxatNAwmv8Q8Iuxv7Zc+q8EkiMQwc9IhyGf4g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-create-class-features-plugin": "^7.25.4",
- "@babel/helper-plugin-utils": "^7.24.8"
+ "@babel/helper-create-class-features-plugin": "^7.25.7",
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -1825,15 +1892,14 @@
}
},
"node_modules/@babel/plugin-transform-class-static-block": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz",
- "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==",
+ "version": "7.25.8",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.25.8.tgz",
+ "integrity": "sha512-e82gl3TCorath6YLf9xUwFehVvjvfqFhdOo4+0iVIVju+6XOi5XHkqB3P2AXnSwoeTX0HBoXq5gJFtvotJzFnQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-create-class-features-plugin": "^7.24.7",
- "@babel/helper-plugin-utils": "^7.24.7",
- "@babel/plugin-syntax-class-static-block": "^7.14.5"
+ "@babel/helper-create-class-features-plugin": "^7.25.7",
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -1843,17 +1909,17 @@
}
},
"node_modules/@babel/plugin-transform-classes": {
- "version": "7.25.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.4.tgz",
- "integrity": "sha512-oexUfaQle2pF/b6E0dwsxQtAol9TLSO88kQvym6HHBWFliV2lGdrPieX+WgMRLSJDVzdYywk7jXbLPuO2KLTLg==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.7.tgz",
+ "integrity": "sha512-9j9rnl+YCQY0IGoeipXvnk3niWicIB6kCsWRGLwX241qSXpbA4MKxtp/EdvFxsc4zI5vqfLxzOd0twIJ7I99zg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-annotate-as-pure": "^7.24.7",
- "@babel/helper-compilation-targets": "^7.25.2",
- "@babel/helper-plugin-utils": "^7.24.8",
- "@babel/helper-replace-supers": "^7.25.0",
- "@babel/traverse": "^7.25.4",
+ "@babel/helper-annotate-as-pure": "^7.25.7",
+ "@babel/helper-compilation-targets": "^7.25.7",
+ "@babel/helper-plugin-utils": "^7.25.7",
+ "@babel/helper-replace-supers": "^7.25.7",
+ "@babel/traverse": "^7.25.7",
"globals": "^11.1.0"
},
"engines": {
@@ -1863,15 +1929,28 @@
"@babel/core": "^7.0.0-0"
}
},
+ "node_modules/@babel/plugin-transform-classes/node_modules/@babel/helper-annotate-as-pure": {
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.7.tgz",
+ "integrity": "sha512-4xwU8StnqnlIhhioZf1tqnVWeQ9pvH/ujS8hRfw/WOza+/a+1qv69BWNy+oY231maTCWgKWhfBU7kDpsds6zAA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.25.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/@babel/plugin-transform-computed-properties": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz",
- "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.7.tgz",
+ "integrity": "sha512-QIv+imtM+EtNxg/XBKL3hiWjgdLjMOmZ+XzQwSgmBfKbfxUjBzGgVPklUuE55eq5/uVoh8gg3dqlrwR/jw3ZeA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.7",
- "@babel/template": "^7.24.7"
+ "@babel/helper-plugin-utils": "^7.25.7",
+ "@babel/template": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -1881,13 +1960,13 @@
}
},
"node_modules/@babel/plugin-transform-destructuring": {
- "version": "7.24.8",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz",
- "integrity": "sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.7.tgz",
+ "integrity": "sha512-xKcfLTlJYUczdaM1+epcdh1UGewJqr9zATgrNHcLBcV2QmfvPPEixo/sK/syql9cEmbr7ulu5HMFG5vbbt/sEA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.8"
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -1897,14 +1976,14 @@
}
},
"node_modules/@babel/plugin-transform-dotall-regex": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz",
- "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.7.tgz",
+ "integrity": "sha512-kXzXMMRzAtJdDEgQBLF4oaiT6ZCU3oWHgpARnTKDAqPkDJ+bs3NrZb310YYevR5QlRo3Kn7dzzIdHbZm1VzJdQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.24.7",
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-create-regexp-features-plugin": "^7.25.7",
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -1914,13 +1993,13 @@
}
},
"node_modules/@babel/plugin-transform-duplicate-keys": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz",
- "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.7.tgz",
+ "integrity": "sha512-by+v2CjoL3aMnWDOyCIg+yxU9KXSRa9tN6MbqggH5xvymmr9p4AMjYkNlQy4brMceBnUyHZ9G8RnpvT8wP7Cfg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -1930,14 +2009,14 @@
}
},
"node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": {
- "version": "7.25.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.0.tgz",
- "integrity": "sha512-YLpb4LlYSc3sCUa35un84poXoraOiQucUTTu8X1j18JV+gNa8E0nyUf/CjZ171IRGr4jEguF+vzJU66QZhn29g==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.7.tgz",
+ "integrity": "sha512-HvS6JF66xSS5rNKXLqkk7L9c/jZ/cdIVIcoPVrnl8IsVpLggTjXs8OWekbLHs/VtYDDh5WXnQyeE3PPUGm22MA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.25.0",
- "@babel/helper-plugin-utils": "^7.24.8"
+ "@babel/helper-create-regexp-features-plugin": "^7.25.7",
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -1947,14 +2026,13 @@
}
},
"node_modules/@babel/plugin-transform-dynamic-import": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz",
- "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==",
+ "version": "7.25.8",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.8.tgz",
+ "integrity": "sha512-gznWY+mr4ZQL/EWPcbBQUP3BXS5FwZp8RUOw06BaRn8tQLzN4XLIxXejpHN9Qo8x8jjBmAAKp6FoS51AgkSA/A==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.7",
- "@babel/plugin-syntax-dynamic-import": "^7.8.3"
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -1964,14 +2042,14 @@
}
},
"node_modules/@babel/plugin-transform-exponentiation-operator": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz",
- "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.25.7.tgz",
+ "integrity": "sha512-yjqtpstPfZ0h/y40fAXRv2snciYr0OAoMXY/0ClC7tm4C/nG5NJKmIItlaYlLbIVAWNfrYuy9dq1bE0SbX0PEg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7",
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-builder-binary-assignment-operator-visitor": "^7.25.7",
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -1981,14 +2059,13 @@
}
},
"node_modules/@babel/plugin-transform-export-namespace-from": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz",
- "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==",
+ "version": "7.25.8",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.8.tgz",
+ "integrity": "sha512-sPtYrduWINTQTW7FtOy99VCTWp4H23UX7vYcut7S4CIMEXU+54zKX9uCoGkLsWXteyaMXzVHgzWbLfQ1w4GZgw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.7",
- "@babel/plugin-syntax-export-namespace-from": "^7.8.3"
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -1998,14 +2075,14 @@
}
},
"node_modules/@babel/plugin-transform-for-of": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz",
- "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.7.tgz",
+ "integrity": "sha512-n/TaiBGJxYFWvpJDfsxSj9lEEE44BFM1EPGz4KEiTipTgkoFVVcCmzAL3qA7fdQU96dpo4gGf5HBx/KnDvqiHw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.7",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7"
+ "@babel/helper-plugin-utils": "^7.25.7",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -2015,15 +2092,15 @@
}
},
"node_modules/@babel/plugin-transform-function-name": {
- "version": "7.25.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.1.tgz",
- "integrity": "sha512-TVVJVdW9RKMNgJJlLtHsKDTydjZAbwIsn6ySBPQaEAUU5+gVvlJt/9nRmqVbsV/IBanRjzWoaAQKLoamWVOUuA==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.7.tgz",
+ "integrity": "sha512-5MCTNcjCMxQ63Tdu9rxyN6cAWurqfrDZ76qvVPrGYdBxIj+EawuuxTu/+dgJlhK5eRz3v1gLwp6XwS8XaX2NiQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-compilation-targets": "^7.24.8",
- "@babel/helper-plugin-utils": "^7.24.8",
- "@babel/traverse": "^7.25.1"
+ "@babel/helper-compilation-targets": "^7.25.7",
+ "@babel/helper-plugin-utils": "^7.25.7",
+ "@babel/traverse": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -2033,14 +2110,13 @@
}
},
"node_modules/@babel/plugin-transform-json-strings": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz",
- "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==",
+ "version": "7.25.8",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.8.tgz",
+ "integrity": "sha512-4OMNv7eHTmJ2YXs3tvxAfa/I43di+VcF+M4Wt66c88EAED1RoGaf1D64cL5FkRpNL+Vx9Hds84lksWvd/wMIdA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.7",
- "@babel/plugin-syntax-json-strings": "^7.8.3"
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -2050,13 +2126,13 @@
}
},
"node_modules/@babel/plugin-transform-literals": {
- "version": "7.25.2",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.2.tgz",
- "integrity": "sha512-HQI+HcTbm9ur3Z2DkO+jgESMAMcYLuN/A7NRw9juzxAezN9AvqvUTnpKP/9kkYANz6u7dFlAyOu44ejuGySlfw==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.7.tgz",
+ "integrity": "sha512-fwzkLrSu2fESR/cm4t6vqd7ebNIopz2QHGtjoU+dswQo/P6lwAG04Q98lliE3jkz/XqnbGFLnUcE0q0CVUf92w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.8"
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -2066,14 +2142,13 @@
}
},
"node_modules/@babel/plugin-transform-logical-assignment-operators": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz",
- "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==",
+ "version": "7.25.8",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.8.tgz",
+ "integrity": "sha512-f5W0AhSbbI+yY6VakT04jmxdxz+WsID0neG7+kQZbCOjuyJNdL5Nn4WIBm4hRpKnUcO9lP0eipUhFN12JpoH8g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.7",
- "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4"
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -2083,13 +2158,13 @@
}
},
"node_modules/@babel/plugin-transform-member-expression-literals": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz",
- "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.7.tgz",
+ "integrity": "sha512-Std3kXwpXfRV0QtQy5JJcRpkqP8/wG4XL7hSKZmGlxPlDqmpXtEPRmhF7ztnlTCtUN3eXRUJp+sBEZjaIBVYaw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -2099,14 +2174,14 @@
}
},
"node_modules/@babel/plugin-transform-modules-amd": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz",
- "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.7.tgz",
+ "integrity": "sha512-CgselSGCGzjQvKzghCvDTxKHP3iooenLpJDO842ehn5D2G5fJB222ptnDwQho0WjEvg7zyoxb9P+wiYxiJX5yA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-module-transforms": "^7.24.7",
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-module-transforms": "^7.25.7",
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -2116,15 +2191,15 @@
}
},
"node_modules/@babel/plugin-transform-modules-commonjs": {
- "version": "7.24.8",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz",
- "integrity": "sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.7.tgz",
+ "integrity": "sha512-L9Gcahi0kKFYXvweO6n0wc3ZG1ChpSFdgG+eV1WYZ3/dGbJK7vvk91FgGgak8YwRgrCuihF8tE/Xg07EkL5COg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-module-transforms": "^7.24.8",
- "@babel/helper-plugin-utils": "^7.24.8",
- "@babel/helper-simple-access": "^7.24.7"
+ "@babel/helper-module-transforms": "^7.25.7",
+ "@babel/helper-plugin-utils": "^7.25.7",
+ "@babel/helper-simple-access": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -2134,16 +2209,16 @@
}
},
"node_modules/@babel/plugin-transform-modules-systemjs": {
- "version": "7.25.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.0.tgz",
- "integrity": "sha512-YPJfjQPDXxyQWg/0+jHKj1llnY5f/R6a0p/vP4lPymxLu7Lvl4k2WMitqi08yxwQcCVUUdG9LCUj4TNEgAp3Jw==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.7.tgz",
+ "integrity": "sha512-t9jZIvBmOXJsiuyOwhrIGs8dVcD6jDyg2icw1VL4A/g+FnWyJKwUfSSU2nwJuMV2Zqui856El9u+ElB+j9fV1g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-module-transforms": "^7.25.0",
- "@babel/helper-plugin-utils": "^7.24.8",
- "@babel/helper-validator-identifier": "^7.24.7",
- "@babel/traverse": "^7.25.0"
+ "@babel/helper-module-transforms": "^7.25.7",
+ "@babel/helper-plugin-utils": "^7.25.7",
+ "@babel/helper-validator-identifier": "^7.25.7",
+ "@babel/traverse": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -2153,14 +2228,14 @@
}
},
"node_modules/@babel/plugin-transform-modules-umd": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz",
- "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.7.tgz",
+ "integrity": "sha512-p88Jg6QqsaPh+EB7I9GJrIqi1Zt4ZBHUQtjw3z1bzEXcLh6GfPqzZJ6G+G1HBGKUNukT58MnKG7EN7zXQBCODw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-module-transforms": "^7.24.7",
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-module-transforms": "^7.25.7",
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -2170,14 +2245,14 @@
}
},
"node_modules/@babel/plugin-transform-named-capturing-groups-regex": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz",
- "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.7.tgz",
+ "integrity": "sha512-BtAT9LzCISKG3Dsdw5uso4oV1+v2NlVXIIomKJgQybotJY3OwCwJmkongjHgwGKoZXd0qG5UZ12JUlDQ07W6Ow==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.24.7",
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-create-regexp-features-plugin": "^7.25.7",
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -2187,13 +2262,13 @@
}
},
"node_modules/@babel/plugin-transform-new-target": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz",
- "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.7.tgz",
+ "integrity": "sha512-CfCS2jDsbcZaVYxRFo2qtavW8SpdzmBXC2LOI4oO0rP+JSRDxxF3inF4GcPsLgfb5FjkhXG5/yR/lxuRs2pySA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -2203,14 +2278,13 @@
}
},
"node_modules/@babel/plugin-transform-nullish-coalescing-operator": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz",
- "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==",
+ "version": "7.25.8",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.25.8.tgz",
+ "integrity": "sha512-Z7WJJWdQc8yCWgAmjI3hyC+5PXIubH9yRKzkl9ZEG647O9szl9zvmKLzpbItlijBnVhTUf1cpyWBsZ3+2wjWPQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.7",
- "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3"
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -2220,14 +2294,13 @@
}
},
"node_modules/@babel/plugin-transform-numeric-separator": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz",
- "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==",
+ "version": "7.25.8",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.8.tgz",
+ "integrity": "sha512-rm9a5iEFPS4iMIy+/A/PiS0QN0UyjPIeVvbU5EMZFKJZHt8vQnasbpo3T3EFcxzCeYO0BHfc4RqooCZc51J86Q==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.7",
- "@babel/plugin-syntax-numeric-separator": "^7.10.4"
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -2237,16 +2310,15 @@
}
},
"node_modules/@babel/plugin-transform-object-rest-spread": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz",
- "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==",
+ "version": "7.25.8",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.8.tgz",
+ "integrity": "sha512-LkUu0O2hnUKHKE7/zYOIjByMa4VRaV2CD/cdGz0AxU9we+VA3kDDggKEzI0Oz1IroG+6gUP6UmWEHBMWZU316g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-compilation-targets": "^7.24.7",
- "@babel/helper-plugin-utils": "^7.24.7",
- "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
- "@babel/plugin-transform-parameters": "^7.24.7"
+ "@babel/helper-compilation-targets": "^7.25.7",
+ "@babel/helper-plugin-utils": "^7.25.7",
+ "@babel/plugin-transform-parameters": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -2256,14 +2328,14 @@
}
},
"node_modules/@babel/plugin-transform-object-super": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz",
- "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.7.tgz",
+ "integrity": "sha512-pWT6UXCEW3u1t2tcAGtE15ornCBvopHj9Bps9D2DsH15APgNVOTwwczGckX+WkAvBmuoYKRCFa4DK+jM8vh5AA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.7",
- "@babel/helper-replace-supers": "^7.24.7"
+ "@babel/helper-plugin-utils": "^7.25.7",
+ "@babel/helper-replace-supers": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -2273,14 +2345,13 @@
}
},
"node_modules/@babel/plugin-transform-optional-catch-binding": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz",
- "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==",
+ "version": "7.25.8",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.8.tgz",
+ "integrity": "sha512-EbQYweoMAHOn7iJ9GgZo14ghhb9tTjgOc88xFgYngifx7Z9u580cENCV159M4xDh3q/irbhSjZVpuhpC2gKBbg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.7",
- "@babel/plugin-syntax-optional-catch-binding": "^7.8.3"
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -2290,15 +2361,14 @@
}
},
"node_modules/@babel/plugin-transform-optional-chaining": {
- "version": "7.24.8",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz",
- "integrity": "sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw==",
+ "version": "7.25.8",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.8.tgz",
+ "integrity": "sha512-q05Bk7gXOxpTHoQ8RSzGSh/LHVB9JEIkKnk3myAWwZHnYiTGYtbdrYkIsS8Xyh4ltKf7GNUSgzs/6P2bJtBAQg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.8",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7",
- "@babel/plugin-syntax-optional-chaining": "^7.8.3"
+ "@babel/helper-plugin-utils": "^7.25.7",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -2308,13 +2378,13 @@
}
},
"node_modules/@babel/plugin-transform-parameters": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz",
- "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.7.tgz",
+ "integrity": "sha512-FYiTvku63me9+1Nz7TOx4YMtW3tWXzfANZtrzHhUZrz4d47EEtMQhzFoZWESfXuAMMT5mwzD4+y1N8ONAX6lMQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -2324,14 +2394,14 @@
}
},
"node_modules/@babel/plugin-transform-private-methods": {
- "version": "7.25.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.4.tgz",
- "integrity": "sha512-ao8BG7E2b/URaUQGqN3Tlsg+M3KlHY6rJ1O1gXAEUnZoyNQnvKyH87Kfg+FoxSeyWUB8ISZZsC91C44ZuBFytw==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.7.tgz",
+ "integrity": "sha512-KY0hh2FluNxMLwOCHbxVOKfdB5sjWG4M183885FmaqWWiGMhRZq4DQRKH6mHdEucbJnyDyYiZNwNG424RymJjA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-create-class-features-plugin": "^7.25.4",
- "@babel/helper-plugin-utils": "^7.24.8"
+ "@babel/helper-create-class-features-plugin": "^7.25.7",
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -2341,16 +2411,15 @@
}
},
"node_modules/@babel/plugin-transform-private-property-in-object": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz",
- "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==",
+ "version": "7.25.8",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.8.tgz",
+ "integrity": "sha512-8Uh966svuB4V8RHHg0QJOB32QK287NBksJOByoKmHMp1TAobNniNalIkI2i5IPj5+S9NYCG4VIjbEuiSN8r+ow==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-annotate-as-pure": "^7.24.7",
- "@babel/helper-create-class-features-plugin": "^7.24.7",
- "@babel/helper-plugin-utils": "^7.24.7",
- "@babel/plugin-syntax-private-property-in-object": "^7.14.5"
+ "@babel/helper-annotate-as-pure": "^7.25.7",
+ "@babel/helper-create-class-features-plugin": "^7.25.7",
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -2359,14 +2428,27 @@
"@babel/core": "^7.0.0-0"
}
},
+ "node_modules/@babel/plugin-transform-private-property-in-object/node_modules/@babel/helper-annotate-as-pure": {
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.7.tgz",
+ "integrity": "sha512-4xwU8StnqnlIhhioZf1tqnVWeQ9pvH/ujS8hRfw/WOza+/a+1qv69BWNy+oY231maTCWgKWhfBU7kDpsds6zAA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.25.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/@babel/plugin-transform-property-literals": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz",
- "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.7.tgz",
+ "integrity": "sha512-lQEeetGKfFi0wHbt8ClQrUSUMfEeI3MMm74Z73T9/kuz990yYVtfofjf3NuA42Jy3auFOpbjDyCSiIkTs1VIYw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -2376,13 +2458,13 @@
}
},
"node_modules/@babel/plugin-transform-regenerator": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz",
- "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.7.tgz",
+ "integrity": "sha512-mgDoQCRjrY3XK95UuV60tZlFCQGXEtMg8H+IsW72ldw1ih1jZhzYXbJvghmAEpg5UVhhnCeia1CkGttUvCkiMQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.7",
+ "@babel/helper-plugin-utils": "^7.25.7",
"regenerator-transform": "^0.15.2"
},
"engines": {
@@ -2393,13 +2475,13 @@
}
},
"node_modules/@babel/plugin-transform-reserved-words": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz",
- "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.7.tgz",
+ "integrity": "sha512-3OfyfRRqiGeOvIWSagcwUTVk2hXBsr/ww7bLn6TRTuXnexA+Udov2icFOxFX9abaj4l96ooYkcNN1qi2Zvqwng==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -2430,13 +2512,13 @@
}
},
"node_modules/@babel/plugin-transform-shorthand-properties": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz",
- "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.7.tgz",
+ "integrity": "sha512-uBbxNwimHi5Bv3hUccmOFlUy3ATO6WagTApenHz9KzoIdn0XeACdB12ZJ4cjhuB2WSi80Ez2FWzJnarccriJeA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -2446,14 +2528,14 @@
}
},
"node_modules/@babel/plugin-transform-spread": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz",
- "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.7.tgz",
+ "integrity": "sha512-Mm6aeymI0PBh44xNIv/qvo8nmbkpZze1KvR8MkEqbIREDxoiWTi18Zr2jryfRMwDfVZF9foKh060fWgni44luw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.7",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7"
+ "@babel/helper-plugin-utils": "^7.25.7",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -2463,13 +2545,13 @@
}
},
"node_modules/@babel/plugin-transform-sticky-regex": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz",
- "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.7.tgz",
+ "integrity": "sha512-ZFAeNkpGuLnAQ/NCsXJ6xik7Id+tHuS+NT+ue/2+rn/31zcdnupCdmunOizEaP0JsUmTFSTOPoQY7PkK2pttXw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -2479,13 +2561,13 @@
}
},
"node_modules/@babel/plugin-transform-template-literals": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz",
- "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.25.7.tgz",
+ "integrity": "sha512-SI274k0nUsFFmyQupiO7+wKATAmMFf8iFgq2O+vVFXZ0SV9lNfT1NGzBEhjquFmD8I9sqHLguH+gZVN3vww2AA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -2495,13 +2577,13 @@
}
},
"node_modules/@babel/plugin-transform-typeof-symbol": {
- "version": "7.24.8",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz",
- "integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.25.7.tgz",
+ "integrity": "sha512-OmWmQtTHnO8RSUbL0NTdtpbZHeNTnm68Gj5pA4Y2blFNh+V4iZR68V1qL9cI37J21ZN7AaCnkfdHtLExQPf2uA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.8"
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -2511,13 +2593,13 @@
}
},
"node_modules/@babel/plugin-transform-unicode-escapes": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz",
- "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.7.tgz",
+ "integrity": "sha512-BN87D7KpbdiABA+t3HbVqHzKWUDN3dymLaTnPFAMyc8lV+KN3+YzNhVRNdinaCPA4AUqx7ubXbQ9shRjYBl3SQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -2527,14 +2609,14 @@
}
},
"node_modules/@babel/plugin-transform-unicode-property-regex": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz",
- "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.7.tgz",
+ "integrity": "sha512-IWfR89zcEPQGB/iB408uGtSPlQd3Jpq11Im86vUgcmSTcoWAiQMCTOa2K2yNNqFJEBVICKhayctee65Ka8OB0w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.24.7",
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-create-regexp-features-plugin": "^7.25.7",
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -2544,14 +2626,14 @@
}
},
"node_modules/@babel/plugin-transform-unicode-regex": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz",
- "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.7.tgz",
+ "integrity": "sha512-8JKfg/hiuA3qXnlLx8qtv5HWRbgyFx2hMMtpDDuU2rTckpKkGu4ycK5yYHwuEa16/quXfoxHBIApEsNyMWnt0g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.24.7",
- "@babel/helper-plugin-utils": "^7.24.7"
+ "@babel/helper-create-regexp-features-plugin": "^7.25.7",
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -2561,14 +2643,14 @@
}
},
"node_modules/@babel/plugin-transform-unicode-sets-regex": {
- "version": "7.25.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.4.tgz",
- "integrity": "sha512-qesBxiWkgN1Q+31xUE9RcMk79eOXXDCv6tfyGMRSs4RGlioSg2WVyQAm07k726cSE56pa+Kb0y9epX2qaXzTvA==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.7.tgz",
+ "integrity": "sha512-YRW8o9vzImwmh4Q3Rffd09bH5/hvY0pxg+1H1i0f7APoUeg12G7+HhLj9ZFNIrYkgBXhIijPJ+IXypN0hLTIbw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.25.2",
- "@babel/helper-plugin-utils": "^7.24.8"
+ "@babel/helper-create-regexp-features-plugin": "^7.25.7",
+ "@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
@@ -2690,13 +2772,6 @@
"@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0"
}
},
- "node_modules/@babel/regjsgen": {
- "version": "0.8.0",
- "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz",
- "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/@babel/runtime": {
"version": "7.25.0",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz",
@@ -2710,30 +2785,30 @@
}
},
"node_modules/@babel/template": {
- "version": "7.25.0",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz",
- "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.7.tgz",
+ "integrity": "sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==",
"license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.24.7",
- "@babel/parser": "^7.25.0",
- "@babel/types": "^7.25.0"
+ "@babel/code-frame": "^7.25.7",
+ "@babel/parser": "^7.25.7",
+ "@babel/types": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/traverse": {
- "version": "7.25.6",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.6.tgz",
- "integrity": "sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.7.tgz",
+ "integrity": "sha512-jatJPT1Zjqvh/1FyJs6qAHL+Dzb7sTb+xr7Q+gM1b+1oBsMsQQ4FkVKb6dFlJvLlVssqkRzV05Jzervt9yhnzg==",
"license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.24.7",
- "@babel/generator": "^7.25.6",
- "@babel/parser": "^7.25.6",
- "@babel/template": "^7.25.0",
- "@babel/types": "^7.25.6",
+ "@babel/code-frame": "^7.25.7",
+ "@babel/generator": "^7.25.7",
+ "@babel/parser": "^7.25.7",
+ "@babel/template": "^7.25.7",
+ "@babel/types": "^7.25.7",
"debug": "^4.3.1",
"globals": "^11.1.0"
},
@@ -2742,28 +2817,40 @@
}
},
"node_modules/@babel/traverse/node_modules/@babel/generator": {
- "version": "7.25.6",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.6.tgz",
- "integrity": "sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==",
+ "version": "7.25.7",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.7.tgz",
+ "integrity": "sha512-5Dqpl5fyV9pIAD62yK9P7fcA768uVPUyrQmqpqstHWgMma4feF1x/oFysBCVZLY5wJ2GkMUCdsNDnGZrPoR6rA==",
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.25.6",
+ "@babel/types": "^7.25.7",
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.25",
- "jsesc": "^2.5.1"
+ "jsesc": "^3.0.2"
},
"engines": {
"node": ">=6.9.0"
}
},
+ "node_modules/@babel/traverse/node_modules/jsesc": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz",
+ "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==",
+ "license": "MIT",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/@babel/types": {
- "version": "7.25.6",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz",
- "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==",
+ "version": "7.25.8",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.8.tgz",
+ "integrity": "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg==",
"license": "MIT",
"dependencies": {
- "@babel/helper-string-parser": "^7.24.8",
- "@babel/helper-validator-identifier": "^7.24.7",
+ "@babel/helper-string-parser": "^7.25.7",
+ "@babel/helper-validator-identifier": "^7.25.7",
"to-fast-properties": "^2.0.0"
},
"engines": {
@@ -2838,9 +2925,9 @@
}
},
"node_modules/@emnapi/core": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.2.0.tgz",
- "integrity": "sha512-E7Vgw78I93we4ZWdYCb4DGAwRROGkMIXk7/y87UmANR+J6qsWusmC3gLt0H+O0KOt5e6O38U8oJamgbudrES/w==",
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.3.1.tgz",
+ "integrity": "sha512-pVGjBIt1Y6gg3EJN8jTcfpP/+uuRksIo055oE/OBkDNcjZqVbfkWCksG1Jp4yZnj3iKWyWX8fdG/j6UDYPbFog==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2849,9 +2936,9 @@
}
},
"node_modules/@emnapi/runtime": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.2.0.tgz",
- "integrity": "sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ==",
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.3.1.tgz",
+ "integrity": "sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3464,9 +3551,9 @@
}
},
"node_modules/@eslint/js": {
- "version": "9.11.1",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.11.1.tgz",
- "integrity": "sha512-/qu+TWz8WwPWc7/HcIJKi+c+MOm46GdVaSlTTQcaqaL53+GsoA6MxWp5PtTx48qbSP7ylM1Kn7nhvkugfJvRSA==",
+ "version": "9.12.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.12.0.tgz",
+ "integrity": "sha512-eohesHH8WFRUprDNyEREgqP6beG6htMeUYeCpkEgBCieCMme5r9zFWjzAJp//9S+Kub4rqE+jXe9Cp1a7IYIIA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -3563,6 +3650,30 @@
"node": ">=6"
}
},
+ "node_modules/@humanfs/core": {
+ "version": "0.19.0",
+ "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.0.tgz",
+ "integrity": "sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanfs/node": {
+ "version": "0.16.5",
+ "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.5.tgz",
+ "integrity": "sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@humanfs/core": "^0.19.0",
+ "@humanwhocodes/retry": "^0.3.0"
+ },
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
"node_modules/@humanwhocodes/module-importer": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
@@ -3578,9 +3689,9 @@
}
},
"node_modules/@humanwhocodes/retry": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz",
- "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==",
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz",
+ "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==",
"dev": true,
"license": "Apache-2.0",
"engines": {
@@ -3699,9 +3810,9 @@
}
},
"node_modules/@inquirer/figures": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.6.tgz",
- "integrity": "sha512-yfZzps3Cso2UbM7WlxKwZQh2Hs6plrbjs1QnzQDZhK2DgyCo6D8AaHps9olkNcUFlcYERMqU3uJSp1gmy3s/qQ==",
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.7.tgz",
+ "integrity": "sha512-m+Trk77mp54Zma6xLkLuY+mvanPxlE4A7yNKs2HBiyZ4UkVs28Mv5c/pgWrHeInx+USHeX/WEPzjrWrcJiQgjw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -4896,9 +5007,9 @@
}
},
"node_modules/@jsonjoy.com/util": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.3.0.tgz",
- "integrity": "sha512-Cebt4Vk7k1xHy87kHY7KSPLT77A7Ev7IfOblyLZhtYEhrdQ6fX4EoLq3xOQ3O/DRMEh2ok5nyC180E+ABS8Wmw==",
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.5.0.tgz",
+ "integrity": "sha512-ojoNsrIuPI9g6o8UxhraZQSyF2ByJanAY4cTFbc8Mf2AXEF4aQRGY1dJxyJpuyav8r9FGflEt/Ff3u5Nt6YMPA==",
"dev": true,
"license": "Apache-2.0",
"engines": {
@@ -5265,9 +5376,9 @@
}
},
"node_modules/@ngtools/webpack": {
- "version": "18.2.6",
- "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-18.2.6.tgz",
- "integrity": "sha512-7HwOPE1EOgcHnpt4brSiT8G2CcXB50G0+CbCBaKGy4LYCG3Y3mrlzF5Fup9HvMJ6Tzqd62RqzpKKYBiGUT7hxg==",
+ "version": "18.2.8",
+ "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-18.2.8.tgz",
+ "integrity": "sha512-sq0kI8gEen4QlM6X8XqOYy7j4B8iLCYNo+iKxatV36ts4AXH0MuVkP56+oMaoH5oZNoSqd0RlfnotEHfvJAr8A==",
"dev": true,
"license": "MIT",
"engines": {
@@ -5597,23 +5708,23 @@
}
},
"node_modules/@nrwl/devkit": {
- "version": "19.6.5",
- "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.6.5.tgz",
- "integrity": "sha512-KaQeVyYaWBQwQSITtumPvx+P7IpKFReETx4gLTcOpQ/a3QD/AZFGbNjiG+xDLbgo1FDh9dRt9k7eWhGk6oPWKQ==",
+ "version": "19.8.4",
+ "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.8.4.tgz",
+ "integrity": "sha512-OoIqDjj2mWzLs3aSF6w5OiC2xywYi/jBxHc7t7Lyi56Vc4dQq8vJMELa9WtG6qH0k05fF7N+jAoKlfvLgbbEFA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@nx/devkit": "19.6.5"
+ "@nx/devkit": "19.8.4"
}
},
"node_modules/@nrwl/tao": {
- "version": "19.6.5",
- "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.6.5.tgz",
- "integrity": "sha512-EoUN/kE6CMWJ4ZZgcXAyiOzn8BSshG2DhC5PNwzLTAxRBus8FgXR/9c0XOzchaP46Kq3hoBGFgeyW434tfuv5w==",
+ "version": "19.8.4",
+ "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.8.4.tgz",
+ "integrity": "sha512-03/+QZ4/6HmKbEmvzCutLI1XIclBspNYtiVHmGPRWuwhnZViqYfnyl8J7RWVdFEoKKA5fhJqpg7e28aGuoMBvQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "nx": "19.6.5",
+ "nx": "19.8.4",
"tslib": "^2.3.0"
},
"bin": {
@@ -5621,13 +5732,13 @@
}
},
"node_modules/@nx/devkit": {
- "version": "19.6.5",
- "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.6.5.tgz",
- "integrity": "sha512-AEaMSr55Ar48QHU8TBi/gzLtjeT100zdyfLmk0RoiLzjjC8pWmm3Xfvqxyt1WsUUf4oQhlHlolJuoM41qKsdZw==",
+ "version": "19.8.4",
+ "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.8.4.tgz",
+ "integrity": "sha512-FPFT8gVDFRSEmU0n7nRkT4Rnqy7OMznfPXLfDZtVuzEi5Cl6ftG3UBUvCgJcJFCYJVAZAUuv6vRSRarHd51XFQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@nrwl/devkit": "19.6.5",
+ "@nrwl/devkit": "19.8.4",
"ejs": "^3.1.7",
"enquirer": "~2.3.6",
"ignore": "^5.0.4",
@@ -5668,9 +5779,9 @@
}
},
"node_modules/@nx/nx-darwin-arm64": {
- "version": "19.6.5",
- "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.6.5.tgz",
- "integrity": "sha512-sFU2k0BaklM17206F2E5C3866y0SICb0xyuPeD6D07a6hB4IstjIUkldUJJN70wEsJ5I3VP4yZ2oJcwnb1TTRQ==",
+ "version": "19.8.4",
+ "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.8.4.tgz",
+ "integrity": "sha512-mbSGt63hYcVCSQ54kpHl0lFqr5CsbkGJ4L3liWE30Da7vXZJwUBr9f+b9DnQ64IZzlu6vAhNcaiYQXa9lAk0yQ==",
"cpu": [
"arm64"
],
@@ -5685,9 +5796,9 @@
}
},
"node_modules/@nx/nx-darwin-x64": {
- "version": "19.6.5",
- "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.6.5.tgz",
- "integrity": "sha512-EJmTbUPmlksgOap6xkQl89+zXwHpaAnZLsyLHUd7i00eVRa21FRhdKFnVsRxtwPDZp/YCG84IzMUye/IrwDFTQ==",
+ "version": "19.8.4",
+ "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.8.4.tgz",
+ "integrity": "sha512-lTcXUCXNvqHdLmrNCOyDF+u6pDx209Ew7nSR47sQPvkycIHYi0gvgk0yndFn1Swah0lP4OxWg7rzAfmOlZd6ew==",
"cpu": [
"x64"
],
@@ -5702,9 +5813,9 @@
}
},
"node_modules/@nx/nx-freebsd-x64": {
- "version": "19.6.5",
- "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.6.5.tgz",
- "integrity": "sha512-rR8NJCskoEmIbK96uxaevHm146WDTA0V3jId+X1joITqjj3E2DMm0U4r5v/OgI5+iqbhFV4S83LrMxP6gBLTsQ==",
+ "version": "19.8.4",
+ "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.8.4.tgz",
+ "integrity": "sha512-4BUplOxPZeUwlUNfzHHMmebNVgDFW/jNX6TWRS+jINwOHnpWLkLFAXu27G80/S3OaniVCzEQklXO9b+1UsdgXw==",
"cpu": [
"x64"
],
@@ -5718,12 +5829,270 @@
"node": ">= 10"
}
},
- "node_modules/@nx/nx-linux-arm-gnueabihf": {
- "version": "19.6.5",
- "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.6.5.tgz",
- "integrity": "sha512-OUHFV6iLlJN7b7qFnqLfa0Yj/aoylEiRXcEhV1bhPm0Ryt1bOeGDmLYScVN8n5t+AVmrwwYHk+ajXMzCOLLeZw==",
+ "node_modules/@nx/nx-linux-arm-gnueabihf": {
+ "version": "19.8.4",
+ "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.8.4.tgz",
+ "integrity": "sha512-Wahul8oz9huEm/Jv3wud5IGWdZxkGG4tdJm9i5TV5wxfUMAWbKU9v2nzZZins452UYESWvwvDkiuBPZqSto3qw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@nx/nx-linux-arm64-gnu": {
+ "version": "19.8.4",
+ "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.8.4.tgz",
+ "integrity": "sha512-L0RVCZkNAtZDplLT7uJV7M9cXxq2Fxw+8ex3eb9XSp7eyLeFO21T0R6vTouJ42E/PEvGApCAcyGqtnyPNMZFfw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@nx/nx-linux-arm64-musl": {
+ "version": "19.8.4",
+ "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.8.4.tgz",
+ "integrity": "sha512-0q8r8I8WCsY3xowDI2j109SCUSkFns/BJ40aCfRh9hhrtaIIc5qXUw2YFTjxUZNcRJXx9j9+hTe9jBkUSIGvCw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@nx/nx-linux-x64-gnu": {
+ "version": "19.8.4",
+ "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.8.4.tgz",
+ "integrity": "sha512-XcRBNe0ws7KB0PMcUlpQqzzjjxMP8VdqirBz7CfB2XQ8xKmP3370p0cDvqs/4oKDHK4PCkmvVFX60tzakutylA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@nx/nx-linux-x64-musl": {
+ "version": "19.8.4",
+ "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.8.4.tgz",
+ "integrity": "sha512-JB4tAuZBCF0yqSnKF3pHXa0b7LA3ebi3Bw08QmMr//ON4aU+eXURGBuj9XvULD2prY+gpBrvf+MsG1XJAHL6Zg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@nx/nx-win32-arm64-msvc": {
+ "version": "19.8.4",
+ "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.8.4.tgz",
+ "integrity": "sha512-WvQag/pN9ofRWRDvOZxj3jvJoTetlvV1uyirnDrhupRgi+Fj67OlGGt2zVUHaXFGEa1MfCEG6Vhk6152m4KyaQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@nx/nx-win32-x64-msvc": {
+ "version": "19.8.4",
+ "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.8.4.tgz",
+ "integrity": "sha512-//JntLrN3L7WL/WgP3D0FE34caYTPcG/GIMBguC9w7YDyTlEikLgLbobjdCPz+2f9OWGvIZbJgGmtHNjnETM/g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@parcel/watcher": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.4.1.tgz",
+ "integrity": "sha512-HNjmfLQEVRZmHRET336f20H/8kOozUGwk7yajvsonjNxbj2wBTK1WsQuHkD5yYh9RxFGL2EyDHryOihOwUoKDA==",
+ "dev": true,
+ "license": "MIT",
+ "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.4.1",
+ "@parcel/watcher-darwin-arm64": "2.4.1",
+ "@parcel/watcher-darwin-x64": "2.4.1",
+ "@parcel/watcher-freebsd-x64": "2.4.1",
+ "@parcel/watcher-linux-arm-glibc": "2.4.1",
+ "@parcel/watcher-linux-arm64-glibc": "2.4.1",
+ "@parcel/watcher-linux-arm64-musl": "2.4.1",
+ "@parcel/watcher-linux-x64-glibc": "2.4.1",
+ "@parcel/watcher-linux-x64-musl": "2.4.1",
+ "@parcel/watcher-win32-arm64": "2.4.1",
+ "@parcel/watcher-win32-ia32": "2.4.1",
+ "@parcel/watcher-win32-x64": "2.4.1"
+ }
+ },
+ "node_modules/@parcel/watcher-android-arm64": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.4.1.tgz",
+ "integrity": "sha512-LOi/WTbbh3aTn2RYddrO8pnapixAziFl6SMxHM69r3tvdSm94JtCenaKgk1GRg5FJ5wpMCpHeW+7yqPlvZv7kg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "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.4.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.4.1.tgz",
+ "integrity": "sha512-ln41eihm5YXIY043vBrrHfn94SIBlqOWmoROhsMVTSXGh0QahKGy77tfEywQ7v3NywyxBBkGIfrWRHm0hsKtzA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "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.4.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.4.1.tgz",
+ "integrity": "sha512-yrw81BRLjjtHyDu7J61oPuSoeYWR3lDElcPGJyOvIXmor6DEo7/G2u1o7I38cwlcoBHQFULqF6nesIX3tsEXMg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "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.4.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.4.1.tgz",
+ "integrity": "sha512-TJa3Pex/gX3CWIx/Co8k+ykNdDCLx+TuZj3f3h7eOjgpdKM+Mnix37RYsYU4LHhiYJz3DK5nFCCra81p6g050w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "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.4.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.4.1.tgz",
+ "integrity": "sha512-4rVYDlsMEYfa537BRXxJ5UF4ddNwnr2/1O4MHM5PjI9cvV2qymvhwZSFgXqbS8YoTk5i/JR0L0JDs69BUn45YA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "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.4.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.4.1.tgz",
+ "integrity": "sha512-BJ7mH985OADVLpbrzCLgrJ3TOpiZggE9FMblfO65PlOCdG++xJpKUJ0Aol74ZUIYfb8WsRlUdgrZxKkz3zXWYA==",
"cpu": [
- "arm"
+ "arm64"
],
"dev": true,
"license": "MIT",
@@ -5732,13 +6101,17 @@
"linux"
],
"engines": {
- "node": ">= 10"
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
}
},
- "node_modules/@nx/nx-linux-arm64-gnu": {
- "version": "19.6.5",
- "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.6.5.tgz",
- "integrity": "sha512-CzbJfb24poaJgBHt4aKLaL8a7bO9KXCLls+TX0SZfmzA9AWX6YuiX9lhxwBv6cqsViXTDB4KnXndMDB/H0Gk4g==",
+ "node_modules/@parcel/watcher-linux-arm64-musl": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.4.1.tgz",
+ "integrity": "sha512-p4Xb7JGq3MLgAfYhslU2SjoV9G0kI0Xry0kuxeG/41UfpjHGOhv7UoUDAz/jb1u2elbhazy4rRBL8PegPJFBhA==",
"cpu": [
"arm64"
],
@@ -5749,15 +6122,19 @@
"linux"
],
"engines": {
- "node": ">= 10"
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
}
},
- "node_modules/@nx/nx-linux-arm64-musl": {
- "version": "19.6.5",
- "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.6.5.tgz",
- "integrity": "sha512-MgidKilQ0KWxQbTnaqXGjASu7wtAC9q6zAwFNKFENkwJq3nThaQH6jQVlnINE4lL9NSgyyg0AS/ix31hiqAgvA==",
+ "node_modules/@parcel/watcher-linux-x64-glibc": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.4.1.tgz",
+ "integrity": "sha512-s9O3fByZ/2pyYDPoLM6zt92yu6P4E39a03zvO0qCHOTjxmt3GHRMLuRZEWhWLASTMSrrnVNWdVI/+pUElJBBBg==",
"cpu": [
- "arm64"
+ "x64"
],
"dev": true,
"license": "MIT",
@@ -5766,13 +6143,17 @@
"linux"
],
"engines": {
- "node": ">= 10"
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
}
},
- "node_modules/@nx/nx-linux-x64-gnu": {
- "version": "19.6.5",
- "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.6.5.tgz",
- "integrity": "sha512-rGDylAoslIlk5TDbEJ6YoQOYxxYP9gCpi6FLke2mFgXVzOmVlLKHfVsegIHYVMYYF26h3NJh0NLGGzGdoBjWgQ==",
+ "node_modules/@parcel/watcher-linux-x64-musl": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.4.1.tgz",
+ "integrity": "sha512-L2nZTYR1myLNST0O632g0Dx9LyMNHrn6TOt76sYxWLdff3cB22/GZX2UPtJnaqQPdCRoszoY5rcOj4oMTtp5fQ==",
"cpu": [
"x64"
],
@@ -5783,32 +6164,40 @@
"linux"
],
"engines": {
- "node": ">= 10"
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
}
},
- "node_modules/@nx/nx-linux-x64-musl": {
- "version": "19.6.5",
- "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.6.5.tgz",
- "integrity": "sha512-C/pNjDL/bDEcrDypgBo4r1AOiPTk8gWJwBsFE1QHIvg7//5WFSreqRj34rJu/GZ95eLYJH5tje1VW6z+atEGkQ==",
+ "node_modules/@parcel/watcher-win32-arm64": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.4.1.tgz",
+ "integrity": "sha512-Uq2BPp5GWhrq/lcuItCHoqxjULU1QYEcyjSO5jqqOK8RNFDBQnenMMx4gAl3v8GiWa59E9+uDM7yZ6LxwUIfRg==",
"cpu": [
- "x64"
+ "arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
- "linux"
+ "win32"
],
"engines": {
- "node": ">= 10"
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
}
},
- "node_modules/@nx/nx-win32-arm64-msvc": {
- "version": "19.6.5",
- "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.6.5.tgz",
- "integrity": "sha512-mMi8i16OFux17xed2iLPWwUdCbS1mYA9Ny/gnoNUCosmihmXX9wrzaGBkNAMsHA28huYQtPhGormsEs+zuiVFg==",
+ "node_modules/@parcel/watcher-win32-ia32": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.4.1.tgz",
+ "integrity": "sha512-maNRit5QQV2kgHFSYwftmPBxiuK5u4DXjbXx7q6eKjq5dsLXZ4FJiVvlcw35QXzk0KrUecJmuVFbj4uV9oYrcw==",
"cpu": [
- "arm64"
+ "ia32"
],
"dev": true,
"license": "MIT",
@@ -5817,13 +6206,17 @@
"win32"
],
"engines": {
- "node": ">= 10"
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
}
},
- "node_modules/@nx/nx-win32-x64-msvc": {
- "version": "19.6.5",
- "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.6.5.tgz",
- "integrity": "sha512-jjhbDYNBkyz9Fg1jf0KZTrgdf/yx4v+k0ifukDIHZjva+jko0Ve5WzdkQ2K07M9ZxxYibDtTDqX9uX6+eFZtoA==",
+ "node_modules/@parcel/watcher-win32-x64": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.4.1.tgz",
+ "integrity": "sha512-+DvS92F9ezicfswqrvIRM2njcYJbd5mb9CUgtrHCHmvn7pPPa+nMDRu1o1bYYz/l5IB2NVGNJWiH7h1E58IF2A==",
"cpu": [
"x64"
],
@@ -5834,9 +6227,33 @@
"win32"
],
"engines": {
- "node": ">= 10"
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher/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==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "detect-libc": "bin/detect-libc.js"
+ },
+ "engines": {
+ "node": ">=0.10"
}
},
+ "node_modules/@parcel/watcher/node_modules/node-addon-api": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
+ "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@pkgjs/parseargs": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
@@ -6153,14 +6570,14 @@
]
},
"node_modules/@schematics/angular": {
- "version": "18.2.6",
- "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-18.2.6.tgz",
- "integrity": "sha512-Y988EoOEQDLEyHu3414T6AeVUyx21AexBHQNbUNQkK8cxlxyB6m1eH1cx6vFgLRFUTsLVv+C6Ln/ICNTfLcG4A==",
+ "version": "18.2.8",
+ "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-18.2.8.tgz",
+ "integrity": "sha512-62Sr7/j/dlhZorxH4GzQgpJy0s162BVts0Q7knZuEacP4VL+IWOUE1NS9OFkh/cbomoyXBdoewkZ5Zd1dVX78w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@angular-devkit/core": "18.2.6",
- "@angular-devkit/schematics": "18.2.6",
+ "@angular-devkit/core": "18.2.8",
+ "@angular-devkit/schematics": "18.2.8",
"jsonc-parser": "3.3.1"
},
"engines": {
@@ -6170,73 +6587,73 @@
}
},
"node_modules/@sentry-internal/browser-utils": {
- "version": "8.32.0",
- "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.32.0.tgz",
- "integrity": "sha512-DpUGhk5O1OVjT0fo9wsbEdO1R/S9gGBRDtn9+FFVeRtieJHwXpeZiLK+tZhTOvaILmtSoTPUEY3L5sK4j5Xq9g==",
+ "version": "8.34.0",
+ "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.34.0.tgz",
+ "integrity": "sha512-4AcYOzPzD1tL5eSRQ/GpKv5enquZf4dMVUez99/Bh3va8qiJrNP55AcM7UzZ7WZLTqKygIYruJTU5Zu2SpEAPQ==",
"license": "MIT",
"dependencies": {
- "@sentry/core": "8.32.0",
- "@sentry/types": "8.32.0",
- "@sentry/utils": "8.32.0"
+ "@sentry/core": "8.34.0",
+ "@sentry/types": "8.34.0",
+ "@sentry/utils": "8.34.0"
},
"engines": {
"node": ">=14.18"
}
},
"node_modules/@sentry-internal/feedback": {
- "version": "8.32.0",
- "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.32.0.tgz",
- "integrity": "sha512-XB7hiVJQW1tNzpoXIHbvm3rjipIt7PZiJJtFg2vxaqu/FzdgOcYqQiwIKivJVAKuRZ9rIeJtK1jdXQFOc/TRJA==",
+ "version": "8.34.0",
+ "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.34.0.tgz",
+ "integrity": "sha512-aYSM2KPUs0FLPxxbJCFSwCYG70VMzlT04xepD1Y/tTlPPOja/02tSv2tyOdZbv8Uw7xslZs3/8Lhj74oYcTBxw==",
"license": "MIT",
"dependencies": {
- "@sentry/core": "8.32.0",
- "@sentry/types": "8.32.0",
- "@sentry/utils": "8.32.0"
+ "@sentry/core": "8.34.0",
+ "@sentry/types": "8.34.0",
+ "@sentry/utils": "8.34.0"
},
"engines": {
"node": ">=14.18"
}
},
"node_modules/@sentry-internal/replay": {
- "version": "8.32.0",
- "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.32.0.tgz",
- "integrity": "sha512-yiEUnn2yyo1AIQIFNeRX3tdK8fmyKIkxdFS1WiVQmeYI/hFwYBTZPly0FcO/g3xnRMSA2tvrS+hZEaaXfK4WhA==",
+ "version": "8.34.0",
+ "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.34.0.tgz",
+ "integrity": "sha512-EoMh9NYljNewZK1quY23YILgtNdGgrkzJ9TPsj6jXUG0LZ0Q7N7eFWd0xOEDBvFxrmI3cSXF1i4d1sBb+eyKRw==",
"license": "MIT",
"dependencies": {
- "@sentry-internal/browser-utils": "8.32.0",
- "@sentry/core": "8.32.0",
- "@sentry/types": "8.32.0",
- "@sentry/utils": "8.32.0"
+ "@sentry-internal/browser-utils": "8.34.0",
+ "@sentry/core": "8.34.0",
+ "@sentry/types": "8.34.0",
+ "@sentry/utils": "8.34.0"
},
"engines": {
"node": ">=14.18"
}
},
"node_modules/@sentry-internal/replay-canvas": {
- "version": "8.32.0",
- "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.32.0.tgz",
- "integrity": "sha512-oBbhtDBkD+5z/T0NVJ5VenBWAid/S9QdVrod/UqxVqU7F8N+E9/INFQI48zCWr4iVlUMcszJPDElvJEsMDvvBQ==",
+ "version": "8.34.0",
+ "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.34.0.tgz",
+ "integrity": "sha512-x8KhZcCDpbKHqFOykYXiamX6x0LRxv6N1OJHoH+XCrMtiDBZr4Yo30d/MaS6rjmKGMtSRij30v+Uq+YWIgxUrg==",
"license": "MIT",
"dependencies": {
- "@sentry-internal/replay": "8.32.0",
- "@sentry/core": "8.32.0",
- "@sentry/types": "8.32.0",
- "@sentry/utils": "8.32.0"
+ "@sentry-internal/replay": "8.34.0",
+ "@sentry/core": "8.34.0",
+ "@sentry/types": "8.34.0",
+ "@sentry/utils": "8.34.0"
},
"engines": {
"node": ">=14.18"
}
},
"node_modules/@sentry/angular": {
- "version": "8.32.0",
- "resolved": "https://registry.npmjs.org/@sentry/angular/-/angular-8.32.0.tgz",
- "integrity": "sha512-HgdpLFTdAMgTG4yz6mb9umg+yGlCkuRDqC4Wv1zNW7ARoSioavyz4kMRkKqJR6hxgGh2vPoXCz6E+w8L4k9oPg==",
+ "version": "8.34.0",
+ "resolved": "https://registry.npmjs.org/@sentry/angular/-/angular-8.34.0.tgz",
+ "integrity": "sha512-FjBN5s+SFzTFHQh5DqWUGUp19p3V7p86I7Dq1a7MBCzmQukGM1bcW8+n6wLj6CxlEoyLCPPZpTIXIO4ulheIwg==",
"license": "MIT",
"dependencies": {
- "@sentry/browser": "8.32.0",
- "@sentry/core": "8.32.0",
- "@sentry/types": "8.32.0",
- "@sentry/utils": "8.32.0",
+ "@sentry/browser": "8.34.0",
+ "@sentry/core": "8.34.0",
+ "@sentry/types": "8.34.0",
+ "@sentry/utils": "8.34.0",
"tslib": "^2.4.1"
},
"engines": {
@@ -6250,52 +6667,52 @@
}
},
"node_modules/@sentry/browser": {
- "version": "8.32.0",
- "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.32.0.tgz",
- "integrity": "sha512-AEKFj64g4iYwEMRvVcxiY0FswmClRXCP1IEvCqujn8OBS8AjMOr1z/RwYieEs0D90yNNB3YEqF8adrKENblJmw==",
+ "version": "8.34.0",
+ "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.34.0.tgz",
+ "integrity": "sha512-3HHG2NXxzHq1lVmDy2uRjYjGNf9NsJsTPlOC70vbQdOb+S49EdH/XMPy+J3ruIoyv6Cu0LwvA6bMOM6rHZOgNQ==",
"license": "MIT",
"dependencies": {
- "@sentry-internal/browser-utils": "8.32.0",
- "@sentry-internal/feedback": "8.32.0",
- "@sentry-internal/replay": "8.32.0",
- "@sentry-internal/replay-canvas": "8.32.0",
- "@sentry/core": "8.32.0",
- "@sentry/types": "8.32.0",
- "@sentry/utils": "8.32.0"
+ "@sentry-internal/browser-utils": "8.34.0",
+ "@sentry-internal/feedback": "8.34.0",
+ "@sentry-internal/replay": "8.34.0",
+ "@sentry-internal/replay-canvas": "8.34.0",
+ "@sentry/core": "8.34.0",
+ "@sentry/types": "8.34.0",
+ "@sentry/utils": "8.34.0"
},
"engines": {
"node": ">=14.18"
}
},
"node_modules/@sentry/core": {
- "version": "8.32.0",
- "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.32.0.tgz",
- "integrity": "sha512-+xidTr0lZ0c755tq4k75dXPEb8PA+qvIefW3U9+dQMORLokBrYoKYMf5zZTG2k/OfSJS6OSxatUj36NFuCs3aA==",
+ "version": "8.34.0",
+ "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.34.0.tgz",
+ "integrity": "sha512-adrXCTK/zsg5pJ67lgtZqdqHvyx6etMjQW3P82NgWdj83c8fb+zH+K79Z47pD4zQjX0ou2Ws5nwwi4wJbz4bfA==",
"license": "MIT",
"dependencies": {
- "@sentry/types": "8.32.0",
- "@sentry/utils": "8.32.0"
+ "@sentry/types": "8.34.0",
+ "@sentry/utils": "8.34.0"
},
"engines": {
"node": ">=14.18"
}
},
"node_modules/@sentry/types": {
- "version": "8.32.0",
- "resolved": "https://registry.npmjs.org/@sentry/types/-/types-8.32.0.tgz",
- "integrity": "sha512-hxckvN2MzS5SgGDgVQ0/QpZXk13Vrq4BtZLwXhPhyeTmZtUiUfWvcL5TFQqLinfKdTKPe9q2MxeAJ0D4LalhMg==",
+ "version": "8.34.0",
+ "resolved": "https://registry.npmjs.org/@sentry/types/-/types-8.34.0.tgz",
+ "integrity": "sha512-zLRc60CzohGCo6zNsNeQ9JF3SiEeRE4aDCP9fDDdIVCOKovS+mn1rtSip0qd0Vp2fidOu0+2yY0ALCz1A3PJSQ==",
"license": "MIT",
"engines": {
"node": ">=14.18"
}
},
"node_modules/@sentry/utils": {
- "version": "8.32.0",
- "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-8.32.0.tgz",
- "integrity": "sha512-t1WVERhgmYURxbBj9J4/H2P2X+VKqm7B3ce9iQyrZbdf5NekhcU4jHIecPUWCPHjQkFIqkVTorqeBmDTlg/UmQ==",
+ "version": "8.34.0",
+ "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-8.34.0.tgz",
+ "integrity": "sha512-W1KoRlFUjprlh3t86DZPFxLfM6mzjRzshVfMY7vRlJFymBelJsnJ3A1lPeBZM9nCraOSiw6GtOWu6k5BAkiGIg==",
"license": "MIT",
"dependencies": {
- "@sentry/types": "8.32.0"
+ "@sentry/types": "8.34.0"
},
"engines": {
"node": ">=14.18"
@@ -6909,9 +7326,9 @@
"license": "MIT"
},
"node_modules/@types/lodash": {
- "version": "4.17.9",
- "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.9.tgz",
- "integrity": "sha512-w9iWudx1XWOHW5lQRS9iKpK/XuRhnN+0T7HvdCCd802FYkT1AMTnxndJHGrNJwRoRHkslGr4S29tjm1cT7x/7w==",
+ "version": "4.17.10",
+ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.10.tgz",
+ "integrity": "sha512-YpS0zzoduEhuOWjAotS6A5AVCva7X4lVlYLF0FYHAY9sdraBfnatttHItlWeZdGhuEkf+OzMNg2ZYAx8t+52uQ==",
"dev": true,
"license": "MIT"
},
@@ -6943,9 +7360,9 @@
}
},
"node_modules/@types/node": {
- "version": "22.7.3",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.3.tgz",
- "integrity": "sha512-qXKfhXXqGTyBskvWEzJZPUxSslAiLaB6JGP1ic/XTH9ctGgzdgYguuLP1C601aRTSDNlLb0jbKqXjZ48GNraSA==",
+ "version": "22.7.5",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz",
+ "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -6993,9 +7410,9 @@
"license": "MIT"
},
"node_modules/@types/react": {
- "version": "18.3.9",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.9.tgz",
- "integrity": "sha512-+BpAVyTpJkNWWSSnaLBk6ePpHLOGJKnEQNbINNovPWzvEUyAe3e+/d494QdEh71RekM/qV7lw6jzf1HGrJyAtQ==",
+ "version": "18.3.11",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.11.tgz",
+ "integrity": "sha512-r6QZ069rFTjrEYgFdOck1gK7FLVsgJE7tTz0pQBczlBNUhBNk0MQH4UbnFSwjpQLMkLzgqvBBa+qGpLje16eTQ==",
"license": "MIT",
"dependencies": {
"@types/prop-types": "*",
@@ -7149,17 +7566,17 @@
"license": "MIT"
},
"node_modules/@typescript-eslint/eslint-plugin": {
- "version": "8.7.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.7.0.tgz",
- "integrity": "sha512-RIHOoznhA3CCfSTFiB6kBGLQtB/sox+pJ6jeFu6FxJvqL8qRxq/FfGO/UhsGgQM9oGdXkV4xUgli+dt26biB6A==",
+ "version": "8.8.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.1.tgz",
+ "integrity": "sha512-xfvdgA8AP/vxHgtgU310+WBnLB4uJQ9XdyP17RebG26rLtDrQJV3ZYrcopX91GrHmMoH8bdSwMRh2a//TiJ1jQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.10.0",
- "@typescript-eslint/scope-manager": "8.7.0",
- "@typescript-eslint/type-utils": "8.7.0",
- "@typescript-eslint/utils": "8.7.0",
- "@typescript-eslint/visitor-keys": "8.7.0",
+ "@typescript-eslint/scope-manager": "8.8.1",
+ "@typescript-eslint/type-utils": "8.8.1",
+ "@typescript-eslint/utils": "8.8.1",
+ "@typescript-eslint/visitor-keys": "8.8.1",
"graphemer": "^1.4.0",
"ignore": "^5.3.1",
"natural-compare": "^1.4.0",
@@ -7183,16 +7600,16 @@
}
},
"node_modules/@typescript-eslint/parser": {
- "version": "8.7.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.7.0.tgz",
- "integrity": "sha512-lN0btVpj2unxHlNYLI//BQ7nzbMJYBVQX5+pbNXvGYazdlgYonMn4AhhHifQ+J4fGRYA/m1DjaQjx+fDetqBOQ==",
+ "version": "8.8.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.8.1.tgz",
+ "integrity": "sha512-hQUVn2Lij2NAxVFEdvIGxT9gP1tq2yM83m+by3whWFsWC+1y8pxxxHUFE1UqDu2VsGi2i6RLcv4QvouM84U+ow==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
- "@typescript-eslint/scope-manager": "8.7.0",
- "@typescript-eslint/types": "8.7.0",
- "@typescript-eslint/typescript-estree": "8.7.0",
- "@typescript-eslint/visitor-keys": "8.7.0",
+ "@typescript-eslint/scope-manager": "8.8.1",
+ "@typescript-eslint/types": "8.8.1",
+ "@typescript-eslint/typescript-estree": "8.8.1",
+ "@typescript-eslint/visitor-keys": "8.8.1",
"debug": "^4.3.4"
},
"engines": {
@@ -7212,14 +7629,14 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
- "version": "8.7.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.7.0.tgz",
- "integrity": "sha512-87rC0k3ZlDOuz82zzXRtQ7Akv3GKhHs0ti4YcbAJtaomllXoSO8hi7Ix3ccEvCd824dy9aIX+j3d2UMAfCtVpg==",
+ "version": "8.8.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.8.1.tgz",
+ "integrity": "sha512-X4JdU+66Mazev/J0gfXlcC/dV6JI37h+93W9BRYXrSn0hrE64IoWgVkO9MSJgEzoWkxONgaQpICWg8vAN74wlA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.7.0",
- "@typescript-eslint/visitor-keys": "8.7.0"
+ "@typescript-eslint/types": "8.8.1",
+ "@typescript-eslint/visitor-keys": "8.8.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -7230,14 +7647,14 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
- "version": "8.7.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.7.0.tgz",
- "integrity": "sha512-tl0N0Mj3hMSkEYhLkjREp54OSb/FI6qyCzfiiclvJvOqre6hsZTGSnHtmFLDU8TIM62G7ygEa1bI08lcuRwEnQ==",
+ "version": "8.8.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.8.1.tgz",
+ "integrity": "sha512-qSVnpcbLP8CALORf0za+vjLYj1Wp8HSoiI8zYU5tHxRVj30702Z1Yw4cLwfNKhTPWp5+P+k1pjmD5Zd1nhxiZA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/typescript-estree": "8.7.0",
- "@typescript-eslint/utils": "8.7.0",
+ "@typescript-eslint/typescript-estree": "8.8.1",
+ "@typescript-eslint/utils": "8.8.1",
"debug": "^4.3.4",
"ts-api-utils": "^1.3.0"
},
@@ -7255,9 +7672,9 @@
}
},
"node_modules/@typescript-eslint/types": {
- "version": "8.7.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.7.0.tgz",
- "integrity": "sha512-LLt4BLHFwSfASHSF2K29SZ+ZCsbQOM+LuarPjRUuHm+Qd09hSe3GCeaQbcCr+Mik+0QFRmep/FyZBO6fJ64U3w==",
+ "version": "8.8.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.8.1.tgz",
+ "integrity": "sha512-WCcTP4SDXzMd23N27u66zTKMuEevH4uzU8C9jf0RO4E04yVHgQgW+r+TeVTNnO1KIfrL8ebgVVYYMMO3+jC55Q==",
"dev": true,
"license": "MIT",
"engines": {
@@ -7269,14 +7686,14 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
- "version": "8.7.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.7.0.tgz",
- "integrity": "sha512-MC8nmcGHsmfAKxwnluTQpNqceniT8SteVwd2voYlmiSWGOtjvGXdPl17dYu2797GVscK30Z04WRM28CrKS9WOg==",
+ "version": "8.8.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.8.1.tgz",
+ "integrity": "sha512-A5d1R9p+X+1js4JogdNilDuuq+EHZdsH9MjTVxXOdVFfTJXunKJR/v+fNNyO4TnoOn5HqobzfRlc70NC6HTcdg==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
- "@typescript-eslint/types": "8.7.0",
- "@typescript-eslint/visitor-keys": "8.7.0",
+ "@typescript-eslint/types": "8.8.1",
+ "@typescript-eslint/visitor-keys": "8.8.1",
"debug": "^4.3.4",
"fast-glob": "^3.3.2",
"is-glob": "^4.0.3",
@@ -7298,16 +7715,16 @@
}
},
"node_modules/@typescript-eslint/utils": {
- "version": "8.7.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.7.0.tgz",
- "integrity": "sha512-ZbdUdwsl2X/s3CiyAu3gOlfQzpbuG3nTWKPoIvAu1pu5r8viiJvv2NPN2AqArL35NCYtw/lrPPfM4gxrMLNLPw==",
+ "version": "8.8.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.8.1.tgz",
+ "integrity": "sha512-/QkNJDbV0bdL7H7d0/y0qBbV2HTtf0TIyjSDTvvmQEzeVx8jEImEbLuOA4EsvE8gIgqMitns0ifb5uQhMj8d9w==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
- "@typescript-eslint/scope-manager": "8.7.0",
- "@typescript-eslint/types": "8.7.0",
- "@typescript-eslint/typescript-estree": "8.7.0"
+ "@typescript-eslint/scope-manager": "8.8.1",
+ "@typescript-eslint/types": "8.8.1",
+ "@typescript-eslint/typescript-estree": "8.8.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -7321,13 +7738,13 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
- "version": "8.7.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.7.0.tgz",
- "integrity": "sha512-b1tx0orFCCh/THWPQa2ZwWzvOeyzzp36vkJYOpVg0u8UVOIsfVrnuC9FqAw9gRKn+rG2VmWQ/zDJZzkxUnj/XQ==",
+ "version": "8.8.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.8.1.tgz",
+ "integrity": "sha512-0/TdC3aeRAsW7MDvYRwEc1Uwm0TIBfzjPFgg60UU2Haj5qsCs9cc3zNgY71edqE3LbWfF/WoZQd3lJoDXFQpag==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.7.0",
+ "@typescript-eslint/types": "8.8.1",
"eslint-visitor-keys": "^3.4.3"
},
"engines": {
@@ -7835,6 +8252,7 @@
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dev": true,
"license": "ISC",
"dependencies": {
"normalize-path": "^3.0.0",
@@ -7848,6 +8266,7 @@
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=8.6"
@@ -8347,6 +8766,7 @@
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
"integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -8691,9 +9111,9 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001664",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001664.tgz",
- "integrity": "sha512-AmE7k4dXiNKQipgn7a2xg558IRqPN3jMQY/rOsbxDhrd0tyChwbITBfiwtnqz8bi2M5mIWbxAYBvk7W7QBUS2g==",
+ "version": "1.0.30001668",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001668.tgz",
+ "integrity": "sha512-nWLrdxqCdblixUO+27JtGJJE/txpJlyUy5YN1u53wLZkP0emYCo5zgS6QYft7VUYR42LGgi/S5hdLZTrnyIddw==",
"funding": [
{
"type": "opencollective",
@@ -8761,6 +9181,7 @@
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"anymatch": "~3.1.2",
@@ -8781,6 +9202,19 @@
"fsevents": "~2.3.2"
}
},
+ "node_modules/chokidar/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/chownr": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
@@ -8851,9 +9285,9 @@
}
},
"node_modules/cli-spinners": {
- "version": "2.9.2",
- "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz",
- "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==",
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz",
+ "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==",
"dev": true,
"license": "MIT",
"engines": {
@@ -9020,9 +9454,9 @@
}
},
"node_modules/code-block-writer": {
- "version": "13.0.2",
- "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-13.0.2.tgz",
- "integrity": "sha512-XfXzAGiStXSmCIwrkdfvc7FS5Dtj8yelCtyOf2p2skCAfvLd6zu0rGzuS9NSCO3bq1JKpFZ7tbKdKlcd5occQA==",
+ "version": "13.0.3",
+ "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-13.0.3.tgz",
+ "integrity": "sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==",
"dev": true,
"license": "MIT"
},
@@ -9218,9 +9652,9 @@
"license": "MIT"
},
"node_modules/cookie": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
- "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz",
+ "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==",
"dev": true,
"license": "MIT",
"engines": {
@@ -9272,19 +9706,6 @@
"webpack": "^5.1.0"
}
},
- "node_modules/copy-webpack-plugin/node_modules/glob-parent": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
- "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "is-glob": "^4.0.3"
- },
- "engines": {
- "node": ">=10.13.0"
- }
- },
"node_modules/core-js": {
"version": "3.38.1",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.38.1.tgz",
@@ -10090,19 +10511,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/default-gateway": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz",
- "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==",
- "dev": true,
- "license": "BSD-2-Clause",
- "dependencies": {
- "execa": "^5.0.0"
- },
- "engines": {
- "node": ">= 10"
- }
- },
"node_modules/defaults": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
@@ -10416,9 +10824,9 @@
}
},
"node_modules/electron-to-chromium": {
- "version": "1.5.29",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.29.tgz",
- "integrity": "sha512-PF8n2AlIhCKXQ+gTpiJi0VhcHDb69kYX4MtCiivctc2QD3XuNZ/XIOlbGzt7WAjjEev0TtaH6Cu3arZExm5DOw==",
+ "version": "1.5.36",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.36.tgz",
+ "integrity": "sha512-HYTX8tKge/VNp6FGO+f/uVDmUkq+cEfcxYhKf15Akc4M5yxt5YmorwlAitKWjWhWQnKcDRBAQKXkhqqXMqcrjw==",
"license": "ISC"
},
"node_modules/emittery": {
@@ -10699,9 +11107,9 @@
}
},
"node_modules/eslint": {
- "version": "9.11.1",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.11.1.tgz",
- "integrity": "sha512-MobhYKIoAO1s1e4VUrgx1l1Sk2JBR/Gqjjgw8+mfgoLE2xwsHur4gdfTxyTgShrhvdVFTaJSgMiQBl1jv/AWxg==",
+ "version": "9.12.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.12.0.tgz",
+ "integrity": "sha512-UVIOlTEWxwIopRL1wgSQYdnVDcEvs2wyaO6DGo5mXqe3r16IoCNWkR29iHhyaP4cICWjbgbmFUGAhh0GJRuGZw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -10710,11 +11118,11 @@
"@eslint/config-array": "^0.18.0",
"@eslint/core": "^0.6.0",
"@eslint/eslintrc": "^3.1.0",
- "@eslint/js": "9.11.1",
+ "@eslint/js": "9.12.0",
"@eslint/plugin-kit": "^0.2.0",
+ "@humanfs/node": "^0.16.5",
"@humanwhocodes/module-importer": "^1.0.1",
- "@humanwhocodes/retry": "^0.3.0",
- "@nodelib/fs.walk": "^1.2.8",
+ "@humanwhocodes/retry": "^0.3.1",
"@types/estree": "^1.0.6",
"@types/json-schema": "^7.0.15",
"ajv": "^6.12.4",
@@ -10722,9 +11130,9 @@
"cross-spawn": "^7.0.2",
"debug": "^4.3.2",
"escape-string-regexp": "^4.0.0",
- "eslint-scope": "^8.0.2",
- "eslint-visitor-keys": "^4.0.0",
- "espree": "^10.1.0",
+ "eslint-scope": "^8.1.0",
+ "eslint-visitor-keys": "^4.1.0",
+ "espree": "^10.2.0",
"esquery": "^1.5.0",
"esutils": "^2.0.2",
"fast-deep-equal": "^3.1.3",
@@ -10734,13 +11142,11 @@
"ignore": "^5.2.0",
"imurmurhash": "^0.1.4",
"is-glob": "^4.0.0",
- "is-path-inside": "^3.0.3",
"json-stable-stringify-without-jsonify": "^1.0.1",
"lodash.merge": "^4.6.2",
"minimatch": "^3.1.2",
"natural-compare": "^1.4.0",
"optionator": "^0.9.3",
- "strip-ansi": "^6.0.1",
"text-table": "^0.2.0"
},
"bin": {
@@ -11157,9 +11563,9 @@
}
},
"node_modules/eslint-scope": {
- "version": "8.0.2",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz",
- "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==",
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz",
+ "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
@@ -11281,9 +11687,9 @@
}
},
"node_modules/eslint/node_modules/eslint-visitor-keys": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz",
- "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz",
+ "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==",
"dev": true,
"license": "Apache-2.0",
"engines": {
@@ -11293,19 +11699,6 @@
"url": "https://opencollective.com/eslint"
}
},
- "node_modules/eslint/node_modules/glob-parent": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
- "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "is-glob": "^4.0.3"
- },
- "engines": {
- "node": ">=10.13.0"
- }
- },
"node_modules/eslint/node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -11350,15 +11743,15 @@
}
},
"node_modules/espree": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz",
- "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==",
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz",
+ "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
"acorn": "^8.12.0",
"acorn-jsx": "^5.3.2",
- "eslint-visitor-keys": "^4.0.0"
+ "eslint-visitor-keys": "^4.1.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -11368,9 +11761,9 @@
}
},
"node_modules/espree/node_modules/eslint-visitor-keys": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz",
- "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz",
+ "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==",
"dev": true,
"license": "Apache-2.0",
"engines": {
@@ -11658,6 +12051,18 @@
"node": ">=8.6.0"
}
},
+ "node_modules/fast-glob/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/fast-json-patch": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-3.1.1.tgz",
@@ -11939,9 +12344,9 @@
}
},
"node_modules/form-data": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
- "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz",
+ "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -12048,31 +12453,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/fs-extra": {
- "version": "11.2.0",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz",
- "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "graceful-fs": "^4.2.0",
- "jsonfile": "^6.0.1",
- "universalify": "^2.0.0"
- },
- "engines": {
- "node": ">=14.14"
- }
- },
- "node_modules/fs-extra/node_modules/universalify": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
- "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 10.0.0"
- }
- },
"node_modules/fs-minipass": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz",
@@ -12097,6 +12477,7 @@
"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,
"license": "MIT",
"optional": true,
@@ -12292,15 +12673,16 @@
}
},
"node_modules/glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
"license": "ISC",
"dependencies": {
- "is-glob": "^4.0.1"
+ "is-glob": "^4.0.3"
},
"engines": {
- "node": ">= 6"
+ "node": ">=10.13.0"
}
},
"node_modules/glob-to-regexp": {
@@ -13053,6 +13435,7 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"binary-extensions": "^2.0.0"
@@ -13201,16 +13584,6 @@
"node": ">=0.12.0"
}
},
- "node_modules/is-path-inside": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
- "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/is-plain-obj": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz",
@@ -14254,9 +14627,9 @@
}
},
"node_modules/jest-fail-on-console": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/jest-fail-on-console/-/jest-fail-on-console-3.3.0.tgz",
- "integrity": "sha512-J9rnFQvQwkcGJw01zCEKe2Uag+E926lFgIyaQGep2LqhQH7OCRHyD+tm/jnNoKlSRnOBO60DmzMjeQAVI3f5cw==",
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/jest-fail-on-console/-/jest-fail-on-console-3.3.1.tgz",
+ "integrity": "sha512-dmq/dmh5OBgJlD1MJdpznzwFQP8S7msf3ghTGWQLGhagWwHKzGtqXza76nuJUKOK7BdwqcTK6CCE49Xxv4ckUQ==",
"dev": true,
"license": "MIT"
},
@@ -15481,13 +15854,13 @@
"license": "MIT"
},
"node_modules/jsdom": {
- "version": "25.0.0",
- "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.0.tgz",
- "integrity": "sha512-OhoFVT59T7aEq75TVw9xxEfkXgacpqAhQaYgP9y/fDqWQCMB/b1H66RfmPm/MaeaAIU9nDwMOVTlPN51+ao6CQ==",
+ "version": "25.0.1",
+ "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.1.tgz",
+ "integrity": "sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "cssstyle": "^4.0.1",
+ "cssstyle": "^4.1.0",
"data-urls": "^5.0.0",
"decimal.js": "^10.4.3",
"form-data": "^4.0.0",
@@ -15500,7 +15873,7 @@
"rrweb-cssom": "^0.7.1",
"saxes": "^6.0.0",
"symbol-tree": "^3.2.4",
- "tough-cookie": "^4.1.4",
+ "tough-cookie": "^5.0.0",
"w3c-xmlserializer": "^5.0.0",
"webidl-conversions": "^7.0.0",
"whatwg-encoding": "^3.1.1",
@@ -15583,29 +15956,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/jsonfile": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
- "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "universalify": "^2.0.0"
- },
- "optionalDependencies": {
- "graceful-fs": "^4.1.6"
- }
- },
- "node_modules/jsonfile/node_modules/universalify": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
- "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 10.0.0"
- }
- },
"node_modules/jsonparse": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz",
@@ -15849,11 +16199,14 @@
}
},
"node_modules/lines-and-columns": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
- "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.3.tgz",
+ "integrity": "sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ }
},
"node_modules/lint-staged": {
"version": "15.2.10",
@@ -16534,9 +16887,9 @@
}
},
"node_modules/memfs": {
- "version": "4.12.0",
- "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.12.0.tgz",
- "integrity": "sha512-74wDsex5tQDSClVkeK1vtxqYCAgCoXxx+K4NSHzgU/muYVYByFqa+0RnrPO9NM6naWm1+G9JmZ0p6QHhXmeYfA==",
+ "version": "4.13.0",
+ "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.13.0.tgz",
+ "integrity": "sha512-dIs5KGy24fbdDhIAg0RxXpFqQp3RwL6wgSMRF9OSuphL/Uc9a4u2/SDJKPLj/zUgtOGKuHrRMrj563+IErj4Cg==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
@@ -16934,9 +17287,9 @@
"license": "MIT"
},
"node_modules/monaco-editor": {
- "version": "0.51.0",
- "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.51.0.tgz",
- "integrity": "sha512-xaGwVV1fq343cM7aOYB6lVE4Ugf0UyimdD/x5PWcWBMKENwectaEu77FAN7c5sFiyumqeJdX1RPTh1ocioyDjw==",
+ "version": "0.52.0",
+ "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.52.0.tgz",
+ "integrity": "sha512-OeWhNpABLCeTqubfqLMXGsqf6OmPU6pHM85kF3dhy6kq5hnhuVS1p3VrEW/XhWHc71P2tHyS5JFySD8mgs1crw==",
"license": "MIT"
},
"node_modules/moo-color": {
@@ -17040,9 +17393,9 @@
}
},
"node_modules/nan": {
- "version": "2.20.0",
- "resolved": "https://registry.npmjs.org/nan/-/nan-2.20.0.tgz",
- "integrity": "sha512-bk3gXBZDGILuuo/6sKtr0DQmSThYHLtNCdSdXk9YkxD/jK6X2vmCyyXBBxyqZ4XcnzTyYEAThfX3DCEnLf6igw==",
+ "version": "2.22.0",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.22.0.tgz",
+ "integrity": "sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw==",
"license": "MIT",
"optional": true
},
@@ -17432,6 +17785,7 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -17589,22 +17943,22 @@
}
},
"node_modules/nwsapi": {
- "version": "2.2.12",
- "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.12.tgz",
- "integrity": "sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w==",
+ "version": "2.2.13",
+ "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.13.tgz",
+ "integrity": "sha512-cTGB9ptp9dY9A5VbMSe7fQBcl/tt22Vcqdq8+eN93rblOuE0aCFu4aZ2vMwct/2t+lFnosm8RkQW1I0Omb1UtQ==",
"dev": true,
"license": "MIT"
},
"node_modules/nx": {
- "version": "19.6.5",
- "resolved": "https://registry.npmjs.org/nx/-/nx-19.6.5.tgz",
- "integrity": "sha512-igPYPsBF1BM1YxEiGDvaLOz0CWWoEvxzR7yQg3iULjGG9zKgDFNHHIHJwkyHsCBTtMhhkgeUl16PsTVgDuil3A==",
+ "version": "19.8.4",
+ "resolved": "https://registry.npmjs.org/nx/-/nx-19.8.4.tgz",
+ "integrity": "sha512-fc833c3UKo6kuoG4z0kSKet17yWym3VzcQ+yPWYspxxxd8GFVVk42+9wieyVQDi9YqtKZQ6PdQfSEPm59/M7SA==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"@napi-rs/wasm-runtime": "0.2.4",
- "@nrwl/tao": "19.6.5",
+ "@nrwl/tao": "19.8.4",
"@yarnpkg/lockfile": "^1.1.0",
"@yarnpkg/parsers": "3.0.0-rc.46",
"@zkochan/js-yaml": "0.0.7",
@@ -17619,11 +17973,10 @@
"figures": "3.2.0",
"flat": "^5.0.2",
"front-matter": "^4.0.2",
- "fs-extra": "^11.1.0",
"ignore": "^5.0.4",
"jest-diff": "^29.4.1",
"jsonc-parser": "3.2.0",
- "lines-and-columns": "~2.0.3",
+ "lines-and-columns": "2.0.3",
"minimatch": "9.0.3",
"node-machine-id": "1.1.12",
"npm-run-path": "^4.0.1",
@@ -17644,16 +17997,16 @@
"nx-cloud": "bin/nx-cloud.js"
},
"optionalDependencies": {
- "@nx/nx-darwin-arm64": "19.6.5",
- "@nx/nx-darwin-x64": "19.6.5",
- "@nx/nx-freebsd-x64": "19.6.5",
- "@nx/nx-linux-arm-gnueabihf": "19.6.5",
- "@nx/nx-linux-arm64-gnu": "19.6.5",
- "@nx/nx-linux-arm64-musl": "19.6.5",
- "@nx/nx-linux-x64-gnu": "19.6.5",
- "@nx/nx-linux-x64-musl": "19.6.5",
- "@nx/nx-win32-arm64-msvc": "19.6.5",
- "@nx/nx-win32-x64-msvc": "19.6.5"
+ "@nx/nx-darwin-arm64": "19.8.4",
+ "@nx/nx-darwin-x64": "19.8.4",
+ "@nx/nx-freebsd-x64": "19.8.4",
+ "@nx/nx-linux-arm-gnueabihf": "19.8.4",
+ "@nx/nx-linux-arm64-gnu": "19.8.4",
+ "@nx/nx-linux-arm64-musl": "19.8.4",
+ "@nx/nx-linux-x64-gnu": "19.8.4",
+ "@nx/nx-linux-x64-musl": "19.8.4",
+ "@nx/nx-win32-arm64-msvc": "19.8.4",
+ "@nx/nx-win32-x64-msvc": "19.8.4"
},
"peerDependencies": {
"@swc-node/register": "^1.8.0",
@@ -17714,19 +18067,6 @@
"node": ">=8"
}
},
- "node_modules/nx/node_modules/cli-spinners": {
- "version": "2.6.1",
- "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz",
- "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/nx/node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@@ -17820,16 +18160,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/nx/node_modules/lines-and-columns": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.4.tgz",
- "integrity": "sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- }
- },
"node_modules/nx/node_modules/minimatch": {
"version": "9.0.3",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
@@ -18388,6 +18718,13 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/parse-json/node_modules/lines-and-columns": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/parse-node-version": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz",
@@ -18548,9 +18885,9 @@
}
},
"node_modules/pdfjs-dist": {
- "version": "4.6.82",
- "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-4.6.82.tgz",
- "integrity": "sha512-BUOryeRFwvbLe0lOU6NhkJNuVQUp06WxlJVVCsxdmJ4y5cU3O3s3/0DunVdK1PMm7v2MUw52qKYaidhDH1Z9+w==",
+ "version": "4.7.76",
+ "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-4.7.76.tgz",
+ "integrity": "sha512-8y6wUgC/Em35IumlGjaJOCm3wV4aY/6sqnIT3fVW/67mXsOZ9HWBn8GDKmJUK0GSzpbmX3gQqwfoFayp78Mtqw==",
"license": "Apache-2.0",
"engines": {
"node": ">=18"
@@ -18885,9 +19222,9 @@
"license": "MIT"
},
"node_modules/posthog-js": {
- "version": "1.165.0",
- "resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.165.0.tgz",
- "integrity": "sha512-rUfRJobvOz3Q9Er+zwb32Eq2qs+ToBe/B4k4IoKzmyszI7240Rf4xVWRB0ky8LvmdZfCeYX5knS2Uv3pnn/d5A==",
+ "version": "1.167.0",
+ "resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.167.0.tgz",
+ "integrity": "sha512-/zXQ6tuJgiF1d4mgg3UsAi/uoyg7UnfFNQtikuALmaE53xFExpcAKbMfHPG/f54QgTvLxSHyGL1kFl/1uspkGg==",
"license": "MIT",
"dependencies": {
"fflate": "^0.4.8",
@@ -18896,9 +19233,9 @@
}
},
"node_modules/preact": {
- "version": "10.24.1",
- "resolved": "https://registry.npmjs.org/preact/-/preact-10.24.1.tgz",
- "integrity": "sha512-PnBAwFI3Yjxxcxw75n6VId/5TFxNW/81zexzWD9jn1+eSrOP84NdsS38H5IkF/UH3frqRPT+MvuCoVHjTDTnDw==",
+ "version": "10.24.2",
+ "resolved": "https://registry.npmjs.org/preact/-/preact-10.24.2.tgz",
+ "integrity": "sha512-1cSoF0aCC8uaARATfrlz4VCBqE8LwZwRfLgkxJOQwAlQt6ayTmi0D9OF7nXid1POI5SZidFuG9CnlXbDfLqY/Q==",
"license": "MIT",
"funding": {
"type": "opencollective",
@@ -19336,6 +19673,7 @@
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"picomatch": "^2.2.1"
@@ -19348,6 +19686,7 @@
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=8.6"
@@ -19439,16 +19778,16 @@
"license": "MIT"
},
"node_modules/regexpu-core": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz",
- "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==",
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.1.1.tgz",
+ "integrity": "sha512-k67Nb9jvwJcJmVpw0jPttR1/zVfnKf8Km0IPatrU/zJ5XeG3+Slx0xLXs9HByJSzXzrlz5EDvN6yLNMDc2qdnw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/regjsgen": "^0.8.0",
"regenerate": "^1.4.2",
- "regenerate-unicode-properties": "^10.1.0",
- "regjsparser": "^0.9.1",
+ "regenerate-unicode-properties": "^10.2.0",
+ "regjsgen": "^0.8.0",
+ "regjsparser": "^0.11.0",
"unicode-match-property-ecmascript": "^2.0.0",
"unicode-match-property-value-ecmascript": "^2.1.0"
},
@@ -19456,26 +19795,37 @@
"node": ">=4"
}
},
+ "node_modules/regjsgen": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz",
+ "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/regjsparser": {
- "version": "0.9.1",
- "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz",
- "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==",
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.11.1.tgz",
+ "integrity": "sha512-1DHODs4B8p/mQHU9kr+jv8+wIC9mtG4eBHxWxIq5mhjE3D5oORhCc6deRKzTjs9DcfRFmj9BHSDguZklqCGFWQ==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
- "jsesc": "~0.5.0"
+ "jsesc": "~3.0.2"
},
"bin": {
"regjsparser": "bin/parser"
}
},
"node_modules/regjsparser/node_modules/jsesc": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
- "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==",
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz",
+ "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==",
"dev": true,
+ "license": "MIT",
"bin": {
"jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=6"
}
},
"node_modules/require-directory": {
@@ -19877,12 +20227,13 @@
"license": "MIT"
},
"node_modules/sass": {
- "version": "1.79.3",
- "resolved": "https://registry.npmjs.org/sass/-/sass-1.79.3.tgz",
- "integrity": "sha512-m7dZxh0W9EZ3cw50Me5GOuYm/tVAJAn91SUnohLRo9cXBixGUOdvmryN+dXpwR831bhoY3Zv7rEFt85PUwTmzA==",
+ "version": "1.79.5",
+ "resolved": "https://registry.npmjs.org/sass/-/sass-1.79.5.tgz",
+ "integrity": "sha512-W1h5kp6bdhqFh2tk3DsI771MoEJjvrSY/2ihJRJS4pjIyfJCw0nTsxqhnrUzaLMOJjFchj8rOvraI/YUVjtx5g==",
"dev": true,
"license": "MIT",
"dependencies": {
+ "@parcel/watcher": "^2.4.1",
"chokidar": "^4.0.0",
"immutable": "^4.0.0",
"source-map-js": ">=0.6.2 <2.0.0"
@@ -19952,9 +20303,9 @@
}
},
"node_modules/sass/node_modules/readdirp": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.1.tgz",
- "integrity": "sha512-GkMg9uOTpIWWKbSsgwb5fA4EavTR+SG/PMPoAY8hkhHfEEY0/vqljY+XHqtDf2cr2IJtoNRDbrrEpZUiZCkYRw==",
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz",
+ "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -21058,9 +21409,9 @@
"license": "MIT"
},
"node_modules/synckit": {
- "version": "0.9.1",
- "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz",
- "integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==",
+ "version": "0.9.2",
+ "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz",
+ "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -21412,22 +21763,22 @@
"license": "MIT"
},
"node_modules/tldts": {
- "version": "6.1.47",
- "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.47.tgz",
- "integrity": "sha512-R/K2tZ5MiY+mVrnSkNJkwqYT2vUv1lcT6wJvd2emGaMJ7PHUGRY4e3tUsdFCXgqxi2QgbHjL3yJgXCo40v9Hxw==",
+ "version": "6.1.51",
+ "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.51.tgz",
+ "integrity": "sha512-33lfQoL0JsDogIbZ8fgRyvv77GnRtwkNE/MOKocwUgPO1WrSfsq7+vQRKxRQZai5zd+zg97Iv9fpFQSzHyWdLA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "tldts-core": "^6.1.47"
+ "tldts-core": "^6.1.51"
},
"bin": {
"tldts": "bin/cli.js"
}
},
"node_modules/tldts-core": {
- "version": "6.1.47",
- "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.47.tgz",
- "integrity": "sha512-6SWyFMnlst1fEt7GQVAAu16EGgFK0cLouH/2Mk6Ftlwhv3Ol40L0dlpGMcnnNiiOMyD2EV/aF3S+U2nKvvLvrA==",
+ "version": "6.1.51",
+ "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.51.tgz",
+ "integrity": "sha512-bu9oCYYWC1iRjx+3UnAjqCsfrWNZV1ghNQf49b3w5xE8J/tNShHTzp5syWJfwGH+pxUgTTLUnzHnfuydW7wmbg==",
"dev": true,
"license": "MIT"
},
@@ -21945,9 +22296,9 @@
}
},
"node_modules/update-browserslist-db": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz",
- "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz",
+ "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==",
"funding": [
{
"type": "opencollective",
@@ -21964,8 +22315,8 @@
],
"license": "MIT",
"dependencies": {
- "escalade": "^3.1.2",
- "picocolors": "^1.0.1"
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.0"
},
"bin": {
"update-browserslist-db": "cli.js"
@@ -22797,9 +23148,9 @@
}
},
"node_modules/webpack-dev-server": {
- "version": "5.0.4",
- "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.0.4.tgz",
- "integrity": "sha512-dljXhUgx3HqKP2d8J/fUMvhxGhzjeNVarDLcbO/EWMSgRizDkxHQDZQaLFL5VJY9tRBj2Gz+rvCEYYvhbqPHNA==",
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.1.0.tgz",
+ "integrity": "sha512-aQpaN81X6tXie1FoOB7xlMfCsN19pSvRAeYUHOdFWOlhpQ/LlbfTqYwwmEDFV0h8GGuqmCmKmT+pxcUV/Nt2gQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -22816,8 +23167,7 @@
"colorette": "^2.0.10",
"compression": "^1.7.4",
"connect-history-api-fallback": "^2.0.0",
- "default-gateway": "^6.0.3",
- "express": "^4.17.3",
+ "express": "^4.19.2",
"graceful-fs": "^4.2.6",
"html-entities": "^2.4.0",
"http-proxy-middleware": "^2.0.3",
@@ -22825,14 +23175,13 @@
"launch-editor": "^2.6.1",
"open": "^10.0.3",
"p-retry": "^6.2.0",
- "rimraf": "^5.0.5",
"schema-utils": "^4.2.0",
"selfsigned": "^2.4.1",
"serve-index": "^1.9.1",
"sockjs": "^0.3.24",
"spdy": "^4.0.2",
- "webpack-dev-middleware": "^7.1.0",
- "ws": "^8.16.0"
+ "webpack-dev-middleware": "^7.4.2",
+ "ws": "^8.18.0"
},
"bin": {
"webpack-dev-server": "bin/webpack-dev-server.js"
@@ -22857,9 +23206,9 @@
}
},
"node_modules/webpack-dev-server/node_modules/http-proxy-middleware": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz",
- "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==",
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz",
+ "integrity": "sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA==",
"dev": true,
"license": "MIT",
"dependencies": {
diff --git a/package.json b/package.json
index 03ab87fb7b80..77b79ed4f3d8 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "artemis",
- "version": "7.5.6",
+ "version": "7.6.1",
"description": "Interactive Learning with Individual Feedback",
"private": true,
"license": "MIT",
@@ -13,18 +13,18 @@
"node_modules"
],
"dependencies": {
- "@angular/animations": "18.2.6",
- "@angular/cdk": "18.2.6",
- "@angular/common": "18.2.6",
- "@angular/compiler": "18.2.6",
- "@angular/core": "18.2.6",
- "@angular/forms": "18.2.6",
- "@angular/localize": "18.2.6",
- "@angular/material": "18.2.6",
- "@angular/platform-browser": "18.2.6",
- "@angular/platform-browser-dynamic": "18.2.6",
- "@angular/router": "18.2.6",
- "@angular/service-worker": "18.2.6",
+ "@angular/animations": "18.2.8",
+ "@angular/cdk": "18.2.8",
+ "@angular/common": "18.2.8",
+ "@angular/compiler": "18.2.8",
+ "@angular/core": "18.2.8",
+ "@angular/forms": "18.2.8",
+ "@angular/localize": "18.2.8",
+ "@angular/material": "18.2.8",
+ "@angular/platform-browser": "18.2.8",
+ "@angular/platform-browser-dynamic": "18.2.8",
+ "@angular/router": "18.2.8",
+ "@angular/service-worker": "18.2.8",
"@ctrl/ngx-emoji-mart": "9.2.0",
"@danielmoncada/angular-datetime-picker": "18.1.0",
"@fingerprintjs/fingerprintjs": "4.5.0",
@@ -36,7 +36,7 @@
"@ng-bootstrap/ng-bootstrap": "17.0.1",
"@ngx-translate/core": "15.0.0",
"@ngx-translate/http-loader": "8.0.0",
- "@sentry/angular": "8.32.0",
+ "@sentry/angular": "8.34.0",
"@siemens/ngx-datatable": "22.4.1",
"@swimlane/ngx-charts": "20.5.0",
"@swimlane/ngx-graph": "8.4.0",
@@ -58,12 +58,12 @@
"jszip": "3.10.1",
"lodash-es": "4.17.21",
"mobile-drag-drop": "3.0.0-rc.0",
- "monaco-editor": "0.51.0",
+ "monaco-editor": "0.52.0",
"ngx-infinite-scroll": "18.0.0",
"ngx-webstorage": "18.0.0",
"papaparse": "5.4.1",
- "pdfjs-dist": "4.6.82",
- "posthog-js": "1.165.0",
+ "pdfjs-dist": "4.7.76",
+ "posthog-js": "1.167.0",
"rxjs": "7.8.1",
"showdown": "2.1.0",
"showdown-highlight": "3.1.0",
@@ -88,18 +88,20 @@
"d3-transition": "^3.0.1"
},
"@typescript-eslint/utils": {
- "eslint": "^9.11.0"
+ "eslint": "^9.12.0"
},
"braces": "3.0.3",
+ "cookie": "0.7.1",
"critters": "0.0.24",
"debug": "4.3.7",
"eslint-plugin-deprecation": {
- "eslint": "^9.11.0"
+ "eslint": "^9.12.0"
},
"eslint-plugin-jest": {
- "@typescript-eslint/eslint-plugin": "^8.6.0"
+ "@typescript-eslint/eslint-plugin": "^8.8.0"
},
- "jsdom": "25.0.0",
+ "express": "4.21.0",
+ "jsdom": "25.0.1",
"katex": "0.16.11",
"postcss": "8.4.47",
"rimraf": "6.0.1",
@@ -110,36 +112,37 @@
"tough-cookie": "5.0.0",
"vite": "5.4.8",
"webpack-dev-middleware": "7.4.2",
+ "webpack-dev-server": "5.1.0",
"word-wrap": "1.2.5",
"ws": "8.18.0",
"yargs-parser": "21.1.1"
},
"devDependencies": {
"@angular-builders/jest": "18.0.0",
- "@angular-devkit/build-angular": "18.2.6",
+ "@angular-devkit/build-angular": "18.2.8",
"@angular-eslint/builder": "18.3.1",
"@angular-eslint/eslint-plugin": "18.3.1",
"@angular-eslint/eslint-plugin-template": "18.3.1",
"@angular-eslint/schematics": "18.3.1",
"@angular-eslint/template-parser": "18.3.1",
- "@angular/cli": "18.2.6",
- "@angular/compiler-cli": "18.2.6",
- "@angular/language-service": "18.2.6",
- "@sentry/types": "8.32.0",
+ "@angular/cli": "18.2.8",
+ "@angular/compiler-cli": "18.2.8",
+ "@angular/language-service": "18.2.8",
+ "@sentry/types": "8.34.0",
"@types/crypto-js": "4.2.2",
"@types/d3-shape": "3.1.6",
"@types/dompurify": "3.0.5",
"@types/jest": "29.5.13",
"@types/lodash-es": "4.17.12",
- "@types/node": "22.7.3",
+ "@types/node": "22.7.5",
"@types/papaparse": "5.3.14",
"@types/showdown": "2.0.6",
"@types/smoothscroll-polyfill": "0.3.4",
"@types/sockjs-client": "1.5.4",
"@types/uuid": "10.0.0",
- "@typescript-eslint/eslint-plugin": "8.7.0",
- "@typescript-eslint/parser": "8.7.0",
- "eslint": "9.11.1",
+ "@typescript-eslint/eslint-plugin": "8.8.1",
+ "@typescript-eslint/parser": "8.8.1",
+ "eslint": "9.12.0",
"eslint-config-prettier": "9.1.0",
"eslint-plugin-deprecation": "3.0.0",
"eslint-plugin-jest": "28.8.3",
@@ -151,7 +154,7 @@
"jest-canvas-mock": "2.5.2",
"jest-date-mock": "1.0.10",
"jest-extended": "4.0.2",
- "jest-fail-on-console": "3.3.0",
+ "jest-fail-on-console": "3.3.1",
"jest-junit": "16.0.0",
"jest-preset-angular": "14.2.4",
"lint-staged": "15.2.10",
@@ -159,7 +162,7 @@
"ng-mocks": "14.13.1",
"prettier": "3.3.3",
"rimraf": "6.0.1",
- "sass": "1.79.3",
+ "sass": "1.79.5",
"ts-jest": "29.2.5",
"typescript": "5.5.4",
"weak-napi": "2.0.2"
diff --git a/prebuild.mjs b/prebuild.mjs
index 7ef783be432c..5f362babe3fc 100644
--- a/prebuild.mjs
+++ b/prebuild.mjs
@@ -5,10 +5,11 @@
* - webpack.DefinePlugin and
* - MergeJsonWebpackPlugin
*/
-import fs from "fs";
-import path from "path";
-import { hashElement } from "folder-hash";
-import { fileURLToPath } from "url";
+import fs from 'fs';
+import path from 'path';
+import { hashElement } from 'folder-hash';
+import { fileURLToPath } from 'url';
+import * as esbuild from 'esbuild';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
@@ -111,4 +112,25 @@ for (const group of groups) {
}
}
+/*
+ * The workers of the monaco editor must be bundled separately.
+ * Specialized workers are available in the vs/esm/language/ directory.
+ * Be sure to modify the MonacoConfig if you choose to add a worker here.
+ * For more details, refer to https://github.com/microsoft/monaco-editor/blob/main/samples/browser-esm-esbuild/build.js
+ */
+const workerEntryPoints = [
+ 'vs/language/json/json.worker.js',
+ 'vs/language/css/css.worker.js',
+ 'vs/language/html/html.worker.js',
+ 'vs/language/typescript/ts.worker.js',
+ 'vs/editor/editor.worker.js'
+];
+await esbuild.build({
+ entryPoints: workerEntryPoints.map((entry) => `node_modules/monaco-editor/esm/${entry}`),
+ bundle: true,
+ format: 'esm',
+ outbase: 'node_modules/monaco-editor/esm',
+ outdir: 'node_modules/monaco-editor/bundles'
+});
+
console.log("Pre-Build complete!");
diff --git a/src/main/java/de/tum/cit/aet/artemis/assessment/domain/Result.java b/src/main/java/de/tum/cit/aet/artemis/assessment/domain/Result.java
index cc14d7a35e34..77c01c6fae19 100644
--- a/src/main/java/de/tum/cit/aet/artemis/assessment/domain/Result.java
+++ b/src/main/java/de/tum/cit/aet/artemis/assessment/domain/Result.java
@@ -629,7 +629,7 @@ public boolean isAutomatic() {
* @return true if the result is an automatic AI Athena result
*/
@JsonIgnore
- public boolean isAthenaAutomatic() {
+ public boolean isAthenaBased() {
return AssessmentType.AUTOMATIC_ATHENA == assessmentType;
}
diff --git a/src/main/java/de/tum/cit/aet/artemis/assessment/repository/ResultRepository.java b/src/main/java/de/tum/cit/aet/artemis/assessment/repository/ResultRepository.java
index 87c381b777d9..5a7b75e82de5 100644
--- a/src/main/java/de/tum/cit/aet/artemis/assessment/repository/ResultRepository.java
+++ b/src/main/java/de/tum/cit/aet/artemis/assessment/repository/ResultRepository.java
@@ -427,6 +427,14 @@ SELECT COUNT(DISTINCT p)
*/
boolean existsByParticipationId(long participationId);
+ /**
+ * Checks if a result exists for the given submission ID.
+ *
+ * @param submissionId the ID of the submission to check.
+ * @return true if a result exists for the given submission ID, false otherwise.
+ */
+ boolean existsBySubmissionId(long submissionId);
+
/**
* Returns true if there is at least one result for the given exercise.
*
diff --git a/src/main/java/de/tum/cit/aet/artemis/atlas/domain/competency/LearningPath.java b/src/main/java/de/tum/cit/aet/artemis/atlas/domain/competency/LearningPath.java
index 267efe722982..ab4c961be143 100644
--- a/src/main/java/de/tum/cit/aet/artemis/atlas/domain/competency/LearningPath.java
+++ b/src/main/java/de/tum/cit/aet/artemis/atlas/domain/competency/LearningPath.java
@@ -31,6 +31,12 @@ public class LearningPath extends DomainObject {
@Column(name = "progress")
private int progress;
+ /**
+ * flag indicating if a student started the learning path
+ */
+ @Column(name = "started_by_student")
+ private boolean startedByStudent = false;
+
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
@@ -89,8 +95,16 @@ public void removeCompetency(CourseCompetency competency) {
this.competencies.remove(competency);
}
+ public boolean isStartedByStudent() {
+ return startedByStudent;
+ }
+
+ public void setStartedByStudent(boolean startedByStudent) {
+ this.startedByStudent = startedByStudent;
+ }
+
@Override
public String toString() {
- return "LearningPath{" + "id=" + getId() + ", user=" + user + ", course=" + course + ", competencies=" + competencies + '}';
+ return "LearningPath{" + "id=" + getId() + ", user=" + user + ", course=" + course + ", competencies=" + competencies + ", startedByStudent=" + startedByStudent + "}";
}
}
diff --git a/src/main/java/de/tum/cit/aet/artemis/atlas/dto/CompetencyGraphNodeDTO.java b/src/main/java/de/tum/cit/aet/artemis/atlas/dto/CompetencyGraphNodeDTO.java
index 59feee0edd6b..c56876064668 100644
--- a/src/main/java/de/tum/cit/aet/artemis/atlas/dto/CompetencyGraphNodeDTO.java
+++ b/src/main/java/de/tum/cit/aet/artemis/atlas/dto/CompetencyGraphNodeDTO.java
@@ -12,7 +12,7 @@
public record CompetencyGraphNodeDTO(String id, String label, ZonedDateTime softDueDate, Double value, CompetencyNodeValueType valueType) {
public enum CompetencyNodeValueType {
- MASTERY_PROGRESS
+ MASTERY_PROGRESS, AVERAGE_MASTERY_PROGRESS,
}
public static CompetencyGraphNodeDTO of(@NotNull CourseCompetency competency, Double value, CompetencyNodeValueType valueType) {
diff --git a/src/main/java/de/tum/cit/aet/artemis/atlas/dto/CompetencyImportOptionsDTO.java b/src/main/java/de/tum/cit/aet/artemis/atlas/dto/CompetencyImportOptionsDTO.java
new file mode 100644
index 000000000000..7d64a43ca560
--- /dev/null
+++ b/src/main/java/de/tum/cit/aet/artemis/atlas/dto/CompetencyImportOptionsDTO.java
@@ -0,0 +1,12 @@
+package de.tum.cit.aet.artemis.atlas.dto;
+
+import java.time.ZonedDateTime;
+import java.util.Optional;
+import java.util.Set;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+
+@JsonInclude(JsonInclude.Include.NON_EMPTY)
+public record CompetencyImportOptionsDTO(Set competencyIds, Optional sourceCourseId, boolean importRelations, boolean importExercises, boolean importLectures,
+ Optional referenceDate, boolean isReleaseDate) {
+}
diff --git a/src/main/java/de/tum/cit/aet/artemis/atlas/dto/LearningPathDTO.java b/src/main/java/de/tum/cit/aet/artemis/atlas/dto/LearningPathDTO.java
new file mode 100644
index 000000000000..f61598b30cf4
--- /dev/null
+++ b/src/main/java/de/tum/cit/aet/artemis/atlas/dto/LearningPathDTO.java
@@ -0,0 +1,13 @@
+package de.tum.cit.aet.artemis.atlas.dto;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+
+import de.tum.cit.aet.artemis.atlas.domain.competency.LearningPath;
+
+@JsonInclude(JsonInclude.Include.NON_EMPTY)
+public record LearningPathDTO(long id, boolean startedByStudent, int progress) {
+
+ public static LearningPathDTO of(LearningPath learningPath) {
+ return new LearningPathDTO(learningPath.getId(), learningPath.isStartedByStudent(), learningPath.getProgress());
+ }
+}
diff --git a/src/main/java/de/tum/cit/aet/artemis/atlas/dto/LearningPathHealthDTO.java b/src/main/java/de/tum/cit/aet/artemis/atlas/dto/LearningPathHealthDTO.java
index 8592378c6a50..05d621746267 100644
--- a/src/main/java/de/tum/cit/aet/artemis/atlas/dto/LearningPathHealthDTO.java
+++ b/src/main/java/de/tum/cit/aet/artemis/atlas/dto/LearningPathHealthDTO.java
@@ -14,6 +14,6 @@ public LearningPathHealthDTO(Set status) {
}
public enum HealthStatus {
- OK, DISABLED, MISSING, NO_COMPETENCIES, NO_RELATIONS
+ MISSING, NO_COMPETENCIES, NO_RELATIONS
}
}
diff --git a/src/main/java/de/tum/cit/aet/artemis/atlas/dto/metrics/CompetencyInformationDTO.java b/src/main/java/de/tum/cit/aet/artemis/atlas/dto/metrics/CompetencyInformationDTO.java
index 02e0fc7edeb2..f361bc402718 100644
--- a/src/main/java/de/tum/cit/aet/artemis/atlas/dto/metrics/CompetencyInformationDTO.java
+++ b/src/main/java/de/tum/cit/aet/artemis/atlas/dto/metrics/CompetencyInformationDTO.java
@@ -4,6 +4,7 @@
import com.fasterxml.jackson.annotation.JsonInclude;
+import de.tum.cit.aet.artemis.atlas.domain.competency.Competency;
import de.tum.cit.aet.artemis.atlas.domain.competency.CompetencyTaxonomy;
/**
@@ -19,4 +20,15 @@
*/
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public record CompetencyInformationDTO(long id, String title, String description, CompetencyTaxonomy taxonomy, ZonedDateTime softDueDate, boolean optional, int masteryThreshold) {
+
+ /**
+ * Creates a CompetencyInformationDTO from a Competency.
+ *
+ * @param competency the Competency to create the DTO from
+ * @return the created DTO
+ */
+ public static CompetencyInformationDTO of(C competency) {
+ return new CompetencyInformationDTO(competency.getId(), competency.getTitle(), competency.getDescription(), competency.getTaxonomy(), competency.getSoftDueDate(),
+ competency.isOptional(), competency.getMasteryThreshold());
+ }
}
diff --git a/src/main/java/de/tum/cit/aet/artemis/atlas/dto/metrics/LectureUnitInformationDTO.java b/src/main/java/de/tum/cit/aet/artemis/atlas/dto/metrics/LectureUnitInformationDTO.java
index 3a5d9cc8bcb4..8f4016a5f346 100644
--- a/src/main/java/de/tum/cit/aet/artemis/atlas/dto/metrics/LectureUnitInformationDTO.java
+++ b/src/main/java/de/tum/cit/aet/artemis/atlas/dto/metrics/LectureUnitInformationDTO.java
@@ -18,4 +18,15 @@
*/
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public record LectureUnitInformationDTO(long id, long lectureId, String lectureTitle, String name, ZonedDateTime releaseDate, Class extends LectureUnit> type) {
+
+ /**
+ * Creates a LectureUnitInformationDTO from a LectureUnit.
+ *
+ * @param lectureUnit the LectureUnit to create the DTO from
+ * @return the created DTO
+ */
+ public static LectureUnitInformationDTO of(L lectureUnit) {
+ return new LectureUnitInformationDTO(lectureUnit.getId(), lectureUnit.getLecture().getId(), lectureUnit.getLecture().getTitle(), lectureUnit.getName(),
+ lectureUnit.getReleaseDate(), lectureUnit.getClass());
+ }
}
diff --git a/src/main/java/de/tum/cit/aet/artemis/atlas/repository/CompetencyProgressRepository.java b/src/main/java/de/tum/cit/aet/artemis/atlas/repository/CompetencyProgressRepository.java
index 85c627b06408..2e397c06db36 100644
--- a/src/main/java/de/tum/cit/aet/artemis/atlas/repository/CompetencyProgressRepository.java
+++ b/src/main/java/de/tum/cit/aet/artemis/atlas/repository/CompetencyProgressRepository.java
@@ -94,4 +94,16 @@ SELECT COUNT(cp)
AND c = :competency
""")
Set findAllPriorByCompetencyId(@Param("competency") CourseCompetency competency, @Param("user") User userId);
+
+ @Query("""
+ SELECT COALESCE(GREATEST(0.0, LEAST(1.0, AVG(cp.progress * cp.confidence / com.masteryThreshold))), 0.0)
+ FROM CompetencyProgress cp
+ LEFT JOIN cp.competency com
+ LEFT JOIN com.course c
+ LEFT JOIN cp.user u
+ WHERE com.id = :competencyId
+ AND cp.progress > 0
+ AND c.studentGroupName MEMBER OF u.groups
+ """)
+ double findAverageOfAllNonZeroStudentProgressByCompetencyId(@Param("competencyId") long competencyId);
}
diff --git a/src/main/java/de/tum/cit/aet/artemis/atlas/repository/CompetencyRepository.java b/src/main/java/de/tum/cit/aet/artemis/atlas/repository/CompetencyRepository.java
index eb2fc3eccab5..91ae85978b42 100644
--- a/src/main/java/de/tum/cit/aet/artemis/atlas/repository/CompetencyRepository.java
+++ b/src/main/java/de/tum/cit/aet/artemis/atlas/repository/CompetencyRepository.java
@@ -26,9 +26,13 @@ public interface CompetencyRepository extends ArtemisJpaRepository findAllForCourse(@Param("courseId") long courseId);
+ Set findAllForCourseWithExercisesAndLectureUnitsAndLecturesAndAttachments(@Param("courseId") long courseId);
@Query("""
SELECT c
diff --git a/src/main/java/de/tum/cit/aet/artemis/atlas/repository/CourseCompetencyRepository.java b/src/main/java/de/tum/cit/aet/artemis/atlas/repository/CourseCompetencyRepository.java
index 9a164343bc0e..d8b66519355c 100644
--- a/src/main/java/de/tum/cit/aet/artemis/atlas/repository/CourseCompetencyRepository.java
+++ b/src/main/java/de/tum/cit/aet/artemis/atlas/repository/CourseCompetencyRepository.java
@@ -45,6 +45,44 @@ public interface CourseCompetencyRepository extends ArtemisJpaRepository findAllForCourse(@Param("courseId") long courseId);
+ @Query("""
+ SELECT c
+ FROM CourseCompetency c
+ LEFT JOIN FETCH c.exercises ex
+ LEFT JOIN FETCH c.lectureUnits lu
+ LEFT JOIN FETCH lu.lecture l
+ LEFT JOIN FETCH l.attachments
+ WHERE c.course.id = :courseId
+ """)
+ Set findAllForCourseWithExercisesAndLectureUnitsAndLecturesAndAttachments(@Param("courseId") long courseId);
+
+ @Query("""
+ SELECT c
+ FROM CourseCompetency c
+ LEFT JOIN FETCH c.exercises ex
+ LEFT JOIN FETCH c.lectureUnits lu
+ LEFT JOIN FETCH lu.lecture l
+ LEFT JOIN FETCH l.lectureUnits
+ LEFT JOIN FETCH l.attachments
+ WHERE c.id = :id
+ """)
+ Optional findByIdWithExercisesAndLectureUnitsAndLectures(@Param("id") long id);
+
+ default CourseCompetency findByIdWithExercisesAndLectureUnitsAndLecturesElseThrow(long id) {
+ return getValueElseThrow(findByIdWithExercisesAndLectureUnitsAndLectures(id), id);
+ }
+
+ @Query("""
+ SELECT c
+ FROM CourseCompetency c
+ LEFT JOIN FETCH c.exercises ex
+ LEFT JOIN FETCH c.lectureUnits lu
+ LEFT JOIN FETCH lu.lecture l
+ LEFT JOIN FETCH l.attachments
+ WHERE c.id IN :ids
+ """)
+ Set findAllByIdWithExercisesAndLectureUnitsAndLecturesAndAttachments(@Param("ids") Set ids);
+
/**
* Fetches all information related to the calculation of the mastery for exercises in a competency.
* The complex grouping by is necessary for postgres
diff --git a/src/main/java/de/tum/cit/aet/artemis/atlas/repository/PrerequisiteRepository.java b/src/main/java/de/tum/cit/aet/artemis/atlas/repository/PrerequisiteRepository.java
index a2187579a427..9616c2a5f34b 100644
--- a/src/main/java/de/tum/cit/aet/artemis/atlas/repository/PrerequisiteRepository.java
+++ b/src/main/java/de/tum/cit/aet/artemis/atlas/repository/PrerequisiteRepository.java
@@ -19,26 +19,30 @@ public interface PrerequisiteRepository extends ArtemisJpaRepository findAllByCourseIdOrderById(long courseId);
@Query("""
- SELECT c
- FROM Prerequisite c
- WHERE c.course.id = :courseId
+ SELECT p
+ FROM Prerequisite p
+ LEFT JOIN FETCH p.exercises
+ LEFT JOIN FETCH p.lectureUnits lu
+ LEFT JOIN FETCH lu.lecture l
+ LEFT JOIN FETCH l.attachments
+ WHERE p.course.id = :courseId
""")
- Set findAllForCourse(@Param("courseId") long courseId);
+ Set findAllForCourseWithExercisesAndLectureUnitsAndLecturesAndAttachments(@Param("courseId") long courseId);
@Query("""
- SELECT c
- FROM Prerequisite c
- LEFT JOIN FETCH c.lectureUnits lu
- LEFT JOIN FETCH c.exercises
- WHERE c.id = :competencyId
+ SELECT p
+ FROM Prerequisite p
+ LEFT JOIN FETCH p.lectureUnits lu
+ LEFT JOIN FETCH p.exercises
+ WHERE p.id = :competencyId
""")
Optional findByIdWithLectureUnitsAndExercises(@Param("competencyId") long competencyId);
@Query("""
- SELECT c
- FROM Prerequisite c
- LEFT JOIN FETCH c.lectureUnits lu
- WHERE c.id = :competencyId
+ SELECT p
+ FROM Prerequisite p
+ LEFT JOIN FETCH p.lectureUnits lu
+ WHERE p.id = :competencyId
""")
Optional findByIdWithLectureUnits(@Param("competencyId") long competencyId);
diff --git a/src/main/java/de/tum/cit/aet/artemis/atlas/service/LearningObjectImportService.java b/src/main/java/de/tum/cit/aet/artemis/atlas/service/LearningObjectImportService.java
new file mode 100644
index 000000000000..6b67d8f01b44
--- /dev/null
+++ b/src/main/java/de/tum/cit/aet/artemis/atlas/service/LearningObjectImportService.java
@@ -0,0 +1,445 @@
+package de.tum.cit.aet.artemis.atlas.service;
+
+import static de.tum.cit.aet.artemis.core.config.Constants.PROFILE_CORE;
+
+import java.io.IOException;
+import java.time.ZonedDateTime;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.annotation.Profile;
+import org.springframework.stereotype.Service;
+import org.springframework.util.function.ThrowingBiFunction;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+
+import de.tum.cit.aet.artemis.assessment.domain.GradingCriterion;
+import de.tum.cit.aet.artemis.assessment.repository.GradingCriterionRepository;
+import de.tum.cit.aet.artemis.atlas.domain.competency.CourseCompetency;
+import de.tum.cit.aet.artemis.atlas.dto.CompetencyImportOptionsDTO;
+import de.tum.cit.aet.artemis.atlas.dto.CompetencyWithTailRelationDTO;
+import de.tum.cit.aet.artemis.atlas.repository.CourseCompetencyRepository;
+import de.tum.cit.aet.artemis.core.domain.Course;
+import de.tum.cit.aet.artemis.core.exception.NoUniqueQueryException;
+import de.tum.cit.aet.artemis.exercise.domain.Exercise;
+import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository;
+import de.tum.cit.aet.artemis.fileupload.domain.FileUploadExercise;
+import de.tum.cit.aet.artemis.fileupload.repository.FileUploadExerciseRepository;
+import de.tum.cit.aet.artemis.fileupload.service.FileUploadExerciseImportService;
+import de.tum.cit.aet.artemis.lecture.domain.Lecture;
+import de.tum.cit.aet.artemis.lecture.domain.LectureUnit;
+import de.tum.cit.aet.artemis.lecture.repository.LectureRepository;
+import de.tum.cit.aet.artemis.lecture.repository.LectureUnitRepository;
+import de.tum.cit.aet.artemis.lecture.service.LectureImportService;
+import de.tum.cit.aet.artemis.lecture.service.LectureUnitImportService;
+import de.tum.cit.aet.artemis.modeling.domain.ModelingExercise;
+import de.tum.cit.aet.artemis.modeling.repository.ModelingExerciseRepository;
+import de.tum.cit.aet.artemis.modeling.service.ModelingExerciseImportService;
+import de.tum.cit.aet.artemis.plagiarism.service.PlagiarismDetectionConfigHelper;
+import de.tum.cit.aet.artemis.programming.domain.ProgrammingExercise;
+import de.tum.cit.aet.artemis.programming.repository.ProgrammingExerciseRepository;
+import de.tum.cit.aet.artemis.programming.repository.hestia.ProgrammingExerciseTaskRepository;
+import de.tum.cit.aet.artemis.programming.service.ProgrammingExerciseImportService;
+import de.tum.cit.aet.artemis.quiz.domain.QuizExercise;
+import de.tum.cit.aet.artemis.quiz.repository.QuizExerciseRepository;
+import de.tum.cit.aet.artemis.quiz.service.QuizExerciseImportService;
+import de.tum.cit.aet.artemis.text.domain.TextExercise;
+import de.tum.cit.aet.artemis.text.repository.TextExerciseRepository;
+import de.tum.cit.aet.artemis.text.service.TextExerciseImportService;
+
+/**
+ * Service for importing learning objects related to competencies.
+ */
+@Profile(PROFILE_CORE)
+@Service
+public class LearningObjectImportService {
+
+ private static final Logger log = LoggerFactory.getLogger(LearningObjectImportService.class);
+
+ private final ExerciseRepository exerciseRepository;
+
+ private final ProgrammingExerciseRepository programmingExerciseRepository;
+
+ private final ProgrammingExerciseImportService programmingExerciseImportService;
+
+ private final FileUploadExerciseRepository fileUploadExerciseRepository;
+
+ private final FileUploadExerciseImportService fileUploadExerciseImportService;
+
+ private final ModelingExerciseRepository modelingExerciseRepository;
+
+ private final ModelingExerciseImportService modelingExerciseImportService;
+
+ private final TextExerciseRepository textExerciseRepository;
+
+ private final TextExerciseImportService textExerciseImportService;
+
+ private final QuizExerciseRepository quizExerciseRepository;
+
+ private final QuizExerciseImportService quizExerciseImportService;
+
+ private final LectureRepository lectureRepository;
+
+ private final LectureImportService lectureImportService;
+
+ private final LectureUnitRepository lectureUnitRepository;
+
+ private final LectureUnitImportService lectureUnitImportService;
+
+ private final CourseCompetencyRepository courseCompetencyRepository;
+
+ private final ProgrammingExerciseTaskRepository programmingExerciseTaskRepository;
+
+ private final GradingCriterionRepository gradingCriterionRepository;
+
+ public LearningObjectImportService(ExerciseRepository exerciseRepository, ProgrammingExerciseRepository programmingExerciseRepository,
+ ProgrammingExerciseImportService programmingExerciseImportService, FileUploadExerciseRepository fileUploadExerciseRepository,
+ FileUploadExerciseImportService fileUploadExerciseImportService, ModelingExerciseRepository modelingExerciseRepository,
+ ModelingExerciseImportService modelingExerciseImportService, TextExerciseRepository textExerciseRepository, TextExerciseImportService textExerciseImportService,
+ QuizExerciseRepository quizExerciseRepository, QuizExerciseImportService quizExerciseImportService, LectureRepository lectureRepository,
+ LectureImportService lectureImportService, LectureUnitRepository lectureUnitRepository, LectureUnitImportService lectureUnitImportService,
+ CourseCompetencyRepository courseCompetencyRepository, ProgrammingExerciseTaskRepository programmingExerciseTaskRepository,
+ GradingCriterionRepository gradingCriterionRepository) {
+ this.exerciseRepository = exerciseRepository;
+ this.programmingExerciseRepository = programmingExerciseRepository;
+ this.programmingExerciseImportService = programmingExerciseImportService;
+ this.fileUploadExerciseRepository = fileUploadExerciseRepository;
+ this.fileUploadExerciseImportService = fileUploadExerciseImportService;
+ this.modelingExerciseRepository = modelingExerciseRepository;
+ this.modelingExerciseImportService = modelingExerciseImportService;
+ this.textExerciseRepository = textExerciseRepository;
+ this.textExerciseImportService = textExerciseImportService;
+ this.quizExerciseRepository = quizExerciseRepository;
+ this.quizExerciseImportService = quizExerciseImportService;
+ this.lectureRepository = lectureRepository;
+ this.lectureImportService = lectureImportService;
+ this.lectureUnitRepository = lectureUnitRepository;
+ this.lectureUnitImportService = lectureUnitImportService;
+ this.courseCompetencyRepository = courseCompetencyRepository;
+ this.programmingExerciseTaskRepository = programmingExerciseTaskRepository;
+ this.gradingCriterionRepository = gradingCriterionRepository;
+ }
+
+ /**
+ * Imports the related learning objects from the source course competencies into the course to import into and links them to the imported competencies.
+ *
+ * @param sourceCourseCompetencies The source course competencies to import from.
+ * @param idToImportedCompetency A map from the source competency IDs to the imported competencies.
+ * @param courseToImportInto The course to import the learning objects into.
+ * @param importOptions The import options.
+ */
+ public void importRelatedLearningObjects(Collection extends CourseCompetency> sourceCourseCompetencies, Map idToImportedCompetency,
+ Course courseToImportInto, CompetencyImportOptionsDTO importOptions) {
+ Set importedCourseCompetencies = idToImportedCompetency.values().stream().map(CompetencyWithTailRelationDTO::competency).collect(Collectors.toSet());
+
+ Set importedExercises = new HashSet<>();
+ if (importOptions.importExercises()) {
+ importOrLoadExercises(sourceCourseCompetencies, idToImportedCompetency, courseToImportInto, importedExercises);
+ }
+ Map titleToImportedLectures = new HashMap<>();
+ Set importedLectureUnits = new HashSet<>();
+ if (importOptions.importLectures()) {
+ importOrLoadLectureUnits(sourceCourseCompetencies, idToImportedCompetency, courseToImportInto, titleToImportedLectures, importedLectureUnits);
+ }
+ Set importedLectures = new HashSet<>(titleToImportedLectures.values());
+
+ if (importOptions.referenceDate().isPresent()) {
+ setAllDates(importedExercises, importedLectures, importedLectureUnits, importedCourseCompetencies, importOptions.referenceDate().get(), importOptions.isReleaseDate());
+ }
+
+ courseCompetencyRepository.saveAll(importedCourseCompetencies);
+ exerciseRepository.saveAll(importedExercises);
+ lectureRepository.saveAll(importedLectures);
+ }
+
+ private void importOrLoadExercises(Collection extends CourseCompetency> sourceCourseCompetencies, Map idToImportedCompetency,
+ Course courseToImportInto, Set importedExercises) {
+ for (CourseCompetency sourceCourseCompetency : sourceCourseCompetencies) {
+ for (Exercise sourceExercise : sourceCourseCompetency.getExercises()) {
+ try {
+ Exercise importedExercise = importOrLoadExercise(sourceExercise, courseToImportInto);
+
+ importedExercises.add(importedExercise);
+
+ importedExercise.getCompetencies().add(idToImportedCompetency.get(sourceCourseCompetency.getId()).competency());
+ idToImportedCompetency.get(sourceCourseCompetency.getId()).competency().getExercises().add(importedExercise);
+ }
+ catch (Exception e) {
+ log.error("Failed to import exercise with title {} together with its competency with id {}", sourceExercise.getTitle(), sourceCourseCompetency.getId(), e);
+ }
+ }
+ }
+ }
+
+ private Exercise importOrLoadExercise(Exercise sourceExercise, Course course) throws JsonProcessingException {
+ return switch (sourceExercise) {
+ case ProgrammingExercise programmingExercise -> importOrLoadProgrammingExercise(programmingExercise, course);
+ case FileUploadExercise fileUploadExercise ->
+ importOrLoadExercise(fileUploadExercise, course, fileUploadExerciseRepository::findUniqueWithCompetenciesByTitleAndCourseId,
+ fileUploadExerciseRepository::findWithGradingCriteriaByIdElseThrow, fileUploadExerciseImportService::importFileUploadExercise);
+ case ModelingExercise modelingExercise -> importOrLoadExercise(modelingExercise, course, modelingExerciseRepository::findUniqueWithCompetenciesByTitleAndCourseId,
+ modelingExerciseRepository::findByIdWithExampleSubmissionsAndResultsAndPlagiarismDetectionConfigElseThrow,
+ modelingExerciseImportService::importModelingExercise);
+ case TextExercise textExercise -> importOrLoadExercise(textExercise, course, textExerciseRepository::findUniqueWithCompetenciesByTitleAndCourseId,
+ textExerciseRepository::findByIdWithExampleSubmissionsAndResultsAndGradingCriteriaElseThrow, textExerciseImportService::importTextExercise);
+ case QuizExercise quizExercise -> importOrLoadExercise(quizExercise, course, quizExerciseRepository::findUniqueWithCompetenciesByTitleAndCourseId,
+ quizExerciseRepository::findByIdWithQuestionsAndStatisticsAndCompetenciesAndBatchesAndGradingCriteriaElseThrow, (exercise, templateExercise) -> {
+ try {
+ return quizExerciseImportService.importQuizExercise(exercise, templateExercise, null);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ });
+ default -> throw new IllegalStateException("Unexpected value: " + sourceExercise);
+ };
+ }
+
+ private Exercise importOrLoadProgrammingExercise(ProgrammingExercise programmingExercise, Course course) throws JsonProcessingException {
+ Optional foundByTitle = programmingExerciseRepository.findWithCompetenciesByTitleAndCourseId(programmingExercise.getTitle(), course.getId());
+ Optional foundByShortName = programmingExerciseRepository.findByShortNameAndCourseIdWithCompetencies(programmingExercise.getShortName(),
+ course.getId());
+
+ if (foundByTitle.isPresent() && foundByShortName.isPresent() && !foundByTitle.get().equals(foundByShortName.get())) {
+ throw new IllegalArgumentException("Two programming exercises with the title or short name already exist in the course");
+ }
+
+ if (foundByTitle.isPresent()) {
+ return foundByTitle.get();
+ }
+ else if (foundByShortName.isPresent()) {
+ return foundByShortName.get();
+ }
+ else {
+ programmingExercise = programmingExerciseRepository.findByIdForImportElseThrow(programmingExercise.getId());
+ // Fetching the tasks separately, as putting it in the query above leads to Hibernate duplicating the tasks.
+ var templateTasks = programmingExerciseTaskRepository.findByExerciseIdWithTestCases(programmingExercise.getId());
+ programmingExercise.setTasks(new ArrayList<>(templateTasks));
+ Set gradingCriteria = gradingCriterionRepository.findByExerciseIdWithEagerGradingCriteria(programmingExercise.getId());
+ programmingExercise.setGradingCriteria(gradingCriteria);
+
+ ProgrammingExercise newExercise = programmingExerciseRepository
+ .findByIdWithTemplateAndSolutionParticipationTeamAssignmentConfigCategoriesAndCompetenciesAndPlagiarismDetectionConfigAndBuildConfigElseThrow(
+ programmingExercise.getId());
+ PlagiarismDetectionConfigHelper.createAndSaveDefaultIfNullAndCourseExercise(newExercise, programmingExerciseRepository);
+ newExercise.setCourse(course);
+ newExercise.forceNewProjectKey();
+
+ clearProgrammingExerciseAttributes(newExercise);
+
+ return programmingExerciseImportService.importProgrammingExercise(programmingExercise, newExercise, false, false, false);
+ }
+ }
+
+ private void clearProgrammingExerciseAttributes(ProgrammingExercise programmingExercise) {
+ programmingExercise.setTasks(null);
+ programmingExercise.setExerciseHints(new HashSet<>());
+ programmingExercise.setTestCases(new HashSet<>());
+ programmingExercise.setStaticCodeAnalysisCategories(new HashSet<>());
+ programmingExercise.setTeams(new HashSet<>());
+ programmingExercise.setGradingCriteria(new HashSet<>());
+ programmingExercise.setStudentParticipations(new HashSet<>());
+ programmingExercise.setTutorParticipations(new HashSet<>());
+ programmingExercise.setExampleSubmissions(new HashSet<>());
+ programmingExercise.setAttachments(new HashSet<>());
+ programmingExercise.setPosts(new HashSet<>());
+ programmingExercise.setPlagiarismCases(new HashSet<>());
+ programmingExercise.setCompetencies(new HashSet<>());
+ }
+
+ /**
+ * Imports or loads an exercise.
+ *
+ * @param exercise The source exercise for the import
+ * @param course The course to import the exercise into
+ * @param findFunction The function to find an existing exercise by title
+ * @param loadForImport The function to load an exercise for import
+ * @param importFunction The function to import the exercise
+ * @return The imported or loaded exercise
+ * @param The type of the exercise
+ */
+ private Exercise importOrLoadExercise(E exercise, Course course, ThrowingBiFunction> findFunction,
+ Function loadForImport, BiFunction importFunction) {
+ Optional foundByTitle = findFunction.apply(exercise.getTitle(), course.getId());
+ if (foundByTitle.isPresent()) {
+ return foundByTitle.get();
+ }
+ else {
+ exercise = loadForImport.apply(exercise.getId());
+ exercise.setCourse(course);
+ exercise.setId(null);
+ exercise.setCompetencies(new HashSet<>());
+
+ return importFunction.apply(exercise, exercise);
+ }
+ }
+
+ /**
+ * Imports or loads a lecture unit. If the lecture unit needs to be imported, the lecture is imported or loaded as well.
+ *
+ * @param sourceCourseCompetencies The source course competencies to import from
+ * @param idToImportedCompetency A map from the source competency IDs to the imported competencies
+ * @param courseToImportInto The course to import the lecture unit into
+ * @param titleToImportedLectures A map from the source lecture titles to the imported lectures
+ * @param importedLectureUnits The set of imported lecture units
+ */
+ private void importOrLoadLectureUnits(Collection extends CourseCompetency> sourceCourseCompetencies, Map idToImportedCompetency,
+ Course courseToImportInto, Map titleToImportedLectures, Set importedLectureUnits) {
+ for (CourseCompetency sourceCourseCompetency : sourceCourseCompetencies) {
+ for (LectureUnit sourceLectureUnit : sourceCourseCompetency.getLectureUnits()) {
+ try {
+ importOrLoadLectureUnit(sourceLectureUnit, sourceCourseCompetency, idToImportedCompetency, courseToImportInto, titleToImportedLectures, importedLectureUnits);
+ }
+ catch (Exception e) {
+ log.error("Failed to import lecture unit with name {} together with its competency with id {}", sourceLectureUnit.getName(), sourceCourseCompetency.getId(), e);
+ }
+ }
+ }
+ }
+
+ private void importOrLoadLectureUnit(LectureUnit sourceLectureUnit, CourseCompetency sourceCourseCompetency, Map idToImportedCompetency,
+ Course courseToImportInto, Map titleToImportedLectures, Set importedLectureUnits) throws NoUniqueQueryException {
+ Lecture sourceLecture = sourceLectureUnit.getLecture();
+ Lecture importedLecture = importOrLoadLecture(sourceLecture, courseToImportInto, titleToImportedLectures);
+
+ Optional foundLectureUnit = lectureUnitRepository.findByNameAndLectureTitleAndCourseIdWithCompetencies(sourceLectureUnit.getName(), sourceLecture.getTitle(),
+ courseToImportInto.getId());
+ LectureUnit importedLectureUnit;
+ if (foundLectureUnit.isEmpty()) {
+ importedLectureUnit = lectureUnitImportService.importLectureUnit(sourceLectureUnit);
+
+ importedLecture.getLectureUnits().add(importedLectureUnit);
+ importedLectureUnit.setLecture(importedLecture);
+ }
+ else {
+ importedLectureUnit = foundLectureUnit.get();
+ }
+
+ importedLectureUnits.add(importedLectureUnit);
+
+ importedLectureUnit.getCompetencies().add(idToImportedCompetency.get(sourceCourseCompetency.getId()).competency());
+ idToImportedCompetency.get(sourceCourseCompetency.getId()).competency().getLectureUnits().add(importedLectureUnit);
+ }
+
+ private Lecture importOrLoadLecture(Lecture sourceLecture, Course courseToImportInto, Map titleToImportedLectures) throws NoUniqueQueryException {
+ Optional foundLecture = Optional.ofNullable(titleToImportedLectures.get(sourceLecture.getTitle()));
+ if (foundLecture.isEmpty()) {
+ foundLecture = lectureRepository.findUniqueByTitleAndCourseIdWithLectureUnitsElseThrow(sourceLecture.getTitle(), courseToImportInto.getId());
+ }
+ Lecture importedLecture = foundLecture.orElseGet(() -> lectureImportService.importLecture(sourceLecture, courseToImportInto, false));
+ titleToImportedLectures.put(importedLecture.getTitle(), importedLecture);
+
+ return importedLecture;
+ }
+
+ private void setAllDates(Set importedExercises, Set importedLectures, Set importedLectureUnits,
+ Set importedCourseCompetencies, ZonedDateTime referenceDate, boolean isReleaseDate) {
+ long timeOffset = determineTimeOffset(importedExercises, importedLectures, importedLectureUnits, importedCourseCompetencies, referenceDate, isReleaseDate);
+ if (timeOffset == 0) {
+ return;
+ }
+
+ importedExercises.forEach(exercise -> setAllExerciseDates(exercise, timeOffset));
+ importedLectures.forEach(lecture -> setAllLectureDates(lecture, timeOffset));
+ importedLectureUnits.forEach(lectureUnit -> setAllLectureUnitDates(lectureUnit, timeOffset));
+ importedCourseCompetencies.forEach(competency -> setAllCompetencyDates(competency, timeOffset));
+ }
+
+ /**
+ * Finds the earliest relevant time and determines the time offset to apply to the dates of the imported learning objects.
+ *
+ * @param importedExercises The imported exercises
+ * @param importedLectures The imported lectures
+ * @param importedLectureUnits The imported lecture units
+ * @param importedCourseCompetencies The imported competencies
+ * @param referenceDate The reference date to calculate the offset from
+ * @param isReleaseDate Whether the offset is for the release date or the due date
+ * @return The time offset to apply
+ */
+ private long determineTimeOffset(Set importedExercises, Set importedLectures, Set importedLectureUnits,
+ Set importedCourseCompetencies, ZonedDateTime referenceDate, boolean isReleaseDate) {
+ Optional earliestTime;
+
+ if (isReleaseDate) {
+ Stream exerciseDates = importedExercises.stream().map(Exercise::getReleaseDate);
+ Stream lectureDates = importedLectures.stream().map(Lecture::getVisibleDate);
+ Stream lectureUnitDates = importedLectureUnits.stream().map(LectureUnit::getReleaseDate);
+ earliestTime = Stream.concat(exerciseDates, Stream.concat(lectureDates, lectureUnitDates)).filter(Objects::nonNull).min(Comparator.naturalOrder());
+ }
+ else {
+ Stream exerciseDates = importedExercises.stream().map(Exercise::getDueDate);
+ Stream lectureDates = importedLectures.stream().map(Lecture::getEndDate);
+ Stream competencyDates = importedCourseCompetencies.stream().map(CourseCompetency::getSoftDueDate);
+ earliestTime = Stream.concat(exerciseDates, Stream.concat(lectureDates, competencyDates)).filter(Objects::nonNull).min(Comparator.naturalOrder());
+ }
+
+ return earliestTime.map(zonedDateTime -> referenceDate.toEpochSecond() - zonedDateTime.toEpochSecond()).orElse(0L);
+ }
+
+ private void setAllExerciseDates(Exercise exercise, long timeOffset) {
+ if (exercise.getReleaseDate() != null) {
+ exercise.setReleaseDate(exercise.getReleaseDate().plusSeconds(timeOffset));
+ }
+ if (exercise.getStartDate() != null) {
+ exercise.setStartDate(exercise.getStartDate().plusSeconds(timeOffset));
+ }
+ if (exercise.getDueDate() != null) {
+ exercise.setDueDate(exercise.getDueDate().plusSeconds(timeOffset));
+ }
+ if (exercise.getAssessmentDueDate() != null) {
+ exercise.setAssessmentDueDate(exercise.getAssessmentDueDate().plusSeconds(timeOffset));
+ }
+ if (exercise.getExampleSolutionPublicationDate() != null) {
+ exercise.setExampleSolutionPublicationDate(exercise.getExampleSolutionPublicationDate().plusSeconds(timeOffset));
+ }
+
+ if (exercise instanceof QuizExercise quizExercise && !quizExercise.getQuizBatches().isEmpty()) {
+ quizExercise.getQuizBatches().forEach(batch -> {
+ if (batch.getStartTime() != null) {
+ batch.setStartTime(batch.getStartTime().plusSeconds(timeOffset));
+ }
+ });
+ }
+
+ if (exercise instanceof ProgrammingExercise programmingExercise && programmingExercise.getBuildAndTestStudentSubmissionsAfterDueDate() != null) {
+ programmingExercise.setBuildAndTestStudentSubmissionsAfterDueDate(programmingExercise.getBuildAndTestStudentSubmissionsAfterDueDate().plusSeconds(timeOffset));
+ }
+ }
+
+ private void setAllLectureDates(Lecture lecture, long timeOffset) {
+ if (lecture.getVisibleDate() != null) {
+ lecture.setVisibleDate(lecture.getVisibleDate().plusSeconds(timeOffset));
+ }
+ if (lecture.getStartDate() != null) {
+ lecture.setStartDate(lecture.getStartDate().plusSeconds(timeOffset));
+ }
+ if (lecture.getEndDate() != null) {
+ lecture.setEndDate(lecture.getEndDate().plusSeconds(timeOffset));
+ }
+ }
+
+ private void setAllLectureUnitDates(LectureUnit lectureUnit, long timeOffset) {
+ if (lectureUnit.getReleaseDate() != null) {
+ lectureUnit.setReleaseDate(lectureUnit.getReleaseDate().plusSeconds(timeOffset));
+ }
+ }
+
+ private void setAllCompetencyDates(CourseCompetency competency, long timeOffset) {
+ if (competency.getSoftDueDate() != null) {
+ competency.setSoftDueDate(competency.getSoftDueDate().plusSeconds(timeOffset));
+ }
+ }
+}
diff --git a/src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CompetencyJolService.java b/src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CompetencyJolService.java
index 8deffa786626..1011cacaf450 100644
--- a/src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CompetencyJolService.java
+++ b/src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CompetencyJolService.java
@@ -86,9 +86,7 @@ public void setJudgementOfLearning(long competencyId, long userId, short jolValu
irisCourseChatSessionService.ifPresent(service -> {
// Inform Iris so it can send a message to the user
try {
- if (userId % 3 > 0) { // HD3-GROUPS: Iris groups are 1 & 2
- service.onJudgementOfLearningSet(jol);
- }
+ service.onJudgementOfLearningSet(jol);
}
catch (Exception e) {
log.warn("Something went wrong while sending the judgement of learning to Iris", e);
diff --git a/src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CompetencyService.java b/src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CompetencyService.java
index 9217aa5196ad..9ec942846bf8 100644
--- a/src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CompetencyService.java
+++ b/src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CompetencyService.java
@@ -13,12 +13,14 @@
import de.tum.cit.aet.artemis.atlas.domain.competency.Competency;
import de.tum.cit.aet.artemis.atlas.domain.competency.CourseCompetency;
+import de.tum.cit.aet.artemis.atlas.dto.CompetencyImportOptionsDTO;
import de.tum.cit.aet.artemis.atlas.dto.CompetencyWithTailRelationDTO;
import de.tum.cit.aet.artemis.atlas.repository.CompetencyProgressRepository;
import de.tum.cit.aet.artemis.atlas.repository.CompetencyRelationRepository;
import de.tum.cit.aet.artemis.atlas.repository.CompetencyRepository;
import de.tum.cit.aet.artemis.atlas.repository.CourseCompetencyRepository;
import de.tum.cit.aet.artemis.atlas.repository.StandardizedCompetencyRepository;
+import de.tum.cit.aet.artemis.atlas.service.LearningObjectImportService;
import de.tum.cit.aet.artemis.atlas.service.learningpath.LearningPathService;
import de.tum.cit.aet.artemis.core.domain.Course;
import de.tum.cit.aet.artemis.core.service.AuthorizationCheckService;
@@ -38,20 +40,22 @@ public class CompetencyService extends CourseCompetencyService {
public CompetencyService(CompetencyRepository competencyRepository, AuthorizationCheckService authCheckService, CompetencyRelationRepository competencyRelationRepository,
LearningPathService learningPathService, CompetencyProgressService competencyProgressService, LectureUnitService lectureUnitService,
CompetencyProgressRepository competencyProgressRepository, LectureUnitCompletionRepository lectureUnitCompletionRepository,
- StandardizedCompetencyRepository standardizedCompetencyRepository, CourseCompetencyRepository courseCompetencyRepository, ExerciseService exerciseService) {
+ StandardizedCompetencyRepository standardizedCompetencyRepository, CourseCompetencyRepository courseCompetencyRepository, ExerciseService exerciseService,
+ LearningObjectImportService learningObjectImportService) {
super(competencyProgressRepository, courseCompetencyRepository, competencyRelationRepository, competencyProgressService, exerciseService, lectureUnitService,
- learningPathService, authCheckService, standardizedCompetencyRepository, lectureUnitCompletionRepository);
+ learningPathService, authCheckService, standardizedCompetencyRepository, lectureUnitCompletionRepository, learningObjectImportService);
this.competencyRepository = competencyRepository;
}
/**
* Imports the given competencies and relations into a course
*
- * @param course the course to import into
- * @param competencies the competencies to import
+ * @param course the course to import into
+ * @param competencies the competencies to import
+ * @param importOptions the options for importing the competencies
* @return The set of imported competencies, each also containing the relations it is the tail competency for.
*/
- public Set importCompetenciesAndRelations(Course course, Collection extends CourseCompetency> competencies) {
+ public Set importCompetencies(Course course, Collection extends CourseCompetency> competencies, CompetencyImportOptionsDTO importOptions) {
var idToImportedCompetency = new HashMap();
for (var competency : competencies) {
@@ -62,7 +66,7 @@ public Set importCompetenciesAndRelations(Course
idToImportedCompetency.put(competency.getId(), new CompetencyWithTailRelationDTO(importedCompetency, new ArrayList<>()));
}
- return importCourseCompetenciesAndRelations(course, idToImportedCompetency);
+ return importCourseCompetencies(course, competencies, idToImportedCompetency, importOptions);
}
/**
@@ -76,17 +80,6 @@ public List importStandardizedCompetencies(List competen
return super.importStandardizedCompetencies(competencyIdsToImport, course, Competency::new);
}
- /**
- * Imports the given course competencies into a course
- *
- * @param course the course to import into
- * @param competencies the course competencies to import
- * @return The list of imported competencies
- */
- public Set importCompetencies(Course course, Collection extends CourseCompetency> competencies) {
- return importCourseCompetencies(course, competencies, Competency::new);
- }
-
/**
* Creates a new competency and links it to a course and lecture units.
*
diff --git a/src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CourseCompetencyService.java b/src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CourseCompetencyService.java
index 05b4f0bca77e..01eb37cf8271 100644
--- a/src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CourseCompetencyService.java
+++ b/src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CourseCompetencyService.java
@@ -24,12 +24,14 @@
import de.tum.cit.aet.artemis.atlas.domain.competency.CourseCompetency;
import de.tum.cit.aet.artemis.atlas.domain.competency.Prerequisite;
import de.tum.cit.aet.artemis.atlas.domain.competency.StandardizedCompetency;
+import de.tum.cit.aet.artemis.atlas.dto.CompetencyImportOptionsDTO;
import de.tum.cit.aet.artemis.atlas.dto.CompetencyRelationDTO;
import de.tum.cit.aet.artemis.atlas.dto.CompetencyWithTailRelationDTO;
import de.tum.cit.aet.artemis.atlas.repository.CompetencyProgressRepository;
import de.tum.cit.aet.artemis.atlas.repository.CompetencyRelationRepository;
import de.tum.cit.aet.artemis.atlas.repository.CourseCompetencyRepository;
import de.tum.cit.aet.artemis.atlas.repository.StandardizedCompetencyRepository;
+import de.tum.cit.aet.artemis.atlas.service.LearningObjectImportService;
import de.tum.cit.aet.artemis.atlas.service.learningpath.LearningPathService;
import de.tum.cit.aet.artemis.core.domain.Course;
import de.tum.cit.aet.artemis.core.domain.User;
@@ -73,10 +75,13 @@ public class CourseCompetencyService {
protected final LectureUnitCompletionRepository lectureUnitCompletionRepository;
+ private final LearningObjectImportService learningObjectImportService;
+
public CourseCompetencyService(CompetencyProgressRepository competencyProgressRepository, CourseCompetencyRepository courseCompetencyRepository,
CompetencyRelationRepository competencyRelationRepository, CompetencyProgressService competencyProgressService, ExerciseService exerciseService,
LectureUnitService lectureUnitService, LearningPathService learningPathService, AuthorizationCheckService authCheckService,
- StandardizedCompetencyRepository standardizedCompetencyRepository, LectureUnitCompletionRepository lectureUnitCompletionRepository) {
+ StandardizedCompetencyRepository standardizedCompetencyRepository, LectureUnitCompletionRepository lectureUnitCompletionRepository,
+ LearningObjectImportService learningObjectImportService) {
this.competencyProgressRepository = competencyProgressRepository;
this.courseCompetencyRepository = courseCompetencyRepository;
this.competencyRelationRepository = competencyRelationRepository;
@@ -87,6 +92,7 @@ public CourseCompetencyService(CompetencyProgressRepository competencyProgressRe
this.authCheckService = authCheckService;
this.standardizedCompetencyRepository = standardizedCompetencyRepository;
this.lectureUnitCompletionRepository = lectureUnitCompletionRepository;
+ this.learningObjectImportService = learningObjectImportService;
}
/**
@@ -158,9 +164,10 @@ public void filterOutLearningObjectsThatUserShouldNotSee(CourseCompetency compet
*
* @param course the course to import into
* @param courseCompetencies the course competencies to import
+ * @param importOptions the import options
* @return The set of imported course competencies, each also containing the relations it is the tail competency for.
*/
- public Set importCourseCompetenciesAndRelations(Course course, Collection courseCompetencies) {
+ public Set importCourseCompetencies(Course course, Collection courseCompetencies, CompetencyImportOptionsDTO importOptions) {
var idToImportedCompetency = new HashMap();
for (var courseCompetency : courseCompetencies) {
@@ -175,37 +182,45 @@ public Set importCourseCompetenciesAndRelations(C
idToImportedCompetency.put(courseCompetency.getId(), new CompetencyWithTailRelationDTO(importedCompetency, new ArrayList<>()));
}
- return importCourseCompetenciesAndRelations(course, idToImportedCompetency);
+ return importCourseCompetencies(course, courseCompetencies, idToImportedCompetency, importOptions);
}
/**
* Imports the given competencies and relations into a course
*
* @param course the course to import into
+ * @param competenciesToImport the source competencies that were imported
* @param idToImportedCompetency map of original competency id to imported competency
+ * @param importOptions the import options
* @return The set of imported competencies, each also containing the relations it is the tail competency for.
*/
- public Set importCourseCompetenciesAndRelations(Course course, Map idToImportedCompetency) {
+ public Set importCourseCompetencies(Course course, Collection extends CourseCompetency> competenciesToImport,
+ Map idToImportedCompetency, CompetencyImportOptionsDTO importOptions) {
if (course.getLearningPathsEnabled()) {
var importedCompetencies = idToImportedCompetency.values().stream().map(CompetencyWithTailRelationDTO::competency).toList();
learningPathService.linkCompetenciesToLearningPathsOfCourse(importedCompetencies, course.getId());
}
- var originalCompetencyIds = idToImportedCompetency.keySet();
- var relations = competencyRelationRepository.findAllByHeadCompetencyIdInAndTailCompetencyIdIn(originalCompetencyIds, originalCompetencyIds);
+ if (importOptions.importRelations()) {
+ var originalCompetencyIds = idToImportedCompetency.keySet();
+ var relations = competencyRelationRepository.findAllByHeadCompetencyIdInAndTailCompetencyIdIn(originalCompetencyIds, originalCompetencyIds);
- for (var relation : relations) {
- var tailCompetencyDTO = idToImportedCompetency.get(relation.getTailCompetency().getId());
- var headCompetencyDTO = idToImportedCompetency.get(relation.getHeadCompetency().getId());
+ for (var relation : relations) {
+ var tailCompetencyDTO = idToImportedCompetency.get(relation.getTailCompetency().getId());
+ var headCompetencyDTO = idToImportedCompetency.get(relation.getHeadCompetency().getId());
- CompetencyRelation relationToImport = new CompetencyRelation();
- relationToImport.setType(relation.getType());
- relationToImport.setTailCompetency(tailCompetencyDTO.competency());
- relationToImport.setHeadCompetency(headCompetencyDTO.competency());
+ CompetencyRelation relationToImport = new CompetencyRelation();
+ relationToImport.setType(relation.getType());
+ relationToImport.setTailCompetency(tailCompetencyDTO.competency());
+ relationToImport.setHeadCompetency(headCompetencyDTO.competency());
- relationToImport = competencyRelationRepository.save(relationToImport);
- tailCompetencyDTO.tailRelations().add(CompetencyRelationDTO.of(relationToImport));
+ relationToImport = competencyRelationRepository.save(relationToImport);
+ tailCompetencyDTO.tailRelations().add(CompetencyRelationDTO.of(relationToImport));
+ }
}
+
+ learningObjectImportService.importRelatedLearningObjects(competenciesToImport, idToImportedCompetency, course, importOptions);
+
return new HashSet<>(idToImportedCompetency.values());
}
@@ -247,51 +262,6 @@ public List importStandardizedCompetencies(List competen
return importedCompetencies;
}
- /**
- * Imports the given course competencies into a course
- *
- * @param course the course to import into
- * @param courseCompetencies the course competencies to import
- * @return The list of imported competencies
- */
- public Set importCourseCompetencies(Course course, Collection courseCompetencies) {
- Function courseCompetencyFunction = courseCompetency -> switch (courseCompetency) {
- case Competency competency -> new Competency(competency);
- case Prerequisite prerequisite -> new Prerequisite(prerequisite);
- default -> throw new IllegalStateException("Unexpected value: " + courseCompetency);
- };
- return importCourseCompetencies(course, courseCompetencies, courseCompetencyFunction);
- }
-
- /**
- * Imports the given course competencies into a course
- *
- * @param course the course to import into
- * @param competencies the course competencies to import
- * @param courseCompetencyFunction the function that creates new course competencies
- * @return The set of imported competencies
- */
- public Set importCourseCompetencies(Course course, Collection extends CourseCompetency> competencies,
- Function courseCompetencyFunction) {
- var importedCompetencies = new ArrayList();
- Set createdDTOs = new HashSet<>();
-
- for (var competency : competencies) {
- CourseCompetency importedCompetency = courseCompetencyFunction.apply(competency);
- importedCompetency.setCourse(course);
-
- importedCompetency = courseCompetencyRepository.save(importedCompetency);
- importedCompetencies.add(importedCompetency);
- createdDTOs.add(new CompetencyWithTailRelationDTO(importedCompetency, Collections.emptyList()));
- }
-
- if (course.getLearningPathsEnabled()) {
- learningPathService.linkCompetenciesToLearningPathsOfCourse(importedCompetencies, course.getId());
- }
-
- return createdDTOs;
- }
-
/**
* Creates a new competency and links it to a course and lecture units.
* If learning paths are enabled, the competency is also linked to the learning paths of the course.
diff --git a/src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/LearningObjectImportService.java b/src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/LearningObjectImportService.java
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/PrerequisiteService.java b/src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/PrerequisiteService.java
index aff6e8927bd7..3fc520a21378 100644
--- a/src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/PrerequisiteService.java
+++ b/src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/PrerequisiteService.java
@@ -13,12 +13,14 @@
import de.tum.cit.aet.artemis.atlas.domain.competency.CourseCompetency;
import de.tum.cit.aet.artemis.atlas.domain.competency.Prerequisite;
+import de.tum.cit.aet.artemis.atlas.dto.CompetencyImportOptionsDTO;
import de.tum.cit.aet.artemis.atlas.dto.CompetencyWithTailRelationDTO;
import de.tum.cit.aet.artemis.atlas.repository.CompetencyProgressRepository;
import de.tum.cit.aet.artemis.atlas.repository.CompetencyRelationRepository;
import de.tum.cit.aet.artemis.atlas.repository.CourseCompetencyRepository;
import de.tum.cit.aet.artemis.atlas.repository.PrerequisiteRepository;
import de.tum.cit.aet.artemis.atlas.repository.StandardizedCompetencyRepository;
+import de.tum.cit.aet.artemis.atlas.service.LearningObjectImportService;
import de.tum.cit.aet.artemis.atlas.service.learningpath.LearningPathService;
import de.tum.cit.aet.artemis.core.domain.Course;
import de.tum.cit.aet.artemis.core.service.AuthorizationCheckService;
@@ -38,9 +40,10 @@ public class PrerequisiteService extends CourseCompetencyService {
public PrerequisiteService(PrerequisiteRepository prerequisiteRepository, AuthorizationCheckService authCheckService, CompetencyRelationRepository competencyRelationRepository,
LearningPathService learningPathService, CompetencyProgressService competencyProgressService, LectureUnitService lectureUnitService,
CompetencyProgressRepository competencyProgressRepository, LectureUnitCompletionRepository lectureUnitCompletionRepository,
- StandardizedCompetencyRepository standardizedCompetencyRepository, CourseCompetencyRepository courseCompetencyRepository, ExerciseService exerciseService) {
+ StandardizedCompetencyRepository standardizedCompetencyRepository, CourseCompetencyRepository courseCompetencyRepository, ExerciseService exerciseService,
+ LearningObjectImportService learningObjectImportService) {
super(competencyProgressRepository, courseCompetencyRepository, competencyRelationRepository, competencyProgressService, exerciseService, lectureUnitService,
- learningPathService, authCheckService, standardizedCompetencyRepository, lectureUnitCompletionRepository);
+ learningPathService, authCheckService, standardizedCompetencyRepository, lectureUnitCompletionRepository, learningObjectImportService);
this.prerequisiteRepository = prerequisiteRepository;
}
@@ -49,9 +52,10 @@ public PrerequisiteService(PrerequisiteRepository prerequisiteRepository, Author
*
* @param course the course to import into
* @param prerequisites the prerequisites to import
+ * @param importOptions the options for importing the prerequisites
* @return The set of imported prerequisites, each also containing the relations for which it is the tail prerequisite for.
*/
- public Set importPrerequisitesAndRelations(Course course, Collection extends CourseCompetency> prerequisites) {
+ public Set importPrerequisites(Course course, Collection extends CourseCompetency> prerequisites, CompetencyImportOptionsDTO importOptions) {
var idToImportedPrerequisite = new HashMap();
for (var prerequisite : prerequisites) {
@@ -62,7 +66,7 @@ public Set importPrerequisitesAndRelations(Course
idToImportedPrerequisite.put(prerequisite.getId(), new CompetencyWithTailRelationDTO(importedPrerequisite, new ArrayList<>()));
}
- return importCourseCompetenciesAndRelations(course, idToImportedPrerequisite);
+ return importCourseCompetencies(course, prerequisites, idToImportedPrerequisite, importOptions);
}
/**
@@ -76,17 +80,6 @@ public List importStandardizedPrerequisites(List prerequ
return super.importStandardizedCompetencies(prerequisiteIdsToImport, course, Prerequisite::new);
}
- /**
- * Imports the given course prerequisites into a course
- *
- * @param course the course to import into
- * @param prerequisites the course prerequisites to import
- * @return The list of imported prerequisites
- */
- public Set importPrerequisites(Course course, Collection extends CourseCompetency> prerequisites) {
- return importCourseCompetencies(course, prerequisites, Prerequisite::new);
- }
-
/**
* Creates a new prerequisite and links it to a course and lecture units.
*
diff --git a/src/main/java/de/tum/cit/aet/artemis/atlas/service/learningpath/LearningPathService.java b/src/main/java/de/tum/cit/aet/artemis/atlas/service/learningpath/LearningPathService.java
index 937123a30fe1..ea2a4bd9ec37 100644
--- a/src/main/java/de/tum/cit/aet/artemis/atlas/service/learningpath/LearningPathService.java
+++ b/src/main/java/de/tum/cit/aet/artemis/atlas/service/learningpath/LearningPathService.java
@@ -25,6 +25,7 @@
import de.tum.cit.aet.artemis.atlas.dto.CompetencyGraphEdgeDTO;
import de.tum.cit.aet.artemis.atlas.dto.CompetencyGraphNodeDTO;
import de.tum.cit.aet.artemis.atlas.dto.LearningPathCompetencyGraphDTO;
+import de.tum.cit.aet.artemis.atlas.dto.LearningPathDTO;
import de.tum.cit.aet.artemis.atlas.dto.LearningPathHealthDTO;
import de.tum.cit.aet.artemis.atlas.dto.LearningPathInformationDTO;
import de.tum.cit.aet.artemis.atlas.dto.LearningPathNavigationOverviewDTO;
@@ -32,6 +33,7 @@
import de.tum.cit.aet.artemis.atlas.repository.CompetencyProgressRepository;
import de.tum.cit.aet.artemis.atlas.repository.CompetencyRelationRepository;
import de.tum.cit.aet.artemis.atlas.repository.CompetencyRepository;
+import de.tum.cit.aet.artemis.atlas.repository.CourseCompetencyRepository;
import de.tum.cit.aet.artemis.atlas.repository.LearningPathRepository;
import de.tum.cit.aet.artemis.atlas.service.competency.CompetencyProgressService;
import de.tum.cit.aet.artemis.core.domain.Course;
@@ -39,6 +41,7 @@
import de.tum.cit.aet.artemis.core.dto.SearchResultPageDTO;
import de.tum.cit.aet.artemis.core.dto.pageablesearch.SearchTermPageableSearchDTO;
import de.tum.cit.aet.artemis.core.exception.AccessForbiddenException;
+import de.tum.cit.aet.artemis.core.exception.ConflictException;
import de.tum.cit.aet.artemis.core.repository.CourseRepository;
import de.tum.cit.aet.artemis.core.repository.UserRepository;
import de.tum.cit.aet.artemis.core.util.PageUtil;
@@ -87,10 +90,13 @@ public class LearningPathService {
private final StudentParticipationRepository studentParticipationRepository;
+ private final CourseCompetencyRepository courseCompetencyRepository;
+
public LearningPathService(UserRepository userRepository, LearningPathRepository learningPathRepository, CompetencyProgressRepository competencyProgressRepository,
LearningPathNavigationService learningPathNavigationService, CourseRepository courseRepository, CompetencyRepository competencyRepository,
CompetencyRelationRepository competencyRelationRepository, LearningPathNgxService learningPathNgxService,
- LectureUnitCompletionRepository lectureUnitCompletionRepository, StudentParticipationRepository studentParticipationRepository) {
+ LectureUnitCompletionRepository lectureUnitCompletionRepository, StudentParticipationRepository studentParticipationRepository,
+ CourseCompetencyRepository courseCompetencyRepository) {
this.userRepository = userRepository;
this.learningPathRepository = learningPathRepository;
this.competencyProgressRepository = competencyProgressRepository;
@@ -101,6 +107,7 @@ public LearningPathService(UserRepository userRepository, LearningPathRepository
this.learningPathNgxService = learningPathNgxService;
this.lectureUnitCompletionRepository = lectureUnitCompletionRepository;
this.studentParticipationRepository = studentParticipationRepository;
+ this.courseCompetencyRepository = courseCompetencyRepository;
}
/**
@@ -243,6 +250,52 @@ private void updateLearningPathProgress(@NotNull LearningPath learningPath) {
log.debug("Updated LearningPath (id={}) for user (id={})", learningPath.getId(), userId);
}
+ /**
+ * Get the learning path for the current user in the given course.
+ *
+ * @param courseId the id of the course
+ * @return the learning path of the current user
+ */
+ public LearningPathDTO getLearningPathForCurrentUser(long courseId) {
+ final var currentUser = userRepository.getUser();
+ final var learningPath = learningPathRepository.findByCourseIdAndUserIdElseThrow(courseId, currentUser.getId());
+ return LearningPathDTO.of(learningPath);
+ }
+
+ /**
+ * Generate a learning path for the current user in the given course.
+ *
+ * @param courseId the id of the course
+ * @return the generated learning path
+ */
+ public LearningPathDTO generateLearningPathForCurrentUser(long courseId) {
+ final var currentUser = userRepository.getUser();
+ final var course = courseRepository.findWithEagerCompetenciesAndPrerequisitesByIdElseThrow(courseId);
+ if (learningPathRepository.findByCourseIdAndUserId(courseId, currentUser.getId()).isPresent()) {
+ throw new ConflictException("Learning path already exists.", "LearningPath", "learningPathAlreadyExists");
+ }
+ final var learningPath = generateLearningPathForUser(course, currentUser);
+ return LearningPathDTO.of(learningPath);
+ }
+
+ /**
+ * Start the learning path for the current user
+ *
+ * @param learningPathId the id of the learning path
+ */
+ public void startLearningPathForCurrentUser(long learningPathId) {
+ final var learningPath = learningPathRepository.findByIdElseThrow(learningPathId);
+ final var currentUser = userRepository.getUser();
+ if (!learningPath.getUser().equals(currentUser)) {
+ throw new AccessForbiddenException("You are not allowed to start this learning path.");
+ }
+ else if (learningPath.isStartedByStudent()) {
+ throw new ConflictException("Learning path already started.", "LearningPath", "learningPathAlreadyStarted");
+ }
+ learningPath.setStartedByStudent(true);
+ learningPathRepository.save(learningPath);
+ }
+
/**
* Gets the health status of learning paths for the given course.
*
@@ -250,20 +303,11 @@ private void updateLearningPathProgress(@NotNull LearningPath learningPath) {
* @return dto containing the health status and additional information (missing learning paths) if needed
*/
public LearningPathHealthDTO getHealthStatusForCourse(@NotNull Course course) {
- if (!course.getLearningPathsEnabled()) {
- return new LearningPathHealthDTO(Set.of(LearningPathHealthDTO.HealthStatus.DISABLED));
- }
-
Set status = new HashSet<>();
Long numberOfMissingLearningPaths = checkMissingLearningPaths(course, status);
checkNoCompetencies(course, status);
checkNoRelations(course, status);
- // if no issues where found, add OK status
- if (status.isEmpty()) {
- status.add(LearningPathHealthDTO.HealthStatus.OK);
- }
-
return new LearningPathHealthDTO(status, numberOfMissingLearningPaths);
}
@@ -318,6 +362,25 @@ public LearningPathCompetencyGraphDTO generateLearningPathCompetencyGraph(@NotNu
return new LearningPathCompetencyGraphDTO(progressDTOs, relationDTOs);
}
+ /**
+ * Generates the graph of competencies with the student's progress for the given learning path.
+ *
+ * @param courseId the id of the course for which the graph should be generated
+ * @return dto containing the competencies and relations of the learning path
+ */
+ public LearningPathCompetencyGraphDTO generateLearningPathCompetencyInstructorGraph(long courseId) {
+ List competencies = courseCompetencyRepository.findByCourseIdOrderById(courseId);
+ Set progressDTOs = competencies.stream().map(competency -> {
+ double averageMasteryProgress = competencyProgressRepository.findAverageOfAllNonZeroStudentProgressByCompetencyId(competency.getId());
+ return CompetencyGraphNodeDTO.of(competency, averageMasteryProgress, CompetencyGraphNodeDTO.CompetencyNodeValueType.AVERAGE_MASTERY_PROGRESS);
+ }).collect(Collectors.toSet());
+
+ Set relations = competencyRelationRepository.findAllWithHeadAndTailByCourseId(courseId);
+ Set relationDTOs = relations.stream().map(CompetencyGraphEdgeDTO::of).collect(Collectors.toSet());
+
+ return new LearningPathCompetencyGraphDTO(progressDTOs, relationDTOs);
+ }
+
/**
* Generates Ngx graph representation of the learning path graph.
*
diff --git a/src/main/java/de/tum/cit/aet/artemis/atlas/web/CompetencyResource.java b/src/main/java/de/tum/cit/aet/artemis/atlas/web/CompetencyResource.java
index aa240c5f9a42..aa1a9f78dc0e 100644
--- a/src/main/java/de/tum/cit/aet/artemis/atlas/web/CompetencyResource.java
+++ b/src/main/java/de/tum/cit/aet/artemis/atlas/web/CompetencyResource.java
@@ -8,7 +8,6 @@
import java.util.Set;
import jakarta.validation.constraints.NotNull;
-import jakarta.ws.rs.BadRequestException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -22,11 +21,11 @@
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import de.tum.cit.aet.artemis.atlas.domain.competency.Competency;
import de.tum.cit.aet.artemis.atlas.domain.competency.CourseCompetency;
+import de.tum.cit.aet.artemis.atlas.dto.CompetencyImportOptionsDTO;
import de.tum.cit.aet.artemis.atlas.dto.CompetencyImportResponseDTO;
import de.tum.cit.aet.artemis.atlas.dto.CompetencyWithTailRelationDTO;
import de.tum.cit.aet.artemis.atlas.repository.CompetencyRepository;
@@ -136,9 +135,8 @@ public ResponseEntity getCompetency(@PathVariable long competencyId,
@EnforceAtLeastInstructorInCourse
public ResponseEntity createCompetency(@PathVariable long courseId, @RequestBody Competency competency) throws URISyntaxException {
log.debug("REST request to create Competency : {}", competency);
- if (competency.getId() != null || competency.getTitle() == null || competency.getTitle().trim().isEmpty()) {
- throw new BadRequestException();
- }
+ checkCompetencyAttributesForCreation(competency);
+
var course = courseRepository.findWithEagerCompetenciesAndPrerequisitesByIdElseThrow(courseId);
final var persistedCompetency = competencyService.createCourseCompetency(competency, course);
@@ -159,9 +157,7 @@ public ResponseEntity createCompetency(@PathVariable long courseId,
public ResponseEntity> createCompetencies(@PathVariable Long courseId, @RequestBody List competencies) throws URISyntaxException {
log.debug("REST request to create Competencies : {}", competencies);
for (Competency competency : competencies) {
- if (competency.getId() != null || competency.getTitle() == null || competency.getTitle().trim().isEmpty()) {
- throw new BadRequestException();
- }
+ checkCompetencyAttributesForCreation(competency);
}
var course = courseRepository.findWithEagerCompetenciesAndPrerequisitesByIdElseThrow(courseId);
@@ -173,25 +169,31 @@ public ResponseEntity> createCompetencies(@PathVariable Long co
/**
* POST courses/:courseId/competencies/import : imports a new competency.
*
- * @param courseId the id of the course to which the competency should be imported to
- * @param competencyId the id of the competency that should be imported
+ * @param courseId the id of the course to which the competency should be imported to
+ * @param importOptions the options for the import
* @return the ResponseEntity with status 201 (Created) and with body containing the imported competency
* @throws URISyntaxException if the Location URI syntax is incorrect
*/
@PostMapping("courses/{courseId}/competencies/import")
@EnforceAtLeastInstructorInCourse
- public ResponseEntity importCompetency(@PathVariable long courseId, @RequestBody long competencyId) throws URISyntaxException {
- log.info("REST request to import a competency: {}", competencyId);
+ public ResponseEntity importCompetency(@PathVariable long courseId, @RequestBody CompetencyImportOptionsDTO importOptions) throws URISyntaxException {
+ log.info("REST request to import a competency: {}", importOptions.competencyIds());
+
+ if (importOptions.competencyIds() == null || importOptions.competencyIds().size() != 1) {
+ throw new BadRequestAlertException("Exactly one competency must be imported", ENTITY_NAME, "noCompetency");
+ }
+ long competencyId = importOptions.competencyIds().iterator().next();
var course = courseRepository.findWithEagerCompetenciesAndPrerequisitesByIdElseThrow(courseId);
- var competencyToImport = courseCompetencyRepository.findByIdElseThrow(competencyId);
+ var competencyToImport = courseCompetencyRepository.findByIdWithExercisesAndLectureUnitsAndLecturesElseThrow(competencyId);
authorizationCheckService.checkHasAtLeastRoleInCourseElseThrow(Role.EDITOR, competencyToImport.getCourse(), null);
if (competencyToImport.getCourse().getId().equals(courseId)) {
throw new BadRequestAlertException("The competency is already added to this course", ENTITY_NAME, "competencyCycle");
}
- Competency createdCompetency = competencyService.createCompetency(competencyToImport, course);
+ Set createdCompetencies = competencyService.importCompetencies(course, Set.of(competencyToImport), importOptions);
+ Competency createdCompetency = (Competency) createdCompetencies.iterator().next().competency();
return ResponseEntity.created(new URI("/api/courses/" + courseId + "/competencies/" + createdCompetency.getId())).body(createdCompetency);
}
@@ -199,21 +201,24 @@ public ResponseEntity importCompetency(@PathVariable long courseId,
/**
* POST courses/:courseId/competencies/import/bulk : imports a number of competencies (and optionally their relations) into a course.
*
- * @param courseId the id of the course to which the competencies should be imported to
- * @param competencyIds the ids of the competencies that should be imported
- * @param importRelations if relations should be imported as well
+ * @param courseId the id of the course to which the competencies should be imported to
+ * @param importOptions the options for the import
* @return the ResponseEntity with status 201 (Created) and with body containing the imported competencies
* @throws URISyntaxException if the Location URI syntax is incorrect
*/
@PostMapping("courses/{courseId}/competencies/import/bulk")
@EnforceAtLeastEditorInCourse
- public ResponseEntity> importCompetencies(@PathVariable long courseId, @RequestBody Set competencyIds,
- @RequestParam(defaultValue = "false") boolean importRelations) throws URISyntaxException {
- log.info("REST request to import competencies: {}", competencyIds);
+ public ResponseEntity> importCompetencies(@PathVariable long courseId, @RequestBody CompetencyImportOptionsDTO importOptions)
+ throws URISyntaxException {
+ log.info("REST request to import competencies: {}", importOptions.competencyIds());
+
+ if (importOptions.competencyIds() == null || importOptions.competencyIds().isEmpty()) {
+ throw new BadRequestAlertException("No competencies to import", ENTITY_NAME, "noCompetencies");
+ }
var course = courseRepository.findWithEagerCompetenciesAndPrerequisitesByIdElseThrow(courseId);
- List competenciesToImport = courseCompetencyRepository.findAllById(competencyIds);
+ Set competenciesToImport = courseCompetencyRepository.findAllByIdWithExercisesAndLectureUnitsAndLecturesAndAttachments(importOptions.competencyIds());
User user = userRepository.getUserWithGroupsAndAuthorities();
competenciesToImport.forEach(competencyToImport -> {
@@ -223,48 +228,37 @@ public ResponseEntity> importCompetencies(@Pa
}
});
- Set importedCompetencies;
- if (importRelations) {
- importedCompetencies = competencyService.importCompetenciesAndRelations(course, competenciesToImport);
- }
- else {
- importedCompetencies = competencyService.importCompetencies(course, competenciesToImport);
- }
+ Set importedCompetencies = competencyService.importCompetencies(course, competenciesToImport, importOptions);
return ResponseEntity.created(new URI("/api/courses/" + courseId + "/competencies/")).body(importedCompetencies);
}
/**
- * POST courses/{courseId}/competencies/import-all/{sourceCourseId} : Imports all competencies of the source course (and optionally their relations) into another.
+ * POST courses/{courseId}/competencies/import-all : Imports all competencies of the source course (and optionally their relations) into another.
*
- * @param courseId the id of the course to import into
- * @param sourceCourseId the id of the course to import from
- * @param importRelations if relations should be imported as well
+ * @param courseId the id of the course to import into
+ * @param importOptions the options for the import
* @return the ResponseEntity with status 201 (Created) and with body containing the imported competencies (and relations)
* @throws URISyntaxException if the Location URI syntax is incorrect
*/
- @PostMapping("courses/{courseId}/competencies/import-all/{sourceCourseId}")
+ @PostMapping("courses/{courseId}/competencies/import-all")
@EnforceAtLeastInstructorInCourse
- public ResponseEntity> importAllCompetenciesFromCourse(@PathVariable long courseId, @PathVariable long sourceCourseId,
- @RequestParam(defaultValue = "false") boolean importRelations) throws URISyntaxException {
- log.info("REST request to all competencies from course {} into course {}", sourceCourseId, courseId);
+ public ResponseEntity> importAllCompetenciesFromCourse(@PathVariable long courseId, @RequestBody CompetencyImportOptionsDTO importOptions)
+ throws URISyntaxException {
+ log.info("REST request to all competencies from course {} into course {}", importOptions.sourceCourseId(), courseId);
- if (courseId == sourceCourseId) {
- throw new BadRequestAlertException("Cannot import from a course into itself", "Course", "courseCycle");
+ if (importOptions.sourceCourseId().isEmpty()) {
+ throw new BadRequestAlertException("No source course specified", ENTITY_NAME, "noSourceCourse");
+ }
+ else if (courseId == importOptions.sourceCourseId().get()) {
+ throw new BadRequestAlertException("Cannot import from a course into itself", ENTITY_NAME, "courseCycle");
}
var targetCourse = courseRepository.findByIdElseThrow(courseId);
- var sourceCourse = courseRepository.findByIdElseThrow(sourceCourseId);
+ var sourceCourse = courseRepository.findByIdElseThrow(importOptions.sourceCourseId().get());
authorizationCheckService.checkHasAtLeastRoleInCourseElseThrow(Role.EDITOR, sourceCourse, null);
- var competencies = competencyRepository.findAllForCourse(sourceCourse.getId());
- Set importedCompetencies;
-
- if (importRelations) {
- importedCompetencies = competencyService.importCompetenciesAndRelations(targetCourse, competencies);
- }
- else {
- importedCompetencies = competencyService.importCompetencies(targetCourse, competencies);
- }
+ var competencies = competencyRepository.findAllForCourseWithExercisesAndLectureUnitsAndLecturesAndAttachments(sourceCourse.getId());
+ Set importedCompetencies = competencyService.importCompetencies(targetCourse, competencies, importOptions);
return ResponseEntity.created(new URI("/api/courses/" + courseId + "/competencies/")).body(importedCompetencies);
}
@@ -300,9 +294,8 @@ public ResponseEntity> importStandardizedCompe
@EnforceAtLeastInstructorInCourse
public ResponseEntity updateCompetency(@PathVariable long courseId, @RequestBody Competency competency) {
log.debug("REST request to update Competency : {}", competency);
- if (competency.getId() == null) {
- throw new BadRequestException();
- }
+ checkCompetencyAttributesForUpdate(competency);
+
var course = courseRepository.findByIdElseThrow(courseId);
var existingCompetency = competencyRepository.findByIdWithLectureUnitsElseThrow(competency.getId());
checkCourseForCompetency(course, existingCompetency);
@@ -334,6 +327,26 @@ public ResponseEntity deleteCompetency(@PathVariable long competencyId, @P
return ResponseEntity.ok().headers(HeaderUtil.createEntityDeletionAlert(applicationName, true, ENTITY_NAME, competency.getTitle())).build();
}
+ private void checkCompetencyAttributesForCreation(Competency competency) {
+ if (competency.getId() != null) {
+ throw new BadRequestAlertException("A new competency should not have an id", ENTITY_NAME, "existingCompetencyId");
+ }
+ checkCompetencyAttributes(competency);
+ }
+
+ private void checkCompetencyAttributesForUpdate(Competency competency) {
+ if (competency.getId() == null) {
+ throw new BadRequestAlertException("An updated competency should have an id", ENTITY_NAME, "missingCompetencyId");
+ }
+ checkCompetencyAttributes(competency);
+ }
+
+ private void checkCompetencyAttributes(Competency competency) {
+ if (competency.getTitle() == null || competency.getTitle().trim().isEmpty() || competency.getMasteryThreshold() < 1 || competency.getMasteryThreshold() > 100) {
+ throw new BadRequestAlertException("The attributes of the competency are invalid!", ENTITY_NAME, "invalidPrerequisiteAttributes");
+ }
+ }
+
/**
* Checks if the competency matches the course.
*
diff --git a/src/main/java/de/tum/cit/aet/artemis/atlas/web/CourseCompetencyResource.java b/src/main/java/de/tum/cit/aet/artemis/atlas/web/CourseCompetencyResource.java
index d335c9285f59..449a92a1d171 100644
--- a/src/main/java/de/tum/cit/aet/artemis/atlas/web/CourseCompetencyResource.java
+++ b/src/main/java/de/tum/cit/aet/artemis/atlas/web/CourseCompetencyResource.java
@@ -28,6 +28,7 @@
import de.tum.cit.aet.artemis.atlas.domain.competency.CompetencyProgress;
import de.tum.cit.aet.artemis.atlas.domain.competency.CourseCompetency;
+import de.tum.cit.aet.artemis.atlas.dto.CompetencyImportOptionsDTO;
import de.tum.cit.aet.artemis.atlas.dto.CompetencyJolPairDTO;
import de.tum.cit.aet.artemis.atlas.dto.CompetencyRelationDTO;
import de.tum.cit.aet.artemis.atlas.dto.CompetencyWithTailRelationDTO;
@@ -232,36 +233,31 @@ public ResponseEntity> getCompetenciesForI
}
/**
- * POST courses/{courseId}/course-competencies/import-all/{sourceCourseId} : Imports all course competencies of the source course (and optionally their relations) into another.
+ * POST courses/{courseId}/course-competencies/import-all : Imports all course competencies of the source course (and optionally their relations) into another.
*
- * @param courseId the id of the course to import into
- * @param sourceCourseId the id of the course to import from
- * @param importRelations if relations should be imported as well
+ * @param courseId the id of the course to import into
+ * @param importOptions the options for the import
* @return the ResponseEntity with status 201 (Created) and with body containing the imported competencies (and relations)
* @throws URISyntaxException if the Location URI syntax is incorrect
*/
- @PostMapping("courses/{courseId}/course-competencies/import-all/{sourceCourseId}")
+ @PostMapping("courses/{courseId}/course-competencies/import-all")
@EnforceAtLeastInstructorInCourse
- public ResponseEntity> importAllCompetenciesFromCourse(@PathVariable long courseId, @PathVariable long sourceCourseId,
- @RequestParam(defaultValue = "false") boolean importRelations) throws URISyntaxException {
- log.info("REST request to all course competencies from course {} into course {}", sourceCourseId, courseId);
+ public ResponseEntity> importAllCompetenciesFromCourse(@PathVariable long courseId, @RequestBody CompetencyImportOptionsDTO importOptions)
+ throws URISyntaxException {
+ log.info("REST request to all course competencies from course {} into course {}", importOptions.sourceCourseId(), courseId);
- if (courseId == sourceCourseId) {
- throw new BadRequestAlertException("Cannot import from a course into itself", "Course", "courseCycle");
+ if (importOptions.sourceCourseId().isEmpty()) {
+ throw new BadRequestAlertException("No source course specified", ENTITY_NAME, "noSourceCourse");
+ }
+ else if (courseId == importOptions.sourceCourseId().get()) {
+ throw new BadRequestAlertException("Cannot import from a course into itself", ENTITY_NAME, "courseCycle");
}
var targetCourse = courseRepository.findByIdElseThrow(courseId);
- var sourceCourse = courseRepository.findByIdElseThrow(sourceCourseId);
+ var sourceCourse = courseRepository.findByIdElseThrow(importOptions.sourceCourseId().get());
authorizationCheckService.checkHasAtLeastRoleInCourseElseThrow(Role.EDITOR, sourceCourse, null);
- var competencies = courseCompetencyRepository.findAllForCourse(sourceCourse.getId());
- Set importedCompetencies;
-
- if (importRelations) {
- importedCompetencies = courseCompetencyService.importCourseCompetenciesAndRelations(targetCourse, competencies);
- }
- else {
- importedCompetencies = courseCompetencyService.importCourseCompetencies(targetCourse, competencies);
- }
+ var competencies = courseCompetencyRepository.findAllForCourseWithExercisesAndLectureUnitsAndLecturesAndAttachments(sourceCourse.getId());
+ Set importedCompetencies = courseCompetencyService.importCourseCompetencies(targetCourse, competencies, importOptions);
return ResponseEntity.created(new URI("/api/courses/" + courseId + "/competencies/")).body(importedCompetencies);
}
diff --git a/src/main/java/de/tum/cit/aet/artemis/atlas/web/LearningPathResource.java b/src/main/java/de/tum/cit/aet/artemis/atlas/web/LearningPathResource.java
index 709ac913cdf9..43a8135f27cb 100644
--- a/src/main/java/de/tum/cit/aet/artemis/atlas/web/LearningPathResource.java
+++ b/src/main/java/de/tum/cit/aet/artemis/atlas/web/LearningPathResource.java
@@ -17,6 +17,7 @@
import org.springframework.context.annotation.Profile;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
@@ -28,6 +29,7 @@
import de.tum.cit.aet.artemis.atlas.dto.CompetencyNameDTO;
import de.tum.cit.aet.artemis.atlas.dto.CompetencyProgressForLearningPathDTO;
import de.tum.cit.aet.artemis.atlas.dto.LearningPathCompetencyGraphDTO;
+import de.tum.cit.aet.artemis.atlas.dto.LearningPathDTO;
import de.tum.cit.aet.artemis.atlas.dto.LearningPathHealthDTO;
import de.tum.cit.aet.artemis.atlas.dto.LearningPathInformationDTO;
import de.tum.cit.aet.artemis.atlas.dto.LearningPathNavigationDTO;
@@ -57,6 +59,7 @@
import de.tum.cit.aet.artemis.lecture.service.LearningObjectService;
@Profile(PROFILE_CORE)
+@FeatureToggle(Feature.LearningPaths)
@RestController
@RequestMapping("api/")
public class LearningPathResource {
@@ -106,7 +109,6 @@ public LearningPathResource(CourseService courseService, CourseRepository course
* @return the ResponseEntity with status 200 (OK)
*/
@PutMapping("courses/{courseId}/learning-paths/enable")
- @FeatureToggle(Feature.LearningPaths)
@EnforceAtLeastInstructorInCourse
public ResponseEntity enableLearningPathsForCourse(@PathVariable long courseId) {
log.debug("REST request to enable learning paths for course with id: {}", courseId);
@@ -127,7 +129,6 @@ public ResponseEntity enableLearningPathsForCourse(@PathVariable long cour
* @return the ResponseEntity with status 200 (OK)
*/
@PutMapping("courses/{courseId}/learning-paths/generate-missing")
- @FeatureToggle(Feature.LearningPaths)
@EnforceAtLeastInstructorInCourse
public ResponseEntity generateMissingLearningPathsForCourse(@PathVariable long courseId) {
log.debug("REST request to generate missing learning paths for course with id: {}", courseId);
@@ -145,7 +146,6 @@ public ResponseEntity generateMissingLearningPathsForCourse(@PathVariable
* @return the ResponseEntity with status 200 (OK) and with body the desired page, sorted and matching the given query
*/
@GetMapping("courses/{courseId}/learning-paths")
- @FeatureToggle(Feature.LearningPaths)
@EnforceAtLeastInstructorInCourse
public ResponseEntity> getLearningPathsOnPage(@PathVariable long courseId, SearchTermPageableSearchDTO search) {
log.debug("REST request to get learning paths for course with id: {}", courseId);
@@ -160,7 +160,6 @@ public ResponseEntity> getLearni
* @return the ResponseEntity with status 200 (OK) and with body the health status
*/
@GetMapping("courses/{courseId}/learning-path-health")
- @FeatureToggle(Feature.LearningPaths)
@EnforceAtLeastInstructorInCourse
public ResponseEntity getHealthStatusForCourse(@PathVariable long courseId) {
log.debug("REST request to get health status of learning paths in course with id: {}", courseId);
@@ -175,7 +174,6 @@ public ResponseEntity getHealthStatusForCourse(@PathVaria
* @return the ResponseEntity with status 200 (OK) and with body the learning path
*/
@GetMapping("learning-path/{learningPathId}")
- @FeatureToggle(Feature.LearningPaths)
@EnforceAtLeastStudent
public ResponseEntity getLearningPath(@PathVariable long learningPathId) {
log.debug("REST request to get learning path with id: {}", learningPathId);
@@ -194,7 +192,6 @@ public ResponseEntity getLearningPath(@PathVariable
* @return the ResponseEntity with status 200 (OK) and with body the graph
*/
@GetMapping("learning-path/{learningPathId}/competency-graph")
- @FeatureToggle(Feature.LearningPaths)
@EnforceAtLeastStudent
public ResponseEntity getLearningPathCompetencyGraph(@PathVariable long learningPathId) {
log.debug("REST request to get competency graph for learning path with id: {}", learningPathId);
@@ -206,6 +203,21 @@ public ResponseEntity getLearningPathCompetencyG
return ResponseEntity.ok(learningPathService.generateLearningPathCompetencyGraph(learningPath, user));
}
+ /**
+ * GET courses/{courseId}/learning-path/competency-instructor-graph : Gets the competency instructor graph
+ *
+ * @param courseId the id of the course for which the graph should be fetched
+ * @return the ResponseEntity with status 200 (OK) and with body the graph
+ */
+ @GetMapping("courses/{courseId}/learning-path/competency-instructor-graph")
+ @FeatureToggle(Feature.LearningPaths)
+ @EnforceAtLeastInstructorInCourse
+ public ResponseEntity getLearningPathCompetencyInstructorGraph(@PathVariable long courseId) {
+ log.debug("REST request to get competency instructor graph for learning path with id: {}", courseId);
+
+ return ResponseEntity.ok(learningPathService.generateLearningPathCompetencyInstructorGraph(courseId));
+ }
+
/**
* GET learning-path/:learningPathId/graph : Gets the ngx representation of the learning path as a graph.
*
@@ -213,7 +225,6 @@ public ResponseEntity getLearningPathCompetencyG
* @return the ResponseEntity with status 200 (OK) and with body the ngx representation of the learning path
*/
@GetMapping("learning-path/{learningPathId}/graph")
- @FeatureToggle(Feature.LearningPaths)
@EnforceAtLeastStudent
public ResponseEntity getLearningPathNgxGraph(@PathVariable long learningPathId) {
log.debug("REST request to get ngx graph representation of learning path with id: {}", learningPathId);
@@ -227,7 +238,6 @@ public ResponseEntity getLearningPathNgxGraph(@PathVariable
* @return the ResponseEntity with status 200 (OK) and with body the ngx representation of the learning path
*/
@GetMapping("learning-path/{learningPathId}/path")
- @FeatureToggle(Feature.LearningPaths)
@EnforceAtLeastStudent
public ResponseEntity getLearningPathNgxPath(@PathVariable long learningPathId) {
log.debug("REST request to get ngx path representation of learning path with id: {}", learningPathId);
@@ -244,7 +254,6 @@ public ResponseEntity getLearningPathNgxPath(@PathVariable l
* @return the ResponseEntity with status 200 (OK) and with body the navigation information
*/
@GetMapping("learning-path/{learningPathId}/relative-navigation")
- @FeatureToggle(Feature.LearningPaths)
@EnforceAtLeastStudent
public ResponseEntity getRelativeLearningPathNavigation(@PathVariable @Valid long learningPathId, @RequestParam long learningObjectId,
@RequestParam LearningObjectType learningObjectType, @RequestParam long competencyId) {
@@ -263,7 +272,6 @@ public ResponseEntity getRelativeLearningPathNavigati
* @return the ResponseEntity with status 200 (OK) and with body the navigation information
*/
@GetMapping("learning-path/{learningPathId}/navigation")
- @FeatureToggle(Feature.LearningPaths)
@EnforceAtLeastStudent
public ResponseEntity getLearningPathNavigation(@PathVariable long learningPathId) {
log.debug("REST request to get navigation for learning path with id: {}", learningPathId);
@@ -279,7 +287,6 @@ public ResponseEntity getLearningPathNavigation(@Path
* @return the ResponseEntity with status 200 (OK) and with body the navigation overview
*/
@GetMapping("learning-path/{learningPathId}/navigation-overview")
- @FeatureToggle(Feature.LearningPaths)
@EnforceAtLeastStudent
public ResponseEntity getLearningPathNavigationOverview(@PathVariable @Valid long learningPathId) {
log.debug("REST request to get navigation overview for learning path with id: {}", learningPathId);
@@ -301,19 +308,31 @@ private ResponseEntity getLearningPathNgx(@PathVariable long
}
/**
- * GET courses/:courseId/learning-path-id : Gets the id of the learning path.
+ * GET courses/:courseId/learning-path/me : Gets the learning path of the current user in the course.
*
- * @param courseId the id of the course from which the learning path id should be fetched
- * @return the ResponseEntity with status 200 (OK) and with body the id of the learning path
+ * @param courseId the id of the course for which the learning path should be fetched
+ * @return the ResponseEntity with status 200 (OK) and with body the learning path
*/
- @GetMapping("courses/{courseId}/learning-path-id")
+ @GetMapping("courses/{courseId}/learning-path/me")
@EnforceAtLeastStudentInCourse
- public ResponseEntity getLearningPathId(@PathVariable long courseId) {
- log.debug("REST request to get learning path id for course with id: {}", courseId);
+ public ResponseEntity getLearningPathForCurrentUser(@PathVariable long courseId) {
+ log.debug("REST request to get learning path of current user for course with id: {}", courseId);
courseService.checkLearningPathsEnabledElseThrow(courseId);
- User user = userRepository.getUser();
- final var learningPath = learningPathRepository.findByCourseIdAndUserIdElseThrow(courseId, user.getId());
- return ResponseEntity.ok(learningPath.getId());
+ return ResponseEntity.ok(learningPathService.getLearningPathForCurrentUser(courseId));
+ }
+
+ /**
+ * PATCH learning-path/:learningPathId/start : Starts the learning path for the current user.
+ *
+ * @param learningPathId the id of the learning path to start
+ * @return the ResponseEntity with status 204 (NO_CONTENT)
+ */
+ @PatchMapping("learning-path/{learningPathId}/start")
+ @EnforceAtLeastStudent
+ public ResponseEntity startLearningPathForCurrentUser(@PathVariable long learningPathId) {
+ log.debug("REST request to start learning path with id: {}", learningPathId);
+ learningPathService.startLearningPathForCurrentUser(learningPathId);
+ return ResponseEntity.noContent().build();
}
/**
@@ -324,20 +343,11 @@ public ResponseEntity getLearningPathId(@PathVariable long courseId) {
*/
@PostMapping("courses/{courseId}/learning-path")
@EnforceAtLeastStudentInCourse
- public ResponseEntity generateLearningPath(@PathVariable long courseId) throws URISyntaxException {
- log.debug("REST request to generate learning path for user in course with id: {}", courseId);
+ public ResponseEntity generateLearningPathForCurrentUser(@PathVariable long courseId) throws URISyntaxException {
+ log.debug("REST request to generate learning path for current user in course with id: {}", courseId);
courseService.checkLearningPathsEnabledElseThrow(courseId);
-
- User user = userRepository.getUser();
- final var learningPathOptional = learningPathRepository.findByCourseIdAndUserId(courseId, user.getId());
-
- if (learningPathOptional.isPresent()) {
- throw new BadRequestException("Learning path already exists.");
- }
-
- final var course = courseRepository.findWithEagerCompetenciesAndPrerequisitesByIdElseThrow(courseId);
- final var learningPath = learningPathService.generateLearningPathForUser(course, user);
- return ResponseEntity.created(new URI("api/learning-path/" + learningPath.getId())).body(learningPath.getId());
+ final var learningPathDTO = learningPathService.generateLearningPathForCurrentUser(courseId);
+ return ResponseEntity.created(new URI("api/learning-path/" + learningPathDTO.id())).body(learningPathDTO);
}
/**
diff --git a/src/main/java/de/tum/cit/aet/artemis/atlas/web/PrerequisiteResource.java b/src/main/java/de/tum/cit/aet/artemis/atlas/web/PrerequisiteResource.java
index 7cd32bdd957a..a9be53c3c4a4 100644
--- a/src/main/java/de/tum/cit/aet/artemis/atlas/web/PrerequisiteResource.java
+++ b/src/main/java/de/tum/cit/aet/artemis/atlas/web/PrerequisiteResource.java
@@ -8,7 +8,6 @@
import java.util.Set;
import jakarta.validation.constraints.NotNull;
-import jakarta.ws.rs.BadRequestException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -22,11 +21,11 @@
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import de.tum.cit.aet.artemis.atlas.domain.competency.CourseCompetency;
import de.tum.cit.aet.artemis.atlas.domain.competency.Prerequisite;
+import de.tum.cit.aet.artemis.atlas.dto.CompetencyImportOptionsDTO;
import de.tum.cit.aet.artemis.atlas.dto.CompetencyImportResponseDTO;
import de.tum.cit.aet.artemis.atlas.dto.CompetencyWithTailRelationDTO;
import de.tum.cit.aet.artemis.atlas.repository.CourseCompetencyRepository;
@@ -39,6 +38,7 @@
import de.tum.cit.aet.artemis.core.repository.CourseRepository;
import de.tum.cit.aet.artemis.core.repository.UserRepository;
import de.tum.cit.aet.artemis.core.security.Role;
+import de.tum.cit.aet.artemis.core.security.annotations.EnforceAtLeastStudent;
import de.tum.cit.aet.artemis.core.security.annotations.enforceRoleInCourse.EnforceAtLeastEditorInCourse;
import de.tum.cit.aet.artemis.core.security.annotations.enforceRoleInCourse.EnforceAtLeastInstructorInCourse;
import de.tum.cit.aet.artemis.core.security.annotations.enforceRoleInCourse.EnforceAtLeastStudentInCourse;
@@ -97,7 +97,7 @@ public PrerequisiteResource(CourseRepository courseRepository, AuthorizationChec
* @return the ResponseEntity with status 200 (OK) and with body the found prerequisites
*/
@GetMapping("courses/{courseId}/prerequisites")
- @EnforceAtLeastStudentInCourse
+ @EnforceAtLeastStudent
public ResponseEntity> getPrerequisitesWithProgress(@PathVariable long courseId) {
log.debug("REST request to get prerequisites for course with id: {}", courseId);
User user = userRepository.getUserWithGroupsAndAuthorities();
@@ -139,9 +139,8 @@ public ResponseEntity getPrerequisite(@PathVariable long prerequis
@EnforceAtLeastInstructorInCourse
public ResponseEntity createPrerequisite(@PathVariable long courseId, @RequestBody Prerequisite prerequisite) throws URISyntaxException {
log.debug("REST request to create Prerequisite : {}", prerequisite);
- if (prerequisite.getId() != null || prerequisite.getTitle() == null || prerequisite.getTitle().trim().isEmpty()) {
- throw new BadRequestException();
- }
+ checkPrerequisitesAttributesForCreation(prerequisite);
+
var course = courseRepository.findWithEagerCompetenciesAndPrerequisitesByIdElseThrow(courseId);
final var persistedPrerequisite = prerequisiteService.createCourseCompetency(prerequisite, course);
@@ -162,9 +161,7 @@ public ResponseEntity createPrerequisite(@PathVariable long course
public ResponseEntity> createPrerequisite(@PathVariable Long courseId, @RequestBody List prerequisites) throws URISyntaxException {
log.debug("REST request to create Prerequisites : {}", prerequisites);
for (Prerequisite prerequisite : prerequisites) {
- if (prerequisite.getId() != null || prerequisite.getTitle() == null || prerequisite.getTitle().trim().isEmpty()) {
- throw new BadRequestException();
- }
+ checkPrerequisitesAttributesForCreation(prerequisite);
}
var course = courseRepository.findWithEagerCompetenciesAndPrerequisitesByIdElseThrow(courseId);
@@ -176,25 +173,31 @@ public ResponseEntity> createPrerequisite(@PathVariable Long
/**
* POST courses/:courseId/prerequisites/import : imports a new prerequisite.
*
- * @param courseId the id of the course to which the prerequisite should be imported to
- * @param prerequisiteId the id of the prerequisite that should be imported
+ * @param courseId the id of the course to which the prerequisite should be imported to
+ * @param importOptions the options for the import
* @return the ResponseEntity with status 201 (Created) and with body containing the imported prerequisite
* @throws URISyntaxException if the Location URI syntax is incorrect
*/
@PostMapping("courses/{courseId}/prerequisites/import")
@EnforceAtLeastInstructorInCourse
- public ResponseEntity importPrerequisite(@PathVariable long courseId, @RequestBody long prerequisiteId) throws URISyntaxException {
- log.info("REST request to import a prerequisite: {}", prerequisiteId);
+ public ResponseEntity importPrerequisite(@PathVariable long courseId, @RequestBody CompetencyImportOptionsDTO importOptions) throws URISyntaxException {
+ log.info("REST request to import a prerequisite: {}", importOptions.competencyIds());
+
+ if (importOptions.competencyIds() == null || importOptions.competencyIds().size() != 1) {
+ throw new BadRequestAlertException("Exactly one prerequisite must be imported", ENTITY_NAME, "noPrerequisite");
+ }
+ long prerequisiteId = importOptions.competencyIds().iterator().next();
var course = courseRepository.findWithEagerCompetenciesAndPrerequisitesByIdElseThrow(courseId);
- var prerequisiteToImport = courseCompetencyRepository.findByIdElseThrow(prerequisiteId);
+ var prerequisiteToImport = courseCompetencyRepository.findByIdWithExercisesAndLectureUnitsAndLecturesElseThrow(prerequisiteId);
authorizationCheckService.checkHasAtLeastRoleInCourseElseThrow(Role.EDITOR, prerequisiteToImport.getCourse(), null);
if (prerequisiteToImport.getCourse().getId().equals(courseId)) {
throw new BadRequestAlertException("The prerequisite is already added to this course", ENTITY_NAME, "prerequisiteCycle");
}
- Prerequisite createdPrerequisite = prerequisiteService.createPrerequisite(prerequisiteToImport, course);
+ Set createdPrerequisites = prerequisiteService.importPrerequisites(course, Set.of(prerequisiteToImport), importOptions);
+ Prerequisite createdPrerequisite = (Prerequisite) createdPrerequisites.iterator().next().competency();
return ResponseEntity.created(new URI("/api/courses/" + courseId + "/prerequisites/" + createdPrerequisite.getId())).body(createdPrerequisite);
}
@@ -202,21 +205,24 @@ public ResponseEntity importPrerequisite(@PathVariable long course
/**
* POST courses/:courseId/prerequisites/import/bulk : imports a number of prerequisites (and optionally their relations) into a course.
*
- * @param courseId the id of the course to which the prerequisites should be imported to
- * @param prerequisiteIds the ids of the prerequisites that should be imported
- * @param importRelations if relations should be imported as well
+ * @param courseId the id of the course to which the prerequisites should be imported to
+ * @param importOptions the options for the import
* @return the ResponseEntity with status 201 (Created) and with body containing the imported prerequisites
* @throws URISyntaxException if the Location URI syntax is incorrect
*/
@PostMapping("courses/{courseId}/prerequisites/import/bulk")
@EnforceAtLeastEditorInCourse
- public ResponseEntity> importPrerequisites(@PathVariable long courseId, @RequestBody Set prerequisiteIds,
- @RequestParam(defaultValue = "false") boolean importRelations) throws URISyntaxException {
- log.info("REST request to import prerequisites: {}", prerequisiteIds);
+ public ResponseEntity> importPrerequisites(@PathVariable long courseId, @RequestBody CompetencyImportOptionsDTO importOptions)
+ throws URISyntaxException {
+ log.info("REST request to import prerequisites: {}", importOptions.competencyIds());
+
+ if (importOptions.competencyIds() == null || importOptions.competencyIds().isEmpty()) {
+ throw new BadRequestAlertException("No prerequisites to import", ENTITY_NAME, "noPrerequisites");
+ }
var course = courseRepository.findWithEagerCompetenciesAndPrerequisitesByIdElseThrow(courseId);
- List prerequisitesToImport = courseCompetencyRepository.findAllById(prerequisiteIds);
+ Set prerequisitesToImport = courseCompetencyRepository.findAllByIdWithExercisesAndLectureUnitsAndLecturesAndAttachments(importOptions.competencyIds());
User user = userRepository.getUserWithGroupsAndAuthorities();
prerequisitesToImport.forEach(prerequisiteToImport -> {
@@ -226,48 +232,37 @@ public ResponseEntity> importPrerequisites(@P
}
});
- Set importedPrerequisites;
- if (importRelations) {
- importedPrerequisites = prerequisiteService.importPrerequisitesAndRelations(course, prerequisitesToImport);
- }
- else {
- importedPrerequisites = prerequisiteService.importPrerequisites(course, prerequisitesToImport);
- }
+ Set importedPrerequisites = prerequisiteService.importPrerequisites(course, prerequisitesToImport, importOptions);
return ResponseEntity.created(new URI("/api/courses/" + courseId + "/prerequisites/")).body(importedPrerequisites);
}
/**
- * POST courses/{courseId}/prerequisites/import-all/{sourceCourseId} : Imports all prerequisites of the source course (and optionally their relations) into another.
+ * POST courses/{courseId}/prerequisites/import-all : Imports all prerequisites of the source course (and optionally their relations) into another.
*
- * @param courseId the id of the course to import into
- * @param sourceCourseId the id of the course to import from
- * @param importRelations if relations should be imported as well
+ * @param courseId the id of the course to import into
+ * @param importOptions the options for the import
* @return the ResponseEntity with status 201 (Created) and with body containing the imported prerequisites (and relations)
* @throws URISyntaxException if the Location URI syntax is incorrect
*/
- @PostMapping("courses/{courseId}/prerequisites/import-all/{sourceCourseId}")
+ @PostMapping("courses/{courseId}/prerequisites/import-all")
@EnforceAtLeastInstructorInCourse
- public ResponseEntity> importAllPrerequisitesFromCourse(@PathVariable long courseId, @PathVariable long sourceCourseId,
- @RequestParam(defaultValue = "false") boolean importRelations) throws URISyntaxException {
- log.info("REST request to all prerequisites from course {} into course {}", sourceCourseId, courseId);
+ public ResponseEntity> importAllPrerequisitesFromCourse(@PathVariable long courseId, @RequestBody CompetencyImportOptionsDTO importOptions)
+ throws URISyntaxException {
+ log.info("REST request to all prerequisites from course {} into course {}", importOptions.sourceCourseId(), courseId);
- if (courseId == sourceCourseId) {
- throw new BadRequestAlertException("Cannot import from a course into itself", "Course", "courseCycle");
+ if (importOptions.sourceCourseId().isEmpty()) {
+ throw new BadRequestAlertException("No source course specified", ENTITY_NAME, "noSourceCourse");
+ }
+ else if (courseId == importOptions.sourceCourseId().get()) {
+ throw new BadRequestAlertException("Cannot import from a course into itself", ENTITY_NAME, "courseCycle");
}
var targetCourse = courseRepository.findByIdElseThrow(courseId);
- var sourceCourse = courseRepository.findByIdElseThrow(sourceCourseId);
+ var sourceCourse = courseRepository.findByIdElseThrow(importOptions.sourceCourseId().get());
authorizationCheckService.checkHasAtLeastRoleInCourseElseThrow(Role.EDITOR, sourceCourse, null);
- var prerequisites = prerequisiteRepository.findAllForCourse(sourceCourse.getId());
- Set importedPrerequisites;
-
- if (importRelations) {
- importedPrerequisites = prerequisiteService.importPrerequisitesAndRelations(targetCourse, prerequisites);
- }
- else {
- importedPrerequisites = prerequisiteService.importPrerequisites(targetCourse, prerequisites);
- }
+ var prerequisites = prerequisiteRepository.findAllForCourseWithExercisesAndLectureUnitsAndLecturesAndAttachments(sourceCourse.getId());
+ Set importedPrerequisites = prerequisiteService.importPrerequisites(targetCourse, prerequisites, importOptions);
return ResponseEntity.created(new URI("/api/courses/" + courseId + "/prerequisites/")).body(importedPrerequisites);
}
@@ -303,9 +298,8 @@ public ResponseEntity> importStandardizedPrere
@EnforceAtLeastInstructorInCourse
public ResponseEntity updatePrerequisite(@PathVariable long courseId, @RequestBody Prerequisite prerequisite) {
log.debug("REST request to update Prerequisite : {}", prerequisite);
- if (prerequisite.getId() == null) {
- throw new BadRequestException();
- }
+ checkPrerequisitesAttributesForUpdate(prerequisite);
+
var course = courseRepository.findByIdElseThrow(courseId);
var existingPrerequisite = prerequisiteRepository.findByIdWithLectureUnitsElseThrow(prerequisite.getId());
checkCourseForPrerequisite(course, existingPrerequisite);
@@ -337,6 +331,26 @@ public ResponseEntity deletePrerequisite(@PathVariable long prerequisiteId
return ResponseEntity.ok().headers(HeaderUtil.createEntityDeletionAlert(applicationName, true, ENTITY_NAME, prerequisite.getTitle())).build();
}
+ private void checkPrerequisitesAttributesForCreation(Prerequisite prerequisite) {
+ if (prerequisite.getId() != null) {
+ throw new BadRequestAlertException("A new prerequiste should not have an id", ENTITY_NAME, "existingPrerequisiteId");
+ }
+ checkPrerequisitesAttributes(prerequisite);
+ }
+
+ private void checkPrerequisitesAttributesForUpdate(Prerequisite prerequisite) {
+ if (prerequisite.getId() == null) {
+ throw new BadRequestAlertException("An updated prerequiste should have an id", ENTITY_NAME, "missingPrerequisiteId");
+ }
+ checkPrerequisitesAttributes(prerequisite);
+ }
+
+ private void checkPrerequisitesAttributes(Prerequisite prerequisite) {
+ if (prerequisite.getTitle() == null || prerequisite.getTitle().trim().isEmpty() || prerequisite.getMasteryThreshold() < 1 || prerequisite.getMasteryThreshold() > 100) {
+ throw new BadRequestAlertException("The attributes of the competency are invalid!", ENTITY_NAME, "invalidPrerequisiteAttributes");
+ }
+ }
+
/**
* Checks if the prerequisite matches the course.
*
diff --git a/src/main/java/de/tum/cit/aet/artemis/atlas/web/ScienceResource.java b/src/main/java/de/tum/cit/aet/artemis/atlas/web/ScienceResource.java
index 7312cc824997..d4e1563df41c 100644
--- a/src/main/java/de/tum/cit/aet/artemis/atlas/web/ScienceResource.java
+++ b/src/main/java/de/tum/cit/aet/artemis/atlas/web/ScienceResource.java
@@ -21,6 +21,7 @@
* REST controller providing the science related endpoints.
*/
@Profile(PROFILE_CORE)
+@FeatureToggle(Feature.Science)
@RestController
@RequestMapping("api/")
public class ScienceResource {
@@ -40,7 +41,6 @@ public ScienceResource(ScienceEventService scienceEventService) {
* @return the ResponseEntity with status 200 (OK)
*/
@PutMapping(value = "science")
- @FeatureToggle(Feature.Science)
@EnforceAtLeastStudent
public ResponseEntity science(@RequestBody ScienceEventDTO event) {
log.debug("REST request to log science event of type {}", event);
diff --git a/src/main/java/de/tum/cit/aet/artemis/atlas/web/StandardizedCompetencyResource.java b/src/main/java/de/tum/cit/aet/artemis/atlas/web/StandardizedCompetencyResource.java
index 8b6316fcc51c..b205db140bc3 100644
--- a/src/main/java/de/tum/cit/aet/artemis/atlas/web/StandardizedCompetencyResource.java
+++ b/src/main/java/de/tum/cit/aet/artemis/atlas/web/StandardizedCompetencyResource.java
@@ -29,6 +29,7 @@
* REST controller for managing {@link StandardizedCompetency} entities.
*/
@Profile(PROFILE_CORE)
+@FeatureToggle(Feature.StandardizedCompetencies)
@RestController
@RequestMapping("api/standardized-competencies/")
public class StandardizedCompetencyResource {
@@ -58,7 +59,6 @@ public StandardizedCompetencyResource(StandardizedCompetencyService standardized
* @return the ResponseEntity with status 200 (OK) and with body containing the standardized competency, or with status 404 (Not Found)
*/
@GetMapping("{competencyId}")
- @FeatureToggle(Feature.StandardizedCompetencies)
@EnforceAtLeastInstructor
public ResponseEntity getStandardizedCompetency(@PathVariable long competencyId) {
log.debug("REST request to get standardized competency with id : {}", competencyId);
@@ -74,7 +74,6 @@ public ResponseEntity getStandardizedCompetency(@PathVar
* @return the ResponseEntity with status 200 (OK) and with body containing the knowledge areas
*/
@GetMapping("for-tree-view")
- @FeatureToggle(Feature.StandardizedCompetencies)
@EnforceAtLeastInstructor
public ResponseEntity> getAllForTreeView() {
log.debug("REST request to all knowledge areas for tree view");
@@ -91,7 +90,6 @@ public ResponseEntity> getAllForTreeView() {
* @return the ResponseEntity with status 200 (OK) and with body containing the knowledge area, or with status 404 (Not Found)
*/
@GetMapping("knowledge-areas/{knowledgeAreaId}")
- @FeatureToggle(Feature.StandardizedCompetencies)
@EnforceAtLeastInstructor
public ResponseEntity getKnowledgeArea(@PathVariable long knowledgeAreaId) {
log.debug("REST request to get knowledge area with id : {}", knowledgeAreaId);
@@ -107,7 +105,6 @@ public ResponseEntity getKnowledgeArea(@PathVariable long knowled
* @return the ResponseEntity with status 200 (OK) and with body containing the list of sources
*/
@GetMapping("sources")
- @FeatureToggle(Feature.StandardizedCompetencies)
@EnforceAtLeastInstructor
public ResponseEntity> getSources() {
log.debug("REST request to get all sources");
diff --git a/src/main/java/de/tum/cit/aet/artemis/atlas/web/admin/AdminStandardizedCompetencyResource.java b/src/main/java/de/tum/cit/aet/artemis/atlas/web/admin/AdminStandardizedCompetencyResource.java
index 376cedb132dc..5c974101f8bb 100644
--- a/src/main/java/de/tum/cit/aet/artemis/atlas/web/admin/AdminStandardizedCompetencyResource.java
+++ b/src/main/java/de/tum/cit/aet/artemis/atlas/web/admin/AdminStandardizedCompetencyResource.java
@@ -38,6 +38,8 @@
* Admin REST controller for managing {@link StandardizedCompetency} entities.
*/
@Profile(PROFILE_CORE)
+@FeatureToggle(Feature.StandardizedCompetencies)
+@EnforceAdmin
@RestController
@RequestMapping("api/admin/")
public class AdminStandardizedCompetencyResource {
@@ -61,8 +63,6 @@ public AdminStandardizedCompetencyResource(StandardizedCompetencyService standar
* @throws URISyntaxException if the Location URI syntax is incorrect
*/
@PostMapping("standardized-competencies")
- @FeatureToggle(Feature.StandardizedCompetencies)
- @EnforceAdmin
public ResponseEntity createStandardizedCompetency(@RequestBody @Valid StandardizedCompetencyRequestDTO competency) throws URISyntaxException {
log.debug("REST request to create standardized competency : {}", competency);
@@ -79,8 +79,6 @@ public ResponseEntity createStandardizedCompete
* @return the ResponseEntity with status 200 (OK) and with body the updated standardized competency
*/
@PutMapping("standardized-competencies/{competencyId}")
- @FeatureToggle(Feature.StandardizedCompetencies)
- @EnforceAdmin
public ResponseEntity updateStandardizedCompetency(@PathVariable long competencyId,
@RequestBody @Valid StandardizedCompetencyRequestDTO competency) {
log.debug("REST request to update standardized competency : {}", competency);
@@ -97,8 +95,6 @@ public ResponseEntity updateStandardizedCompete
* @return the ResponseEntity with status 200 (OK)
*/
@DeleteMapping("standardized-competencies/{competencyId}")
- @FeatureToggle(Feature.StandardizedCompetencies)
- @EnforceAdmin
public ResponseEntity deleteStandardizedCompetency(@PathVariable long competencyId) {
log.debug("REST request to delete standardized competency : {}", competencyId);
@@ -115,8 +111,6 @@ public ResponseEntity deleteStandardizedCompetency(@PathVariable long comp
* @throws URISyntaxException if the Location URI syntax is incorrect
*/
@PostMapping("standardized-competencies/knowledge-areas")
- @FeatureToggle(Feature.StandardizedCompetencies)
- @EnforceAdmin
public ResponseEntity createKnowledgeArea(@RequestBody @Valid KnowledgeAreaRequestDTO knowledgeArea) throws URISyntaxException {
log.debug("REST request to create knowledge area : {}", knowledgeArea);
@@ -134,8 +128,6 @@ public ResponseEntity createKnowledgeArea(@RequestBody @
* @return the ResponseEntity with status 200 (OK) and with body the updated knowledge area
*/
@PutMapping("standardized-competencies/knowledge-areas/{knowledgeAreaId}")
- @FeatureToggle(Feature.StandardizedCompetencies)
- @EnforceAdmin
public ResponseEntity updateKnowledgeArea(@PathVariable long knowledgeAreaId, @RequestBody @Valid KnowledgeAreaRequestDTO knowledgeArea) {
log.debug("REST request to update knowledge area : {}", knowledgeArea);
@@ -151,8 +143,6 @@ public ResponseEntity updateKnowledgeArea(@PathVariable
* @return the ResponseEntity with status 200 (OK)
*/
@DeleteMapping("standardized-competencies/knowledge-areas/{knowledgeAreaId}")
- @FeatureToggle(Feature.StandardizedCompetencies)
- @EnforceAdmin
public ResponseEntity deleteKnowledgeArea(@PathVariable long knowledgeAreaId) {
log.debug("REST request to delete knowledge area : {}", knowledgeAreaId);
@@ -168,8 +158,6 @@ public ResponseEntity deleteKnowledgeArea(@PathVariable long knowledgeArea
* @return the ResponseEntity with status 200 (OK)
*/
@PutMapping("standardized-competencies/import")
- @FeatureToggle(Feature.StandardizedCompetencies)
- @EnforceAdmin
public ResponseEntity importStandardizedCompetencyCatalog(@RequestBody @Valid StandardizedCompetencyCatalogDTO standardizedCompetencyCatalogDTO) {
log.debug("REST request to import standardized competency catalog");
@@ -184,8 +172,6 @@ public ResponseEntity importStandardizedCompetencyCatalog(@RequestBody @Va
* @return the ResponseEntity with status 200 (OK) and the body containing the JSON string of the standardized competency catalog
*/
@GetMapping("standardized-competencies/export")
- @FeatureToggle(Feature.StandardizedCompetencies)
- @EnforceAdmin
public ResponseEntity exportStandardizedCompetencyCatalog() {
log.debug("REST request to export standardized competency catalog");
diff --git a/src/main/java/de/tum/cit/aet/artemis/buildagent/dto/BuildConfig.java b/src/main/java/de/tum/cit/aet/artemis/buildagent/dto/BuildConfig.java
index bce9a9b20e65..9a41fc6fdc20 100644
--- a/src/main/java/de/tum/cit/aet/artemis/buildagent/dto/BuildConfig.java
+++ b/src/main/java/de/tum/cit/aet/artemis/buildagent/dto/BuildConfig.java
@@ -15,7 +15,7 @@
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public record BuildConfig(String buildScript, String dockerImage, String commitHashToBuild, String assignmentCommitHash, String testCommitHash, String branch,
ProgrammingLanguage programmingLanguage, ProjectType projectType, boolean scaEnabled, boolean sequentialTestRunsEnabled, boolean testwiseCoverageEnabled,
- List resultPaths) implements Serializable {
+ List resultPaths, int timeoutSeconds, String assignmentCheckoutPath, String testCheckoutPath, String solutionCheckoutPath) implements Serializable {
@Override
public String dockerImage() {
diff --git a/src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobContainerService.java b/src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobContainerService.java
index 8df60f45026f..b7c97daa9786 100644
--- a/src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobContainerService.java
+++ b/src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobContainerService.java
@@ -24,6 +24,7 @@
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
+import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
@@ -275,11 +276,22 @@ public String getIDOfRunningContainer(String containerName) {
* @param auxiliaryRepositoriesPaths An array of paths for auxiliary repositories to be included in the build process.
* @param auxiliaryRepositoryCheckoutDirectories An array of directory names within the container where each auxiliary repository should be checked out.
* @param programmingLanguage The programming language of the repositories, which influences directory naming conventions.
+ * @param assignmentCheckoutPath The directory within the container where the assignment repository should be checked out; can be null if not applicable,
+ * default would be used.
+ * @param testCheckoutPath The directory within the container where the test repository should be checked out; can be null if not applicable, default
+ * would be used.
+ * @param solutionCheckoutPath The directory within the container where the solution repository should be checked out; can be null if not applicable, default
+ * would be used.
*/
public void populateBuildJobContainer(String buildJobContainerId, Path assignmentRepositoryPath, Path testRepositoryPath, Path solutionRepositoryPath,
- Path[] auxiliaryRepositoriesPaths, String[] auxiliaryRepositoryCheckoutDirectories, ProgrammingLanguage programmingLanguage) {
- String testCheckoutPath = RepositoryCheckoutPath.TEST.forProgrammingLanguage(programmingLanguage);
- String assignmentCheckoutPath = RepositoryCheckoutPath.ASSIGNMENT.forProgrammingLanguage(programmingLanguage);
+ Path[] auxiliaryRepositoriesPaths, String[] auxiliaryRepositoryCheckoutDirectories, ProgrammingLanguage programmingLanguage, String assignmentCheckoutPath,
+ String testCheckoutPath, String solutionCheckoutPath) {
+
+ assignmentCheckoutPath = (!StringUtils.isBlank(assignmentCheckoutPath)) ? assignmentCheckoutPath
+ : RepositoryCheckoutPath.ASSIGNMENT.forProgrammingLanguage(programmingLanguage);
+
+ String defaultTestCheckoutPath = RepositoryCheckoutPath.TEST.forProgrammingLanguage(programmingLanguage);
+ testCheckoutPath = (!StringUtils.isBlank(defaultTestCheckoutPath) && !StringUtils.isBlank(testCheckoutPath)) ? testCheckoutPath : defaultTestCheckoutPath;
// Make sure to create the working directory in case it does not exist.
// In case the test checkout path is the working directory, we only create up to the parent, as the working directory is created below.
@@ -292,7 +304,8 @@ public void populateBuildJobContainer(String buildJobContainerId, Path assignmen
// Copy the assignment repository to the container and move it to the assignment checkout path
addAndPrepareDirectory(buildJobContainerId, assignmentRepositoryPath, LOCALCI_WORKING_DIRECTORY + "/testing-dir/" + assignmentCheckoutPath);
if (solutionRepositoryPath != null) {
- String solutionCheckoutPath = RepositoryCheckoutPath.SOLUTION.forProgrammingLanguage(programmingLanguage);
+ solutionCheckoutPath = (!StringUtils.isBlank(solutionCheckoutPath)) ? solutionCheckoutPath
+ : RepositoryCheckoutPath.SOLUTION.forProgrammingLanguage(programmingLanguage);
addAndPrepareDirectory(buildJobContainerId, solutionRepositoryPath, LOCALCI_WORKING_DIRECTORY + "/testing-dir/" + solutionCheckoutPath);
}
for (int i = 0; i < auxiliaryRepositoriesPaths.length; i++) {
@@ -309,6 +322,7 @@ private void createScriptFile(String buildJobContainerId) {
private void addAndPrepareDirectory(String containerId, Path repositoryPath, String newDirectoryName) {
copyToContainer(repositoryPath.toString(), containerId);
+ addDirectory(containerId, getParentFolderPath(newDirectoryName), true);
renameDirectoryOrFile(containerId, LOCALCI_WORKING_DIRECTORY + "/" + repositoryPath.getFileName().toString(), newDirectoryName);
}
@@ -428,4 +442,9 @@ private Container getContainerForName(String containerName) {
List containers = dockerClient.listContainersCmd().withShowAll(true).exec();
return containers.stream().filter(container -> container.getNames()[0].equals("/" + containerName)).findFirst().orElse(null);
}
+
+ private String getParentFolderPath(String path) {
+ Path parentPath = Paths.get(path).normalize().getParent();
+ return parentPath != null ? parentPath.toString() : "";
+ }
}
diff --git a/src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobExecutionService.java b/src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobExecutionService.java
index f25d5b6f749d..9c968c453e47 100644
--- a/src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobExecutionService.java
+++ b/src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobExecutionService.java
@@ -245,7 +245,8 @@ private BuildResult runScriptAndParseResults(BuildJobQueueItem buildJob, String
buildLogsMap.appendBuildLogEntry(buildJob.id(), msg);
log.debug(msg);
buildJobContainerService.populateBuildJobContainer(containerId, assignmentRepositoryPath, testsRepositoryPath, solutionRepositoryPath, auxiliaryRepositoriesPaths,
- buildJob.repositoryInfo().auxiliaryRepositoryCheckoutDirectories(), buildJob.buildConfig().programmingLanguage());
+ buildJob.repositoryInfo().auxiliaryRepositoryCheckoutDirectories(), buildJob.buildConfig().programmingLanguage(), buildJob.buildConfig().assignmentCheckoutPath(),
+ buildJob.buildConfig().testCheckoutPath(), buildJob.buildConfig().solutionCheckoutPath());
msg = "~~~~~~~~~~~~~~~~~~~~ Executing Build Script for Build job " + buildJob.id() + " ~~~~~~~~~~~~~~~~~~~~";
buildLogsMap.appendBuildLogEntry(buildJob.id(), msg);
diff --git a/src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobManagementService.java b/src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobManagementService.java
index f514d59496cd..804d7d1e50df 100644
--- a/src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobManagementService.java
+++ b/src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobManagementService.java
@@ -58,7 +58,7 @@ public class BuildJobManagementService {
private final ReentrantLock lock = new ReentrantLock();
- @Value("${artemis.continuous-integration.timeout-seconds:240}")
+ @Value("${artemis.continuous-integration.timeout-seconds:120}")
private int timeoutSeconds;
@Value("${artemis.continuous-integration.asynchronous:true}")
@@ -149,9 +149,17 @@ public CompletableFuture executeBuildJob(BuildJobQueueItem buildJob
lock.unlock();
}
+ int buildJobTimeoutSeconds;
+ if (buildJobItem.buildConfig().timeoutSeconds() != 0 && buildJobItem.buildConfig().timeoutSeconds() < this.timeoutSeconds) {
+ buildJobTimeoutSeconds = buildJobItem.buildConfig().timeoutSeconds();
+ }
+ else {
+ buildJobTimeoutSeconds = this.timeoutSeconds;
+ }
+
CompletableFuture futureResult = createCompletableFuture(() -> {
try {
- return future.get(timeoutSeconds, TimeUnit.SECONDS);
+ return future.get(buildJobTimeoutSeconds, TimeUnit.SECONDS);
}
catch (Exception e) {
// RejectedExecutionException is thrown if the queue size limit (defined in "artemis.continuous-integration.queue-size-limit") is reached.
diff --git a/src/main/java/de/tum/cit/aet/artemis/buildagent/service/SharedQueueProcessingService.java b/src/main/java/de/tum/cit/aet/artemis/buildagent/service/SharedQueueProcessingService.java
index f82f7aa7a36f..7534de04e3bf 100644
--- a/src/main/java/de/tum/cit/aet/artemis/buildagent/service/SharedQueueProcessingService.java
+++ b/src/main/java/de/tum/cit/aet/artemis/buildagent/service/SharedQueueProcessingService.java
@@ -294,6 +294,7 @@ private void processBuild(BuildJobQueueItem buildJob) {
CompletableFuture futureResult = buildJobManagementService.executeBuildJob(buildJob);
futureResult.thenAccept(buildResult -> {
+ log.debug("Build job completed: {}", buildJob);
JobTimingInfo jobTimingInfo = new JobTimingInfo(buildJob.jobTimingInfo().submissionDate(), buildJob.jobTimingInfo().buildStartDate(), ZonedDateTime.now());
BuildJobQueueItem finishedJob = new BuildJobQueueItem(buildJob.id(), buildJob.name(), buildJob.buildAgentAddress(), buildJob.participationId(), buildJob.courseId(),
@@ -316,6 +317,8 @@ private void processBuild(BuildJobQueueItem buildJob) {
});
futureResult.exceptionally(ex -> {
+ log.debug("Build job completed with exception: {}", buildJob, ex);
+
ZonedDateTime completionDate = ZonedDateTime.now();
BuildJobQueueItem job;
@@ -364,6 +367,7 @@ public class QueuedBuildJobItemListener implements ItemListener event) {
log.debug("CIBuildJobQueueItem added to queue: {}", event.getItem());
+ log.debug("Current queued items: {}", queue.size());
checkAvailabilityAndProcessNextBuild();
}
diff --git a/src/main/java/de/tum/cit/aet/artemis/communication/domain/Faq.java b/src/main/java/de/tum/cit/aet/artemis/communication/domain/Faq.java
new file mode 100644
index 000000000000..fd7ce4fca468
--- /dev/null
+++ b/src/main/java/de/tum/cit/aet/artemis/communication/domain/Faq.java
@@ -0,0 +1,99 @@
+package de.tum.cit.aet.artemis.communication.domain;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import jakarta.persistence.CollectionTable;
+import jakarta.persistence.Column;
+import jakarta.persistence.ElementCollection;
+import jakarta.persistence.Entity;
+import jakarta.persistence.EnumType;
+import jakarta.persistence.Enumerated;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.Table;
+
+import org.hibernate.annotations.Cache;
+import org.hibernate.annotations.CacheConcurrencyStrategy;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+
+import de.tum.cit.aet.artemis.core.domain.AbstractAuditingEntity;
+import de.tum.cit.aet.artemis.core.domain.Course;
+
+/**
+ * A FAQ.
+ */
+@Entity
+@Table(name = "faq")
+@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
+@JsonInclude(JsonInclude.Include.NON_EMPTY)
+public class Faq extends AbstractAuditingEntity {
+
+ @Column(name = "question_title")
+ private String questionTitle;
+
+ @Column(name = "question_answer")
+ private String questionAnswer;
+
+ @ElementCollection(fetch = FetchType.EAGER)
+ @CollectionTable(name = "faq_category", joinColumns = @JoinColumn(name = "faq_id"))
+ @Column(name = "category")
+ private Set categories = new HashSet<>();
+
+ @Enumerated(EnumType.STRING)
+ @Column(name = "faq_state")
+ private FaqState faqState;
+
+ @ManyToOne
+ @JsonIgnoreProperties(value = { "faqs" }, allowSetters = true)
+ private Course course;
+
+ public String getQuestionTitle() {
+ return questionTitle;
+ }
+
+ public void setQuestionTitle(String questionTitle) {
+ this.questionTitle = questionTitle;
+ }
+
+ public String getQuestionAnswer() {
+ return questionAnswer;
+ }
+
+ public void setQuestionAnswer(String questionAnswer) {
+ this.questionAnswer = questionAnswer;
+ }
+
+ public Course getCourse() {
+ return course;
+ }
+
+ public void setCourse(Course course) {
+ this.course = course;
+ }
+
+ public Set getCategories() {
+ return categories;
+ }
+
+ public void setCategories(Set categories) {
+ this.categories = categories;
+ }
+
+ public FaqState getFaqState() {
+ return faqState;
+ }
+
+ public void setFaqState(FaqState faqState) {
+ this.faqState = faqState;
+ }
+
+ @Override
+ public String toString() {
+ return "Faq{" + "id=" + getId() + ", questionTitle='" + getQuestionTitle() + "'" + ", questionAnswer='" + getQuestionAnswer() + "'" + ", faqState='" + getFaqState() + "}";
+ }
+
+}
diff --git a/src/main/java/de/tum/cit/aet/artemis/communication/domain/FaqState.java b/src/main/java/de/tum/cit/aet/artemis/communication/domain/FaqState.java
new file mode 100644
index 000000000000..9018a3be3a12
--- /dev/null
+++ b/src/main/java/de/tum/cit/aet/artemis/communication/domain/FaqState.java
@@ -0,0 +1,5 @@
+package de.tum.cit.aet.artemis.communication.domain;
+
+public enum FaqState {
+ ACCEPTED, REJECTED, PROPOSED
+}
diff --git a/src/main/java/de/tum/cit/aet/artemis/communication/domain/Post.java b/src/main/java/de/tum/cit/aet/artemis/communication/domain/Post.java
index d3bf4e217ea3..4ff2d48fedf5 100644
--- a/src/main/java/de/tum/cit/aet/artemis/communication/domain/Post.java
+++ b/src/main/java/de/tum/cit/aet/artemis/communication/domain/Post.java
@@ -167,6 +167,10 @@ public void addTag(String tag) {
this.tags.add(tag);
}
+ public void setCourse(Course course) {
+ this.course = course;
+ }
+
public Conversation getConversation() {
return conversation;
}
diff --git a/src/main/java/de/tum/cit/aet/artemis/communication/domain/notification/SingleUserNotificationFactory.java b/src/main/java/de/tum/cit/aet/artemis/communication/domain/notification/SingleUserNotificationFactory.java
index f143f959f89f..71dc52ae4e93 100644
--- a/src/main/java/de/tum/cit/aet/artemis/communication/domain/notification/SingleUserNotificationFactory.java
+++ b/src/main/java/de/tum/cit/aet/artemis/communication/domain/notification/SingleUserNotificationFactory.java
@@ -434,7 +434,7 @@ public static String[] createPlaceholdersForUserGroupChat(String courseTitle, St
}
@NotificationPlaceholderCreator(values = { CONVERSATION_ADD_USER_CHANNEL, CONVERSATION_REMOVE_USER_CHANNEL, CONVERSATION_DELETE_CHANNEL })
- public static String[] createPlaceholdersForUserChannel(String courseTitle, String channelName, String responsibleForUserName) {
- return new String[] { courseTitle, channelName, responsibleForUserName };
+ public static String[] createPlaceholdersForUserChannel(String courseTitle, String conversationName, String responsibleForUserName) {
+ return new String[] { courseTitle, conversationName, responsibleForUserName };
}
}
diff --git a/src/main/java/de/tum/cit/aet/artemis/communication/domain/push_notification/PushNotificationDeviceConfiguration.java b/src/main/java/de/tum/cit/aet/artemis/communication/domain/push_notification/PushNotificationDeviceConfiguration.java
index c6bfd3384110..b9a911ce6194 100644
--- a/src/main/java/de/tum/cit/aet/artemis/communication/domain/push_notification/PushNotificationDeviceConfiguration.java
+++ b/src/main/java/de/tum/cit/aet/artemis/communication/domain/push_notification/PushNotificationDeviceConfiguration.java
@@ -106,7 +106,9 @@ public boolean equals(Object object) {
return false;
}
PushNotificationDeviceConfiguration that = (PushNotificationDeviceConfiguration) object;
- return token.equals(that.token) && deviceType == that.deviceType && expirationDate.equals(that.expirationDate) && Arrays.equals(secretKey, that.secretKey)
+ // Use compareTo rather than equals for dates to ensure timestamps and dates with the same time are considered equal
+ // This is caused by Java internal design having different classes for Date (java.util) and Timestamp (java.sql)
+ return token.equals(that.token) && deviceType == that.deviceType && expirationDate.compareTo(that.expirationDate) == 0 && Arrays.equals(secretKey, that.secretKey)
&& owner.equals(that.owner);
}
diff --git a/src/main/java/de/tum/cit/aet/artemis/communication/dto/FaqDTO.java b/src/main/java/de/tum/cit/aet/artemis/communication/dto/FaqDTO.java
new file mode 100644
index 000000000000..efab02ad1bf9
--- /dev/null
+++ b/src/main/java/de/tum/cit/aet/artemis/communication/dto/FaqDTO.java
@@ -0,0 +1,17 @@
+package de.tum.cit.aet.artemis.communication.dto;
+
+import java.util.Set;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+
+import de.tum.cit.aet.artemis.communication.domain.Faq;
+import de.tum.cit.aet.artemis.communication.domain.FaqState;
+
+@JsonInclude(JsonInclude.Include.NON_EMPTY)
+public record FaqDTO(Long id, String questionTitle, String questionAnswer, Set categories, FaqState faqState) {
+
+ public FaqDTO(Faq faq) {
+ this(faq.getId(), faq.getQuestionTitle(), faq.getQuestionAnswer(), faq.getCategories(), faq.getFaqState());
+ }
+
+}
diff --git a/src/main/java/de/tum/cit/aet/artemis/communication/repository/AnswerPostRepository.java b/src/main/java/de/tum/cit/aet/artemis/communication/repository/AnswerPostRepository.java
index c6a915b994e2..db61138b3a73 100644
--- a/src/main/java/de/tum/cit/aet/artemis/communication/repository/AnswerPostRepository.java
+++ b/src/main/java/de/tum/cit/aet/artemis/communication/repository/AnswerPostRepository.java
@@ -30,4 +30,6 @@ default AnswerPost findAnswerPostByIdElseThrow(Long answerPostId) {
default AnswerPost findAnswerMessageByIdElseThrow(Long answerPostId) {
return getValueElseThrow(findById(answerPostId).filter(answerPost -> answerPost.getPost().getConversation() != null), answerPostId);
}
+
+ long countAnswerPostsByPostIdIn(List postIds);
}
diff --git a/src/main/java/de/tum/cit/aet/artemis/communication/repository/FaqRepository.java b/src/main/java/de/tum/cit/aet/artemis/communication/repository/FaqRepository.java
new file mode 100644
index 000000000000..bd8bb8989995
--- /dev/null
+++ b/src/main/java/de/tum/cit/aet/artemis/communication/repository/FaqRepository.java
@@ -0,0 +1,37 @@
+package de.tum.cit.aet.artemis.communication.repository;
+
+import static de.tum.cit.aet.artemis.core.config.Constants.PROFILE_CORE;
+
+import java.util.Set;
+
+import org.springframework.context.annotation.Profile;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+import de.tum.cit.aet.artemis.communication.domain.Faq;
+import de.tum.cit.aet.artemis.core.repository.base.ArtemisJpaRepository;
+
+/**
+ * Spring Data repository for the Faq entity.
+ */
+@Profile(PROFILE_CORE)
+@Repository
+public interface FaqRepository extends ArtemisJpaRepository {
+
+ Set findAllByCourseId(Long courseId);
+
+ @Query("""
+ SELECT DISTINCT faq.categories
+ FROM Faq faq
+ WHERE faq.course.id = :courseId
+ """)
+ Set findAllCategoriesByCourseId(@Param("courseId") Long courseId);
+
+ @Transactional
+ @Modifying
+ void deleteAllByCourseId(Long courseId);
+
+}
diff --git a/src/main/java/de/tum/cit/aet/artemis/communication/repository/PostRepository.java b/src/main/java/de/tum/cit/aet/artemis/communication/repository/PostRepository.java
index 449a629fb4af..aacfbc33d179 100644
--- a/src/main/java/de/tum/cit/aet/artemis/communication/repository/PostRepository.java
+++ b/src/main/java/de/tum/cit/aet/artemis/communication/repository/PostRepository.java
@@ -45,4 +45,8 @@ default Post findPostByIdElseThrow(Long postId) throws EntityNotFoundException {
default Post findPostOrMessagePostByIdElseThrow(Long postId) throws EntityNotFoundException {
return getValueElseThrow(findById(postId), postId);
}
+
+ List findAllByConversationId(Long conversationId);
+
+ List findAllByCourseId(Long courseId);
}
diff --git a/src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/ConversationNotificationService.java b/src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/ConversationNotificationService.java
index 1e13dce59c5a..d009074927b2 100644
--- a/src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/ConversationNotificationService.java
+++ b/src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/ConversationNotificationService.java
@@ -18,6 +18,7 @@
import de.tum.cit.aet.artemis.communication.domain.conversation.Channel;
import de.tum.cit.aet.artemis.communication.domain.conversation.Conversation;
import de.tum.cit.aet.artemis.communication.domain.conversation.GroupChat;
+import de.tum.cit.aet.artemis.communication.domain.conversation.OneToOneChat;
import de.tum.cit.aet.artemis.communication.domain.notification.ConversationNotification;
import de.tum.cit.aet.artemis.communication.domain.notification.NotificationPlaceholderCreator;
import de.tum.cit.aet.artemis.communication.domain.notification.SingleUserNotification;
@@ -57,37 +58,39 @@ public ConversationNotificationService(ConversationNotificationRepository conver
* @return the created notification
*/
public ConversationNotification createNotification(Post createdMessage, Conversation conversation, Course course, Set mentionedUsers) {
- String notificationText;
- String[] placeholders;
NotificationType notificationType = CONVERSATION_NEW_MESSAGE;
String conversationName = conversation.getHumanReadableNameForReceiver(createdMessage.getAuthor());
+ String conversationType;
+ String notificationText;
// add channel/groupChat/oneToOneChat string to placeholders for notification to distinguish in mobile client
- if (conversation instanceof Channel channel) {
- notificationText = NEW_MESSAGE_CHANNEL_TEXT;
- placeholders = createPlaceholdersNewMessageChannelText(course.getTitle(), createdMessage.getContent(), createdMessage.getCreationDate().toString(),
- createdMessage.getAuthor().getName(), conversationName, "channel");
- notificationType = getNotificationTypeForChannel(channel);
- }
- else if (conversation instanceof GroupChat) {
- notificationText = NEW_MESSAGE_GROUP_CHAT_TEXT;
- placeholders = createPlaceholdersNewMessageChannelText(course.getTitle(), createdMessage.getContent(), createdMessage.getCreationDate().toString(),
- createdMessage.getAuthor().getName(), conversationName, "groupChat");
- }
- else {
- notificationText = NEW_MESSAGE_DIRECT_TEXT;
- placeholders = createPlaceholdersNewMessageChannelText(course.getTitle(), createdMessage.getContent(), createdMessage.getCreationDate().toString(),
- createdMessage.getAuthor().getName(), conversationName, "oneToOneChat");
+ switch (conversation) {
+ case Channel channel -> {
+ notificationText = NEW_MESSAGE_CHANNEL_TEXT;
+ conversationType = "channel";
+ notificationType = getNotificationTypeForChannel(channel);
+ }
+ case GroupChat ignored -> {
+ notificationText = NEW_MESSAGE_GROUP_CHAT_TEXT;
+ conversationType = "groupChat";
+ }
+ case OneToOneChat ignored -> {
+ notificationText = NEW_MESSAGE_DIRECT_TEXT;
+ conversationType = "oneToOneChat";
+ }
+ default -> throw new IllegalStateException("Unexpected value: " + conversation);
}
+ String[] placeholders = createPlaceholdersNewMessageChannelText(course.getTitle(), createdMessage.getContent(), createdMessage.getCreationDate().toString(),
+ conversationName, createdMessage.getAuthor().getName(), conversationType);
ConversationNotification notification = createConversationMessageNotification(course.getId(), createdMessage, notificationType, notificationText, true, placeholders);
save(notification, mentionedUsers, placeholders);
return notification;
}
@NotificationPlaceholderCreator(values = { CONVERSATION_NEW_MESSAGE })
- public static String[] createPlaceholdersNewMessageChannelText(String courseTitle, String messageContent, String messageCreationDate, String channelName, String authorName,
- String conversationType) {
- return new String[] { courseTitle, messageContent, messageCreationDate, channelName, authorName, conversationType };
+ public static String[] createPlaceholdersNewMessageChannelText(String courseTitle, String messageContent, String messageCreationDate, String conversationName,
+ String authorName, String conversationType) {
+ return new String[] { courseTitle, messageContent, messageCreationDate, conversationName, authorName, conversationType };
}
private void save(ConversationNotification notification, Set mentionedUsers, String[] placeHolders) {
diff --git a/src/main/java/de/tum/cit/aet/artemis/communication/web/FaqResource.java b/src/main/java/de/tum/cit/aet/artemis/communication/web/FaqResource.java
new file mode 100644
index 000000000000..91a542aaa220
--- /dev/null
+++ b/src/main/java/de/tum/cit/aet/artemis/communication/web/FaqResource.java
@@ -0,0 +1,194 @@
+package de.tum.cit.aet.artemis.communication.web;
+
+import static de.tum.cit.aet.artemis.core.config.Constants.PROFILE_CORE;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Profile;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import de.tum.cit.aet.artemis.communication.domain.Faq;
+import de.tum.cit.aet.artemis.communication.dto.FaqDTO;
+import de.tum.cit.aet.artemis.communication.repository.FaqRepository;
+import de.tum.cit.aet.artemis.core.domain.Course;
+import de.tum.cit.aet.artemis.core.exception.BadRequestAlertException;
+import de.tum.cit.aet.artemis.core.repository.CourseRepository;
+import de.tum.cit.aet.artemis.core.security.Role;
+import de.tum.cit.aet.artemis.core.security.annotations.EnforceAtLeastInstructor;
+import de.tum.cit.aet.artemis.core.security.annotations.EnforceAtLeastStudent;
+import de.tum.cit.aet.artemis.core.service.AuthorizationCheckService;
+import de.tum.cit.aet.artemis.core.util.HeaderUtil;
+
+/**
+ * REST controller for managing Faqs.
+ */
+@Profile(PROFILE_CORE)
+@RestController
+@RequestMapping("api/")
+public class FaqResource {
+
+ private static final Logger log = LoggerFactory.getLogger(FaqResource.class);
+
+ private static final String ENTITY_NAME = "faq";
+
+ @Value("${jhipster.clientApp.name}")
+ private String applicationName;
+
+ private final CourseRepository courseRepository;
+
+ private final AuthorizationCheckService authCheckService;
+
+ private final FaqRepository faqRepository;
+
+ public FaqResource(CourseRepository courseRepository, AuthorizationCheckService authCheckService, FaqRepository faqRepository) {
+
+ this.courseRepository = courseRepository;
+ this.authCheckService = authCheckService;
+ this.faqRepository = faqRepository;
+ }
+
+ /**
+ * POST /courses/:courseId/faqs : Create a new faq.
+ *
+ * @param faq the faq to create *
+ * @param courseId the id of the course the faq belongs to
+ * @return the ResponseEntity with status 201 (Created) and with body the new faq, or with status 400 (Bad Request)
+ * if the faq has already an ID or if the faq course id does not match with the path variable
+ * @throws URISyntaxException if the Location URI syntax is incorrect
+ */
+ @PostMapping("courses/{courseId}/faqs")
+ @EnforceAtLeastInstructor
+ public ResponseEntity createFaq(@RequestBody Faq faq, @PathVariable Long courseId) throws URISyntaxException {
+ log.debug("REST request to save Faq : {}", faq);
+ if (faq.getId() != null) {
+ throw new BadRequestAlertException("A new faq cannot already have an ID", ENTITY_NAME, "idExists");
+ }
+
+ if (faq.getCourse() == null || !faq.getCourse().getId().equals(courseId)) {
+ throw new BadRequestAlertException("Course ID in path and FAQ do not match", ENTITY_NAME, "courseIdMismatch");
+ }
+ authCheckService.checkHasAtLeastRoleInCourseElseThrow(Role.INSTRUCTOR, faq.getCourse(), null);
+
+ Faq savedFaq = faqRepository.save(faq);
+ FaqDTO dto = new FaqDTO(savedFaq);
+ return ResponseEntity.created(new URI("/api/courses/" + courseId + "/faqs/" + savedFaq.getId())).body(dto);
+ }
+
+ /**
+ * PUT /courses/:courseId/faqs/:faqId : Updates an existing faq.
+ *
+ * @param faq the faq to update
+ * @param faqId id of the faq to be updated *
+ * @param courseId the id of the course the faq belongs to
+ * @return the ResponseEntity with status 200 (OK) and with body the updated faq, or with status 400 (Bad Request)
+ * if the faq is not valid or if the faq course id does not match with the path variable
+ */
+ @PutMapping("courses/{courseId}/faqs/{faqId}")
+ @EnforceAtLeastInstructor
+ public ResponseEntity updateFaq(@RequestBody Faq faq, @PathVariable Long faqId, @PathVariable Long courseId) {
+ log.debug("REST request to update Faq : {}", faq);
+ if (faqId == null || !faqId.equals(faq.getId())) {
+ throw new BadRequestAlertException("Id of FAQ and path must match", ENTITY_NAME, "idNull");
+ }
+ authCheckService.checkHasAtLeastRoleInCourseElseThrow(Role.INSTRUCTOR, faq.getCourse(), null);
+ Faq existingFaq = faqRepository.findByIdElseThrow(faqId);
+ if (!Objects.equals(existingFaq.getCourse().getId(), courseId)) {
+ throw new BadRequestAlertException("Course ID of the FAQ provided courseID must match", ENTITY_NAME, "idNull");
+ }
+ Faq updatedFaq = faqRepository.save(faq);
+ FaqDTO dto = new FaqDTO(updatedFaq);
+ return ResponseEntity.ok().body(dto);
+ }
+
+ /**
+ * GET /courses/:courseId/faqs/:faqId : get the faq with the id faqId.
+ *
+ * @param faqId the faqId of the faq to retrieve *
+ * @param courseId the id of the course the faq belongs to
+ * @return the ResponseEntity with status 200 (OK) and with body the faq, or with status 404 (Not Found)
+ */
+ @GetMapping("courses/{courseId}/faqs/{faqId}")
+ @EnforceAtLeastStudent
+ public ResponseEntity getFaq(@PathVariable Long faqId, @PathVariable Long courseId) {
+ log.debug("REST request to get faq {}", faqId);
+ Faq faq = faqRepository.findByIdElseThrow(faqId);
+ if (faq.getCourse() == null || !faq.getCourse().getId().equals(courseId)) {
+ throw new BadRequestAlertException("Course ID in path and FAQ do not match", ENTITY_NAME, "courseIdMismatch");
+ }
+ authCheckService.checkHasAtLeastRoleInCourseElseThrow(Role.STUDENT, faq.getCourse(), null);
+ FaqDTO dto = new FaqDTO(faq);
+ return ResponseEntity.ok(dto);
+ }
+
+ /**
+ * DELETE /courses/:courseId/faqs/:faqId : delete the "id" faq.
+ *
+ * @param faqId the id of the faq to delete
+ * @param courseId the id of the course the faq belongs to
+ * @return the ResponseEntity with status 200 (OK)
+ */
+ @DeleteMapping("courses/{courseId}/faqs/{faqId}")
+ @EnforceAtLeastInstructor
+ public ResponseEntity deleteFaq(@PathVariable Long faqId, @PathVariable Long courseId) {
+
+ log.debug("REST request to delete faq {}", faqId);
+ Faq existingFaq = faqRepository.findByIdElseThrow(faqId);
+ authCheckService.checkHasAtLeastRoleInCourseElseThrow(Role.INSTRUCTOR, existingFaq.getCourse(), null);
+ if (!Objects.equals(existingFaq.getCourse().getId(), courseId)) {
+ throw new BadRequestAlertException("Course ID of the FAQ provided courseID must match", ENTITY_NAME, "idNull");
+ }
+ faqRepository.deleteById(faqId);
+ return ResponseEntity.ok().headers(HeaderUtil.createEntityDeletionAlert(applicationName, true, ENTITY_NAME, faqId.toString())).build();
+ }
+
+ /**
+ * GET /courses/:courseId/faqs : get all the faqs of a course
+ *
+ * @param courseId the courseId of the course for which all faqs should be returned
+ * @return the ResponseEntity with status 200 (OK) and the list of faqs in body
+ */
+ @GetMapping("courses/{courseId}/faqs")
+ @EnforceAtLeastStudent
+ public ResponseEntity> getFaqForCourse(@PathVariable Long courseId) {
+ log.debug("REST request to get all Faqs for the course with id : {}", courseId);
+
+ Course course = courseRepository.findByIdElseThrow(courseId);
+ authCheckService.checkHasAtLeastRoleInCourseElseThrow(Role.STUDENT, course, null);
+ Set faqs = faqRepository.findAllByCourseId(courseId);
+ Set faqDTOS = faqs.stream().map(FaqDTO::new).collect(Collectors.toSet());
+ return ResponseEntity.ok().body(faqDTOS);
+ }
+
+ /**
+ * GET /courses/:courseId/faq-categories : get all the faq categories of a course
+ *
+ * @param courseId the courseId of the course for which all faq categories should be returned
+ * @return the ResponseEntity with status 200 (OK) and the list of faqs in body
+ */
+ @GetMapping("courses/{courseId}/faq-categories")
+ @EnforceAtLeastStudent
+ public ResponseEntity> getFaqCategoriesForCourse(@PathVariable Long courseId) {
+ log.debug("REST request to get all Faq Categories for the course with id : {}", courseId);
+
+ Course course = courseRepository.findByIdElseThrow(courseId);
+ authCheckService.checkHasAtLeastRoleInCourseElseThrow(Role.STUDENT, course, null);
+ Set faqs = faqRepository.findAllCategoriesByCourseId(courseId);
+
+ return ResponseEntity.ok().body(faqs);
+ }
+}
diff --git a/src/main/java/de/tum/cit/aet/artemis/communication/web/admin/AdminSystemNotificationResource.java b/src/main/java/de/tum/cit/aet/artemis/communication/web/admin/AdminSystemNotificationResource.java
index 6850598633e9..4e94766284d6 100644
--- a/src/main/java/de/tum/cit/aet/artemis/communication/web/admin/AdminSystemNotificationResource.java
+++ b/src/main/java/de/tum/cit/aet/artemis/communication/web/admin/AdminSystemNotificationResource.java
@@ -30,6 +30,7 @@
* REST controller for administrating system notifications.
*/
@Profile(PROFILE_CORE)
+@EnforceAdmin
@RestController
@RequestMapping("api/admin/")
public class AdminSystemNotificationResource {
@@ -58,7 +59,6 @@ public AdminSystemNotificationResource(SystemNotificationRepository systemNotifi
* @throws URISyntaxException if the Location URI syntax is incorrect
*/
@PostMapping("system-notifications")
- @EnforceAdmin
public ResponseEntity