From 9be9cd1b0c1e6591224303084e88e7a9c13243af Mon Sep 17 00:00:00 2001 From: Cobel Date: Fri, 6 Mar 2026 12:48:27 +0900 Subject: [PATCH] Studio On branch studio Your branch is up to date with 'origin/studio'. Changes to be committed: modified: .github/workflows/core-ci.yml modified: core/apps/common/error.py renamed: core/apps/operation/management/commands/create_base_policies.py -> core/apps/operation/management/commands/setup_base_operation_data.py new file: core/apps/operation/migrations/0002_alter_faq_name.py modified: core/apps/operation/models.py modified: core/apps/operation/tests/factories.py modified: core/apps/studio/api/v1/__init__.py modified: core/apps/studio/api/v1/assignment.py modified: core/apps/studio/api/v1/course.py modified: core/apps/studio/api/v1/discussion.py modified: core/apps/studio/api/v1/exam.py modified: core/apps/studio/api/v1/media.py modified: core/apps/studio/api/v1/quiz.py modified: core/apps/studio/api/v1/survey.py modified: core/apps/studio/tests/test_studio_assignment_api.py modified: core/apps/studio/tests/test_studio_course_api.py modified: core/apps/studio/tests/test_studio_discussion_api.py modified: core/apps/studio/tests/test_studio_exam_api.py modified: core/apps/studio/tests/test_studio_quiz_api.py modified: core/apps/studio/tests/test_studio_survey_api.py modified: core/apps/survey/models.py modified: core/apps/warehouse/models.py new file: core/apps/warehouse/tests/test_warehouse_model.py modified: core/dev.py modified: core/uv.lock modified: dev.sh modified: web/biome.json modified: web/package-lock.json modified: web/package.json modified: web/src/api/client.gen.ts modified: web/src/api/client/client.gen.ts modified: web/src/api/client/types.gen.ts modified: web/src/api/core/bodySerializer.gen.ts modified: web/src/api/index.ts modified: web/src/api/sdk.gen.ts modified: web/src/api/types.gen.ts modified: web/src/api/valibot.gen.ts modified: web/src/routes/(app)/-shared/goal/CategorySelect.tsx modified: web/src/routes/(app)/course/-session/Outline.tsx modified: web/src/routes/(app)/dashboard/learning.tsx modified: web/src/routes/(app)/dashboard/search.tsx modified: web/src/routes/(app)/media/-media/Subtitle.tsx modified: web/src/routes/(public)/survey/-SurveyForm.tsx modified: web/src/routes/studio/$app.$id.tsx modified: web/src/routes/studio/-assignment/Assignment.tsx modified: web/src/routes/studio/-assignment/Question.tsx modified: web/src/routes/studio/-assignment/QuestionPool.tsx modified: web/src/routes/studio/-assignment/data.ts modified: web/src/routes/studio/-course/App.tsx modified: web/src/routes/studio/-course/Assessments.tsx modified: web/src/routes/studio/-course/Categories.tsx modified: web/src/routes/studio/-course/Certificates.tsx modified: web/src/routes/studio/-course/Course.tsx modified: web/src/routes/studio/-course/CourseRelations.tsx deleted: web/src/routes/studio/-course/FaqItems.tsx modified: web/src/routes/studio/-course/Instructors.tsx modified: web/src/routes/studio/-course/Lessons.tsx modified: web/src/routes/studio/-course/Surveys.tsx modified: web/src/routes/studio/-course/data.ts modified: web/src/routes/studio/-discussion/Discussion.tsx modified: web/src/routes/studio/-discussion/Question.tsx modified: web/src/routes/studio/-discussion/QuestionPool.tsx modified: web/src/routes/studio/-discussion/data.ts modified: web/src/routes/studio/-exam/Exam.tsx modified: web/src/routes/studio/-exam/Question.tsx modified: web/src/routes/studio/-exam/QuestionPool.tsx modified: web/src/routes/studio/-exam/data.ts modified: web/src/routes/studio/-media/Media.tsx modified: web/src/routes/studio/-media/SubtitleSet.tsx modified: web/src/routes/studio/-quiz/Question.tsx modified: web/src/routes/studio/-quiz/QuestionPool.tsx modified: web/src/routes/studio/-quiz/Quiz.tsx modified: web/src/routes/studio/-quiz/data.ts modified: web/src/routes/studio/-studio/DataAction.tsx modified: web/src/routes/studio/-studio/InlineSuggestion.tsx modified: web/src/routes/studio/-studio/Menu.tsx deleted: web/src/routes/studio/-studio/RichtextField.tsx modified: web/src/routes/studio/-studio/field.tsx modified: web/src/routes/studio/-survey/Question.tsx modified: web/src/routes/studio/-survey/QuestionPool.tsx modified: web/src/routes/studio/-survey/Survey.tsx modified: web/src/routes/studio/-survey/data.ts modified: web/src/routes/studio/index.tsx modified: web/src/routes/studio/route.tsx modified: web/src/shared/AutocompleteInput.tsx modified: web/src/shared/solid/cached-store.ts modified: web/src/shared/toast/ToastContainer.tsx modified: web/src/styles.css --- .github/workflows/core-ci.yml | 17 +- core/apps/common/error.py | 1 + ...licies.py => setup_base_operation_data.py} | 25 +- .../migrations/0002_alter_faq_name.py | 18 + core/apps/operation/models.py | 19 +- core/apps/operation/tests/factories.py | 5 +- core/apps/studio/api/v1/__init__.py | 114 ++-- core/apps/studio/api/v1/assignment.py | 50 +- core/apps/studio/api/v1/course.py | 88 +-- core/apps/studio/api/v1/discussion.py | 103 ++-- core/apps/studio/api/v1/exam.py | 44 +- core/apps/studio/api/v1/media.py | 10 +- core/apps/studio/api/v1/quiz.py | 30 +- core/apps/studio/api/v1/survey.py | 48 +- .../tests/test_studio_assignment_api.py | 2 +- .../studio/tests/test_studio_course_api.py | 14 +- .../tests/test_studio_discussion_api.py | 18 +- .../apps/studio/tests/test_studio_exam_api.py | 6 +- .../apps/studio/tests/test_studio_quiz_api.py | 6 +- .../studio/tests/test_studio_survey_api.py | 6 +- core/apps/survey/models.py | 4 +- core/apps/warehouse/models.py | 4 +- .../warehouse/tests/test_warehouse_model.py | 16 + core/dev.py | 8 +- core/uv.lock | 42 +- dev.sh | 4 +- web/biome.json | 2 +- web/package-lock.json | 330 +++++------ web/package.json | 23 +- web/src/api/client.gen.ts | 2 +- web/src/api/client/client.gen.ts | 5 +- web/src/api/client/types.gen.ts | 2 +- web/src/api/core/bodySerializer.gen.ts | 14 +- web/src/api/index.ts | 4 +- web/src/api/sdk.gen.ts | 113 ++-- web/src/api/types.gen.ts | 546 +++++++----------- web/src/api/valibot.gen.ts | 348 ++++------- .../(app)/-shared/goal/CategorySelect.tsx | 1 - .../routes/(app)/course/-session/Outline.tsx | 1 + web/src/routes/(app)/dashboard/learning.tsx | 2 +- web/src/routes/(app)/dashboard/search.tsx | 2 +- .../routes/(app)/media/-media/Subtitle.tsx | 5 +- .../routes/(public)/survey/-SurveyForm.tsx | 2 +- web/src/routes/studio/$app.$id.tsx | 2 +- .../routes/studio/-assignment/Assignment.tsx | 31 +- .../routes/studio/-assignment/Question.tsx | 6 +- .../studio/-assignment/QuestionPool.tsx | 2 +- web/src/routes/studio/-assignment/data.ts | 13 +- web/src/routes/studio/-course/App.tsx | 2 - web/src/routes/studio/-course/Assessments.tsx | 44 +- web/src/routes/studio/-course/Categories.tsx | 45 +- .../routes/studio/-course/Certificates.tsx | 43 +- web/src/routes/studio/-course/Course.tsx | 34 +- .../routes/studio/-course/CourseRelations.tsx | 43 +- web/src/routes/studio/-course/FaqItems.tsx | 208 ------- web/src/routes/studio/-course/Instructors.tsx | 43 +- web/src/routes/studio/-course/Lessons.tsx | 60 +- web/src/routes/studio/-course/Surveys.tsx | 41 +- web/src/routes/studio/-course/data.ts | 16 +- .../routes/studio/-discussion/Discussion.tsx | 31 +- .../routes/studio/-discussion/Question.tsx | 10 +- .../studio/-discussion/QuestionPool.tsx | 2 +- web/src/routes/studio/-discussion/data.ts | 17 +- web/src/routes/studio/-exam/Exam.tsx | 28 +- web/src/routes/studio/-exam/Question.tsx | 6 +- web/src/routes/studio/-exam/QuestionPool.tsx | 58 +- web/src/routes/studio/-exam/data.ts | 9 +- web/src/routes/studio/-media/Media.tsx | 25 +- web/src/routes/studio/-media/SubtitleSet.tsx | 2 +- web/src/routes/studio/-quiz/Question.tsx | 6 +- web/src/routes/studio/-quiz/QuestionPool.tsx | 59 +- web/src/routes/studio/-quiz/Quiz.tsx | 21 +- web/src/routes/studio/-quiz/data.ts | 2 - web/src/routes/studio/-studio/DataAction.tsx | 12 +- .../studio/-studio/InlineSuggestion.tsx | 68 ++- web/src/routes/studio/-studio/Menu.tsx | 21 +- .../routes/studio/-studio/RichtextField.tsx | 212 ------- web/src/routes/studio/-studio/field.tsx | 429 +++++++++++--- web/src/routes/studio/-survey/Question.tsx | 6 +- .../routes/studio/-survey/QuestionPool.tsx | 60 +- web/src/routes/studio/-survey/Survey.tsx | 9 - web/src/routes/studio/-survey/data.ts | 6 - web/src/routes/studio/index.tsx | 70 ++- web/src/routes/studio/route.tsx | 1 + web/src/shared/AutocompleteInput.tsx | 12 +- web/src/shared/solid/cached-store.ts | 32 +- web/src/shared/toast/ToastContainer.tsx | 2 +- web/src/styles.css | 4 - 88 files changed, 1792 insertions(+), 2165 deletions(-) rename core/apps/operation/management/commands/{create_base_policies.py => setup_base_operation_data.py} (59%) create mode 100644 core/apps/operation/migrations/0002_alter_faq_name.py create mode 100644 core/apps/warehouse/tests/test_warehouse_model.py delete mode 100644 web/src/routes/studio/-course/FaqItems.tsx delete mode 100644 web/src/routes/studio/-studio/RichtextField.tsx diff --git a/.github/workflows/core-ci.yml b/.github/workflows/core-ci.yml index 36e8e8d..3cd49a2 100644 --- a/.github/workflows/core-ci.yml +++ b/.github/workflows/core-ci.yml @@ -53,26 +53,15 @@ jobs: - name: Start services run: docker compose up -d - - name: Bootstrap django - run: | - commands="python manage.py migrate && \ - python manage.py collectstatic --noinput && \ - python manage.py createsuperuser --noinput || true && \ - python manage.py create_roles && \ - python manage.py opensearch index create --force --ignore-error && \ - python manage.py create_platform_partner && \ - python manage.py create_base_policies && \ - python manage.py load_ncs_data && \ - python manage.py loaddata ncs_category_en.json" - docker compose exec -T minima sh -c "$commands" - docker compose restart minima worker - - name: Install uv and dev tools run: | pip install uv uv tool install pyrefly uv tool install ruff + - name: Bootstrap apps + run: uv run dev.py bootstrap --no-tty + - name: Run linting run: | uv run pyrefly check diff --git a/core/apps/common/error.py b/core/apps/common/error.py index ca04a7a..c027725 100644 --- a/core/apps/common/error.py +++ b/core/apps/common/error.py @@ -63,6 +63,7 @@ class ErrorCode: SSO_SESSION_EXPIRED = "SSO_SESSION_EXPIRED" THUMBNAIL_GENERATION_FAILED = "THUMBNAIL_GENERATION_FAILED" TITLE_ALREADY_EXISTS = "TITLE_ALREADY_EXISTS" + UNKNOWN_CONTENT = "UNKNOWN_CONTENT" UNKNOWN_COURSE_CONTENT = "UNKNOWN_COURSE_CONTENT" USER_ALREADY_ACTIVE = "USER_ALREADY_ACTIVE" USER_NOT_ACTIVE = "USER_NOT_ACTIVE" diff --git a/core/apps/operation/management/commands/create_base_policies.py b/core/apps/operation/management/commands/setup_base_operation_data.py similarity index 59% rename from core/apps/operation/management/commands/create_base_policies.py rename to core/apps/operation/management/commands/setup_base_operation_data.py index 1621048..63a607e 100644 --- a/core/apps/operation/management/commands/create_base_policies.py +++ b/core/apps/operation/management/commands/setup_base_operation_data.py @@ -2,16 +2,17 @@ from django.core.management.base import BaseCommand from django.utils import timezone +from django.utils.translation import gettext_lazy as _ -from apps.operation.models import Policy +from apps.operation.models import FAQ, HonorCode, Policy log = logging.getLogger(__name__) class Command(BaseCommand): - help = "Create empty policies" - def handle(self, *args: object, **options: dict[str, object]): + + # policies for i, (value, label) in enumerate(Policy.KindChoices.choices): policy, created = Policy.objects.get_or_create( kind=value, @@ -26,7 +27,7 @@ def handle(self, *args: object, **options: dict[str, object]): if created: policy.policy_versions.create( - body=f"Write your {label} policy here", + body=f"Write default {label} policy here", data_category={}, version="1.0", effective_date=timezone.now(), @@ -34,3 +35,19 @@ def handle(self, *args: object, **options: dict[str, object]): self.stdout.write(self.style.SUCCESS(f"Successfully created policy: {policy.title}")) else: self.stdout.write(self.style.WARNING(f"Policy already exists: {policy.title}")) + + # honor code + HonorCode.objects.get_or_create( + title=_("Student Honor Code"), defaults={"code": "Write default student honor code here"} + ) + + # faq + faq, created = FAQ.objects.get_or_create( + name=_("Frequently Asked Questions"), defaults={"description": _("default faq")} + ) + + if created: + for i in range(1, 5): + faq.items.create( + question=_("Write FAQ question %d here") % i, answer=_("Write FAQ answer %d here") % i, ordering=i + ) diff --git a/core/apps/operation/migrations/0002_alter_faq_name.py b/core/apps/operation/migrations/0002_alter_faq_name.py new file mode 100644 index 0000000..0cd14dc --- /dev/null +++ b/core/apps/operation/migrations/0002_alter_faq_name.py @@ -0,0 +1,18 @@ +# Generated by Django 6.0.3 on 2026-03-04 01:48 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('operation', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='faq', + name='name', + field=models.CharField(max_length=255, verbose_name='Name'), + ), + ] diff --git a/core/apps/operation/models.py b/core/apps/operation/models.py index 63122a8..8c52e4b 100644 --- a/core/apps/operation/models.py +++ b/core/apps/operation/models.py @@ -189,7 +189,7 @@ def __str__(self): @pghistory.track() class HonorCode(TimeStampedMixin): - title = CharField(max_length=255, verbose_name=_("Title")) + title = CharField(_("Title"), max_length=255, unique=True) code = TextField(_("Code")) class Meta(TimeStampedMixin.Meta): @@ -292,8 +292,19 @@ async def update_attachments(self, *, files: Sequence[File] | None, owner_id: st existing_attachments = [] if self.pk: - async for a in self.attachments.all(): - existing_attachments.append(a) + cached = ( + self._prefetched_objects_cache.get("attachments") + if hasattr(self, "_prefetched_objects_cache") + else None + ) + + if cached is not None: + existing_attachments = list(cached) + else: + async for a in self.attachments.all(): + existing_attachments.append(a) + + for a in existing_attachments: if self.restore_filename(a.file.name) in used_filenames: attachments_to_keep.append(a) seen_hashes.add((a.hash, owner_id)) @@ -320,6 +331,8 @@ async def update_attachments(self, *, files: Sequence[File] | None, owner_id: st existing_ids = set(a.id for a in existing_attachments) new_ids = set(a.pk for a in attachments_to_keep) if existing_ids != new_ids: + if hasattr(self, "_prefetched_objects_cache"): + self._prefetched_objects_cache.pop("attachments", None) await self.attachments.aset(attachments_to_keep) if hasattr(self, "_prefetched_objects_cache"): diff --git a/core/apps/operation/tests/factories.py b/core/apps/operation/tests/factories.py index 507b66d..95192db 100644 --- a/core/apps/operation/tests/factories.py +++ b/core/apps/operation/tests/factories.py @@ -2,7 +2,6 @@ from django.conf import settings from django.core.files.base import ContentFile from django.utils import timezone -from django.utils.translation import gettext_lazy as _ from factory.declarations import Iterator, LazyAttribute, LazyFunction, Sequence, SubFactory from factory.django import DjangoModelFactory from factory.helpers import lazy_attribute, post_generation @@ -58,7 +57,7 @@ class Meta: class HonorCodeFactory(DjangoModelFactory[HonorCode]): - title = LazyFunction(lambda: f"{generic.food.fruit()} {_('Honor Code')}") + title = LazyFunction(lambda: " ".join(generic.text.words(quantity=generic.random.randint(3, 5)))) code = LazyFunction( lambda: "\n\n".join([ generic.text.text(quantity=generic.random.randint(2, 4)) for _ in range(generic.random.randint(5, 10)) @@ -71,7 +70,7 @@ class Meta: class FAQFactory(DjangoModelFactory[FAQ]): - name = FactoryField("text.title") + name = LazyFunction(lambda: " ".join(generic.text.words(quantity=generic.random.randint(3, 5)))) description = FactoryField("sentence") class Meta: diff --git a/core/apps/studio/api/v1/__init__.py b/core/apps/studio/api/v1/__init__.py index 59c5389..1ff67d8 100644 --- a/core/apps/studio/api/v1/__init__.py +++ b/core/apps/studio/api/v1/__init__.py @@ -5,12 +5,13 @@ from asgiref.sync import sync_to_async from django.conf import settings from django.db import connection -from django.db.models import Value +from django.db.models import F, Value from django.db.models.functions import JSONObject from ninja import Router from ninja.params import functions from apps.assignment.models import Assignment +from apps.common.error import ErrorCode from apps.common.schema import ContentTypeSchema, Schema from apps.common.util import HttpRequest, PaginatedResponse from apps.competency.models import Certificate @@ -18,7 +19,7 @@ from apps.course.models import ASSESSIBLE_MODELS, Course from apps.discussion.models import Discussion from apps.exam.models import Exam -from apps.operation.models import FAQ, Category, FAQItem, Instructor +from apps.operation.models import FAQ, Category, HonorCode, Instructor from apps.quiz.models import Quiz from apps.studio.api.v1.assignment import router as assignment_router from apps.studio.api.v1.course import router as course_router @@ -48,11 +49,6 @@ } -class StudioContentTypeSpec(Schema): - app_label: str - model: StudioModel - - class StudioContentSpec(Schema): id: str title: str @@ -125,103 +121,83 @@ def execute(): return {"items": rows, "count": total, "size": size, "page": page, "pages": ceil(total / size) if total else 1} -class ContentSuggestionSpec(Schema): - id: str - title: str - - MAX_SUGGESTIONS = 1000 -@router.get("/suggestion/content", response=list[ContentSuggestionSpec]) -@editor_required() -async def content_suggestions(request: HttpRequest, kind: Annotated[StudioModel, functions.Query(...)]): - return [ - raw - async for raw in STUDIO_MODELS[kind] - .objects.filter(owner_id=request.auth) - .values("title", "id") - .order_by("-modified")[:MAX_SUGGESTIONS] - ] - - -class AssessmentSuggestion(Schema): +class AssessmentSuggestionSpec(Schema): id: str - title: str + label: str item_type: ContentTypeSchema -@router.get("/suggestion/assessment", response=list[AssessmentSuggestion]) +@router.get("/suggestion/assessment", response=list[AssessmentSuggestionSpec]) @editor_required() async def assessment_suggestions(request: HttpRequest): qs = [ M.objects - .filter(owner_id=request.auth) + .filter(owner_id=request.auth) # required owner permission .annotate(item_type=JSONObject(app_label=Value(M._meta.app_label), model=Value(M._meta.model_name))) - .values("id", "title", "item_type") - .order_by("-modified")[:MAX_SUGGESTIONS] + .annotate(label=F("title")) + .values("id", "label", "item_type") + .order_by("label")[:MAX_SUGGESTIONS] for M in ASSESSIBLE_MODELS ] return [o async for o in qs[0].union(*qs[1:], all=True)] -class CertificateSuggestionSpec(Schema): - id: int - name: str - - -@router.get("/suggestion/certificate", response=list[CertificateSuggestionSpec]) -@editor_required() -async def certificate_suggestions(request: HttpRequest): - return [c async for c in Certificate.objects.filter(active=True).order_by("-modified")] - - -class CategorySuggestionSpec(Schema): - id: int - full_path: str +class ContentSuggestionSpec(Schema): + id: str + label: str -@router.get("/suggestion/category", response=list[CategorySuggestionSpec]) +@router.get("/suggestion/content", response=list[ContentSuggestionSpec]) @editor_required() -async def category_suggestions(request: HttpRequest): +async def content_suggestions(request: HttpRequest, kind: Annotated[StudioModel, functions.Query(...)]): return [ - {"id": c.id, "full_path": " / ".join([*c.ancestors, c.name])} - async for c in Category.objects.filter(depth=3).order_by("id") + raw + async for raw in STUDIO_MODELS[kind] + .objects.annotate(label=F("title")) + .filter(owner_id=request.auth) # required owner permission + .values("label", "id") + .order_by("label")[:MAX_SUGGESTIONS] ] -class InstructorSuggestionSpec(Schema): +class InlineSuggestionSpec(Schema): id: int - name: str + label: str -@router.get("/suggestion/instructor", response=list[InstructorSuggestionSpec]) -@editor_required() -async def instructor_suggestions(request: HttpRequest): - return [c async for c in Instructor.objects.filter(active=True).order_by("-modified")] +InlineItem = Literal["honor_code", "faq", "category", "instructor", "certificate"] -class FAQSuggestionSpec(Schema): - id: int - name: str +@router.get("/suggestion/inline", response=list[InlineSuggestionSpec]) +@editor_required() +async def inline_suggestions(request: HttpRequest, kind: Annotated[InlineItem, functions.Query(...)]): + qs = None + if kind == "honor_code": + qs = HonorCode.objects.annotate(label=F("title")) -@router.get("/suggestion/faq", response=list[FAQSuggestionSpec]) -@editor_required() -async def faq_suggestions(request: HttpRequest): - return [c async for c in FAQ.objects.order_by("-id")] + elif kind == "faq": + qs = FAQ.objects.annotate(label=F("name")) + elif kind == "instructor": + qs = Instructor.objects.filter(active=True).annotate(label=F("name")) -class FAQItemCopySpec(Schema): - question: str - answer: str - active: bool + elif kind == "certificate": + qs = Certificate.objects.filter(active=True).annotate(label=F("name")) + elif kind == "category": + return [ + {"id": c.id, "label": " / ".join([*c.ancestors, c.name])} + async for c in Category.objects.filter(depth=3).order_by("id") + ][:MAX_SUGGESTIONS] -@router.get("/faq/{id}/item", response=list[FAQItemCopySpec]) -@editor_required() -async def get_faq_items(request: HttpRequest, id: int): - return [c async for c in FAQItem.objects.filter(faq_id=id, active=True).order_by("ordering")] + if qs is None: + raise ValueError(ErrorCode.UNKNOWN_CONTENT) + + return [item async for item in qs.values("id", "label").order_by("label")][:MAX_SUGGESTIONS] router.add_router("", exam_router, tags=["studio"]) diff --git a/core/apps/studio/api/v1/assignment.py b/core/apps/studio/api/v1/assignment.py index 0b35268..5d0ef9d 100644 --- a/core/apps/studio/api/v1/assignment.py +++ b/core/apps/studio/api/v1/assignment.py @@ -19,13 +19,11 @@ Schema, ) from apps.common.util import HttpRequest -from apps.operation.models import HonorCode -from apps.studio.api.v1.schema import HonorCodeSpec from apps.studio.decorator import editor_required, track_draft class AssignmentQuestionSaveSpec(Schema): - id: int + id: Annotated[int, Field(None)] question: str supplement: str attachment_file_count: int @@ -34,6 +32,7 @@ class AssignmentQuestionSaveSpec(Schema): class AssignmentQuestionSpec(AssignmentQuestionSaveSpec): + id: int sample_attachment: str | None @staticmethod @@ -50,12 +49,8 @@ class AssignmentQuestionsSpec(RootModel[list[AssignmentQuestionSpec]]): class AssignmentSpec(LearningObjectMixinSchema, GradeWorkflowMixinSchema): - class AssignmentQuestionPoolSpec(Schema): - description: str - id: str - honor_code: HonorCodeSpec - question_pool: AssignmentQuestionPoolSpec + honor_code_id: int questions: AssignmentQuestionsSpec @staticmethod @@ -75,8 +70,7 @@ class AssignmentSaveSpec(Schema): grade_due_days: int appeal_deadline_days: int confirm_due_days: int - honor_code: HonorCodeSpec - question_pool: AssignmentSpec.AssignmentQuestionPoolSpec + honor_code_id: int router = Router(by_alias=True) @@ -85,14 +79,9 @@ class AssignmentSaveSpec(Schema): @router.get("/assignment/{id}", response=AssignmentSpec) @editor_required() async def get_assignment(request: HttpRequest, id: str): - assignment = ( - await Assignment.objects - .select_related("honor_code", "question_pool") - .prefetch_related( - Prefetch("question_pool__questions", queryset=Question.objects.prefetch_related("attachments")) - ) - .aget(id=id, owner_id=request.auth) - ) + assignment = await Assignment.objects.prefetch_related( + Prefetch("question_pool__questions", queryset=Question.objects.prefetch_related("attachments").order_by("id")) + ).aget(id=id, owner_id=request.auth) return assignment @@ -110,8 +99,6 @@ async def save_assignment( ): assignment_dict = data.model_dump(exclude_unset=True) assignment_id = assignment_dict.pop("id", None) - honor_code = assignment_dict.pop("honor_code") - question_pool = assignment_dict.pop("question_pool") if thumbnail: assignment_dict["thumbnail"] = thumbnail @@ -121,20 +108,15 @@ async def save_assignment( for key, value in assignment_dict.items(): setattr(assignment, key, value) await assignment.asave() - await HonorCode.objects.filter(id=assignment.honor_code_id).aupdate(**honor_code) - await QuestionPool.objects.filter(id=assignment.question_pool_id).aupdate(**question_pool) else: @sync_to_async @transaction.atomic def create_new(): - code = HonorCode.objects.create(**honor_code) try: - pool = QuestionPool.objects.create(**question_pool, owner_id=request.auth, title=data.title) - assignment = Assignment.objects.create( - **assignment_dict, honor_code=code, question_pool=pool, owner_id=request.auth - ) + pool = QuestionPool.objects.create(owner_id=request.auth, title=data.title) + assignment = Assignment.objects.create(**assignment_dict, question_pool=pool, owner_id=request.auth) except IntegrityError: # both title conflict raise ValueError(ErrorCode.TITLE_ALREADY_EXISTS) @@ -145,13 +127,25 @@ def create_new(): return assignment.id +@router.get("/assignment/{id}/question", response=list[AssignmentQuestionSpec]) +@editor_required() +async def get_assignment_questions(request: HttpRequest, id: str): + return [ + q + async for q in Question.objects + .select_related("solution") + .prefetch_related("attachments") + .filter(pool__assignment__id=id, pool__assignment__owner_id=request.auth) + ] + + @router.post("/assignment/{id}/question", response=int) @editor_required() @track_draft(Assignment, id_field="id") async def save_assignment_question( request: HttpRequest, id: str, - data: AssignmentQuestionSaveSpec, # form doesn't work nested model + data: AssignmentQuestionSaveSpec, files: Annotated[ list[Annotated[UploadedFile, FileSizeValidator(), FileTypeValidator()]], functions.File(None, description=f"Max size: {settings.ATTACHMENT_MAX_SIZE_MB}MB"), diff --git a/core/apps/studio/api/v1/course.py b/core/apps/studio/api/v1/course.py index c6c5c2f..7096eb6 100644 --- a/core/apps/studio/api/v1/course.py +++ b/core/apps/studio/api/v1/course.py @@ -35,8 +35,6 @@ Lesson, LessonMedia, ) -from apps.operation.models import FAQ, FAQItem, HonorCode -from apps.studio.api.v1.schema import HonorCodeSpec from apps.studio.decorator import editor_required, track_draft log = logging.getLogger(__name__) @@ -99,11 +97,6 @@ class CourseCategorySpec(Schema): category_id: int -class FAQSpec(Schema): - name: str - description: str - - class FAQItemSpec(Schema): id: int question: str @@ -119,7 +112,6 @@ class CourseAssetsSpec(Schema): course_certificates: list[CourseCertificateSpec] course_categories: list[CourseCategorySpec] course_instructors: list[CourseInstructorSpec] - faq_items: list[FAQItemSpec] class CourseSpec(LearningObjectMixinSchema): @@ -128,8 +120,8 @@ class CourseSpec(LearningObjectMixinSchema): preview_url: str | None effort_hours: int level: Course.LevelChoices - honor_code: HonorCodeSpec - faq: FAQSpec + honor_code_id: int + faq_id: int grading_policy: GradingPolicySpec assets: CourseAssetsSpec @@ -143,7 +135,6 @@ def resolve_assets(obj: Course): "course_certificates": obj.course_certificates.all(), "course_categories": obj.course_categories.all(), "course_instructors": obj.course_instructors.all(), - "faq_items": obj.faq.items.all() if obj.faq else [], } @@ -160,8 +151,8 @@ class CourseSaveSpec(Schema): preview_url: HttpUrl effort_hours: int level: Course.LevelChoices - honor_code: HonorCodeSpec - faq: FAQSpec + honor_code_id: int + faq_id: int grading_policy: GradingPolicySpec @@ -199,10 +190,7 @@ async def get_course(request: HttpRequest, id: str): .prefetch_related(Prefetch("course_categories", CourseCategory.objects.order_by("ordering"))) .prefetch_related(Prefetch("course_certificates", CourseCertificate.objects.order_by("ordering"))) .prefetch_related(Prefetch("course_instructors", CourseInstructor.objects.order_by("ordering"))) - .prefetch_related( - Prefetch("faq", FAQ.objects.prefetch_related(Prefetch("items", FAQItem.objects.order_by("ordering")))) - ) - .select_related("honor_code", "grading_policy") + .select_related("grading_policy") .aget(id=id, owner_id=request.auth) ) @@ -221,8 +209,6 @@ async def save_course( course_dict = data.model_dump(exclude_unset=True) course_id = course_dict.pop("id", None) grading_policy = course_dict.pop("grading_policy") - honor_code = course_dict.pop("honor_code") - faq = course_dict.pop("faq") if thumbnail: course_dict["thumbnail"] = thumbnail @@ -232,18 +218,14 @@ async def save_course( for key, value in course_dict.items(): setattr(course, key, value) await course.asave() - await HonorCode.objects.filter(id=course.honor_code_id).aupdate(**honor_code) - await FAQ.objects.filter(id=course.faq_id).aupdate(**faq) else: @sync_to_async() @transaction.atomic def create_new(): - c = HonorCode.objects.create(**honor_code) try: - f = FAQ.objects.create(**faq) - course = Course.objects.create(**course_dict, honor_code=c, faq=f, owner_id=request.auth) + course = Course.objects.create(**course_dict, owner_id=request.auth) except IntegrityError: raise ValueError(ErrorCode.TITLE_ALREADY_EXISTS) return course @@ -517,61 +499,3 @@ async def remove_course_instructor(request: HttpRequest, id: str, course_instruc ).adelete() if count == 0: raise ValueError(ErrorCode.NOT_FOUND) - - -class FAQItemSaveSpec(FAQItemSpec): - id: Annotated[int, Field(None)] - - -@router.post("/course/{id}/faqitem", response=list[int]) -@editor_required() -@track_draft(Course, id_field="id") -async def save_course_faq_items(request: HttpRequest, id: str, data: RootModel[list[FAQItemSaveSpec]]): - course = await aget_object_or_404(Course, id=id, owner_id=request.auth) - - seen_ids = set() - deduped = [] - for c in data.model_dump(): - key = c["id"] - if key is None or key not in seen_ids: - deduped.append(c) - if key is not None: - seen_ids.add(key) - - new_items = [(i, c) for i, c in enumerate(deduped) if c["id"] is None] - existing_items = [(i, c) for i, c in enumerate(deduped) if c["id"] is not None] - - try: - created = ( - await FAQItem.objects.abulk_create([ - FAQItem(faq_id=course.faq_id, ordering=i, **{k: v for k, v in c.items() if k != "id"}) - for i, c in new_items - ]) - if new_items - else [] - ) - except IntegrityError: - raise ValueError(ErrorCode.DATA_ERROR) - - updated = ( - await FAQItem.objects.abulk_create( - [FAQItem(faq_id=course.faq_id, ordering=i, **c) for i, c in existing_items], - update_conflicts=True, - unique_fields=["id"], - update_fields=["question", "answer", "active", "ordering"], - ) - if existing_items - else [] - ) - - return [f.id for f in created + updated] - - -@router.delete("/course/{id}/faqitem/{faq_item_id}") -@editor_required() -@track_draft(Course, id_field="id") -async def remove_course_faq_item(request: HttpRequest, id: str, faq_item_id: int): - course = await aget_object_or_404(Course, id=id, owner_id=request.auth) - count, _ = await FAQItem.objects.filter(faq_id=course.faq_id, id=faq_item_id).adelete() - if count == 0: - raise ValueError(ErrorCode.NOT_FOUND) diff --git a/core/apps/studio/api/v1/discussion.py b/core/apps/studio/api/v1/discussion.py index 05fc42b..90a0242 100644 --- a/core/apps/studio/api/v1/discussion.py +++ b/core/apps/studio/api/v1/discussion.py @@ -19,13 +19,11 @@ ) from apps.common.util import HttpRequest from apps.discussion.models import Attempt, Discussion, Question, QuestionPool -from apps.operation.models import HonorCode -from apps.studio.api.v1.schema import HonorCodeSpec from apps.studio.decorator import editor_required, track_draft class DiscussionQuestionSaveSpec(Schema): - id: int + id: Annotated[int, Field(None)] directive: str supplement: str post_point: int @@ -36,13 +34,16 @@ class DiscussionQuestionSaveSpec(Schema): class DiscussionQuestionSpec(DiscussionQuestionSaveSpec): + id: int + @staticmethod def resolve_supplement(obj: Question): return obj.cleaned_supplement -class DiscussionQuestionsSaveSpec(RootModel[list[DiscussionQuestionSaveSpec]]): - pass +# RootModel not working with multipart +class DiscussionQuestionsSaveSpec(Schema): + data: list[DiscussionQuestionSaveSpec] class DiscussionQuestionsSpec(RootModel[list[DiscussionQuestionSpec]]): @@ -50,13 +51,9 @@ class DiscussionQuestionsSpec(RootModel[list[DiscussionQuestionSpec]]): class DiscussionSpec(LearningObjectMixinSchema, GradeWorkflowMixinSchema): - class DiscussionQuestionPoolSpec(Schema): - description: str - id: str - honor_code: HonorCodeSpec - question_pool: DiscussionQuestionPoolSpec + honor_code_id: int questions: DiscussionQuestionsSpec @staticmethod @@ -76,8 +73,7 @@ class DiscussionSaveSpec(Schema): grade_due_days: int appeal_deadline_days: int confirm_due_days: int - honor_code: HonorCodeSpec - question_pool: DiscussionSpec.DiscussionQuestionPoolSpec + honor_code_id: int router = Router(by_alias=True) @@ -86,14 +82,9 @@ class DiscussionSaveSpec(Schema): @router.get("/discussion/{id}", response=DiscussionSpec) @editor_required() async def get_discussion(request: HttpRequest, id: str): - return ( - await Discussion.objects - .select_related("honor_code", "question_pool") - .prefetch_related( - Prefetch("question_pool__questions", queryset=Question.objects.prefetch_related("attachments")) - ) - .aget(id=id, owner_id=request.auth) - ) + return await Discussion.objects.prefetch_related( + Prefetch("question_pool__questions", queryset=Question.objects.prefetch_related("attachments").order_by("id")) + ).aget(id=id, owner_id=request.auth) @router.post("/discussion", response=str) @@ -109,8 +100,6 @@ async def save_discussion( ): discussion_dict = data.model_dump(exclude_unset=True) discussion_id = discussion_dict.pop("id", None) - honor_code = discussion_dict.pop("honor_code") - question_pool = discussion_dict.pop("question_pool") if thumbnail: discussion_dict["thumbnail"] = thumbnail @@ -120,20 +109,15 @@ async def save_discussion( for key, value in discussion_dict.items(): setattr(discussion, key, value) await discussion.asave() - await HonorCode.objects.filter(id=discussion.honor_code_id).aupdate(**honor_code) - await QuestionPool.objects.filter(id=discussion.question_pool_id).aupdate(**question_pool) else: @sync_to_async @transaction.atomic def create_new(): - code = HonorCode.objects.create(**honor_code) try: - pool = QuestionPool.objects.create(**question_pool, owner_id=request.auth, title=data.title) - discussion = Discussion.objects.create( - **discussion_dict, honor_code=code, question_pool=pool, owner_id=request.auth - ) + pool = QuestionPool.objects.create(owner_id=request.auth, title=data.title) + discussion = Discussion.objects.create(**discussion_dict, question_pool=pool, owner_id=request.auth) except IntegrityError: # both title conflict raise ValueError(ErrorCode.TITLE_ALREADY_EXISTS) @@ -144,34 +128,63 @@ def create_new(): return discussion.id -@router.post("/discussion/{id}/question", response=int) +@router.get("/discussion/{id}/question", response=list[DiscussionQuestionSpec]) +@editor_required() +async def get_discussion_questions(request: HttpRequest, id: str): + return [ + q + async for q in Question.objects.prefetch_related("attachments").filter( + pool__discussion__id=id, pool__discussion__owner_id=request.auth + ) + ] + + +@router.post("/discussion/{id}/question", response=list[int]) @editor_required() @track_draft(Discussion, id_field="id") async def save_discussion_question( request: HttpRequest, id: str, - data: DiscussionQuestionSaveSpec, # form doesn't work nested model + data: DiscussionQuestionsSaveSpec, files: Annotated[ list[Annotated[UploadedFile, FileSizeValidator(), FileTypeValidator()]], functions.File(None, description=f"Max size: {settings.ATTACHMENT_MAX_SIZE_MB}MB"), ], ): discussion = await aget_object_or_404(Discussion, id=id, owner_id=request.auth) - question, _ = await Question.objects.aupdate_or_create( - id=None if not data.id else data.id, - pool_id=discussion.question_pool_id, - defaults={ - "directive": data.directive, - "supplement": data.supplement, - "post_point": data.post_point, - "reply_point": data.reply_point, - "tutor_assessment_point": data.tutor_assessment_point, - "post_min_characters": data.post_min_characters, - "reply_min_characters": data.reply_min_characters, - }, + questions, is_new = [], [] + + dumped = data.model_dump()["data"] + for question_data in dumped: + is_new.append(not question_data["id"]) + + if not question_data["id"]: + question_data["id"] = None + + question = Question(pool_id=discussion.question_pool_id, **question_data) + questions.append(question) + + await Question.objects.abulk_create( + questions, + update_conflicts=True, + unique_fields=["id"], + update_fields=[ + "directive", + "supplement", + "post_point", + "reply_point", + "tutor_assessment_point", + "post_min_characters", + "reply_min_characters", + ], ) - await question.update_attachments(files=files, owner_id=request.auth, content=question.supplement) - return question.pk + + for question, new in zip(questions, is_new): + if new: + question._prefetched_objects_cache = {"attachments": []} + await question.update_attachments(files=files, owner_id=request.auth, content=question.supplement) + + return [q.id for q in questions] @router.delete("/discussion/{id}/question/{question_id}") diff --git a/core/apps/studio/api/v1/exam.py b/core/apps/studio/api/v1/exam.py index 94ebc77..2e43ab4 100644 --- a/core/apps/studio/api/v1/exam.py +++ b/core/apps/studio/api/v1/exam.py @@ -19,8 +19,6 @@ ) from apps.common.util import HttpRequest from apps.exam.models import Attempt, Exam, Question, QuestionPool, Solution -from apps.operation.models import HonorCode -from apps.studio.api.v1.schema import HonorCodeSpec from apps.studio.decorator import editor_required, track_draft @@ -30,7 +28,7 @@ class ExamQuestionSolutionSpec(Schema): correct_criteria: str explanation: str - id: int + id: Annotated[int, Field(None)] format: Question.ExamQuestionFormatChoices question: str supplement: str @@ -40,6 +38,8 @@ class ExamQuestionSolutionSpec(Schema): class ExamQuestionSpec(ExamQuestionSaveSpec): + id: int + @staticmethod def resolve_supplement(obj: Question): return obj.cleaned_supplement @@ -56,13 +56,11 @@ class ExamQuestionsSpec(RootModel[list[ExamQuestionSpec]]): class ExamSpec(LearningObjectMixinSchema, GradeWorkflowMixinSchema): class ExamQuestionPoolSpec(Schema): - description: str composition: dict[Question.ExamQuestionFormatChoices, int] id: str duration_seconds: float - - honor_code: HonorCodeSpec + honor_code_id: int question_pool: ExamQuestionPoolSpec questions: ExamQuestionsSpec @@ -84,7 +82,7 @@ class ExamSaveSpec(Schema): grade_due_days: int appeal_deadline_days: int confirm_due_days: int - honor_code: HonorCodeSpec + honor_code_id: int question_pool: ExamSpec.ExamQuestionPoolSpec @@ -96,11 +94,11 @@ class ExamSaveSpec(Schema): async def get_exam(request: HttpRequest, id: str): return ( await Exam.objects - .select_related("honor_code", "question_pool") + .select_related("question_pool") .prefetch_related( Prefetch( "question_pool__questions", - queryset=Question.objects.prefetch_related("attachments").select_related("solution"), + queryset=Question.objects.prefetch_related("attachments").select_related("solution").order_by("id"), ) ) .aget(id=id, owner_id=request.auth) @@ -120,7 +118,6 @@ async def save_exam( ): exam_dict = data.model_dump(exclude_unset=True) exam_id = exam_dict.pop("id", None) - honor_code = exam_dict.pop("honor_code") question_pool = exam_dict.pop("question_pool") if thumbnail: @@ -131,7 +128,6 @@ async def save_exam( for key, value in exam_dict.items(): setattr(exam, key, value) await exam.asave() - await HonorCode.objects.filter(id=exam.honor_code_id).aupdate(**honor_code) await QuestionPool.objects.filter(id=exam.question_pool_id).aupdate(**question_pool) else: @@ -139,10 +135,9 @@ async def save_exam( @sync_to_async @transaction.atomic def create_new(): - code = HonorCode.objects.create(**honor_code) try: pool = QuestionPool.objects.create(**question_pool, owner_id=request.auth, title=data.title) - exam = Exam.objects.create(**exam_dict, honor_code=code, question_pool=pool, owner_id=request.auth) + exam = Exam.objects.create(**exam_dict, question_pool=pool, owner_id=request.auth) except IntegrityError: # both title conflict raise ValueError(ErrorCode.TITLE_ALREADY_EXISTS) @@ -153,6 +148,18 @@ def create_new(): return exam.id +@router.get("/exam/{id}/question", response=list[ExamQuestionSpec]) +@editor_required() +async def get_exam_questions(request: HttpRequest, id: str): + return [ + q + async for q in Question.objects + .select_related("solution") + .prefetch_related("attachments") + .filter(pool__exam__id=id, pool__exam__owner_id=request.auth) + ] + + @router.post("/exam/{id}/question", response=list[int]) @editor_required() @track_draft(Exam, id_field="id") @@ -166,9 +173,12 @@ async def save_exam_questions( ], ): exam = await aget_object_or_404(Exam, id=id, owner_id=request.auth) - questions, solutions = [], [] + questions, solutions, is_new = [], [], [] + + dumped = data.model_dump()["data"] + for question_data in dumped: + is_new.append(not question_data["id"]) - for question_data in data.model_dump()["data"]: if not question_data["id"]: question_data["id"] = None @@ -193,7 +203,9 @@ async def save_exam_questions( update_fields=["correct_answers", "correct_criteria", "explanation"], ) - for question in questions: + for question, new in zip(questions, is_new): + if new: + question._prefetched_objects_cache = {"attachments": []} await question.update_attachments(files=files, owner_id=request.auth, content=question.supplement) return [q.id for q in questions] diff --git a/core/apps/studio/api/v1/media.py b/core/apps/studio/api/v1/media.py index d6cbb49..98a8e15 100644 --- a/core/apps/studio/api/v1/media.py +++ b/core/apps/studio/api/v1/media.py @@ -4,7 +4,7 @@ from django.conf import settings from django.contrib.postgres.aggregates import ArrayAgg from django.db import IntegrityError -from django.db.models import Q +from django.db.models import Prefetch, Q from django.shortcuts import aget_object_or_404 from ninja import Field, Router, UploadedFile from ninja.params import functions @@ -13,6 +13,7 @@ from apps.common.schema import FileSizeValidator, FileTypeValidator, LearningObjectMixinSchema, Schema from apps.common.util import HttpRequest from apps.content.models import Media, Subtitle +from apps.quiz.models import Quiz from apps.studio.decorator import editor_required, track_draft @@ -60,7 +61,12 @@ class MediaSaveSpec(Schema): @router.get("/media/{id}", response=MediaSpec) @editor_required() async def get_media(request: HttpRequest, id: str): - return await Media.objects.prefetch_related("subtitles", "quizzes").aget(id=id, owner_id=request.auth) + return ( + await Media.objects + .prefetch_related(Prefetch("subtitles", queryset=Subtitle.objects.order_by("id"))) + .prefetch_related(Prefetch("quizzes", queryset=Quiz.objects.order_by("mediaquiz__id"))) + .aget(id=id, owner_id=request.auth) + ) @router.post("/media", response=str) diff --git a/core/apps/studio/api/v1/quiz.py b/core/apps/studio/api/v1/quiz.py index 64a4686..5936834 100644 --- a/core/apps/studio/api/v1/quiz.py +++ b/core/apps/studio/api/v1/quiz.py @@ -21,7 +21,7 @@ class QuizQuestionSolutionSpec(Schema): correct_answers: list[str] explanation: str - id: int + id: Annotated[int, Field(None)] question: str supplement: str options: list[str] @@ -30,6 +30,8 @@ class QuizQuestionSolutionSpec(Schema): class QuizQuestionSpec(QuizQuestionSaveSpec): + id: int + @staticmethod def resolve_supplement(obj: Question): return obj.cleaned_supplement @@ -46,7 +48,6 @@ class QuizQuestionsSpec(RootModel[list[QuizQuestionSpec]]): class QuizSpec(LearningObjectMixinSchema): class QuizQuestionPoolSpec(Schema): - description: str select_count: int id: str @@ -82,7 +83,7 @@ async def get_quiz(request: HttpRequest, id: str): .prefetch_related( Prefetch( "question_pool__questions", - queryset=Question.objects.prefetch_related("attachments").select_related("solution"), + queryset=Question.objects.prefetch_related("attachments").select_related("solution").order_by("id"), ) ) .aget(id=id, owner_id=request.auth) @@ -130,6 +131,18 @@ def create_new(): return quiz.id +@router.get("/quiz/{id}/question", response=list[QuizQuestionSpec]) +@editor_required() +async def get_quiz_questions(request: HttpRequest, id: str): + return [ + q + async for q in Question.objects + .select_related("solution") + .prefetch_related("attachments") + .filter(pool__quiz__id=id, pool__quiz__owner_id=request.auth) + ] + + @router.post("/quiz/{id}/question", response=list[int]) @editor_required() @track_draft(Quiz, id_field="id") @@ -143,9 +156,12 @@ async def save_quiz_questions( ], ): quiz = await aget_object_or_404(Quiz, id=id, owner_id=request.auth) - questions, solutions = [], [] + questions, solutions, is_new = [], [], [] + + dumped = data.model_dump()["data"] + for question_data in dumped: + is_new.append(not question_data["id"]) - for question_data in data.model_dump()["data"]: if not question_data["id"]: question_data["id"] = None @@ -170,7 +186,9 @@ async def save_quiz_questions( update_fields=["correct_answers", "explanation"], ) - for question in questions: + for question, new in zip(questions, is_new): + if new: + question._prefetched_objects_cache = {"attachments": []} await question.update_attachments(files=files, owner_id=request.auth, content=question.supplement) return [q.id for q in questions] diff --git a/core/apps/studio/api/v1/survey.py b/core/apps/studio/api/v1/survey.py index 3a9eeed..4903775 100644 --- a/core/apps/studio/api/v1/survey.py +++ b/core/apps/studio/api/v1/survey.py @@ -17,7 +17,7 @@ class SurveyQuestionSaveSpec(Schema): - id: int + id: Annotated[int, Field(None)] format: Question.SurveyQuestionFormatChoices question: str supplement: str @@ -27,6 +27,8 @@ class SurveyQuestionSaveSpec(Schema): class SurveyQuestionSpec(SurveyQuestionSaveSpec): + id: int + @staticmethod def resolve_supplement(obj: Question): return obj.cleaned_supplement @@ -42,11 +44,7 @@ class SurveyQuestionsSpec(RootModel[list[SurveyQuestionSpec]]): class SurveySpec(LearningObjectMixinSchema): - class SurveyQuestionPoolSpec(Schema): - description: str - id: str - question_pool: SurveyQuestionPoolSpec questions: SurveyQuestionsSpec complete_message: str anonymous: bool @@ -63,7 +61,6 @@ class SurveySaveSpec(Schema): description: str audience: str featured: bool - question_pool: SurveySpec.SurveyQuestionPoolSpec complete_message: str anonymous: bool show_results: bool @@ -75,16 +72,9 @@ class SurveySaveSpec(Schema): @router.get("/survey/{id}", response=SurveySpec) @editor_required() async def get_survey(request: HttpRequest, id: str): - return ( - await Survey.objects - .select_related("question_pool") - .prefetch_related( - Prefetch( - "question_pool__questions", queryset=Question.objects.prefetch_related("attachments").order_by("id") - ) - ) - .aget(id=id, owner_id=request.auth) - ) + return await Survey.objects.prefetch_related( + Prefetch("question_pool__questions", queryset=Question.objects.prefetch_related("attachments").order_by("id")) + ).aget(id=id, owner_id=request.auth) @router.post("/survey", response=str) @@ -100,7 +90,6 @@ async def save_survey( ): survey_dict = data.model_dump(exclude_unset=True) survey_id = survey_dict.pop("id", None) - question_pool_data = survey_dict.pop("question_pool") if thumbnail: survey_dict["thumbnail"] = thumbnail @@ -110,7 +99,6 @@ async def save_survey( for key, value in survey_dict.items(): setattr(survey, key, value) await survey.asave() - await QuestionPool.objects.filter(id=survey.question_pool_id).aupdate(**question_pool_data) else: @@ -118,7 +106,7 @@ async def save_survey( @transaction.atomic def create_new(): try: - pool = QuestionPool.objects.create(**question_pool_data, owner_id=request.auth, title=data.title) + pool = QuestionPool.objects.create(owner_id=request.auth, title=data.title) survey = Survey.objects.create(**survey_dict, question_pool=pool, owner_id=request.auth) except IntegrityError: # both title conflict @@ -130,6 +118,17 @@ def create_new(): return survey.id +@router.get("/survey/{id}/question", response=list[SurveyQuestionSpec]) +@editor_required() +async def get_survey_questions(request: HttpRequest, id: str): + return [ + q + async for q in Question.objects.prefetch_related("attachments").filter( + pool__survey__id=id, pool__survey__owner_id=request.auth + ) + ] + + @router.post("/survey/{id}/question", response=list[int]) @editor_required() @track_draft(Survey, id_field="id") @@ -143,9 +142,12 @@ async def save_survey_questions( ], ): survey = await aget_object_or_404(Survey, id=id, owner_id=request.auth) - questions = [] + questions, is_new = [], [] + + dumped = data.model_dump()["data"] + for question_data in dumped: + is_new.append(not question_data["id"]) - for question_data in data.model_dump()["data"]: if not question_data["id"]: question_data["id"] = None @@ -159,7 +161,9 @@ async def save_survey_questions( update_fields=["format", "question", "supplement", "options", "mandatory"], ) - for question in questions: + for question, new in zip(questions, is_new): + if new: + question._prefetched_objects_cache = {"attachments": []} await question.update_attachments(files=files, owner_id=request.auth, content=question.supplement) return [q.id for q in questions] diff --git a/core/apps/studio/tests/test_studio_assignment_api.py b/core/apps/studio/tests/test_studio_assignment_api.py index baac7e0..1c4f4fb 100644 --- a/core/apps/studio/tests/test_studio_assignment_api.py +++ b/core/apps/studio/tests/test_studio_assignment_api.py @@ -40,7 +40,7 @@ def test_studio_assignment_flow(client: Client, admin_user: AdminUser): assert res.status_code == 200, "create new assignment" question = questions[0] - question["id"] = 0 + del question["id"] # save assignment question res = client.post( diff --git a/core/apps/studio/tests/test_studio_course_api.py b/core/apps/studio/tests/test_studio_course_api.py index 5243440..560ddbd 100644 --- a/core/apps/studio/tests/test_studio_course_api.py +++ b/core/apps/studio/tests/test_studio_course_api.py @@ -3,6 +3,7 @@ import pytest from django.test.client import Client +from apps.course.models import CourseRelation from apps.course.tests.factories import CourseFactory from conftest import AdminUser @@ -12,13 +13,15 @@ def test_studio_course_flow(client: Client, admin_user: AdminUser): admin_user.login() - CourseFactory.create_batch(2, owner=admin_user.get_user()) + c1, c2 = CourseFactory.create_batch(2, owner=admin_user.get_user()) + CourseRelation.objects.get_or_create(course=c1, related_course=c2, defaults={"label": c2.title, "ordering": 0}) + CourseRelation.objects.get_or_create(course=c2, related_course=c1, defaults={"label": c1.title, "ordering": 0}) # get content suggestions res = client.get("/api/v1/studio/suggestion/content?kind=course") assert res.status_code == 200, "get content suggestions" - course_id = res.json()[0]["id"] + course_id = c2.id # get course res = client.get(f"/api/v1/studio/course/{course_id}") @@ -34,7 +37,6 @@ def test_studio_course_flow(client: Client, admin_user: AdminUser): data["id"] = "" data["title"] += "unique" - data["faq"]["name"] += "unique" # create new course res = client.post("/api/v1/studio/course", data={"data": json.dumps(data)}, format="multipart") @@ -77,7 +79,7 @@ def test_studio_course_flow(client: Client, admin_user: AdminUser): assert res.status_code == 200, "delete course lesson" # certificate suggestions - res = client.get("/api/v1/studio/suggestion/certificate") + res = client.get("/api/v1/studio/suggestion/inline?kind=certificate") assert res.status_code == 200, "get certificate suggestions" # save course certificates @@ -133,7 +135,7 @@ def test_studio_course_flow(client: Client, admin_user: AdminUser): assert res.status_code == 200, "add related course" # category suggestions - res = client.get("/api/v1/studio/suggestion/category") + res = client.get("/api/v1/studio/suggestion/inline?kind=category") assert res.status_code == 200, "get category suggestions" # save category @@ -161,7 +163,7 @@ def test_studio_course_flow(client: Client, admin_user: AdminUser): assert res.status_code == 200, "add category" # instructor suggestions - res = client.get("/api/v1/studio/suggestion/instructor") + res = client.get("/api/v1/studio/suggestion/inline?kind=instructor") assert res.status_code == 200, "get instructor suggestions" # save instructor diff --git a/core/apps/studio/tests/test_studio_discussion_api.py b/core/apps/studio/tests/test_studio_discussion_api.py index ac7747d..1cb62e7 100644 --- a/core/apps/studio/tests/test_studio_discussion_api.py +++ b/core/apps/studio/tests/test_studio_discussion_api.py @@ -39,15 +39,21 @@ def test_studio_discussion_flow(client: Client, admin_user: AdminUser): res = client.post("/api/v1/studio/discussion", data={"data": json.dumps(data)}, format="multipart") assert res.status_code == 200, "create new discussion" - question = questions[0] - question["id"] = 0 + # get discussion questions + res = client.get(f"/api/v1/studio/discussion/{discussion_id}/question") + assert res.status_code == 200, "get discussion questions" - # save discussion question + for question in questions: + del question["id"] + + # save discussion questions res = client.post( - f"/api/v1/studio/discussion/{discussion_id}/question", data={"data": json.dumps(question)}, format="multipart" + f"/api/v1/studio/discussion/{discussion_id}/question", + data={"data": json.dumps({"data": questions})}, + format="multipart", ) - assert res.status_code == 200, "save discussion question" + assert res.status_code == 200, "save discussion questions" # delete discussion question - res = client.delete(f"/api/v1/studio/discussion/{discussion_id}/question/{res.json()}") + res = client.delete(f"/api/v1/studio/discussion/{discussion_id}/question/{res.json()[0]}") assert res.status_code == 200, "delete discussion question" diff --git a/core/apps/studio/tests/test_studio_exam_api.py b/core/apps/studio/tests/test_studio_exam_api.py index b1773aa..0d781f4 100644 --- a/core/apps/studio/tests/test_studio_exam_api.py +++ b/core/apps/studio/tests/test_studio_exam_api.py @@ -41,8 +41,12 @@ def test_studio_exam_flow(client: Client, admin_user: AdminUser): res = client.post("/api/v1/studio/exam", data={"data": json.dumps(data)}, format="multipart") assert res.status_code == 200, "create new exam" + # get exam questions + res = client.get(f"/api/v1/studio/exam/{exam_id}/question") + assert res.status_code == 200, "get exam questions" + for question in questions: - question["question"] += "1" + del question["id"] # save exam questions res = client.post( diff --git a/core/apps/studio/tests/test_studio_quiz_api.py b/core/apps/studio/tests/test_studio_quiz_api.py index 71b1a0b..6335249 100644 --- a/core/apps/studio/tests/test_studio_quiz_api.py +++ b/core/apps/studio/tests/test_studio_quiz_api.py @@ -41,8 +41,12 @@ def test_studio_quiz_flow(client: Client, admin_user: AdminUser): res = client.post("/api/v1/studio/quiz", data={"data": json.dumps(data)}, format="multipart") assert res.status_code == 200, "create new quiz" + # get quiz questions + res = client.get(f"/api/v1/studio/quiz/{quiz_id}/question") + assert res.status_code == 200, "get quiz questions" + for question in questions: - question["question"] += "1" + del question["id"] # save quiz questions res = client.post( diff --git a/core/apps/studio/tests/test_studio_survey_api.py b/core/apps/studio/tests/test_studio_survey_api.py index 551e57b..3c116dd 100644 --- a/core/apps/studio/tests/test_studio_survey_api.py +++ b/core/apps/studio/tests/test_studio_survey_api.py @@ -39,8 +39,12 @@ def test_studio_survey_flow(client: Client, admin_user: AdminUser): res = client.post("/api/v1/studio/survey", data={"data": json.dumps(data)}, format="multipart") assert res.status_code == 200, "create new survey" + # get survey questions + res = client.get(f"/api/v1/studio/survey/{survey_id}/question") + assert res.status_code == 200, "get survey questions" + for question in questions: - question["question"] += "1" + del question["id"] # save survey questions res = client.post( diff --git a/core/apps/survey/models.py b/core/apps/survey/models.py index a15da6a..1d4b1b6 100644 --- a/core/apps/survey/models.py +++ b/core/apps/survey/models.py @@ -25,7 +25,7 @@ from django.utils.translation import gettext_lazy as _ from apps.common.error import ErrorCode -from apps.common.models import AttemptMixin, LearningObjectMixin, OrderableMixin, TimeStampedMixin +from apps.common.models import AttemptMixin, LearningObjectMixin, OrderableMixin from apps.common.util import ModeChoices from apps.operation.models import AttachmentMixin @@ -120,7 +120,7 @@ class Submission(AttemptMixin): respondent = ForeignKey(User, SET_NULL, null=True, blank=True, related_name="+", verbose_name=_("Respondent")) answers = JSONField(_("Answers")) - class Meta(TimeStampedMixin.Meta): + class Meta: verbose_name = _("Submission") verbose_name_plural = _("Submissions") constraints = [ diff --git a/core/apps/warehouse/models.py b/core/apps/warehouse/models.py index 743c7bf..772a912 100644 --- a/core/apps/warehouse/models.py +++ b/core/apps/warehouse/models.py @@ -202,7 +202,7 @@ class Meta: ("watch_count", Watch, "created"), # survey ("survey_count", Survey, "created"), - ("survey_submission_count", SurveySubmission, "created"), + ("survey_submission_count", SurveySubmission, "started"), # quiz ("quiz_count", Quiz, "created"), ("quiz_submission_count", QuizSubmission, "created"), @@ -223,7 +223,7 @@ class Meta: ("discussion_grade_confirmed_count", DiscussionGrade, "confirmed"), # course ("course_count", Course, "created"), - ("course_engagement_count", CourseEngagement, "created"), + ("course_engagement_count", CourseEngagement, "started"), ("course_grade_confirmed_count", CourseGradebook, "confirmed"), # learning ("enrollment_count", Enrollment, "enrolled"), diff --git a/core/apps/warehouse/tests/test_warehouse_model.py b/core/apps/warehouse/tests/test_warehouse_model.py new file mode 100644 index 0000000..a7bb0a1 --- /dev/null +++ b/core/apps/warehouse/tests/test_warehouse_model.py @@ -0,0 +1,16 @@ +import pytest + +from apps.warehouse.models import DailySnapshot, DailyUsageFact + + +@pytest.mark.django_db +def test_daily_snapshot(): + DailySnapshot.collect_daily_snapshot() + DailySnapshot.collect_daily_snapshot() + assert DailySnapshot.objects.count() == 1 + + +@pytest.mark.django_db +def test_daily_usage(): + DailyUsageFact.collect_daily_usage() + assert DailyUsageFact.objects.count() == 1 diff --git a/core/dev.py b/core/dev.py index c2d65df..f27acb3 100644 --- a/core/dev.py +++ b/core/dev.py @@ -23,7 +23,7 @@ def up(): @app.command() -def bootstrap(): +def bootstrap(tty: bool = True): category_fixture = "ncs_category_ko.json" if LANG.lower() == "ko-kr" else "ncs_category_en.json" commands = [ @@ -33,12 +33,12 @@ def bootstrap(): "python manage.py create_roles", "python manage.py opensearch index create --force --ignore-error", "python manage.py create_platform_partner", - "python manage.py create_base_policies", + "python manage.py setup_base_operation_data", "python manage.py load_ncs_data", f"python manage.py loaddata {category_fixture}", ] - - subprocess.run(["docker", "compose", "exec", "minima", "sh", "-c", " && ".join(commands)]) + tty_flag: list[str] = [] if tty else ["-T"] + subprocess.run(["docker", "compose", "exec", *tty_flag, "minima", "sh", "-c", " && ".join(commands)]) subprocess.run(["docker", "compose", "restart", "minima", "worker"]) diff --git a/core/uv.lock b/core/uv.lock index 48b4158..cf81eb9 100644 --- a/core/uv.lock +++ b/core/uv.lock @@ -140,29 +140,29 @@ wheels = [ [[package]] name = "boto3" -version = "1.42.59" +version = "1.42.62" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "botocore" }, { name = "jmespath" }, { name = "s3transfer" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b0/4e/499cb52aaee9468c346bcc1158965e24e72b4e2a20052725b680e0ac949b/boto3-1.42.59.tar.gz", hash = "sha256:6c4a14a4eb37b58a9048901bdeefbe1c529638b73e8f55413319a25f010ca211", size = 112725, upload-time = "2026-02-27T20:25:33.228Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f7/7e/c952803c8900f14e6f6158fddbd35da5afb2e3fa68bf498a761e6ba2c2ae/boto3-1.42.62.tar.gz", hash = "sha256:6b26ff56c458685caec3d42adde0549f6a55410e557e1f51bebde5c8abcf3037", size = 112848, upload-time = "2026-03-05T21:20:37.755Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/17/c0/22d868b9408dc5a33935a72896ec8d638b2766c459668d1b37c3e5ac2066/boto3-1.42.59-py3-none-any.whl", hash = "sha256:7a66e3e8e2087ea4403e135e9de592e6d63fc9a91080d8dac415bb74df873a72", size = 140557, upload-time = "2026-02-27T20:25:31.774Z" }, + { url = "https://files.pythonhosted.org/packages/1f/68/b5e82dedd9c8d53a9542df4e3475d2d3ec331eef4a4a801e9c5fa98b583a/boto3-1.42.62-py3-none-any.whl", hash = "sha256:eef0ee08f30e5ed16d8296719808801a827fa0f3126a3e2a9ef9be9eb5e6a313", size = 140556, upload-time = "2026-03-05T21:20:35.354Z" }, ] [[package]] name = "boto3-stubs" -version = "1.42.59" +version = "1.42.61" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "botocore-stubs" }, { name = "types-s3transfer" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/80/71/8544fa7874697fad677d1956397426915754114f5d2dfee436f662f0809f/boto3_stubs-1.42.59.tar.gz", hash = "sha256:4a6fc520560ee6a2cb9e05bdfcd45d4e07d9fb91cf483dfbd3a5ab87efe6b860", size = 101012, upload-time = "2026-02-27T20:47:29.017Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f1/f6/07d823217af2023f4a5ac1ef0b7370f1375d31d40d2208438b2e7446670c/boto3_stubs-1.42.61.tar.gz", hash = "sha256:e8c87eeb4a27932e02d647c795693ac075e6eb148084d00959c61f2f64e30e78", size = 100995, upload-time = "2026-03-04T21:01:25.278Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/bd/f2/79308660f3732fe01a8ba204a9e0f8ab6587a12fd7b175d461454ea1e544/boto3_stubs-1.42.59-py3-none-any.whl", hash = "sha256:bef0080a1bbb3f6bfe0cdc0c3d0771bdb91729f5a415ad09397df1ec2aca7256", size = 69824, upload-time = "2026-02-27T20:47:19.061Z" }, + { url = "https://files.pythonhosted.org/packages/50/f3/3ae7094d0f5c33fb0f80cb96a991abdbe87d49477cc8cdfe3f2648e81382/boto3_stubs-1.42.61-py3-none-any.whl", hash = "sha256:f4cfd8cb90302824cf299253db6162f27b1281e528939ee3e32ddba19a697924", size = 69825, upload-time = "2026-03-04T21:01:12.318Z" }, ] [package.optional-dependencies] @@ -172,16 +172,16 @@ s3 = [ [[package]] name = "botocore" -version = "1.42.59" +version = "1.42.62" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jmespath" }, { name = "python-dateutil" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/45/ae/50fb33bdf1911c216d50f98d989dd032a506f054cf829ebd737c6fa7e3e6/botocore-1.42.59.tar.gz", hash = "sha256:5314f19e1da8fc0ebc41bdb8bbe17c9a7397d87f4d887076ac8bdef972a34138", size = 14950271, upload-time = "2026-02-27T20:25:20.614Z" } +sdist = { url = "https://files.pythonhosted.org/packages/af/e7/031f2f03f22817f8a8def7ad1caa138979c20ac35062b055274e0a505c3f/botocore-1.42.62.tar.gz", hash = "sha256:c210dc93b0b81bf72cfe745a7b1c8df765d04bd90b4ac6c8707fbb6714141dae", size = 14966114, upload-time = "2026-03-05T21:20:25.518Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/59/df/9d52819e0d804ead073d53ab1823bc0f0cb172a250fba31107b0b43fbb04/botocore-1.42.59-py3-none-any.whl", hash = "sha256:d2f2ff7ecc31e86ef46b5daee112cfbca052c13801285fb23af909f7bff5b657", size = 14619293, upload-time = "2026-02-27T20:25:17.455Z" }, + { url = "https://files.pythonhosted.org/packages/8d/57/9bc5c1aad3a354dd7da54ba52d43ee821badb3deedbea4c5117c4bd05eab/botocore-1.42.62-py3-none-any.whl", hash = "sha256:86d327fded96775268ffe8d8bd6ed96c4a1db86cf24eb64ff85233db12dbc287", size = 14638389, upload-time = "2026-03-05T21:20:22.359Z" }, ] [[package]] @@ -708,14 +708,14 @@ wheels = [ [[package]] name = "django-unfold" -version = "0.82.0" +version = "0.83.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "django" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/52/13/02145332d2dbaa484f2c52646bc497fb9d5bc2326f6e15de9bd736b04a5a/django_unfold-0.82.0.tar.gz", hash = "sha256:d3920e0d98e72bbdcb0698e4307dc35cf6ffab55b92a6bdc6c20a79147df3472", size = 1111407, upload-time = "2026-03-03T09:48:59.753Z" } +sdist = { url = "https://files.pythonhosted.org/packages/7c/66/5ddc3a921a6b4540b3bb319faa9a0a097efb5c2b86e4386ddffd349ec248/django_unfold-0.83.1.tar.gz", hash = "sha256:af3f9710496d172f0079343d1ba3128528da6d8ef4a57b070efcfc6456d8ed2b", size = 1111682, upload-time = "2026-03-05T17:40:31.518Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0d/82/46f5fd2e4b4f1063956d2211f3794d161b71bf3e1274f570dedd9afa425b/django_unfold-0.82.0-py3-none-any.whl", hash = "sha256:0d90264fd399ae54d3f63e9d0a8d2dea003de479e417e88f274473f78713c253", size = 1226434, upload-time = "2026-03-03T09:48:58.37Z" }, + { url = "https://files.pythonhosted.org/packages/78/fb/f3822627068f99de66989e3f2bdb9cf0eaafa50cbe49615011c74de41706/django_unfold-0.83.1-py3-none-any.whl", hash = "sha256:233cca8f7d9d173518597ce4dbafb0167f3075b556d7fb2b97e44217a1c6ba0f", size = 1227058, upload-time = "2026-03-05T17:40:30.054Z" }, ] [[package]] @@ -780,14 +780,14 @@ wheels = [ [[package]] name = "faker" -version = "40.5.1" +version = "40.8.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "tzdata", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/03/2a/96fff3edcb10f6505143448a4b91535f77b74865cec45be52690ee280443/faker-40.5.1.tar.gz", hash = "sha256:70222361cd82aa10cb86066d1a4e8f47f2bcdc919615c412045a69c4e6da0cd3", size = 1952684, upload-time = "2026-02-23T21:34:38.362Z" } +sdist = { url = "https://files.pythonhosted.org/packages/70/03/14428edc541467c460d363f6e94bee9acc271f3e62470630fc9a647d0cf2/faker-40.8.0.tar.gz", hash = "sha256:936a3c9be6c004433f20aa4d99095df5dec82b8c7ad07459756041f8c1728875", size = 1956493, upload-time = "2026-03-04T16:18:48.161Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4d/a9/1eed4db92d0aec2f9bfdf1faae0ab0418b5e121dda5701f118a7a4f0cd6a/faker-40.5.1-py3-none-any.whl", hash = "sha256:c69640c1e13bad49b4bcebcbf1b52f9f1a872b6ea186c248ada34d798f1661bf", size = 1987053, upload-time = "2026-02-23T21:34:36.418Z" }, + { url = "https://files.pythonhosted.org/packages/4c/3b/c6348f1e285e75b069085b18110a4e6325b763a5d35d5e204356fc7c20b3/faker-40.8.0-py3-none-any.whl", hash = "sha256:eb21bdba18f7a8375382eb94fb436fce07046893dc94cb20817d28deb0c3d579", size = 1989124, upload-time = "2026-03-04T16:18:46.45Z" }, ] [[package]] @@ -948,7 +948,7 @@ wheels = [ [[package]] name = "google-genai" -version = "1.65.0" +version = "1.66.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -962,9 +962,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/79/f9/cc1191c2540d6a4e24609a586c4ed45d2db57cfef47931c139ee70e5874a/google_genai-1.65.0.tar.gz", hash = "sha256:d470eb600af802d58a79c7f13342d9ea0d05d965007cae8f76c7adff3d7a4750", size = 497206, upload-time = "2026-02-26T00:20:33.824Z" } +sdist = { url = "https://files.pythonhosted.org/packages/9b/ba/0b343b0770d4710ad2979fd9301d7caa56c940174d5361ed4a7cc4979241/google_genai-1.66.0.tar.gz", hash = "sha256:ffc01647b65046bca6387320057aa51db0ad64bcc72c8e3e914062acfa5f7c49", size = 504386, upload-time = "2026-03-04T22:15:28.156Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/68/3c/3fea4e7c91357c71782d7dcaad7a2577d636c90317e003386893c25bc62c/google_genai-1.65.0-py3-none-any.whl", hash = "sha256:68c025205856919bc03edb0155c11b4b833810b7ce17ad4b7a9eeba5158f6c44", size = 724429, upload-time = "2026-02-26T00:20:32.186Z" }, + { url = "https://files.pythonhosted.org/packages/d1/dd/403949d922d4e261b08b64aaa132af4e456c3b15c8e2a2d9e6ef693f66e2/google_genai-1.66.0-py3-none-any.whl", hash = "sha256:7f127a39cf695277104ce4091bb26e417c59bb46e952ff3699c3a982d9c474ee", size = 732174, upload-time = "2026-03-04T22:15:26.63Z" }, ] [[package]] @@ -2201,9 +2201,9 @@ wheels = [ [[package]] name = "yt-dlp" -version = "2026.2.21" +version = "2026.3.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/58/d9/55ffff25204733e94a507552ad984d5a8a8e4f9d1f0d91763e6b1a41c79b/yt_dlp-2026.2.21.tar.gz", hash = "sha256:4407dfc1a71fec0dee5ef916a8d4b66057812939b509ae45451fa8fb4376b539", size = 3116630, upload-time = "2026-02-21T20:40:53.522Z" } +sdist = { url = "https://files.pythonhosted.org/packages/66/6f/7427d23609353e5ef3470ff43ef551b8bd7b166dd4fef48957f0d0e040fe/yt_dlp-2026.3.3.tar.gz", hash = "sha256:3db7969e3a8964dc786bdebcffa2653f31123bf2a630f04a17bdafb7bbd39952", size = 3118658, upload-time = "2026-03-03T16:54:53.909Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5a/40/664c99ee36d80d84ce7a96cd98aebcb3d16c19e6c3ad3461d2cf5424040e/yt_dlp-2026.2.21-py3-none-any.whl", hash = "sha256:0d8408f5b6d20487f5caeb946dfd04f9bcd2f1a3a125b744a0a982b590e449f7", size = 3313392, upload-time = "2026-02-21T20:40:51.514Z" }, + { url = "https://files.pythonhosted.org/packages/7e/a4/8b5cd28ab87aef48ef15e74241befec3445496327db028f34147a9e0f14f/yt_dlp-2026.3.3-py3-none-any.whl", hash = "sha256:166c6e68c49ba526474bd400e0129f58aa522c2896204aa73be669c3d2f15e63", size = 3315599, upload-time = "2026-03-03T16:54:51.899Z" }, ] diff --git a/dev.sh b/dev.sh index a78b52b..2345e41 100755 --- a/dev.sh +++ b/dev.sh @@ -37,8 +37,8 @@ up) echo "" echo "Elapsed: $((SECONDS - _start_time))s" echo "" - echo "Admin: http://localhost:8000/admin" - echo "Web: http://localhost:5173" + echo "Admin: http://localhost:8000/admin" + echo "Web: http://localhost:5173" echo "" ;; diff --git a/web/biome.json b/web/biome.json index ffd36e3..e6aa44e 100644 --- a/web/biome.json +++ b/web/biome.json @@ -1,5 +1,5 @@ { - "$schema": "https://biomejs.dev/schemas/2.4.5/schema.json", + "$schema": "https://biomejs.dev/schemas/2.4.6/schema.json", "vcs": { "enabled": true, "clientKind": "git", diff --git a/web/package-lock.json b/web/package-lock.json index ecd9003..976410b 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -13,11 +13,11 @@ "@solid-primitives/resize-observer": "^2.1.5", "@solid-primitives/scheduled": "^1.5.3", "@solid-primitives/scroll": "^2.1.5", - "@tabler/icons-solidjs": "^3.38.0", + "@tabler/icons-solidjs": "^3.39.0", "@tailwindcss/vite": "^4.2.1", - "@tanstack/router-plugin": "^1.164.0", - "@tanstack/solid-router": "^1.163.3", - "@tanstack/solid-virtual": "^3.13.19", + "@tanstack/router-plugin": "^1.166.2", + "@tanstack/solid-router": "^1.166.2", + "@tanstack/solid-virtual": "^3.13.20", "@tiptap/core": "^3.20.0", "@tiptap/extension-dropcursor": "^3.20.0", "@tiptap/extension-file-handler": "^3.20.0", @@ -32,14 +32,13 @@ "axios": "^1.13.6", "cropperjs": "^2.1.0", "date-fns": "^4.1.0", - "dompurify": "^3.3.1", - "es-toolkit": "^1.45.0", + "dompurify": "^3.3.2", "fflate": "^0.8.2", "firebase": "^12.10.0", - "i18next": "^25.8.13", + "i18next": "^25.8.14", "i18next-browser-languagedetector": "^8.2.1", "korean-regexp": "^1.0.13", - "marked": "^17.0.3", + "marked": "^17.0.4", "papaparse": "^5.5.3", "plyr": "^3.8.4", "solid-js": "^1.9.11", @@ -48,15 +47,15 @@ "valibot": "^1.2.0" }, "devDependencies": { - "@biomejs/biome": "^2.4.5", - "@hey-api/openapi-ts": "^0.93.1", + "@biomejs/biome": "^2.4.6", + "@hey-api/openapi-ts": "^0.94.0", "@solidjs/testing-library": "^0.8.10", "@tailwindcss/typography": "^0.5.19", "@testing-library/jest-dom": "^6.9.1", - "@types/node": "^25.3.3", + "@types/node": "^25.3.5", "@types/papaparse": "^5.5.2", "daisyui": "^5.5.19", - "i18next-cli": "^1.47.9", + "i18next-cli": "^1.49.3", "jsdom": "^28.1.0", "typescript": "^5.9.3", "vite": "^7.3.1", @@ -426,9 +425,9 @@ } }, "node_modules/@biomejs/biome": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.4.5.tgz", - "integrity": "sha512-OWNCyMS0Q011R6YifXNOg6qsOg64IVc7XX6SqGsrGszPbkVCoaO7Sr/lISFnXZ9hjQhDewwZ40789QmrG0GYgQ==", + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.4.6.tgz", + "integrity": "sha512-QnHe81PMslpy3mnpL8DnO2M4S4ZnYPkjlGCLWBZT/3R9M6b5daArWMMtEfP52/n174RKnwRIf3oT8+wc9ihSfQ==", "dev": true, "license": "MIT OR Apache-2.0", "peer": true, @@ -443,20 +442,20 @@ "url": "https://opencollective.com/biome" }, "optionalDependencies": { - "@biomejs/cli-darwin-arm64": "2.4.5", - "@biomejs/cli-darwin-x64": "2.4.5", - "@biomejs/cli-linux-arm64": "2.4.5", - "@biomejs/cli-linux-arm64-musl": "2.4.5", - "@biomejs/cli-linux-x64": "2.4.5", - "@biomejs/cli-linux-x64-musl": "2.4.5", - "@biomejs/cli-win32-arm64": "2.4.5", - "@biomejs/cli-win32-x64": "2.4.5" + "@biomejs/cli-darwin-arm64": "2.4.6", + "@biomejs/cli-darwin-x64": "2.4.6", + "@biomejs/cli-linux-arm64": "2.4.6", + "@biomejs/cli-linux-arm64-musl": "2.4.6", + "@biomejs/cli-linux-x64": "2.4.6", + "@biomejs/cli-linux-x64-musl": "2.4.6", + "@biomejs/cli-win32-arm64": "2.4.6", + "@biomejs/cli-win32-x64": "2.4.6" } }, "node_modules/@biomejs/cli-darwin-arm64": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.4.5.tgz", - "integrity": "sha512-lGS4Nd5O3KQJ6TeWv10mElnx1phERhBxqGP/IKq0SvZl78kcWDFMaTtVK+w3v3lusRFxJY78n07PbKplirsU5g==", + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.4.6.tgz", + "integrity": "sha512-NW18GSyxr+8sJIqgoGwVp5Zqm4SALH4b4gftIA0n62PTuBs6G2tHlwNAOj0Vq0KKSs7Sf88VjjmHh0O36EnzrQ==", "cpu": [ "arm64" ], @@ -471,9 +470,9 @@ } }, "node_modules/@biomejs/cli-darwin-x64": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.4.5.tgz", - "integrity": "sha512-6MoH4tyISIBNkZ2Q5T1R7dLd5BsITb2yhhhrU9jHZxnNSNMWl+s2Mxu7NBF8Y3a7JJcqq9nsk8i637z4gqkJxQ==", + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.4.6.tgz", + "integrity": "sha512-4uiE/9tuI7cnjtY9b07RgS7gGyYOAfIAGeVJWEfeCnAarOAS7qVmuRyX6d7JTKw28/mt+rUzMasYeZ+0R/U1Mw==", "cpu": [ "x64" ], @@ -488,9 +487,9 @@ } }, "node_modules/@biomejs/cli-linux-arm64": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.4.5.tgz", - "integrity": "sha512-U1GAG6FTjhAO04MyH4xn23wRNBkT6H7NentHh+8UxD6ShXKBm5SY4RedKJzkUThANxb9rUKIPc7B8ew9Xo/cWg==", + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.4.6.tgz", + "integrity": "sha512-kMLaI7OF5GN1Q8Doymjro1P8rVEoy7BKQALNz6fiR8IC1WKduoNyteBtJlHT7ASIL0Cx2jR6VUOBIbcB1B8pew==", "cpu": [ "arm64" ], @@ -505,9 +504,9 @@ } }, "node_modules/@biomejs/cli-linux-arm64-musl": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.4.5.tgz", - "integrity": "sha512-iqLDgpzobG7gpBF0fwEVS/LT8kmN7+S0E2YKFDtqliJfzNLnAiV2Nnyb+ehCDCJgAZBASkYHR2o60VQWikpqIg==", + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.4.6.tgz", + "integrity": "sha512-F/JdB7eN22txiTqHM5KhIVt0jVkzZwVYrdTR1O3Y4auBOQcXxHK4dxULf4z43QyZI5tsnQJrRBHZy7wwtL+B3A==", "cpu": [ "arm64" ], @@ -522,9 +521,9 @@ } }, "node_modules/@biomejs/cli-linux-x64": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.4.5.tgz", - "integrity": "sha512-NdODlSugMzTlENPTa4z0xB82dTUlCpsrOxc43///aNkTLblIYH4XpYflBbf5ySlQuP8AA4AZd1qXhV07IdrHdQ==", + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.4.6.tgz", + "integrity": "sha512-oHXmUFEoH8Lql1xfc3QkFLiC1hGR7qedv5eKNlC185or+o4/4HiaU7vYODAH3peRCfsuLr1g6v2fK9dFFOYdyw==", "cpu": [ "x64" ], @@ -539,9 +538,9 @@ } }, "node_modules/@biomejs/cli-linux-x64-musl": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.4.5.tgz", - "integrity": "sha512-NlKa7GpbQmNhZf9kakQeddqZyT7itN7jjWdakELeXyTU3pg/83fTysRRDPJD0akTfKDl6vZYNT9Zqn4MYZVBOA==", + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.4.6.tgz", + "integrity": "sha512-C9s98IPDu7DYarjlZNuzJKTjVHN03RUnmHV5htvqsx6vEUXCDSJ59DNwjKVD5XYoSS4N+BYhq3RTBAL8X6svEg==", "cpu": [ "x64" ], @@ -556,9 +555,9 @@ } }, "node_modules/@biomejs/cli-win32-arm64": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.4.5.tgz", - "integrity": "sha512-EBfrTqRIWOFSd7CQb/0ttjHMR88zm3hGravnDwUA9wHAaCAYsULKDebWcN5RmrEo1KBtl/gDVJMrFjNR0pdGUw==", + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.4.6.tgz", + "integrity": "sha512-xzThn87Pf3YrOGTEODFGONmqXpTwUNxovQb72iaUOdcw8sBSY3+3WD8Hm9IhMYLnPi0n32s3L3NWU6+eSjfqFg==", "cpu": [ "arm64" ], @@ -573,9 +572,9 @@ } }, "node_modules/@biomejs/cli-win32-x64": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.4.5.tgz", - "integrity": "sha512-Pmhv9zT95YzECfjEHNl3mN9Vhusw9VA5KHY0ZvlGsxsjwS5cb7vpRnHzJIv0vG7jB0JI7xEaMH9ddfZm/RozBw==", + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.4.6.tgz", + "integrity": "sha512-7++XhnsPlr1HDbor5amovPjOH6vsrFOCdp93iKXhFn6bcMUI6soodj3WWKfgEO6JosKU1W5n3uky3WW9RlRjTg==", "cpu": [ "x64" ], @@ -1951,9 +1950,9 @@ } }, "node_modules/@hey-api/codegen-core": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@hey-api/codegen-core/-/codegen-core-0.7.0.tgz", - "integrity": "sha512-HglL4B4QwpzocE+c8qDU6XK8zMf8W8Pcv0RpFDYxHuYALWLTnpDUuEsglC7NQ4vC1maoXsBpMbmwpco0N4QviA==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@hey-api/codegen-core/-/codegen-core-0.7.1.tgz", + "integrity": "sha512-X5qG+rr/BJvr+pEGcoW6l2azoZGrVuxsviEIhuf+3VwL9bk0atfubT65Xwo+4jDxXvjbhZvlwS0Ty3I7mLE2fg==", "dev": true, "license": "MIT", "dependencies": { @@ -1991,15 +1990,15 @@ } }, "node_modules/@hey-api/openapi-ts": { - "version": "0.93.1", - "resolved": "https://registry.npmjs.org/@hey-api/openapi-ts/-/openapi-ts-0.93.1.tgz", - "integrity": "sha512-oQJPHiVkJKesZFpoW3jfQhrSQ7xdgzai7895ENl6ZDjCaIK6bOUTly7bsu+7+0ONsGH9jbtGbkoUzC+MtY+RKg==", + "version": "0.94.0", + "resolved": "https://registry.npmjs.org/@hey-api/openapi-ts/-/openapi-ts-0.94.0.tgz", + "integrity": "sha512-dbg3GG+v7sg9/Ahb7yFzwzQIJwm151JAtsnh9KtFyqiN0rGkMGA3/VqogEUq1kJB9XWrlMQwigwzhiEQ33VCSg==", "dev": true, "license": "MIT", "dependencies": { - "@hey-api/codegen-core": "0.7.0", + "@hey-api/codegen-core": "0.7.1", "@hey-api/json-schema-ref-parser": "1.3.1", - "@hey-api/shared": "0.2.1", + "@hey-api/shared": "0.2.2", "@hey-api/types": "0.1.3", "ansi-colors": "4.1.3", "color-support": "1.1.3", @@ -2019,13 +2018,13 @@ } }, "node_modules/@hey-api/shared": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@hey-api/shared/-/shared-0.2.1.tgz", - "integrity": "sha512-uWI9047e9OVe3Ss+6vPMnRiixjRcjcBbdgpeq4IQymet3+wsn0+N/4RLDHBz1h57SemaxayPRUA0JOOsuC1qyA==", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@hey-api/shared/-/shared-0.2.2.tgz", + "integrity": "sha512-vMqCS+j7F9xpWoXC7TBbqZkaelwrdeuSB+s/3elu54V5iq++S59xhkSq5rOgDIpI1trpE59zZQa6dpyUxItOgw==", "dev": true, "license": "MIT", "dependencies": { - "@hey-api/codegen-core": "0.7.0", + "@hey-api/codegen-core": "0.7.1", "@hey-api/json-schema-ref-parser": "1.3.1", "@hey-api/types": "0.1.3", "ansi-colors": "4.1.3", @@ -3413,9 +3412,9 @@ "license": "MIT" }, "node_modules/@swc/core": { - "version": "1.15.17", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.15.17.tgz", - "integrity": "sha512-Mu3eOrYlkdQPl7yqotNckitTr6FZ0yd7mlWIBEzK+EGIyybgMENJHmbS2DeA7BMleJiBElP6ke+Nz93pkKmKJw==", + "version": "1.15.18", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.15.18.tgz", + "integrity": "sha512-z87aF9GphWp//fnkRsqvtY+inMVPgYW3zSlXH1kJFvRT5H/wiAn+G32qW5l3oEk63KSF1x3Ov0BfHCObAmT8RA==", "dev": true, "hasInstallScript": true, "license": "Apache-2.0", @@ -3431,16 +3430,16 @@ "url": "https://opencollective.com/swc" }, "optionalDependencies": { - "@swc/core-darwin-arm64": "1.15.17", - "@swc/core-darwin-x64": "1.15.17", - "@swc/core-linux-arm-gnueabihf": "1.15.17", - "@swc/core-linux-arm64-gnu": "1.15.17", - "@swc/core-linux-arm64-musl": "1.15.17", - "@swc/core-linux-x64-gnu": "1.15.17", - "@swc/core-linux-x64-musl": "1.15.17", - "@swc/core-win32-arm64-msvc": "1.15.17", - "@swc/core-win32-ia32-msvc": "1.15.17", - "@swc/core-win32-x64-msvc": "1.15.17" + "@swc/core-darwin-arm64": "1.15.18", + "@swc/core-darwin-x64": "1.15.18", + "@swc/core-linux-arm-gnueabihf": "1.15.18", + "@swc/core-linux-arm64-gnu": "1.15.18", + "@swc/core-linux-arm64-musl": "1.15.18", + "@swc/core-linux-x64-gnu": "1.15.18", + "@swc/core-linux-x64-musl": "1.15.18", + "@swc/core-win32-arm64-msvc": "1.15.18", + "@swc/core-win32-ia32-msvc": "1.15.18", + "@swc/core-win32-x64-msvc": "1.15.18" }, "peerDependencies": { "@swc/helpers": ">=0.5.17" @@ -3452,9 +3451,9 @@ } }, "node_modules/@swc/core-darwin-arm64": { - "version": "1.15.17", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.15.17.tgz", - "integrity": "sha512-eB9qdyt4E60323IS0rgV/rd79DJ+YWSyIKi+sT1dlIgR3ns4xlBiunREM3lVH0FKcUbhttiBvdVubT4QoOuZ+w==", + "version": "1.15.18", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.15.18.tgz", + "integrity": "sha512-+mIv7uBuSaywN3C9LNuWaX1jJJ3SKfiJuE6Lr3bd+/1Iv8oMU7oLBjYMluX1UrEPzwN2qCdY6Io0yVicABoCwQ==", "cpu": [ "arm64" ], @@ -3469,9 +3468,9 @@ } }, "node_modules/@swc/core-darwin-x64": { - "version": "1.15.17", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.15.17.tgz", - "integrity": "sha512-k1TZARYs8947jJpSioqcPrusz+wEeABF4iiSdwcSyQh2rIUdIEk5FOyaqJASFPJ6dZfx7ZVOyjtDATVAegs2/Q==", + "version": "1.15.18", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.15.18.tgz", + "integrity": "sha512-wZle0eaQhnzxWX5V/2kEOI6Z9vl/lTFEC6V4EWcn+5pDjhemCpQv9e/TDJ0GIoiClX8EDWRvuZwh+Z3dhL1NAg==", "cpu": [ "x64" ], @@ -3486,9 +3485,9 @@ } }, "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.15.17", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.15.17.tgz", - "integrity": "sha512-p6282NQZo5bzx0wphz1ETGjhcRB9CN+/XUAjQwApyoyX9iCloI5IT/RC3vjbflo42g8RPTxUTaItAO0hlLSesQ==", + "version": "1.15.18", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.15.18.tgz", + "integrity": "sha512-ao61HGXVqrJFHAcPtF4/DegmwEkVCo4HApnotLU8ognfmU8x589z7+tcf3hU+qBiU1WOXV5fQX6W9Nzs6hjxDw==", "cpu": [ "arm" ], @@ -3503,9 +3502,9 @@ } }, "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.15.17", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.15.17.tgz", - "integrity": "sha512-TGnDS4ejy8y9jqxXqZCyA+DvFc64nXUHS9rxdyeJ9B9uyIdtKVhBrA2xfghYRS/sSPSyHZ0yu89NxBICvONH+A==", + "version": "1.15.18", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.15.18.tgz", + "integrity": "sha512-3xnctOBLIq3kj8PxOCgPrGjBLP/kNOddr6f5gukYt/1IZxsITQaU9TDyjeX6jG+FiCIHjCuWuffsyQDL5Ew1bg==", "cpu": [ "arm64" ], @@ -3520,9 +3519,9 @@ } }, "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.15.17", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.15.17.tgz", - "integrity": "sha512-D0/6Hj4CkgSTTahtlGxv9IDsLTuvQz30mkZEMDp8TqwYhCL8AomznkibwlQU8HtY4q/dqd1OGRPH+FmNb4BBEA==", + "version": "1.15.18", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.15.18.tgz", + "integrity": "sha512-0a+Lix+FSSHBSBOA0XznCcHo5/1nA6oLLjcnocvzXeqtdjnPb+SvchItHI+lfeiuj1sClYPDvPMLSLyXFaiIKw==", "cpu": [ "arm64" ], @@ -3537,9 +3536,9 @@ } }, "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.15.17", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.15.17.tgz", - "integrity": "sha512-1s2OFsg6DeRkWU7c+PIfIHZsFCbiZ34akXFHrg7KjpF8zIvpHZNoUUZimoWEwcB6GquXSkAO+1b5KpG5nusTeQ==", + "version": "1.15.18", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.15.18.tgz", + "integrity": "sha512-wG9J8vReUlpaHz4KOD/5UE1AUgirimU4UFT9oZmupUDEofxJKYb1mTA/DrMj0s78bkBiNI+7Fo2EgPuvOJfuAA==", "cpu": [ "x64" ], @@ -3554,9 +3553,9 @@ } }, "node_modules/@swc/core-linux-x64-musl": { - "version": "1.15.17", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.15.17.tgz", - "integrity": "sha512-gtxGMGYtRWWmCcgx6xM2Yos43uiE/j8kZwkeL/LNGG9zM0tatd23NsfL9PnQJ45hY7QZ+dx2rM68e4ArgG4kJg==", + "version": "1.15.18", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.15.18.tgz", + "integrity": "sha512-4nwbVvCphKzicwNWRmvD5iBaZj8JYsRGa4xOxJmOyHlMDpsvvJ2OR2cODlvWyGFH6BYL1MfIAK3qph3hp0Az6g==", "cpu": [ "x64" ], @@ -3571,9 +3570,9 @@ } }, "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.15.17", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.15.17.tgz", - "integrity": "sha512-gxi+/Miytez/O9vJ/QiheIivA3oWZjPp9nJu3VmAfLMWUzcZORMwgaI1ygtDTLjz7CzcwlGMJz/Ab66Y5DfNpg==", + "version": "1.15.18", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.15.18.tgz", + "integrity": "sha512-zk0RYO+LjiBCat2RTMHzAWaMky0cra9loH4oRrLKLLNuL+jarxKLFDA8xTZWEkCPLjUTwlRN7d28eDLLMgtUcQ==", "cpu": [ "arm64" ], @@ -3588,9 +3587,9 @@ } }, "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.15.17", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.15.17.tgz", - "integrity": "sha512-KUsRqNbTp7SpNK0T9m4+i8GlngzNjwb69a3ttKA6XJ5r6Pewm+NSYji93pNkawXIivbWY2jhvceGMAyd+4hWaQ==", + "version": "1.15.18", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.15.18.tgz", + "integrity": "sha512-yVuTrZ0RccD5+PEkpcLOBAuPbYBXS6rslENvIXfvJGXSdX5QGi1ehC4BjAMl5FkKLiam4kJECUI0l7Hq7T1vwg==", "cpu": [ "ia32" ], @@ -3605,9 +3604,9 @@ } }, "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.15.17", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.15.17.tgz", - "integrity": "sha512-zqtEGE0/rTKvEC5sOtpANLHeWEPjsTD4/rwpUxo6ymztcLI/Z+L9Wi9xQvIGmLTUih1gvNZcAwROqdfRP3oAWQ==", + "version": "1.15.18", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.15.18.tgz", + "integrity": "sha512-7NRmE4hmUQNCbYU3Hn9Tz57mK9Qq4c97ZS+YlamlK6qG9Fb5g/BB3gPDe0iLlJkns/sYv2VWSkm8c3NmbEGjbg==", "cpu": [ "x64" ], @@ -3639,9 +3638,9 @@ } }, "node_modules/@tabler/icons": { - "version": "3.38.0", - "resolved": "https://registry.npmjs.org/@tabler/icons/-/icons-3.38.0.tgz", - "integrity": "sha512-FdETQSpQ3lN7BEjEUzjKhsfTDCamrvMDops4HEMphTm3DmkIFpThoODn8XXZ8Q9MhjshIvphIYVHHB7zpq167w==", + "version": "3.39.0", + "resolved": "https://registry.npmjs.org/@tabler/icons/-/icons-3.39.0.tgz", + "integrity": "sha512-nd9f5+OVJNDR13v6rqPdmALkVhDknDuGMLuj16sK9UaRkOTQWwQM+EWG2fMYBNSH8ISsHiXfryNGQogIpsar4g==", "license": "MIT", "funding": { "type": "github", @@ -3649,12 +3648,12 @@ } }, "node_modules/@tabler/icons-solidjs": { - "version": "3.38.0", - "resolved": "https://registry.npmjs.org/@tabler/icons-solidjs/-/icons-solidjs-3.38.0.tgz", - "integrity": "sha512-Nanr9LltfxBNYPfeQLElrBgzU2kmBNkiJCiGR5CiamPwC1ZU8HdVfcVAyou8HANHHj+9xR4h+hy0ZxVkod0bBw==", + "version": "3.39.0", + "resolved": "https://registry.npmjs.org/@tabler/icons-solidjs/-/icons-solidjs-3.39.0.tgz", + "integrity": "sha512-vuHtfuRpSShBIOKmX7iLm8qvvpioPhTx2Py5hnCdGQBu5J0kHzk0X4WjaHlR/2gfzIj9Y6S0D3Fohb0xFd6OOA==", "license": "MIT", "dependencies": { - "@tabler/icons": "3.38.0" + "@tabler/icons": "3.39.0" }, "funding": { "type": "github", @@ -3948,9 +3947,9 @@ } }, "node_modules/@tanstack/router-core": { - "version": "1.163.3", - "resolved": "https://registry.npmjs.org/@tanstack/router-core/-/router-core-1.163.3.tgz", - "integrity": "sha512-jPptiGq/w3nuPzcMC7RNa79aU+b6OjaDzWJnBcV2UAwL4ThJamRS4h42TdhJE+oF5yH9IEnCOGQdfnbw45LbfA==", + "version": "1.166.2", + "resolved": "https://registry.npmjs.org/@tanstack/router-core/-/router-core-1.166.2.tgz", + "integrity": "sha512-zn3NhENOAX9ToQiX077UV2OH3aJKOvV2ZMNZZxZ3gDG3i3WqL8NfWfEgetEAfMN37/Mnt90PpotYgf7IyuoKqQ==", "license": "MIT", "dependencies": { "@tanstack/history": "1.161.4", @@ -3970,12 +3969,12 @@ } }, "node_modules/@tanstack/router-generator": { - "version": "1.164.0", - "resolved": "https://registry.npmjs.org/@tanstack/router-generator/-/router-generator-1.164.0.tgz", - "integrity": "sha512-Uiyj+RtW0kdeqEd8NEd3Np1Z2nhJ2xgLS8U+5mTvFrm/s3xkM2LYjJHoLzc6am7sKPDsmeF9a4/NYq3R7ZJP0Q==", + "version": "1.166.2", + "resolved": "https://registry.npmjs.org/@tanstack/router-generator/-/router-generator-1.166.2.tgz", + "integrity": "sha512-wbvdyP1PKKQKk4aVlGeK9S5uDy8zodTr3tEZ2gRKNavJLusXbEWqtoo42JxHFFNB6dtguehFMt8PyZPAtkgWwQ==", "license": "MIT", "dependencies": { - "@tanstack/router-core": "1.163.3", + "@tanstack/router-core": "1.166.2", "@tanstack/router-utils": "1.161.4", "@tanstack/virtual-file-routes": "1.161.4", "prettier": "^3.5.0", @@ -3993,9 +3992,9 @@ } }, "node_modules/@tanstack/router-plugin": { - "version": "1.164.0", - "resolved": "https://registry.npmjs.org/@tanstack/router-plugin/-/router-plugin-1.164.0.tgz", - "integrity": "sha512-cZPsEMhqzyzmuPuDbsTAzBZaT+cj0pGjwdhjxJfPCM06Ax8v4tFR7n/Ug0UCwnNAUEmKZWN3lA9uT+TxXnk9PQ==", + "version": "1.166.2", + "resolved": "https://registry.npmjs.org/@tanstack/router-plugin/-/router-plugin-1.166.2.tgz", + "integrity": "sha512-TnyV/7//Vp5fR49mmNbOWHGz9IJTm1lqVxzPdtpzg7D5PjkW2HFmLFLtWwpJgz2R7AJJWR4Ge5kIPmC+fVZ6eQ==", "license": "MIT", "dependencies": { "@babel/core": "^7.28.5", @@ -4004,8 +4003,8 @@ "@babel/template": "^7.27.2", "@babel/traverse": "^7.28.5", "@babel/types": "^7.28.5", - "@tanstack/router-core": "1.163.3", - "@tanstack/router-generator": "1.164.0", + "@tanstack/router-core": "1.166.2", + "@tanstack/router-generator": "1.166.2", "@tanstack/router-utils": "1.161.4", "@tanstack/virtual-file-routes": "1.161.4", "chokidar": "^3.6.0", @@ -4021,7 +4020,7 @@ }, "peerDependencies": { "@rsbuild/core": ">=1.0.2", - "@tanstack/react-router": "^1.163.3", + "@tanstack/react-router": "^1.166.2", "vite": ">=5.0.0 || >=6.0.0 || >=7.0.0", "vite-plugin-solid": "^2.11.10", "webpack": ">=5.92.0" @@ -4069,16 +4068,16 @@ } }, "node_modules/@tanstack/solid-router": { - "version": "1.163.3", - "resolved": "https://registry.npmjs.org/@tanstack/solid-router/-/solid-router-1.163.3.tgz", - "integrity": "sha512-ZeOhCumtus+EatqgLozHTHwJyfjb4PqT1TtpGwxAImWfUmedc9MrBCwRdnTeSejLCdlfyyI6OL5dPgHjXkT21w==", + "version": "1.166.2", + "resolved": "https://registry.npmjs.org/@tanstack/solid-router/-/solid-router-1.166.2.tgz", + "integrity": "sha512-S0SwU+uiKNdEBdap7D0AWpRaJQyCDQWeXVstY/lfM37Yrp4i1kxmZG5hRmQWVSimD8dDFxJfIVKUWRtwtItwcg==", "license": "MIT", "dependencies": { "@solid-devtools/logger": "^0.9.4", "@solid-primitives/refs": "^1.0.8", "@solidjs/meta": "^0.29.4", "@tanstack/history": "1.161.4", - "@tanstack/router-core": "1.163.3", + "@tanstack/router-core": "1.166.2", "@tanstack/solid-store": "^0.9.1", "isbot": "^5.1.22", "tiny-invariant": "^1.3.3", @@ -4112,12 +4111,12 @@ } }, "node_modules/@tanstack/solid-virtual": { - "version": "3.13.19", - "resolved": "https://registry.npmjs.org/@tanstack/solid-virtual/-/solid-virtual-3.13.19.tgz", - "integrity": "sha512-4uCuwY/nfQzoxuJCOroEGgRQkoDuzRE4wVdDq47InQ9WPQ+1dkBUyE7k7frcTPy+l1yjCCmLGdq9h9GQyofVHw==", + "version": "3.13.20", + "resolved": "https://registry.npmjs.org/@tanstack/solid-virtual/-/solid-virtual-3.13.20.tgz", + "integrity": "sha512-9ThhJ7X1d25lx/uVfTNTk5Wyt/OLnKLRaxb8Indx5uxw2rxokcGHFpRXEaSYyxLtRURcGdJ4+M5P0D6lVH4eDg==", "license": "MIT", "dependencies": { - "@tanstack/virtual-core": "3.13.19" + "@tanstack/virtual-core": "3.13.20" }, "funding": { "type": "github", @@ -4138,9 +4137,9 @@ } }, "node_modules/@tanstack/virtual-core": { - "version": "3.13.19", - "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.13.19.tgz", - "integrity": "sha512-/BMP7kNhzKOd7wnDeB8NrIRNLwkf5AhCYCvtfZV2GXWbBieFm/el0n6LOAXlTi6ZwHICSNnQcIxRCWHrLzDY+g==", + "version": "3.13.20", + "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.13.20.tgz", + "integrity": "sha512-Djnq7ujPWcRAKyDpwqL4JDe6ZTN9AWAqE2wLstBlsEu4OnO7Im0p8KsHzLU7TPIvLQgNKpkn9EmgBH6xs8yjfA==", "license": "MIT", "funding": { "type": "github", @@ -4798,9 +4797,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "25.3.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.3.3.tgz", - "integrity": "sha512-DpzbrH7wIcBaJibpKo9nnSQL0MTRdnWttGyE5haGwK86xgMOkFLp7vEyfQPGLOJh5wNYiJ3V9PmUMDhV9u8kkQ==", + "version": "25.3.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.3.5.tgz", + "integrity": "sha512-oX8xrhvpiyRCQkG1MFchB09f+cXftgIXb3a7UUa4Y3wpmZPw5tyZGTLWhlESOLq1Rq6oDlc8npVU2/9xiCuXMA==", "license": "MIT", "dependencies": { "undici-types": "~7.18.0" @@ -5845,10 +5844,13 @@ "license": "MIT" }, "node_modules/dompurify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.1.tgz", - "integrity": "sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.2.tgz", + "integrity": "sha512-6obghkliLdmKa56xdbLOpUZ43pAR6xFy1uOrxBaIDjT+yaRuuybLjGS9eVBoSR/UPU5fq3OXClEHLJNGvbxKpQ==", "license": "(MPL-2.0 OR Apache-2.0)", + "engines": { + "node": ">=20" + }, "optionalDependencies": { "@types/trusted-types": "^2.0.7" } @@ -5969,16 +5971,6 @@ "node": ">= 0.4" } }, - "node_modules/es-toolkit": { - "version": "1.45.0", - "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.45.0.tgz", - "integrity": "sha512-RArCX+Zea16+R1jg4mH223Z8p/ivbJjIkU3oC6ld2bdUfmDxiCkFYSi9zLOR2anucWJUeH4Djnzgd0im0nD3dw==", - "license": "MIT", - "workspaces": [ - "docs", - "benchmarks" - ] - }, "node_modules/esbuild": { "version": "0.27.2", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", @@ -6553,9 +6545,9 @@ } }, "node_modules/i18next": { - "version": "25.8.13", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.8.13.tgz", - "integrity": "sha512-E0vzjBY1yM+nsFrtgkjLhST2NBkirkvOVoQa0MSldhsuZ3jUge7ZNpuwG0Cfc74zwo5ZwRzg3uOgT+McBn32iA==", + "version": "25.8.14", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.8.14.tgz", + "integrity": "sha512-paMUYkfWJMsWPeE/Hejcw+XLhHrQPehem+4wMo+uELnvIwvCG019L9sAIljwjCmEMtFQQO3YeitJY8Kctei3iA==", "funding": [ { "type": "individual", @@ -6594,14 +6586,14 @@ } }, "node_modules/i18next-cli": { - "version": "1.47.9", - "resolved": "https://registry.npmjs.org/i18next-cli/-/i18next-cli-1.47.9.tgz", - "integrity": "sha512-ZdiV1BOufpw0SEuCkzHFSadW6Ldn0qXiEdOX1o/C4NbjNjSxSXKmXFxAQFLc1EMUyR0wAQTTFCjKYzBASlo+Ig==", + "version": "1.49.3", + "resolved": "https://registry.npmjs.org/i18next-cli/-/i18next-cli-1.49.3.tgz", + "integrity": "sha512-QVWEc/P8ub7DtXLr2PrHUBYh9QvNE7CvGLCORz7BDgrs+oieYIu6cFoR4RdOZwhPlgcOFVQpOSJlMIX8RVpiAg==", "dev": true, "license": "MIT", "dependencies": { "@croct/json5-parser": "0.2.2", - "@swc/core": "1.15.17", + "@swc/core": "1.15.18", "chokidar": "5.0.0", "commander": "14.0.3", "execa": "9.6.1", @@ -6610,11 +6602,11 @@ "inquirer": "13.3.0", "jiti": "2.6.1", "jsonc-parser": "3.3.1", - "magic-string": "0.30.12", + "magic-string": "0.30.21", "minimatch": "10.2.4", "ora": "9.3.0", "react": "^19.2.4", - "react-i18next": "^16.5.4", + "react-i18next": "^16.5.5", "yaml": "2.8.2" }, "bin": { @@ -6640,16 +6632,6 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/i18next-cli/node_modules/magic-string": { - "version": "0.30.12", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", - "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" - } - }, "node_modules/i18next-cli/node_modules/readdirp": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", @@ -7450,9 +7432,9 @@ } }, "node_modules/marked": { - "version": "17.0.3", - "resolved": "https://registry.npmjs.org/marked/-/marked-17.0.3.tgz", - "integrity": "sha512-jt1v2ObpyOKR8p4XaUJVk3YWRJ5n+i4+rjQopxvV32rSndTJXvIzuUdWWIy/1pFQMkQmvTXawzDNqOH/CUmx6A==", + "version": "17.0.4", + "resolved": "https://registry.npmjs.org/marked/-/marked-17.0.4.tgz", + "integrity": "sha512-NOmVMM+KAokHMvjWmC5N/ZOvgmSWuqJB8FoYI019j4ogb/PeRMKoKIjReZ2w3376kkA8dSJIP8uD993Kxc0iRQ==", "license": "MIT", "bin": { "marked": "bin/marked.js" @@ -8314,9 +8296,9 @@ } }, "node_modules/react-i18next": { - "version": "16.5.4", - "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-16.5.4.tgz", - "integrity": "sha512-6yj+dcfMncEC21QPhOTsW8mOSO+pzFmT6uvU7XXdvM/Cp38zJkmTeMeKmTrmCMD5ToT79FmiE/mRWiYWcJYW4g==", + "version": "16.5.5", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-16.5.5.tgz", + "integrity": "sha512-5Z35e2JMALNR16FK/LDNQoAatQTVuO/4m4uHrIzewOPXIyf75gAHzuNLSWwmj5lRDJxDvXRJDECThkxWSAReng==", "dev": true, "license": "MIT", "dependencies": { diff --git a/web/package.json b/web/package.json index 6aef650..57f846d 100644 --- a/web/package.json +++ b/web/package.json @@ -22,11 +22,11 @@ "@solid-primitives/resize-observer": "^2.1.5", "@solid-primitives/scheduled": "^1.5.3", "@solid-primitives/scroll": "^2.1.5", - "@tabler/icons-solidjs": "^3.38.0", + "@tabler/icons-solidjs": "^3.39.0", "@tailwindcss/vite": "^4.2.1", - "@tanstack/router-plugin": "^1.164.0", - "@tanstack/solid-router": "^1.163.3", - "@tanstack/solid-virtual": "^3.13.19", + "@tanstack/router-plugin": "^1.166.2", + "@tanstack/solid-router": "^1.166.2", + "@tanstack/solid-virtual": "^3.13.20", "@tiptap/core": "^3.20.0", "@tiptap/extension-dropcursor": "^3.20.0", "@tiptap/extension-file-handler": "^3.20.0", @@ -41,14 +41,13 @@ "axios": "^1.13.6", "cropperjs": "^2.1.0", "date-fns": "^4.1.0", - "dompurify": "^3.3.1", - "es-toolkit": "^1.45.0", + "dompurify": "^3.3.2", "fflate": "^0.8.2", "firebase": "^12.10.0", - "i18next": "^25.8.13", + "i18next": "^25.8.14", "i18next-browser-languagedetector": "^8.2.1", "korean-regexp": "^1.0.13", - "marked": "^17.0.3", + "marked": "^17.0.4", "papaparse": "^5.5.3", "plyr": "^3.8.4", "solid-js": "^1.9.11", @@ -57,15 +56,15 @@ "valibot": "^1.2.0" }, "devDependencies": { - "@biomejs/biome": "^2.4.5", - "@hey-api/openapi-ts": "^0.93.1", + "@biomejs/biome": "^2.4.6", + "@hey-api/openapi-ts": "^0.94.0", "@solidjs/testing-library": "^0.8.10", "@tailwindcss/typography": "^0.5.19", "@testing-library/jest-dom": "^6.9.1", - "@types/node": "^25.3.3", + "@types/node": "^25.3.5", "@types/papaparse": "^5.5.2", "daisyui": "^5.5.19", - "i18next-cli": "^1.47.9", + "i18next-cli": "^1.49.3", "jsdom": "^28.1.0", "typescript": "^5.9.3", "vite": "^7.3.1", diff --git a/web/src/api/client.gen.ts b/web/src/api/client.gen.ts index 54e1f1d..988ea75 100644 --- a/web/src/api/client.gen.ts +++ b/web/src/api/client.gen.ts @@ -11,6 +11,6 @@ import type { ClientOptions as ClientOptions2 } from './types.gen'; * `setConfig()`. This is useful for example if you're using Next.js * to ensure your client always has the correct values. */ -export type CreateClientConfig = (override?: Config) => Config & T> | Promise & T>>; +export type CreateClientConfig = (override?: Config) => Config & T>; export const client = createClient(createConfig({ throwOnError: true })); diff --git a/web/src/api/client/client.gen.ts b/web/src/api/client/client.gen.ts index 9b3b2fa..a421bbe 100644 --- a/web/src/api/client/client.gen.ts +++ b/web/src/api/client/client.gen.ts @@ -126,8 +126,11 @@ export const createClient = (config: Config = {}): Client => { }); }; + const _buildUrl: Client['buildUrl'] = (options) => + buildUrl({ axios: instance, ..._config, ...options }); + return { - buildUrl, + buildUrl: _buildUrl, connect: makeMethodFn('CONNECT'), delete: makeMethodFn('DELETE'), get: makeMethodFn('GET'), diff --git a/web/src/api/client/types.gen.ts b/web/src/api/client/types.gen.ts index a2b0d19..e789d42 100644 --- a/web/src/api/client/types.gen.ts +++ b/web/src/api/client/types.gen.ts @@ -141,7 +141,7 @@ export type Client = CoreClient */ export type CreateClientConfig = ( override?: Config, -) => Config & T> | Promise & T>>; +) => Config & T>; export interface TDataShape { body?: unknown; diff --git a/web/src/api/core/bodySerializer.gen.ts b/web/src/api/core/bodySerializer.gen.ts index 8ad92c9..67daca6 100644 --- a/web/src/api/core/bodySerializer.gen.ts +++ b/web/src/api/core/bodySerializer.gen.ts @@ -4,7 +4,7 @@ import type { ArrayStyle, ObjectStyle, SerializerOptions } from './pathSerialize export type QuerySerializer = (query: Record) => string; -export type BodySerializer = (body: any) => any; +export type BodySerializer = (body: unknown) => unknown; type QuerySerializerOptionsObject = { allowReserved?: boolean; @@ -39,12 +39,10 @@ const serializeUrlSearchParamsPair = (data: URLSearchParams, key: string, value: }; export const formDataBodySerializer = { - bodySerializer: | Array>>( - body: T, - ): FormData => { + bodySerializer: (body: unknown): FormData => { const data = new FormData(); - Object.entries(body).forEach(([key, value]) => { + Object.entries(body as Record).forEach(([key, value]) => { if (value === undefined || value === null) { return; } @@ -60,15 +58,15 @@ export const formDataBodySerializer = { }; export const jsonBodySerializer = { - bodySerializer: (body: T): string => + bodySerializer: (body: unknown): string => JSON.stringify(body, (_key, value) => (typeof value === 'bigint' ? value.toString() : value)), }; export const urlSearchParamsBodySerializer = { - bodySerializer: | Array>>(body: T): string => { + bodySerializer: (body: unknown): string => { const data = new URLSearchParams(); - Object.entries(body).forEach(([key, value]) => { + Object.entries(body as Record).forEach(([key, value]) => { if (value === undefined || value === null) { return; } diff --git a/web/src/api/index.ts b/web/src/api/index.ts index e2a1555..3e0e27b 100644 --- a/web/src/api/index.ts +++ b/web/src/api/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { accountV1Activate, accountV1ApplyEmailChange, accountV1ApplyPasswordChange, accountV1CompleteOtpSetup, accountV1GetMe, accountV1Join, accountV1Login, accountV1Logout, accountV1RequestActivation, accountV1RequestEmailChange, accountV1RequestPasswordChange, accountV1ResetOtp, accountV1SetupOtp, accountV1UpdateMe, accountV1UploadAvatar, accountV1VerifyOtp, assignmentV1DeactivateAttempt, assignmentV1GetSession, assignmentV1StartAttempt, assignmentV1SubmitAttempt, assistantV1ChatMessage, assistantV1DeleteChat, assistantV1GetChatMessages, assistantV1GetChats, assistantV1SaveAssistantNote, assistantV1UpdateChatMessage, competencyV1DeleteCompetencyGoal, competencyV1GetCertificateAwards, competencyV1GetCertificates, competencyV1GetClassificationSkillsData, competencyV1GetClassificationTree, competencyV1GetCompetencyGoals, competencyV1SaveCompetencyGoal, contentV1DeleteMediaWatch, contentV1GetMedia, contentV1GetMediaNote, contentV1GetMediaWatch, contentV1GetSubtitles, contentV1GetWatchMedias, contentV1SaveMediaNote, contentV1Search, contentV1SearchSuggestion, contentV1UpdateMediaWatch, courseV1GetDetail, courseV1GetSession, courseV1RequestCertificate, courseV1StartEngagement, discussionV1CreatePost, discussionV1DeactivateAttempt, discussionV1DeletePost, discussionV1GetOwnPosts, discussionV1GetPosts, discussionV1GetSession, discussionV1StartAttempt, discussionV1UpdatePost, examV1DeactivateAttempt, examV1GetSession, examV1GetTimestamp, examV1SaveAnswers, examV1StartAttempt, examV1SubmitAttempt, learningV1EnrollCatalogItem, learningV1GetCatalogItems, learningV1GetCatalogs, learningV1GetEnrolled, learningV1GetRecords, learningV1GetReport, learningV1Unenroll, minimaApiHealth, operationV1AgreePolicies, operationV1CreateAppeal, operationV1CreateInquiry, operationV1CreateThread, operationV1DeleteComment, operationV1DeleteDevice, operationV1EffectivePolicies, operationV1GetAnnouncements, operationV1GetComments, operationV1GetDevices, operationV1GetInquiries, operationV1GetThread, operationV1GetThreadComments, operationV1GetUnreadMessages, operationV1ReadAnnouncement, operationV1ReadMessage, operationV1RegisterDevice, operationV1SaveComment, operationV1ToggleDeviceActive, operationV1UpdateInquiry, type Options, partnerV1MemberInfos, quizV1DeactivateAttempt, quizV1GetSession, quizV1StartAttempt, quizV1SubmitAttempt, ssoV1Authorize, ssoV1Callback, ssoV1DeleteAccount, ssoV1GetAccounts, ssoV1Link, studioV1AssessmentSuggestions, studioV1CategorySuggestions, studioV1CertificateSuggestions, studioV1Content, studioV1ContentSuggestions, studioV1CreateMediaQuiz, studioV1DeleteAssignmentQuesion, studioV1DeleteDiscussionQuesion, studioV1DeleteExamQuesion, studioV1DeleteMediaSubtitle, studioV1DeleteQuizQuesion, studioV1DeleteSurveyQuesion, studioV1FaqSuggestions, studioV1GetAssignment, studioV1GetCourse, studioV1GetDiscussion, studioV1GetExam, studioV1GetFaqItems, studioV1GetMedia, studioV1GetQuiz, studioV1GetSurvey, studioV1InstructorSuggestions, studioV1RemoveCourseAssessment, studioV1RemoveCourseCategory, studioV1RemoveCourseCertificate, studioV1RemoveCourseFaqItem, studioV1RemoveCourseInstructor, studioV1RemoveCourseLesson, studioV1RemoveCourseRelation, studioV1RemoveCourseSurvey, studioV1SaveAssignment, studioV1SaveAssignmentQuestion, studioV1SaveCourse, studioV1SaveCourseAssessments, studioV1SaveCourseCategories, studioV1SaveCourseCertificates, studioV1SaveCourseFaqItems, studioV1SaveCourseInstructors, studioV1SaveCourseLessons, studioV1SaveCourseRelations, studioV1SaveCourseSurveys, studioV1SaveDiscussion, studioV1SaveDiscussionQuestion, studioV1SaveExam, studioV1SaveExamQuestions, studioV1SaveMedia, studioV1SaveMediaSubtitle, studioV1SaveQuiz, studioV1SaveQuizQuestions, studioV1SaveSurvey, studioV1SaveSurveyQuestions, surveyV1GetAnonymousSurvey, surveyV1GetSurvey, surveyV1Results, surveyV1ResultsAnonymous, surveyV1Submit, surveyV1SubmitAnonymous } from './sdk.gen'; -export type { AccessDateSchema, AccountActivatedSchema, AccountActivateSchema, AccountV1ActivateData, AccountV1ActivateResponse, AccountV1ActivateResponses, AccountV1ApplyEmailChangeData, AccountV1ApplyEmailChangeResponses, AccountV1ApplyPasswordChangeData, AccountV1ApplyPasswordChangeResponses, AccountV1CompleteOtpSetupData, AccountV1CompleteOtpSetupResponse, AccountV1CompleteOtpSetupResponses, AccountV1GetMeData, AccountV1GetMeResponse, AccountV1GetMeResponses, AccountV1JoinData, AccountV1JoinResponses, AccountV1LoginData, AccountV1LoginResponse, AccountV1LoginResponses, AccountV1LogoutData, AccountV1LogoutResponses, AccountV1RequestActivationData, AccountV1RequestActivationResponses, AccountV1RequestEmailChangeData, AccountV1RequestEmailChangeResponses, AccountV1RequestPasswordChangeData, AccountV1RequestPasswordChangeResponses, AccountV1ResetOtpData, AccountV1ResetOtpResponses, AccountV1SetupOtpData, AccountV1SetupOtpResponse, AccountV1SetupOtpResponses, AccountV1UpdateMeData, AccountV1UpdateMeResponse, AccountV1UpdateMeResponses, AccountV1UploadAvatarData, AccountV1UploadAvatarResponse, AccountV1UploadAvatarResponses, AccountV1VerifyOtpData, AccountV1VerifyOtpResponses, AnnounceSchema, AppealCreateSchema, AppealSchema, ApplyEmailChangeSchema, ApplyPasswordChangeSchema, AssessmentSaveSpec, AssessmentSpec, AssessmentSuggestion, AssignmentAttemptSchema, AssignmentGradeSchema, AssignmentQuestionPoolSpec, AssignmentQuestionSaveSpec, AssignmentQuestionSchema, AssignmentQuestionSpec, AssignmentQuestionsSpec, AssignmentSaveSpec, AssignmentSchema, AssignmentSessionSchema, AssignmentSolutionSchema, AssignmentSpec, AssignmentSubmissionSchema, AssignmentSubmitSchema, AssignmentV1DeactivateAttemptData, AssignmentV1DeactivateAttemptResponses, AssignmentV1GetSessionData, AssignmentV1GetSessionResponse, AssignmentV1GetSessionResponses, AssignmentV1StartAttemptData, AssignmentV1StartAttemptResponse, AssignmentV1StartAttemptResponses, AssignmentV1SubmitAttemptData, AssignmentV1SubmitAttemptResponse, AssignmentV1SubmitAttemptResponses, AssistantNoteSaveSchema, AssistantV1ChatMessageData, AssistantV1ChatMessageResponses, AssistantV1DeleteChatData, AssistantV1DeleteChatResponses, AssistantV1GetChatMessagesData, AssistantV1GetChatMessagesResponse, AssistantV1GetChatMessagesResponses, AssistantV1GetChatsData, AssistantV1GetChatsResponse, AssistantV1GetChatsResponses, AssistantV1SaveAssistantNoteData, AssistantV1SaveAssistantNoteResponses, AssistantV1UpdateChatMessageData, AssistantV1UpdateChatMessageResponses, AuthorizeResponseSchema, AuthorizeSchema, CatalogContentSchema, CatalogItemEnrollSchema, CatalogItemSchema, CatalogSchema, CategorySuggestionSpec, CertificateAwardSchema, CertificateEndorsementSchema, CertificateFilterSchema, CertificateSchema, CertificateSkillSchema, CertificateSuggestionSpec, ChatListSchema, ChatMessageCreateSchema, ChatMessageSchema, ChatMessageUpdateSchema, ChatSchema, ClassificationSchema, ClassificationTreeNodeSchema, ClientOptions, CohortSchema, CohortStaffSchema, CommentBriefSchema, CommentNestedSchema, CommentSavedSchema, CommentSaveSchema, CommentSchema, CommentThreadSchema, CompetencyFactorySchema, CompetencyGoalSaveSchema, CompetencyGoalSchema, CompetencySkillSchema, CompetencyV1DeleteCompetencyGoalData, CompetencyV1DeleteCompetencyGoalResponses, CompetencyV1GetCertificateAwardsData, CompetencyV1GetCertificateAwardsResponse, CompetencyV1GetCertificateAwardsResponses, CompetencyV1GetCertificatesData, CompetencyV1GetCertificatesResponse, CompetencyV1GetCertificatesResponses, CompetencyV1GetClassificationSkillsDataData, CompetencyV1GetClassificationSkillsDataResponse, CompetencyV1GetClassificationSkillsDataResponses, CompetencyV1GetClassificationTreeData, CompetencyV1GetClassificationTreeResponse, CompetencyV1GetClassificationTreeResponses, CompetencyV1GetCompetencyGoalsData, CompetencyV1GetCompetencyGoalsResponse, CompetencyV1GetCompetencyGoalsResponses, CompetencyV1SaveCompetencyGoalData, CompetencyV1SaveCompetencyGoalResponse, CompetencyV1SaveCompetencyGoalResponses, ContentSuggestionSpec, ContentTypeSchema, ContentV1DeleteMediaWatchData, ContentV1DeleteMediaWatchResponses, ContentV1GetMediaData, ContentV1GetMediaNoteData, ContentV1GetMediaNoteResponse, ContentV1GetMediaNoteResponses, ContentV1GetMediaResponse, ContentV1GetMediaResponses, ContentV1GetMediaWatchData, ContentV1GetMediaWatchResponse, ContentV1GetMediaWatchResponses, ContentV1GetSubtitlesData, ContentV1GetSubtitlesResponse, ContentV1GetSubtitlesResponses, ContentV1GetWatchMediasData, ContentV1GetWatchMediasResponse, ContentV1GetWatchMediasResponses, ContentV1SaveMediaNoteData, ContentV1SaveMediaNoteResponse, ContentV1SaveMediaNoteResponses, ContentV1SearchData, ContentV1SearchResponse, ContentV1SearchResponses, ContentV1SearchSuggestionData, ContentV1SearchSuggestionResponse, ContentV1SearchSuggestionResponses, ContentV1UpdateMediaWatchData, ContentV1UpdateMediaWatchResponses, CourseAssetsSpec, CourseCategorySaveSpec, CourseCategorySchema, CourseCategorySpec, CourseCertificateItemSchema, CourseCertificateRequestSchema, CourseCertificateSaveSpec, CourseCertificateSchema, CourseCertificateSpec, CourseDetailSchema, CourseEngagementSchema, CourseGradebookSchema, CourseInstructorItemSchema, CourseInstructorSaveSpec, CourseInstructorSchema, CourseInstructorSpec, CourseRelationItemSchema, CourseRelationSaveSpec, CourseRelationSchema, CourseRelationSpec, CourseSaveSpec, CourseSchema, CourseSessionSchema, CourseSpec, CourseSurveyItemSchema, CourseSurveySaveSpec, CourseSurveySchema, CourseSurveySpec, CourseV1GetDetailData, CourseV1GetDetailResponse, CourseV1GetDetailResponses, CourseV1GetSessionData, CourseV1GetSessionResponse, CourseV1GetSessionResponses, CourseV1RequestCertificateData, CourseV1RequestCertificateResponse, CourseV1RequestCertificateResponses, CourseV1StartEngagementData, CourseV1StartEngagementResponse, CourseV1StartEngagementResponses, DeviceRegisterSchema, DeviceSchema, DiscussionAttemptSchema, DiscussionEarnedDetailsSchema, DiscussionFeedbackSchema, DiscussionGradeSchema, DiscussionOwnPostSchema, DiscussionPostCountSchema, DiscussionPostNestedSchema, DiscussionPostSaveSchema, DiscussionPostSchema, DiscussionPostWithCountSchema, DiscussionQuestionPoolSpec, DiscussionQuestionSaveSpec, DiscussionQuestionSchema, DiscussionQuestionSpec, DiscussionQuestionsSpec, DiscussionSaveSpec, DiscussionSchema, DiscussionSessionSchema, DiscussionSpec, DiscussionV1CreatePostData, DiscussionV1CreatePostResponse, DiscussionV1CreatePostResponses, DiscussionV1DeactivateAttemptData, DiscussionV1DeactivateAttemptResponses, DiscussionV1DeletePostData, DiscussionV1DeletePostResponses, DiscussionV1GetOwnPostsData, DiscussionV1GetOwnPostsResponse, DiscussionV1GetOwnPostsResponses, DiscussionV1GetPostsData, DiscussionV1GetPostsResponse, DiscussionV1GetPostsResponses, DiscussionV1GetSessionData, DiscussionV1GetSessionResponse, DiscussionV1GetSessionResponses, DiscussionV1StartAttemptData, DiscussionV1StartAttemptResponse, DiscussionV1StartAttemptResponses, DiscussionV1UpdatePostData, DiscussionV1UpdatePostResponse, DiscussionV1UpdatePostResponses, EnrollmentContentSchema, EnrollmentSchema, EnrollmentSuccessSchema, ExamAttemptAnswersSchema, ExamAttemptSchema, ExamGradeSchema, ExamQuestionFormatChoices, ExamQuestionPoolSchema, ExamQuestionPoolSpec, ExamQuestionSaveSpec, ExamQuestionSchema, ExamQuestionSolutionSpec, ExamQuestionSpec, ExamQuestionsSaveSpec, ExamQuestionsSpec, ExamSaveSpec, ExamSchema, ExamSessionSchema, ExamSolutionSchema, ExamSpec, ExamSubmissionSchema, ExamV1DeactivateAttemptData, ExamV1DeactivateAttemptResponses, ExamV1GetSessionData, ExamV1GetSessionResponse, ExamV1GetSessionResponses, ExamV1GetTimestampData, ExamV1GetTimestampResponse, ExamV1GetTimestampResponses, ExamV1SaveAnswersData, ExamV1SaveAnswersResponses, ExamV1StartAttemptData, ExamV1StartAttemptResponse, ExamV1StartAttemptResponses, ExamV1SubmitAttemptData, ExamV1SubmitAttemptResponse, ExamV1SubmitAttemptResponses, FactoryDataSchema, FaqItemCopySpec, FaqItemSaveSpec, FaqItemSchema, FaqItemSpec, FaqSchema, FaqSpec, FaqSuggestionSpec, GradingCriterionSchema, GradingDateSchema, GradingPolicySpec, HonorCodeSchema, HonorCodeSpec, Input, InquiryCreateSchema, InquiryFilterSchema, InquiryResponseSchema, InquirySavedSchema, InquirySchema, InquiryUpdateSchema, InstructorSuggestionSpec, JoinSchema, KindChoices, LearningRecordSchema, LearningReportSchema, LearningSessionStep, LearningV1EnrollCatalogItemData, LearningV1EnrollCatalogItemResponse, LearningV1EnrollCatalogItemResponses, LearningV1GetCatalogItemsData, LearningV1GetCatalogItemsResponse, LearningV1GetCatalogItemsResponses, LearningV1GetCatalogsData, LearningV1GetCatalogsResponse, LearningV1GetCatalogsResponses, LearningV1GetEnrolledData, LearningV1GetEnrolledResponse, LearningV1GetEnrolledResponses, LearningV1GetRecordsData, LearningV1GetRecordsResponse, LearningV1GetRecordsResponses, LearningV1GetReportData, LearningV1GetReportResponse, LearningV1GetReportResponses, LearningV1UnenrollData, LearningV1UnenrollResponses, LessonMediaItemSchema, LessonMediaSchema, LessonSaveSpec, LessonSchema, LessonSpec, LevelChoices, LoginSchema, MatchedLineSchema, MediaFormatChoices, MediaSaveSpec, MediaSchema, MediaSpec, MessageDataSchema, MessageSchema, MinimaApiHealthData, MinimaApiHealthResponses, NoteSaveSchema, NoteSchema, OperationV1AgreePoliciesData, OperationV1AgreePoliciesResponses, OperationV1CreateAppealData, OperationV1CreateAppealResponse, OperationV1CreateAppealResponses, OperationV1CreateInquiryData, OperationV1CreateInquiryResponse, OperationV1CreateInquiryResponses, OperationV1CreateThreadData, OperationV1CreateThreadResponse, OperationV1CreateThreadResponses, OperationV1DeleteCommentData, OperationV1DeleteCommentResponses, OperationV1DeleteDeviceData, OperationV1DeleteDeviceResponses, OperationV1EffectivePoliciesData, OperationV1EffectivePoliciesResponse, OperationV1EffectivePoliciesResponses, OperationV1GetAnnouncementsData, OperationV1GetAnnouncementsResponse, OperationV1GetAnnouncementsResponses, OperationV1GetCommentsData, OperationV1GetCommentsResponse, OperationV1GetCommentsResponses, OperationV1GetDevicesData, OperationV1GetDevicesResponse, OperationV1GetDevicesResponses, OperationV1GetInquiriesData, OperationV1GetInquiriesResponse, OperationV1GetInquiriesResponses, OperationV1GetThreadCommentsData, OperationV1GetThreadCommentsResponse, OperationV1GetThreadCommentsResponses, OperationV1GetThreadData, OperationV1GetThreadResponse, OperationV1GetThreadResponses, OperationV1GetUnreadMessagesData, OperationV1GetUnreadMessagesResponse, OperationV1GetUnreadMessagesResponses, OperationV1ReadAnnouncementData, OperationV1ReadAnnouncementResponses, OperationV1ReadMessageData, OperationV1ReadMessageResponses, OperationV1RegisterDeviceData, OperationV1RegisterDeviceResponse, OperationV1RegisterDeviceResponses, OperationV1SaveCommentData, OperationV1SaveCommentResponse, OperationV1SaveCommentResponses, OperationV1ToggleDeviceActiveData, OperationV1ToggleDeviceActiveResponses, OperationV1UpdateInquiryData, OperationV1UpdateInquiryResponse, OperationV1UpdateInquiryResponses, OtpSetupCompleteSchema, OtpSetupSchema, OtpVerifySchema, OwnerSchema, PagedAnnounceSchema, PagedCertificateAwardSchema, PagedChatMessageSchema, PagedCommentBriefSchema, PagedCommentNestedSchema, PagedDiscussionPostNestedSchema, PagedInquirySchema, PagedMessageSchema, PagedWatchedMediaSchema, PaginatedResponseCatalogItemSchema, PaginatedResponseEnrollmentSchema, PaginatedResponseSearchedMediaSchema, PaginatedResponseStudioContentSpec, PartnerGroupMemberSchema, PartnerGroupSchema, PartnerSchema, PartnerV1MemberInfosData, PartnerV1MemberInfosResponse, PartnerV1MemberInfosResponses, PerformanceLevelSchema, PolicyVersionAgreementSchema, QuizAttemptAnswersSchema, QuizAttemptSchema, QuizGradeSchema, QuizQuestionPoolSpec, QuizQuestionSaveSpec, QuizQuestionSchema, QuizQuestionSolutionSpec, QuizQuestionSpec, QuizQuestionsSaveSpec, QuizQuestionsSpec, QuizSaveSpec, QuizSchema, QuizSessionSchema, QuizSolutionSchema, QuizSpec, QuizSubmissionSchema, QuizV1DeactivateAttemptData, QuizV1DeactivateAttemptResponses, QuizV1GetSessionData, QuizV1GetSessionResponse, QuizV1GetSessionResponses, QuizV1StartAttemptData, QuizV1StartAttemptResponse, QuizV1StartAttemptResponses, QuizV1SubmitAttemptData, QuizV1SubmitAttemptResponse, QuizV1SubmitAttemptResponses, RequestActivationSchema, RequestEmailChangeSchema, RequestPasswordChangeSchema, RoleChoices, RootModelListAssessmentSaveSpec, RootModelListCourseCategorySaveSpec, RootModelListCourseCertificateSaveSpec, RootModelListCourseInstructorSaveSpec, RootModelListCourseRelationSaveSpec, RootModelListCourseSurveySaveSpec, RootModelListFaqItemSaveSpec, RootModelListLessonSaveSpec, RubricCriterionSchema, RubricSchema, ScoreStatsSchema, SearchedMediaSchema, SitePolicySchema, SitePolicyVersionSchema, SkillDataSchema, SsoAccountSchema, SsoV1AuthorizeData, SsoV1AuthorizeResponse, SsoV1AuthorizeResponses, SsoV1CallbackData, SsoV1CallbackResponses, SsoV1DeleteAccountData, SsoV1DeleteAccountResponses, SsoV1GetAccountsData, SsoV1GetAccountsResponse, SsoV1GetAccountsResponses, SsoV1LinkData, SsoV1LinkResponse, SsoV1LinkResponses, StudioContentSpec, StudioV1AssessmentSuggestionsData, StudioV1AssessmentSuggestionsResponse, StudioV1AssessmentSuggestionsResponses, StudioV1CategorySuggestionsData, StudioV1CategorySuggestionsResponse, StudioV1CategorySuggestionsResponses, StudioV1CertificateSuggestionsData, StudioV1CertificateSuggestionsResponse, StudioV1CertificateSuggestionsResponses, StudioV1ContentData, StudioV1ContentResponse, StudioV1ContentResponses, StudioV1ContentSuggestionsData, StudioV1ContentSuggestionsResponse, StudioV1ContentSuggestionsResponses, StudioV1CreateMediaQuizData, StudioV1CreateMediaQuizResponse, StudioV1CreateMediaQuizResponses, StudioV1DeleteAssignmentQuesionData, StudioV1DeleteAssignmentQuesionResponses, StudioV1DeleteDiscussionQuesionData, StudioV1DeleteDiscussionQuesionResponses, StudioV1DeleteExamQuesionData, StudioV1DeleteExamQuesionResponses, StudioV1DeleteMediaSubtitleData, StudioV1DeleteMediaSubtitleResponses, StudioV1DeleteQuizQuesionData, StudioV1DeleteQuizQuesionResponses, StudioV1DeleteSurveyQuesionData, StudioV1DeleteSurveyQuesionResponses, StudioV1FaqSuggestionsData, StudioV1FaqSuggestionsResponse, StudioV1FaqSuggestionsResponses, StudioV1GetAssignmentData, StudioV1GetAssignmentResponse, StudioV1GetAssignmentResponses, StudioV1GetCourseData, StudioV1GetCourseResponse, StudioV1GetCourseResponses, StudioV1GetDiscussionData, StudioV1GetDiscussionResponse, StudioV1GetDiscussionResponses, StudioV1GetExamData, StudioV1GetExamResponse, StudioV1GetExamResponses, StudioV1GetFaqItemsData, StudioV1GetFaqItemsResponse, StudioV1GetFaqItemsResponses, StudioV1GetMediaData, StudioV1GetMediaResponse, StudioV1GetMediaResponses, StudioV1GetQuizData, StudioV1GetQuizResponse, StudioV1GetQuizResponses, StudioV1GetSurveyData, StudioV1GetSurveyResponse, StudioV1GetSurveyResponses, StudioV1InstructorSuggestionsData, StudioV1InstructorSuggestionsResponse, StudioV1InstructorSuggestionsResponses, StudioV1RemoveCourseAssessmentData, StudioV1RemoveCourseAssessmentResponses, StudioV1RemoveCourseCategoryData, StudioV1RemoveCourseCategoryResponses, StudioV1RemoveCourseCertificateData, StudioV1RemoveCourseCertificateResponses, StudioV1RemoveCourseFaqItemData, StudioV1RemoveCourseFaqItemResponses, StudioV1RemoveCourseInstructorData, StudioV1RemoveCourseInstructorResponses, StudioV1RemoveCourseLessonData, StudioV1RemoveCourseLessonResponses, StudioV1RemoveCourseRelationData, StudioV1RemoveCourseRelationResponses, StudioV1RemoveCourseSurveyData, StudioV1RemoveCourseSurveyResponses, StudioV1SaveAssignmentData, StudioV1SaveAssignmentQuestionData, StudioV1SaveAssignmentQuestionResponse, StudioV1SaveAssignmentQuestionResponses, StudioV1SaveAssignmentResponse, StudioV1SaveAssignmentResponses, StudioV1SaveCourseAssessmentsData, StudioV1SaveCourseAssessmentsResponse, StudioV1SaveCourseAssessmentsResponses, StudioV1SaveCourseCategoriesData, StudioV1SaveCourseCategoriesResponse, StudioV1SaveCourseCategoriesResponses, StudioV1SaveCourseCertificatesData, StudioV1SaveCourseCertificatesResponse, StudioV1SaveCourseCertificatesResponses, StudioV1SaveCourseData, StudioV1SaveCourseFaqItemsData, StudioV1SaveCourseFaqItemsResponse, StudioV1SaveCourseFaqItemsResponses, StudioV1SaveCourseInstructorsData, StudioV1SaveCourseInstructorsResponse, StudioV1SaveCourseInstructorsResponses, StudioV1SaveCourseLessonsData, StudioV1SaveCourseLessonsResponse, StudioV1SaveCourseLessonsResponses, StudioV1SaveCourseRelationsData, StudioV1SaveCourseRelationsResponse, StudioV1SaveCourseRelationsResponses, StudioV1SaveCourseResponse, StudioV1SaveCourseResponses, StudioV1SaveCourseSurveysData, StudioV1SaveCourseSurveysResponse, StudioV1SaveCourseSurveysResponses, StudioV1SaveDiscussionData, StudioV1SaveDiscussionQuestionData, StudioV1SaveDiscussionQuestionResponse, StudioV1SaveDiscussionQuestionResponses, StudioV1SaveDiscussionResponse, StudioV1SaveDiscussionResponses, StudioV1SaveExamData, StudioV1SaveExamQuestionsData, StudioV1SaveExamQuestionsResponse, StudioV1SaveExamQuestionsResponses, StudioV1SaveExamResponse, StudioV1SaveExamResponses, StudioV1SaveMediaData, StudioV1SaveMediaResponse, StudioV1SaveMediaResponses, StudioV1SaveMediaSubtitleData, StudioV1SaveMediaSubtitleResponses, StudioV1SaveQuizData, StudioV1SaveQuizQuestionsData, StudioV1SaveQuizQuestionsResponse, StudioV1SaveQuizQuestionsResponses, StudioV1SaveQuizResponse, StudioV1SaveQuizResponses, StudioV1SaveSurveyData, StudioV1SaveSurveyQuestionsData, StudioV1SaveSurveyQuestionsResponse, StudioV1SaveSurveyQuestionsResponses, StudioV1SaveSurveyResponse, StudioV1SaveSurveyResponses, SubtitleSchema, SubtitleSpec, SurveyAnswersSchema, SurveyQuestionFormatChoices, SurveyQuestionPoolSpec, SurveyQuestionSaveSpec, SurveyQuestionSchema, SurveyQuestionSpec, SurveyQuestionsSaveSpec, SurveyQuestionsSpec, SurveySaveSpec, SurveySchema, SurveySpec, SurveyV1GetAnonymousSurveyData, SurveyV1GetAnonymousSurveyResponse, SurveyV1GetAnonymousSurveyResponses, SurveyV1GetSurveyData, SurveyV1GetSurveyResponse, SurveyV1GetSurveyResponses, SurveyV1ResultsAnonymousData, SurveyV1ResultsAnonymousResponse, SurveyV1ResultsAnonymousResponses, SurveyV1ResultsData, SurveyV1ResultsResponse, SurveyV1ResultsResponses, SurveyV1SubmitAnonymousData, SurveyV1SubmitAnonymousResponses, SurveyV1SubmitData, SurveyV1SubmitResponses, ThreadCreateSchema, ThreadSchema, TotpDeviceSchema, UserSchema, UserUpdateSchema, WatchedMediaSchema, WatchInSchema, WatchOutSchema } from './types.gen'; +export { accountV1Activate, accountV1ApplyEmailChange, accountV1ApplyPasswordChange, accountV1CompleteOtpSetup, accountV1GetMe, accountV1Join, accountV1Login, accountV1Logout, accountV1RequestActivation, accountV1RequestEmailChange, accountV1RequestPasswordChange, accountV1ResetOtp, accountV1SetupOtp, accountV1UpdateMe, accountV1UploadAvatar, accountV1VerifyOtp, assignmentV1DeactivateAttempt, assignmentV1GetSession, assignmentV1StartAttempt, assignmentV1SubmitAttempt, assistantV1ChatMessage, assistantV1DeleteChat, assistantV1GetChatMessages, assistantV1GetChats, assistantV1SaveAssistantNote, assistantV1UpdateChatMessage, competencyV1DeleteCompetencyGoal, competencyV1GetCertificateAwards, competencyV1GetCertificates, competencyV1GetClassificationSkillsData, competencyV1GetClassificationTree, competencyV1GetCompetencyGoals, competencyV1SaveCompetencyGoal, contentV1DeleteMediaWatch, contentV1GetMedia, contentV1GetMediaNote, contentV1GetMediaWatch, contentV1GetSubtitles, contentV1GetWatchMedias, contentV1SaveMediaNote, contentV1Search, contentV1SearchSuggestion, contentV1UpdateMediaWatch, courseV1GetDetail, courseV1GetSession, courseV1RequestCertificate, courseV1StartEngagement, discussionV1CreatePost, discussionV1DeactivateAttempt, discussionV1DeletePost, discussionV1GetOwnPosts, discussionV1GetPosts, discussionV1GetSession, discussionV1StartAttempt, discussionV1UpdatePost, examV1DeactivateAttempt, examV1GetSession, examV1GetTimestamp, examV1SaveAnswers, examV1StartAttempt, examV1SubmitAttempt, learningV1EnrollCatalogItem, learningV1GetCatalogItems, learningV1GetCatalogs, learningV1GetEnrolled, learningV1GetRecords, learningV1GetReport, learningV1Unenroll, minimaApiHealth, operationV1AgreePolicies, operationV1CreateAppeal, operationV1CreateInquiry, operationV1CreateThread, operationV1DeleteComment, operationV1DeleteDevice, operationV1EffectivePolicies, operationV1GetAnnouncements, operationV1GetComments, operationV1GetDevices, operationV1GetInquiries, operationV1GetThread, operationV1GetThreadComments, operationV1GetUnreadMessages, operationV1ReadAnnouncement, operationV1ReadMessage, operationV1RegisterDevice, operationV1SaveComment, operationV1ToggleDeviceActive, operationV1UpdateInquiry, type Options, partnerV1MemberInfos, quizV1DeactivateAttempt, quizV1GetSession, quizV1StartAttempt, quizV1SubmitAttempt, ssoV1Authorize, ssoV1Callback, ssoV1DeleteAccount, ssoV1GetAccounts, ssoV1Link, studioV1AssessmentSuggestions, studioV1Content, studioV1ContentSuggestions, studioV1CreateMediaQuiz, studioV1DeleteAssignmentQuesion, studioV1DeleteDiscussionQuesion, studioV1DeleteExamQuesion, studioV1DeleteMediaSubtitle, studioV1DeleteQuizQuesion, studioV1DeleteSurveyQuesion, studioV1GetAssignment, studioV1GetAssignmentQuestions, studioV1GetCourse, studioV1GetDiscussion, studioV1GetDiscussionQuestions, studioV1GetExam, studioV1GetExamQuestions, studioV1GetMedia, studioV1GetQuiz, studioV1GetQuizQuestions, studioV1GetSurvey, studioV1GetSurveyQuestions, studioV1InlineSuggestions, studioV1RemoveCourseAssessment, studioV1RemoveCourseCategory, studioV1RemoveCourseCertificate, studioV1RemoveCourseInstructor, studioV1RemoveCourseLesson, studioV1RemoveCourseRelation, studioV1RemoveCourseSurvey, studioV1SaveAssignment, studioV1SaveAssignmentQuestion, studioV1SaveCourse, studioV1SaveCourseAssessments, studioV1SaveCourseCategories, studioV1SaveCourseCertificates, studioV1SaveCourseInstructors, studioV1SaveCourseLessons, studioV1SaveCourseRelations, studioV1SaveCourseSurveys, studioV1SaveDiscussion, studioV1SaveDiscussionQuestion, studioV1SaveExam, studioV1SaveExamQuestions, studioV1SaveMedia, studioV1SaveMediaSubtitle, studioV1SaveQuiz, studioV1SaveQuizQuestions, studioV1SaveSurvey, studioV1SaveSurveyQuestions, surveyV1GetAnonymousSurvey, surveyV1GetSurvey, surveyV1Results, surveyV1ResultsAnonymous, surveyV1Submit, surveyV1SubmitAnonymous } from './sdk.gen'; +export type { AccessDateSchema, AccountActivatedSchema, AccountActivateSchema, AccountV1ActivateData, AccountV1ActivateResponse, AccountV1ActivateResponses, AccountV1ApplyEmailChangeData, AccountV1ApplyEmailChangeResponses, AccountV1ApplyPasswordChangeData, AccountV1ApplyPasswordChangeResponses, AccountV1CompleteOtpSetupData, AccountV1CompleteOtpSetupResponse, AccountV1CompleteOtpSetupResponses, AccountV1GetMeData, AccountV1GetMeResponse, AccountV1GetMeResponses, AccountV1JoinData, AccountV1JoinResponses, AccountV1LoginData, AccountV1LoginResponse, AccountV1LoginResponses, AccountV1LogoutData, AccountV1LogoutResponses, AccountV1RequestActivationData, AccountV1RequestActivationResponses, AccountV1RequestEmailChangeData, AccountV1RequestEmailChangeResponses, AccountV1RequestPasswordChangeData, AccountV1RequestPasswordChangeResponses, AccountV1ResetOtpData, AccountV1ResetOtpResponses, AccountV1SetupOtpData, AccountV1SetupOtpResponse, AccountV1SetupOtpResponses, AccountV1UpdateMeData, AccountV1UpdateMeResponse, AccountV1UpdateMeResponses, AccountV1UploadAvatarData, AccountV1UploadAvatarResponse, AccountV1UploadAvatarResponses, AccountV1VerifyOtpData, AccountV1VerifyOtpResponses, AnnounceSchema, AppealCreateSchema, AppealSchema, ApplyEmailChangeSchema, ApplyPasswordChangeSchema, AssessmentSaveSpec, AssessmentSpec, AssessmentSuggestionSpec, AssignmentAttemptSchema, AssignmentGradeSchema, AssignmentQuestionSaveSpec, AssignmentQuestionSchema, AssignmentQuestionSpec, AssignmentQuestionsSpec, AssignmentSaveSpec, AssignmentSchema, AssignmentSessionSchema, AssignmentSolutionSchema, AssignmentSpec, AssignmentSubmissionSchema, AssignmentSubmitSchema, AssignmentV1DeactivateAttemptData, AssignmentV1DeactivateAttemptResponses, AssignmentV1GetSessionData, AssignmentV1GetSessionResponse, AssignmentV1GetSessionResponses, AssignmentV1StartAttemptData, AssignmentV1StartAttemptResponse, AssignmentV1StartAttemptResponses, AssignmentV1SubmitAttemptData, AssignmentV1SubmitAttemptResponse, AssignmentV1SubmitAttemptResponses, AssistantNoteSaveSchema, AssistantV1ChatMessageData, AssistantV1ChatMessageResponses, AssistantV1DeleteChatData, AssistantV1DeleteChatResponses, AssistantV1GetChatMessagesData, AssistantV1GetChatMessagesResponse, AssistantV1GetChatMessagesResponses, AssistantV1GetChatsData, AssistantV1GetChatsResponse, AssistantV1GetChatsResponses, AssistantV1SaveAssistantNoteData, AssistantV1SaveAssistantNoteResponses, AssistantV1UpdateChatMessageData, AssistantV1UpdateChatMessageResponses, AuthorizeResponseSchema, AuthorizeSchema, CatalogContentSchema, CatalogItemEnrollSchema, CatalogItemSchema, CatalogSchema, CertificateAwardSchema, CertificateEndorsementSchema, CertificateFilterSchema, CertificateSchema, CertificateSkillSchema, ChatListSchema, ChatMessageCreateSchema, ChatMessageSchema, ChatMessageUpdateSchema, ChatSchema, ClassificationSchema, ClassificationTreeNodeSchema, ClientOptions, CohortSchema, CohortStaffSchema, CommentBriefSchema, CommentNestedSchema, CommentSavedSchema, CommentSaveSchema, CommentSchema, CommentThreadSchema, CompetencyFactorySchema, CompetencyGoalSaveSchema, CompetencyGoalSchema, CompetencySkillSchema, CompetencyV1DeleteCompetencyGoalData, CompetencyV1DeleteCompetencyGoalResponses, CompetencyV1GetCertificateAwardsData, CompetencyV1GetCertificateAwardsResponse, CompetencyV1GetCertificateAwardsResponses, CompetencyV1GetCertificatesData, CompetencyV1GetCertificatesResponse, CompetencyV1GetCertificatesResponses, CompetencyV1GetClassificationSkillsDataData, CompetencyV1GetClassificationSkillsDataResponse, CompetencyV1GetClassificationSkillsDataResponses, CompetencyV1GetClassificationTreeData, CompetencyV1GetClassificationTreeResponse, CompetencyV1GetClassificationTreeResponses, CompetencyV1GetCompetencyGoalsData, CompetencyV1GetCompetencyGoalsResponse, CompetencyV1GetCompetencyGoalsResponses, CompetencyV1SaveCompetencyGoalData, CompetencyV1SaveCompetencyGoalResponse, CompetencyV1SaveCompetencyGoalResponses, ContentSuggestionSpec, ContentTypeSchema, ContentV1DeleteMediaWatchData, ContentV1DeleteMediaWatchResponses, ContentV1GetMediaData, ContentV1GetMediaNoteData, ContentV1GetMediaNoteResponse, ContentV1GetMediaNoteResponses, ContentV1GetMediaResponse, ContentV1GetMediaResponses, ContentV1GetMediaWatchData, ContentV1GetMediaWatchResponse, ContentV1GetMediaWatchResponses, ContentV1GetSubtitlesData, ContentV1GetSubtitlesResponse, ContentV1GetSubtitlesResponses, ContentV1GetWatchMediasData, ContentV1GetWatchMediasResponse, ContentV1GetWatchMediasResponses, ContentV1SaveMediaNoteData, ContentV1SaveMediaNoteResponse, ContentV1SaveMediaNoteResponses, ContentV1SearchData, ContentV1SearchResponse, ContentV1SearchResponses, ContentV1SearchSuggestionData, ContentV1SearchSuggestionResponse, ContentV1SearchSuggestionResponses, ContentV1UpdateMediaWatchData, ContentV1UpdateMediaWatchResponses, CourseAssetsSpec, CourseCategorySaveSpec, CourseCategorySchema, CourseCategorySpec, CourseCertificateItemSchema, CourseCertificateRequestSchema, CourseCertificateSaveSpec, CourseCertificateSchema, CourseCertificateSpec, CourseDetailSchema, CourseEngagementSchema, CourseGradebookSchema, CourseInstructorItemSchema, CourseInstructorSaveSpec, CourseInstructorSchema, CourseInstructorSpec, CourseRelationItemSchema, CourseRelationSaveSpec, CourseRelationSchema, CourseRelationSpec, CourseSaveSpec, CourseSchema, CourseSessionSchema, CourseSpec, CourseSurveyItemSchema, CourseSurveySaveSpec, CourseSurveySchema, CourseSurveySpec, CourseV1GetDetailData, CourseV1GetDetailResponse, CourseV1GetDetailResponses, CourseV1GetSessionData, CourseV1GetSessionResponse, CourseV1GetSessionResponses, CourseV1RequestCertificateData, CourseV1RequestCertificateResponse, CourseV1RequestCertificateResponses, CourseV1StartEngagementData, CourseV1StartEngagementResponse, CourseV1StartEngagementResponses, DeviceRegisterSchema, DeviceSchema, DiscussionAttemptSchema, DiscussionEarnedDetailsSchema, DiscussionFeedbackSchema, DiscussionGradeSchema, DiscussionOwnPostSchema, DiscussionPostCountSchema, DiscussionPostNestedSchema, DiscussionPostSaveSchema, DiscussionPostSchema, DiscussionPostWithCountSchema, DiscussionQuestionSaveSpec, DiscussionQuestionSchema, DiscussionQuestionSpec, DiscussionQuestionsSaveSpec, DiscussionQuestionsSpec, DiscussionSaveSpec, DiscussionSchema, DiscussionSessionSchema, DiscussionSpec, DiscussionV1CreatePostData, DiscussionV1CreatePostResponse, DiscussionV1CreatePostResponses, DiscussionV1DeactivateAttemptData, DiscussionV1DeactivateAttemptResponses, DiscussionV1DeletePostData, DiscussionV1DeletePostResponses, DiscussionV1GetOwnPostsData, DiscussionV1GetOwnPostsResponse, DiscussionV1GetOwnPostsResponses, DiscussionV1GetPostsData, DiscussionV1GetPostsResponse, DiscussionV1GetPostsResponses, DiscussionV1GetSessionData, DiscussionV1GetSessionResponse, DiscussionV1GetSessionResponses, DiscussionV1StartAttemptData, DiscussionV1StartAttemptResponse, DiscussionV1StartAttemptResponses, DiscussionV1UpdatePostData, DiscussionV1UpdatePostResponse, DiscussionV1UpdatePostResponses, EnrollmentContentSchema, EnrollmentSchema, EnrollmentSuccessSchema, ExamAttemptAnswersSchema, ExamAttemptSchema, ExamGradeSchema, ExamQuestionFormatChoices, ExamQuestionPoolSchema, ExamQuestionPoolSpec, ExamQuestionSaveSpec, ExamQuestionSchema, ExamQuestionSolutionSpec, ExamQuestionSpec, ExamQuestionsSaveSpec, ExamQuestionsSpec, ExamSaveSpec, ExamSchema, ExamSessionSchema, ExamSolutionSchema, ExamSpec, ExamSubmissionSchema, ExamV1DeactivateAttemptData, ExamV1DeactivateAttemptResponses, ExamV1GetSessionData, ExamV1GetSessionResponse, ExamV1GetSessionResponses, ExamV1GetTimestampData, ExamV1GetTimestampResponse, ExamV1GetTimestampResponses, ExamV1SaveAnswersData, ExamV1SaveAnswersResponses, ExamV1StartAttemptData, ExamV1StartAttemptResponse, ExamV1StartAttemptResponses, ExamV1SubmitAttemptData, ExamV1SubmitAttemptResponse, ExamV1SubmitAttemptResponses, FactoryDataSchema, FaqItemSchema, FaqSchema, GradingCriterionSchema, GradingDateSchema, GradingPolicySpec, HonorCodeSchema, InlineSuggestionSpec, Input, InquiryCreateSchema, InquiryFilterSchema, InquiryResponseSchema, InquirySavedSchema, InquirySchema, InquiryUpdateSchema, JoinSchema, KindChoices, LearningRecordSchema, LearningReportSchema, LearningSessionStep, LearningV1EnrollCatalogItemData, LearningV1EnrollCatalogItemResponse, LearningV1EnrollCatalogItemResponses, LearningV1GetCatalogItemsData, LearningV1GetCatalogItemsResponse, LearningV1GetCatalogItemsResponses, LearningV1GetCatalogsData, LearningV1GetCatalogsResponse, LearningV1GetCatalogsResponses, LearningV1GetEnrolledData, LearningV1GetEnrolledResponse, LearningV1GetEnrolledResponses, LearningV1GetRecordsData, LearningV1GetRecordsResponse, LearningV1GetRecordsResponses, LearningV1GetReportData, LearningV1GetReportResponse, LearningV1GetReportResponses, LearningV1UnenrollData, LearningV1UnenrollResponses, LessonMediaItemSchema, LessonMediaSchema, LessonSaveSpec, LessonSchema, LessonSpec, LevelChoices, LoginSchema, MatchedLineSchema, MediaFormatChoices, MediaSaveSpec, MediaSchema, MediaSpec, MessageDataSchema, MessageSchema, MinimaApiHealthData, MinimaApiHealthResponses, NoteSaveSchema, NoteSchema, OperationV1AgreePoliciesData, OperationV1AgreePoliciesResponses, OperationV1CreateAppealData, OperationV1CreateAppealResponse, OperationV1CreateAppealResponses, OperationV1CreateInquiryData, OperationV1CreateInquiryResponse, OperationV1CreateInquiryResponses, OperationV1CreateThreadData, OperationV1CreateThreadResponse, OperationV1CreateThreadResponses, OperationV1DeleteCommentData, OperationV1DeleteCommentResponses, OperationV1DeleteDeviceData, OperationV1DeleteDeviceResponses, OperationV1EffectivePoliciesData, OperationV1EffectivePoliciesResponse, OperationV1EffectivePoliciesResponses, OperationV1GetAnnouncementsData, OperationV1GetAnnouncementsResponse, OperationV1GetAnnouncementsResponses, OperationV1GetCommentsData, OperationV1GetCommentsResponse, OperationV1GetCommentsResponses, OperationV1GetDevicesData, OperationV1GetDevicesResponse, OperationV1GetDevicesResponses, OperationV1GetInquiriesData, OperationV1GetInquiriesResponse, OperationV1GetInquiriesResponses, OperationV1GetThreadCommentsData, OperationV1GetThreadCommentsResponse, OperationV1GetThreadCommentsResponses, OperationV1GetThreadData, OperationV1GetThreadResponse, OperationV1GetThreadResponses, OperationV1GetUnreadMessagesData, OperationV1GetUnreadMessagesResponse, OperationV1GetUnreadMessagesResponses, OperationV1ReadAnnouncementData, OperationV1ReadAnnouncementResponses, OperationV1ReadMessageData, OperationV1ReadMessageResponses, OperationV1RegisterDeviceData, OperationV1RegisterDeviceResponse, OperationV1RegisterDeviceResponses, OperationV1SaveCommentData, OperationV1SaveCommentResponse, OperationV1SaveCommentResponses, OperationV1ToggleDeviceActiveData, OperationV1ToggleDeviceActiveResponses, OperationV1UpdateInquiryData, OperationV1UpdateInquiryResponse, OperationV1UpdateInquiryResponses, OtpSetupCompleteSchema, OtpSetupSchema, OtpVerifySchema, OwnerSchema, PagedAnnounceSchema, PagedCertificateAwardSchema, PagedChatMessageSchema, PagedCommentBriefSchema, PagedCommentNestedSchema, PagedDiscussionPostNestedSchema, PagedInquirySchema, PagedMessageSchema, PagedWatchedMediaSchema, PaginatedResponseCatalogItemSchema, PaginatedResponseEnrollmentSchema, PaginatedResponseSearchedMediaSchema, PaginatedResponseStudioContentSpec, PartnerGroupMemberSchema, PartnerGroupSchema, PartnerSchema, PartnerV1MemberInfosData, PartnerV1MemberInfosResponse, PartnerV1MemberInfosResponses, PerformanceLevelSchema, PolicyVersionAgreementSchema, QuizAttemptAnswersSchema, QuizAttemptSchema, QuizGradeSchema, QuizQuestionPoolSpec, QuizQuestionSaveSpec, QuizQuestionSchema, QuizQuestionSolutionSpec, QuizQuestionSpec, QuizQuestionsSaveSpec, QuizQuestionsSpec, QuizSaveSpec, QuizSchema, QuizSessionSchema, QuizSolutionSchema, QuizSpec, QuizSubmissionSchema, QuizV1DeactivateAttemptData, QuizV1DeactivateAttemptResponses, QuizV1GetSessionData, QuizV1GetSessionResponse, QuizV1GetSessionResponses, QuizV1StartAttemptData, QuizV1StartAttemptResponse, QuizV1StartAttemptResponses, QuizV1SubmitAttemptData, QuizV1SubmitAttemptResponse, QuizV1SubmitAttemptResponses, RequestActivationSchema, RequestEmailChangeSchema, RequestPasswordChangeSchema, RoleChoices, RootModelListAssessmentSaveSpec, RootModelListCourseCategorySaveSpec, RootModelListCourseCertificateSaveSpec, RootModelListCourseInstructorSaveSpec, RootModelListCourseRelationSaveSpec, RootModelListCourseSurveySaveSpec, RootModelListLessonSaveSpec, RubricCriterionSchema, RubricSchema, ScoreStatsSchema, SearchedMediaSchema, SitePolicySchema, SitePolicyVersionSchema, SkillDataSchema, SsoAccountSchema, SsoV1AuthorizeData, SsoV1AuthorizeResponse, SsoV1AuthorizeResponses, SsoV1CallbackData, SsoV1CallbackResponses, SsoV1DeleteAccountData, SsoV1DeleteAccountResponses, SsoV1GetAccountsData, SsoV1GetAccountsResponse, SsoV1GetAccountsResponses, SsoV1LinkData, SsoV1LinkResponse, SsoV1LinkResponses, StudioContentSpec, StudioV1AssessmentSuggestionsData, StudioV1AssessmentSuggestionsResponse, StudioV1AssessmentSuggestionsResponses, StudioV1ContentData, StudioV1ContentResponse, StudioV1ContentResponses, StudioV1ContentSuggestionsData, StudioV1ContentSuggestionsResponse, StudioV1ContentSuggestionsResponses, StudioV1CreateMediaQuizData, StudioV1CreateMediaQuizResponse, StudioV1CreateMediaQuizResponses, StudioV1DeleteAssignmentQuesionData, StudioV1DeleteAssignmentQuesionResponses, StudioV1DeleteDiscussionQuesionData, StudioV1DeleteDiscussionQuesionResponses, StudioV1DeleteExamQuesionData, StudioV1DeleteExamQuesionResponses, StudioV1DeleteMediaSubtitleData, StudioV1DeleteMediaSubtitleResponses, StudioV1DeleteQuizQuesionData, StudioV1DeleteQuizQuesionResponses, StudioV1DeleteSurveyQuesionData, StudioV1DeleteSurveyQuesionResponses, StudioV1GetAssignmentData, StudioV1GetAssignmentQuestionsData, StudioV1GetAssignmentQuestionsResponse, StudioV1GetAssignmentQuestionsResponses, StudioV1GetAssignmentResponse, StudioV1GetAssignmentResponses, StudioV1GetCourseData, StudioV1GetCourseResponse, StudioV1GetCourseResponses, StudioV1GetDiscussionData, StudioV1GetDiscussionQuestionsData, StudioV1GetDiscussionQuestionsResponse, StudioV1GetDiscussionQuestionsResponses, StudioV1GetDiscussionResponse, StudioV1GetDiscussionResponses, StudioV1GetExamData, StudioV1GetExamQuestionsData, StudioV1GetExamQuestionsResponse, StudioV1GetExamQuestionsResponses, StudioV1GetExamResponse, StudioV1GetExamResponses, StudioV1GetMediaData, StudioV1GetMediaResponse, StudioV1GetMediaResponses, StudioV1GetQuizData, StudioV1GetQuizQuestionsData, StudioV1GetQuizQuestionsResponse, StudioV1GetQuizQuestionsResponses, StudioV1GetQuizResponse, StudioV1GetQuizResponses, StudioV1GetSurveyData, StudioV1GetSurveyQuestionsData, StudioV1GetSurveyQuestionsResponse, StudioV1GetSurveyQuestionsResponses, StudioV1GetSurveyResponse, StudioV1GetSurveyResponses, StudioV1InlineSuggestionsData, StudioV1InlineSuggestionsResponse, StudioV1InlineSuggestionsResponses, StudioV1RemoveCourseAssessmentData, StudioV1RemoveCourseAssessmentResponses, StudioV1RemoveCourseCategoryData, StudioV1RemoveCourseCategoryResponses, StudioV1RemoveCourseCertificateData, StudioV1RemoveCourseCertificateResponses, StudioV1RemoveCourseInstructorData, StudioV1RemoveCourseInstructorResponses, StudioV1RemoveCourseLessonData, StudioV1RemoveCourseLessonResponses, StudioV1RemoveCourseRelationData, StudioV1RemoveCourseRelationResponses, StudioV1RemoveCourseSurveyData, StudioV1RemoveCourseSurveyResponses, StudioV1SaveAssignmentData, StudioV1SaveAssignmentQuestionData, StudioV1SaveAssignmentQuestionResponse, StudioV1SaveAssignmentQuestionResponses, StudioV1SaveAssignmentResponse, StudioV1SaveAssignmentResponses, StudioV1SaveCourseAssessmentsData, StudioV1SaveCourseAssessmentsResponse, StudioV1SaveCourseAssessmentsResponses, StudioV1SaveCourseCategoriesData, StudioV1SaveCourseCategoriesResponse, StudioV1SaveCourseCategoriesResponses, StudioV1SaveCourseCertificatesData, StudioV1SaveCourseCertificatesResponse, StudioV1SaveCourseCertificatesResponses, StudioV1SaveCourseData, StudioV1SaveCourseInstructorsData, StudioV1SaveCourseInstructorsResponse, StudioV1SaveCourseInstructorsResponses, StudioV1SaveCourseLessonsData, StudioV1SaveCourseLessonsResponse, StudioV1SaveCourseLessonsResponses, StudioV1SaveCourseRelationsData, StudioV1SaveCourseRelationsResponse, StudioV1SaveCourseRelationsResponses, StudioV1SaveCourseResponse, StudioV1SaveCourseResponses, StudioV1SaveCourseSurveysData, StudioV1SaveCourseSurveysResponse, StudioV1SaveCourseSurveysResponses, StudioV1SaveDiscussionData, StudioV1SaveDiscussionQuestionData, StudioV1SaveDiscussionQuestionResponse, StudioV1SaveDiscussionQuestionResponses, StudioV1SaveDiscussionResponse, StudioV1SaveDiscussionResponses, StudioV1SaveExamData, StudioV1SaveExamQuestionsData, StudioV1SaveExamQuestionsResponse, StudioV1SaveExamQuestionsResponses, StudioV1SaveExamResponse, StudioV1SaveExamResponses, StudioV1SaveMediaData, StudioV1SaveMediaResponse, StudioV1SaveMediaResponses, StudioV1SaveMediaSubtitleData, StudioV1SaveMediaSubtitleResponses, StudioV1SaveQuizData, StudioV1SaveQuizQuestionsData, StudioV1SaveQuizQuestionsResponse, StudioV1SaveQuizQuestionsResponses, StudioV1SaveQuizResponse, StudioV1SaveQuizResponses, StudioV1SaveSurveyData, StudioV1SaveSurveyQuestionsData, StudioV1SaveSurveyQuestionsResponse, StudioV1SaveSurveyQuestionsResponses, StudioV1SaveSurveyResponse, StudioV1SaveSurveyResponses, SubtitleSchema, SubtitleSpec, SurveyAnswersSchema, SurveyQuestionFormatChoices, SurveyQuestionSaveSpec, SurveyQuestionSchema, SurveyQuestionSpec, SurveyQuestionsSaveSpec, SurveyQuestionsSpec, SurveySaveSpec, SurveySchema, SurveySpec, SurveyV1GetAnonymousSurveyData, SurveyV1GetAnonymousSurveyResponse, SurveyV1GetAnonymousSurveyResponses, SurveyV1GetSurveyData, SurveyV1GetSurveyResponse, SurveyV1GetSurveyResponses, SurveyV1ResultsAnonymousData, SurveyV1ResultsAnonymousResponse, SurveyV1ResultsAnonymousResponses, SurveyV1ResultsData, SurveyV1ResultsResponse, SurveyV1ResultsResponses, SurveyV1SubmitAnonymousData, SurveyV1SubmitAnonymousResponses, SurveyV1SubmitData, SurveyV1SubmitResponses, ThreadCreateSchema, ThreadSchema, TotpDeviceSchema, UserSchema, UserUpdateSchema, WatchedMediaSchema, WatchInSchema, WatchOutSchema } from './types.gen'; diff --git a/web/src/api/sdk.gen.ts b/web/src/api/sdk.gen.ts index 89dc59a..72ff612 100644 --- a/web/src/api/sdk.gen.ts +++ b/web/src/api/sdk.gen.ts @@ -2,7 +2,7 @@ import { type Client, formDataBodySerializer, type Options as Options2, type TDataShape } from './client'; import { client } from './client.gen'; -import type { AccountV1ActivateData, AccountV1ActivateResponses, AccountV1ApplyEmailChangeData, AccountV1ApplyEmailChangeResponses, AccountV1ApplyPasswordChangeData, AccountV1ApplyPasswordChangeResponses, AccountV1CompleteOtpSetupData, AccountV1CompleteOtpSetupResponses, AccountV1GetMeData, AccountV1GetMeResponses, AccountV1JoinData, AccountV1JoinResponses, AccountV1LoginData, AccountV1LoginResponses, AccountV1LogoutData, AccountV1LogoutResponses, AccountV1RequestActivationData, AccountV1RequestActivationResponses, AccountV1RequestEmailChangeData, AccountV1RequestEmailChangeResponses, AccountV1RequestPasswordChangeData, AccountV1RequestPasswordChangeResponses, AccountV1ResetOtpData, AccountV1ResetOtpResponses, AccountV1SetupOtpData, AccountV1SetupOtpResponses, AccountV1UpdateMeData, AccountV1UpdateMeResponses, AccountV1UploadAvatarData, AccountV1UploadAvatarResponses, AccountV1VerifyOtpData, AccountV1VerifyOtpResponses, AssignmentV1DeactivateAttemptData, AssignmentV1DeactivateAttemptResponses, AssignmentV1GetSessionData, AssignmentV1GetSessionResponses, AssignmentV1StartAttemptData, AssignmentV1StartAttemptResponses, AssignmentV1SubmitAttemptData, AssignmentV1SubmitAttemptResponses, AssistantV1ChatMessageData, AssistantV1ChatMessageResponses, AssistantV1DeleteChatData, AssistantV1DeleteChatResponses, AssistantV1GetChatMessagesData, AssistantV1GetChatMessagesResponses, AssistantV1GetChatsData, AssistantV1GetChatsResponses, AssistantV1SaveAssistantNoteData, AssistantV1SaveAssistantNoteResponses, AssistantV1UpdateChatMessageData, AssistantV1UpdateChatMessageResponses, CompetencyV1DeleteCompetencyGoalData, CompetencyV1DeleteCompetencyGoalResponses, CompetencyV1GetCertificateAwardsData, CompetencyV1GetCertificateAwardsResponses, CompetencyV1GetCertificatesData, CompetencyV1GetCertificatesResponses, CompetencyV1GetClassificationSkillsDataData, CompetencyV1GetClassificationSkillsDataResponses, CompetencyV1GetClassificationTreeData, CompetencyV1GetClassificationTreeResponses, CompetencyV1GetCompetencyGoalsData, CompetencyV1GetCompetencyGoalsResponses, CompetencyV1SaveCompetencyGoalData, CompetencyV1SaveCompetencyGoalResponses, ContentV1DeleteMediaWatchData, ContentV1DeleteMediaWatchResponses, ContentV1GetMediaData, ContentV1GetMediaNoteData, ContentV1GetMediaNoteResponses, ContentV1GetMediaResponses, ContentV1GetMediaWatchData, ContentV1GetMediaWatchResponses, ContentV1GetSubtitlesData, ContentV1GetSubtitlesResponses, ContentV1GetWatchMediasData, ContentV1GetWatchMediasResponses, ContentV1SaveMediaNoteData, ContentV1SaveMediaNoteResponses, ContentV1SearchData, ContentV1SearchResponses, ContentV1SearchSuggestionData, ContentV1SearchSuggestionResponses, ContentV1UpdateMediaWatchData, ContentV1UpdateMediaWatchResponses, CourseV1GetDetailData, CourseV1GetDetailResponses, CourseV1GetSessionData, CourseV1GetSessionResponses, CourseV1RequestCertificateData, CourseV1RequestCertificateResponses, CourseV1StartEngagementData, CourseV1StartEngagementResponses, DiscussionV1CreatePostData, DiscussionV1CreatePostResponses, DiscussionV1DeactivateAttemptData, DiscussionV1DeactivateAttemptResponses, DiscussionV1DeletePostData, DiscussionV1DeletePostResponses, DiscussionV1GetOwnPostsData, DiscussionV1GetOwnPostsResponses, DiscussionV1GetPostsData, DiscussionV1GetPostsResponses, DiscussionV1GetSessionData, DiscussionV1GetSessionResponses, DiscussionV1StartAttemptData, DiscussionV1StartAttemptResponses, DiscussionV1UpdatePostData, DiscussionV1UpdatePostResponses, ExamV1DeactivateAttemptData, ExamV1DeactivateAttemptResponses, ExamV1GetSessionData, ExamV1GetSessionResponses, ExamV1GetTimestampData, ExamV1GetTimestampResponses, ExamV1SaveAnswersData, ExamV1SaveAnswersResponses, ExamV1StartAttemptData, ExamV1StartAttemptResponses, ExamV1SubmitAttemptData, ExamV1SubmitAttemptResponses, LearningV1EnrollCatalogItemData, LearningV1EnrollCatalogItemResponses, LearningV1GetCatalogItemsData, LearningV1GetCatalogItemsResponses, LearningV1GetCatalogsData, LearningV1GetCatalogsResponses, LearningV1GetEnrolledData, LearningV1GetEnrolledResponses, LearningV1GetRecordsData, LearningV1GetRecordsResponses, LearningV1GetReportData, LearningV1GetReportResponses, LearningV1UnenrollData, LearningV1UnenrollResponses, MinimaApiHealthData, MinimaApiHealthResponses, OperationV1AgreePoliciesData, OperationV1AgreePoliciesResponses, OperationV1CreateAppealData, OperationV1CreateAppealResponses, OperationV1CreateInquiryData, OperationV1CreateInquiryResponses, OperationV1CreateThreadData, OperationV1CreateThreadResponses, OperationV1DeleteCommentData, OperationV1DeleteCommentResponses, OperationV1DeleteDeviceData, OperationV1DeleteDeviceResponses, OperationV1EffectivePoliciesData, OperationV1EffectivePoliciesResponses, OperationV1GetAnnouncementsData, OperationV1GetAnnouncementsResponses, OperationV1GetCommentsData, OperationV1GetCommentsResponses, OperationV1GetDevicesData, OperationV1GetDevicesResponses, OperationV1GetInquiriesData, OperationV1GetInquiriesResponses, OperationV1GetThreadCommentsData, OperationV1GetThreadCommentsResponses, OperationV1GetThreadData, OperationV1GetThreadResponses, OperationV1GetUnreadMessagesData, OperationV1GetUnreadMessagesResponses, OperationV1ReadAnnouncementData, OperationV1ReadAnnouncementResponses, OperationV1ReadMessageData, OperationV1ReadMessageResponses, OperationV1RegisterDeviceData, OperationV1RegisterDeviceResponses, OperationV1SaveCommentData, OperationV1SaveCommentResponses, OperationV1ToggleDeviceActiveData, OperationV1ToggleDeviceActiveResponses, OperationV1UpdateInquiryData, OperationV1UpdateInquiryResponses, PartnerV1MemberInfosData, PartnerV1MemberInfosResponses, QuizV1DeactivateAttemptData, QuizV1DeactivateAttemptResponses, QuizV1GetSessionData, QuizV1GetSessionResponses, QuizV1StartAttemptData, QuizV1StartAttemptResponses, QuizV1SubmitAttemptData, QuizV1SubmitAttemptResponses, SsoV1AuthorizeData, SsoV1AuthorizeResponses, SsoV1CallbackData, SsoV1CallbackResponses, SsoV1DeleteAccountData, SsoV1DeleteAccountResponses, SsoV1GetAccountsData, SsoV1GetAccountsResponses, SsoV1LinkData, SsoV1LinkResponses, StudioV1AssessmentSuggestionsData, StudioV1AssessmentSuggestionsResponses, StudioV1CategorySuggestionsData, StudioV1CategorySuggestionsResponses, StudioV1CertificateSuggestionsData, StudioV1CertificateSuggestionsResponses, StudioV1ContentData, StudioV1ContentResponses, StudioV1ContentSuggestionsData, StudioV1ContentSuggestionsResponses, StudioV1CreateMediaQuizData, StudioV1CreateMediaQuizResponses, StudioV1DeleteAssignmentQuesionData, StudioV1DeleteAssignmentQuesionResponses, StudioV1DeleteDiscussionQuesionData, StudioV1DeleteDiscussionQuesionResponses, StudioV1DeleteExamQuesionData, StudioV1DeleteExamQuesionResponses, StudioV1DeleteMediaSubtitleData, StudioV1DeleteMediaSubtitleResponses, StudioV1DeleteQuizQuesionData, StudioV1DeleteQuizQuesionResponses, StudioV1DeleteSurveyQuesionData, StudioV1DeleteSurveyQuesionResponses, StudioV1FaqSuggestionsData, StudioV1FaqSuggestionsResponses, StudioV1GetAssignmentData, StudioV1GetAssignmentResponses, StudioV1GetCourseData, StudioV1GetCourseResponses, StudioV1GetDiscussionData, StudioV1GetDiscussionResponses, StudioV1GetExamData, StudioV1GetExamResponses, StudioV1GetFaqItemsData, StudioV1GetFaqItemsResponses, StudioV1GetMediaData, StudioV1GetMediaResponses, StudioV1GetQuizData, StudioV1GetQuizResponses, StudioV1GetSurveyData, StudioV1GetSurveyResponses, StudioV1InstructorSuggestionsData, StudioV1InstructorSuggestionsResponses, StudioV1RemoveCourseAssessmentData, StudioV1RemoveCourseAssessmentResponses, StudioV1RemoveCourseCategoryData, StudioV1RemoveCourseCategoryResponses, StudioV1RemoveCourseCertificateData, StudioV1RemoveCourseCertificateResponses, StudioV1RemoveCourseFaqItemData, StudioV1RemoveCourseFaqItemResponses, StudioV1RemoveCourseInstructorData, StudioV1RemoveCourseInstructorResponses, StudioV1RemoveCourseLessonData, StudioV1RemoveCourseLessonResponses, StudioV1RemoveCourseRelationData, StudioV1RemoveCourseRelationResponses, StudioV1RemoveCourseSurveyData, StudioV1RemoveCourseSurveyResponses, StudioV1SaveAssignmentData, StudioV1SaveAssignmentQuestionData, StudioV1SaveAssignmentQuestionResponses, StudioV1SaveAssignmentResponses, StudioV1SaveCourseAssessmentsData, StudioV1SaveCourseAssessmentsResponses, StudioV1SaveCourseCategoriesData, StudioV1SaveCourseCategoriesResponses, StudioV1SaveCourseCertificatesData, StudioV1SaveCourseCertificatesResponses, StudioV1SaveCourseData, StudioV1SaveCourseFaqItemsData, StudioV1SaveCourseFaqItemsResponses, StudioV1SaveCourseInstructorsData, StudioV1SaveCourseInstructorsResponses, StudioV1SaveCourseLessonsData, StudioV1SaveCourseLessonsResponses, StudioV1SaveCourseRelationsData, StudioV1SaveCourseRelationsResponses, StudioV1SaveCourseResponses, StudioV1SaveCourseSurveysData, StudioV1SaveCourseSurveysResponses, StudioV1SaveDiscussionData, StudioV1SaveDiscussionQuestionData, StudioV1SaveDiscussionQuestionResponses, StudioV1SaveDiscussionResponses, StudioV1SaveExamData, StudioV1SaveExamQuestionsData, StudioV1SaveExamQuestionsResponses, StudioV1SaveExamResponses, StudioV1SaveMediaData, StudioV1SaveMediaResponses, StudioV1SaveMediaSubtitleData, StudioV1SaveMediaSubtitleResponses, StudioV1SaveQuizData, StudioV1SaveQuizQuestionsData, StudioV1SaveQuizQuestionsResponses, StudioV1SaveQuizResponses, StudioV1SaveSurveyData, StudioV1SaveSurveyQuestionsData, StudioV1SaveSurveyQuestionsResponses, StudioV1SaveSurveyResponses, SurveyV1GetAnonymousSurveyData, SurveyV1GetAnonymousSurveyResponses, SurveyV1GetSurveyData, SurveyV1GetSurveyResponses, SurveyV1ResultsAnonymousData, SurveyV1ResultsAnonymousResponses, SurveyV1ResultsData, SurveyV1ResultsResponses, SurveyV1SubmitAnonymousData, SurveyV1SubmitAnonymousResponses, SurveyV1SubmitData, SurveyV1SubmitResponses } from './types.gen'; +import type { AccountV1ActivateData, AccountV1ActivateResponses, AccountV1ApplyEmailChangeData, AccountV1ApplyEmailChangeResponses, AccountV1ApplyPasswordChangeData, AccountV1ApplyPasswordChangeResponses, AccountV1CompleteOtpSetupData, AccountV1CompleteOtpSetupResponses, AccountV1GetMeData, AccountV1GetMeResponses, AccountV1JoinData, AccountV1JoinResponses, AccountV1LoginData, AccountV1LoginResponses, AccountV1LogoutData, AccountV1LogoutResponses, AccountV1RequestActivationData, AccountV1RequestActivationResponses, AccountV1RequestEmailChangeData, AccountV1RequestEmailChangeResponses, AccountV1RequestPasswordChangeData, AccountV1RequestPasswordChangeResponses, AccountV1ResetOtpData, AccountV1ResetOtpResponses, AccountV1SetupOtpData, AccountV1SetupOtpResponses, AccountV1UpdateMeData, AccountV1UpdateMeResponses, AccountV1UploadAvatarData, AccountV1UploadAvatarResponses, AccountV1VerifyOtpData, AccountV1VerifyOtpResponses, AssignmentV1DeactivateAttemptData, AssignmentV1DeactivateAttemptResponses, AssignmentV1GetSessionData, AssignmentV1GetSessionResponses, AssignmentV1StartAttemptData, AssignmentV1StartAttemptResponses, AssignmentV1SubmitAttemptData, AssignmentV1SubmitAttemptResponses, AssistantV1ChatMessageData, AssistantV1ChatMessageResponses, AssistantV1DeleteChatData, AssistantV1DeleteChatResponses, AssistantV1GetChatMessagesData, AssistantV1GetChatMessagesResponses, AssistantV1GetChatsData, AssistantV1GetChatsResponses, AssistantV1SaveAssistantNoteData, AssistantV1SaveAssistantNoteResponses, AssistantV1UpdateChatMessageData, AssistantV1UpdateChatMessageResponses, CompetencyV1DeleteCompetencyGoalData, CompetencyV1DeleteCompetencyGoalResponses, CompetencyV1GetCertificateAwardsData, CompetencyV1GetCertificateAwardsResponses, CompetencyV1GetCertificatesData, CompetencyV1GetCertificatesResponses, CompetencyV1GetClassificationSkillsDataData, CompetencyV1GetClassificationSkillsDataResponses, CompetencyV1GetClassificationTreeData, CompetencyV1GetClassificationTreeResponses, CompetencyV1GetCompetencyGoalsData, CompetencyV1GetCompetencyGoalsResponses, CompetencyV1SaveCompetencyGoalData, CompetencyV1SaveCompetencyGoalResponses, ContentV1DeleteMediaWatchData, ContentV1DeleteMediaWatchResponses, ContentV1GetMediaData, ContentV1GetMediaNoteData, ContentV1GetMediaNoteResponses, ContentV1GetMediaResponses, ContentV1GetMediaWatchData, ContentV1GetMediaWatchResponses, ContentV1GetSubtitlesData, ContentV1GetSubtitlesResponses, ContentV1GetWatchMediasData, ContentV1GetWatchMediasResponses, ContentV1SaveMediaNoteData, ContentV1SaveMediaNoteResponses, ContentV1SearchData, ContentV1SearchResponses, ContentV1SearchSuggestionData, ContentV1SearchSuggestionResponses, ContentV1UpdateMediaWatchData, ContentV1UpdateMediaWatchResponses, CourseV1GetDetailData, CourseV1GetDetailResponses, CourseV1GetSessionData, CourseV1GetSessionResponses, CourseV1RequestCertificateData, CourseV1RequestCertificateResponses, CourseV1StartEngagementData, CourseV1StartEngagementResponses, DiscussionV1CreatePostData, DiscussionV1CreatePostResponses, DiscussionV1DeactivateAttemptData, DiscussionV1DeactivateAttemptResponses, DiscussionV1DeletePostData, DiscussionV1DeletePostResponses, DiscussionV1GetOwnPostsData, DiscussionV1GetOwnPostsResponses, DiscussionV1GetPostsData, DiscussionV1GetPostsResponses, DiscussionV1GetSessionData, DiscussionV1GetSessionResponses, DiscussionV1StartAttemptData, DiscussionV1StartAttemptResponses, DiscussionV1UpdatePostData, DiscussionV1UpdatePostResponses, ExamV1DeactivateAttemptData, ExamV1DeactivateAttemptResponses, ExamV1GetSessionData, ExamV1GetSessionResponses, ExamV1GetTimestampData, ExamV1GetTimestampResponses, ExamV1SaveAnswersData, ExamV1SaveAnswersResponses, ExamV1StartAttemptData, ExamV1StartAttemptResponses, ExamV1SubmitAttemptData, ExamV1SubmitAttemptResponses, LearningV1EnrollCatalogItemData, LearningV1EnrollCatalogItemResponses, LearningV1GetCatalogItemsData, LearningV1GetCatalogItemsResponses, LearningV1GetCatalogsData, LearningV1GetCatalogsResponses, LearningV1GetEnrolledData, LearningV1GetEnrolledResponses, LearningV1GetRecordsData, LearningV1GetRecordsResponses, LearningV1GetReportData, LearningV1GetReportResponses, LearningV1UnenrollData, LearningV1UnenrollResponses, MinimaApiHealthData, MinimaApiHealthResponses, OperationV1AgreePoliciesData, OperationV1AgreePoliciesResponses, OperationV1CreateAppealData, OperationV1CreateAppealResponses, OperationV1CreateInquiryData, OperationV1CreateInquiryResponses, OperationV1CreateThreadData, OperationV1CreateThreadResponses, OperationV1DeleteCommentData, OperationV1DeleteCommentResponses, OperationV1DeleteDeviceData, OperationV1DeleteDeviceResponses, OperationV1EffectivePoliciesData, OperationV1EffectivePoliciesResponses, OperationV1GetAnnouncementsData, OperationV1GetAnnouncementsResponses, OperationV1GetCommentsData, OperationV1GetCommentsResponses, OperationV1GetDevicesData, OperationV1GetDevicesResponses, OperationV1GetInquiriesData, OperationV1GetInquiriesResponses, OperationV1GetThreadCommentsData, OperationV1GetThreadCommentsResponses, OperationV1GetThreadData, OperationV1GetThreadResponses, OperationV1GetUnreadMessagesData, OperationV1GetUnreadMessagesResponses, OperationV1ReadAnnouncementData, OperationV1ReadAnnouncementResponses, OperationV1ReadMessageData, OperationV1ReadMessageResponses, OperationV1RegisterDeviceData, OperationV1RegisterDeviceResponses, OperationV1SaveCommentData, OperationV1SaveCommentResponses, OperationV1ToggleDeviceActiveData, OperationV1ToggleDeviceActiveResponses, OperationV1UpdateInquiryData, OperationV1UpdateInquiryResponses, PartnerV1MemberInfosData, PartnerV1MemberInfosResponses, QuizV1DeactivateAttemptData, QuizV1DeactivateAttemptResponses, QuizV1GetSessionData, QuizV1GetSessionResponses, QuizV1StartAttemptData, QuizV1StartAttemptResponses, QuizV1SubmitAttemptData, QuizV1SubmitAttemptResponses, SsoV1AuthorizeData, SsoV1AuthorizeResponses, SsoV1CallbackData, SsoV1CallbackResponses, SsoV1DeleteAccountData, SsoV1DeleteAccountResponses, SsoV1GetAccountsData, SsoV1GetAccountsResponses, SsoV1LinkData, SsoV1LinkResponses, StudioV1AssessmentSuggestionsData, StudioV1AssessmentSuggestionsResponses, StudioV1ContentData, StudioV1ContentResponses, StudioV1ContentSuggestionsData, StudioV1ContentSuggestionsResponses, StudioV1CreateMediaQuizData, StudioV1CreateMediaQuizResponses, StudioV1DeleteAssignmentQuesionData, StudioV1DeleteAssignmentQuesionResponses, StudioV1DeleteDiscussionQuesionData, StudioV1DeleteDiscussionQuesionResponses, StudioV1DeleteExamQuesionData, StudioV1DeleteExamQuesionResponses, StudioV1DeleteMediaSubtitleData, StudioV1DeleteMediaSubtitleResponses, StudioV1DeleteQuizQuesionData, StudioV1DeleteQuizQuesionResponses, StudioV1DeleteSurveyQuesionData, StudioV1DeleteSurveyQuesionResponses, StudioV1GetAssignmentData, StudioV1GetAssignmentQuestionsData, StudioV1GetAssignmentQuestionsResponses, StudioV1GetAssignmentResponses, StudioV1GetCourseData, StudioV1GetCourseResponses, StudioV1GetDiscussionData, StudioV1GetDiscussionQuestionsData, StudioV1GetDiscussionQuestionsResponses, StudioV1GetDiscussionResponses, StudioV1GetExamData, StudioV1GetExamQuestionsData, StudioV1GetExamQuestionsResponses, StudioV1GetExamResponses, StudioV1GetMediaData, StudioV1GetMediaResponses, StudioV1GetQuizData, StudioV1GetQuizQuestionsData, StudioV1GetQuizQuestionsResponses, StudioV1GetQuizResponses, StudioV1GetSurveyData, StudioV1GetSurveyQuestionsData, StudioV1GetSurveyQuestionsResponses, StudioV1GetSurveyResponses, StudioV1InlineSuggestionsData, StudioV1InlineSuggestionsResponses, StudioV1RemoveCourseAssessmentData, StudioV1RemoveCourseAssessmentResponses, StudioV1RemoveCourseCategoryData, StudioV1RemoveCourseCategoryResponses, StudioV1RemoveCourseCertificateData, StudioV1RemoveCourseCertificateResponses, StudioV1RemoveCourseInstructorData, StudioV1RemoveCourseInstructorResponses, StudioV1RemoveCourseLessonData, StudioV1RemoveCourseLessonResponses, StudioV1RemoveCourseRelationData, StudioV1RemoveCourseRelationResponses, StudioV1RemoveCourseSurveyData, StudioV1RemoveCourseSurveyResponses, StudioV1SaveAssignmentData, StudioV1SaveAssignmentQuestionData, StudioV1SaveAssignmentQuestionResponses, StudioV1SaveAssignmentResponses, StudioV1SaveCourseAssessmentsData, StudioV1SaveCourseAssessmentsResponses, StudioV1SaveCourseCategoriesData, StudioV1SaveCourseCategoriesResponses, StudioV1SaveCourseCertificatesData, StudioV1SaveCourseCertificatesResponses, StudioV1SaveCourseData, StudioV1SaveCourseInstructorsData, StudioV1SaveCourseInstructorsResponses, StudioV1SaveCourseLessonsData, StudioV1SaveCourseLessonsResponses, StudioV1SaveCourseRelationsData, StudioV1SaveCourseRelationsResponses, StudioV1SaveCourseResponses, StudioV1SaveCourseSurveysData, StudioV1SaveCourseSurveysResponses, StudioV1SaveDiscussionData, StudioV1SaveDiscussionQuestionData, StudioV1SaveDiscussionQuestionResponses, StudioV1SaveDiscussionResponses, StudioV1SaveExamData, StudioV1SaveExamQuestionsData, StudioV1SaveExamQuestionsResponses, StudioV1SaveExamResponses, StudioV1SaveMediaData, StudioV1SaveMediaResponses, StudioV1SaveMediaSubtitleData, StudioV1SaveMediaSubtitleResponses, StudioV1SaveQuizData, StudioV1SaveQuizQuestionsData, StudioV1SaveQuizQuestionsResponses, StudioV1SaveQuizResponses, StudioV1SaveSurveyData, StudioV1SaveSurveyQuestionsData, StudioV1SaveSurveyQuestionsResponses, StudioV1SaveSurveyResponses, SurveyV1GetAnonymousSurveyData, SurveyV1GetAnonymousSurveyResponses, SurveyV1GetSurveyData, SurveyV1GetSurveyResponses, SurveyV1ResultsAnonymousData, SurveyV1ResultsAnonymousResponses, SurveyV1ResultsData, SurveyV1ResultsResponses, SurveyV1SubmitAnonymousData, SurveyV1SubmitAnonymousResponses, SurveyV1SubmitData, SurveyV1SubmitResponses } from './types.gen'; export type Options = Options2 & { /** @@ -980,15 +980,6 @@ export const studioV1Content = (options?: O ...options }); -/** - * Content Suggestions - */ -export const studioV1ContentSuggestions = (options: Options) => (options.client ?? client).get({ - responseType: 'json', - url: '/api/v1/studio/suggestion/content', - ...options -}); - /** * Assessment Suggestions */ @@ -999,47 +990,20 @@ export const studioV1AssessmentSuggestions = (options?: Options) => (options?.client ?? client).get({ - responseType: 'json', - url: '/api/v1/studio/suggestion/certificate', - ...options -}); - -/** - * Category Suggestions - */ -export const studioV1CategorySuggestions = (options?: Options) => (options?.client ?? client).get({ - responseType: 'json', - url: '/api/v1/studio/suggestion/category', - ...options -}); - -/** - * Instructor Suggestions - */ -export const studioV1InstructorSuggestions = (options?: Options) => (options?.client ?? client).get({ - responseType: 'json', - url: '/api/v1/studio/suggestion/instructor', - ...options -}); - -/** - * Faq Suggestions + * Content Suggestions */ -export const studioV1FaqSuggestions = (options?: Options) => (options?.client ?? client).get({ +export const studioV1ContentSuggestions = (options: Options) => (options.client ?? client).get({ responseType: 'json', - url: '/api/v1/studio/suggestion/faq', + url: '/api/v1/studio/suggestion/content', ...options }); /** - * Get Faq Items + * Inline Suggestions */ -export const studioV1GetFaqItems = (options: Options) => (options.client ?? client).get({ +export const studioV1InlineSuggestions = (options: Options) => (options.client ?? client).get({ responseType: 'json', - url: '/api/v1/studio/faq/{id}/item', + url: '/api/v1/studio/suggestion/inline', ...options }); @@ -1066,6 +1030,15 @@ export const studioV1SaveExam = (options: O } }); +/** + * Get Exam Questions + */ +export const studioV1GetExamQuestions = (options: Options) => (options.client ?? client).get({ + responseType: 'json', + url: '/api/v1/studio/exam/{id}/question', + ...options +}); + /** * Save Exam Questions */ @@ -1108,6 +1081,15 @@ export const studioV1SaveQuiz = (options: O } }); +/** + * Get Quiz Questions + */ +export const studioV1GetQuizQuestions = (options: Options) => (options.client ?? client).get({ + responseType: 'json', + url: '/api/v1/studio/quiz/{id}/question', + ...options +}); + /** * Save Quiz Questions */ @@ -1150,6 +1132,15 @@ export const studioV1SaveSurvey = (options: } }); +/** + * Get Survey Questions + */ +export const studioV1GetSurveyQuestions = (options: Options) => (options.client ?? client).get({ + responseType: 'json', + url: '/api/v1/studio/survey/{id}/question', + ...options +}); + /** * Save Survey Questions */ @@ -1192,6 +1183,15 @@ export const studioV1SaveDiscussion = (opti } }); +/** + * Get Discussion Questions + */ +export const studioV1GetDiscussionQuestions = (options: Options) => (options.client ?? client).get({ + responseType: 'json', + url: '/api/v1/studio/discussion/{id}/question', + ...options +}); + /** * Save Discussion Question */ @@ -1234,6 +1234,15 @@ export const studioV1SaveAssignment = (opti } }); +/** + * Get Assignment Questions + */ +export const studioV1GetAssignmentQuestions = (options: Options) => (options.client ?? client).get({ + responseType: 'json', + url: '/api/v1/studio/assignment/{id}/question', + ...options +}); + /** * Save Assignment Question */ @@ -1451,24 +1460,6 @@ export const studioV1SaveCourseInstructors = (options: Options) => (options.client ?? client).delete({ url: '/api/v1/studio/course/{id}/instructor/{course_instructor_id}', ...options }); -/** - * Save Course Faq Items - */ -export const studioV1SaveCourseFaqItems = (options: Options) => (options.client ?? client).post({ - responseType: 'json', - url: '/api/v1/studio/course/{id}/faqitem', - ...options, - headers: { - 'Content-Type': 'application/json', - ...options.headers - } -}); - -/** - * Remove Course Faq Item - */ -export const studioV1RemoveCourseFaqItem = (options: Options) => (options.client ?? client).delete({ url: '/api/v1/studio/course/{id}/faqitem/{faq_item_id}', ...options }); - /** * Get Survey */ diff --git a/web/src/api/types.gen.ts b/web/src/api/types.gen.ts index 892358b..50d6d93 100644 --- a/web/src/api/types.gen.ts +++ b/web/src/api/types.gen.ts @@ -4599,116 +4599,52 @@ export type StudioContentSpec = { }; /** - * ContentSuggestionSpec - */ -export type ContentSuggestionSpec = { - /** - * Id - */ - id: string; - /** - * Title - */ - title: string; -}; - -/** - * AssessmentSuggestion + * AssessmentSuggestionSpec */ -export type AssessmentSuggestion = { +export type AssessmentSuggestionSpec = { /** * Id */ id: string; /** - * Title + * Label */ - title: string; + label: string; itemType: ContentTypeSchema; }; /** - * CertificateSuggestionSpec - */ -export type CertificateSuggestionSpec = { - /** - * Id - */ - id: number; - /** - * Name - */ - name: string; -}; - -/** - * CategorySuggestionSpec - */ -export type CategorySuggestionSpec = { - /** - * Id - */ - id: number; - /** - * Fullpath - */ - fullPath: string; -}; - -/** - * InstructorSuggestionSpec + * ContentSuggestionSpec */ -export type InstructorSuggestionSpec = { +export type ContentSuggestionSpec = { /** * Id */ - id: number; + id: string; /** - * Name + * Label */ - name: string; + label: string; }; /** - * FAQSuggestionSpec + * InlineSuggestionSpec */ -export type FaqSuggestionSpec = { +export type InlineSuggestionSpec = { /** * Id */ id: number; /** - * Name - */ - name: string; -}; - -/** - * FAQItemCopySpec - */ -export type FaqItemCopySpec = { - /** - * Question - */ - question: string; - /** - * Answer - */ - answer: string; - /** - * Active + * Label */ - active: boolean; + label: string; }; /** * ExamQuestionPoolSpec */ export type ExamQuestionPoolSpec = { - /** - * Description - */ - description: string; /** * Composition */ @@ -4840,23 +4776,12 @@ export type ExamSpec = { * Id */ id: string; - honorCode: HonorCodeSpec; - questionPool: ExamQuestionPoolSpec; - questions: ExamQuestionsSpec; -}; - -/** - * HonorCodeSpec - */ -export type HonorCodeSpec = { /** - * Title + * Honorcodeid */ - title: string; - /** - * Code - */ - code: string; + honorCodeId: number; + questionPool: ExamQuestionPoolSpec; + questions: ExamQuestionsSpec; }; /** @@ -4911,7 +4836,10 @@ export type ExamSaveSpec = { * Confirmduedays */ confirmDueDays: number; - honorCode: HonorCodeSpec; + /** + * Honorcodeid + */ + honorCodeId: number; questionPool: ExamQuestionPoolSpec; }; @@ -4922,7 +4850,7 @@ export type ExamQuestionSaveSpec = { /** * Id */ - id: number; + id?: number; format: ExamQuestionFormatChoices; /** * Question @@ -4957,10 +4885,6 @@ export type ExamQuestionsSaveSpec = { * QuizQuestionPoolSpec */ export type QuizQuestionPoolSpec = { - /** - * Description - */ - description: string; /** * Selectcount */ @@ -5119,7 +5043,7 @@ export type QuizQuestionSaveSpec = { /** * Id */ - id: number; + id?: number; /** * Question */ @@ -5154,16 +5078,6 @@ export type QuizQuestionsSaveSpec = { */ export type SurveyQuestionFormatChoices = 'single_choice' | 'text_input' | 'number_input'; -/** - * SurveyQuestionPoolSpec - */ -export type SurveyQuestionPoolSpec = { - /** - * Description - */ - description: string; -}; - /** * SurveyQuestionSpec */ @@ -5260,7 +5174,6 @@ export type SurveySpec = { * Id */ id: string; - questionPool: SurveyQuestionPoolSpec; questions: SurveyQuestionsSpec; /** * Completemessage @@ -5300,7 +5213,6 @@ export type SurveySaveSpec = { * Featured */ featured: boolean; - questionPool: SurveyQuestionPoolSpec; /** * Completemessage */ @@ -5322,7 +5234,7 @@ export type SurveyQuestionSaveSpec = { /** * Id */ - id: number; + id?: number; format: SurveyQuestionFormatChoices; /** * Question @@ -5356,16 +5268,6 @@ export type SurveyQuestionsSaveSpec = { data: Array; }; -/** - * DiscussionQuestionPoolSpec - */ -export type DiscussionQuestionPoolSpec = { - /** - * Description - */ - description: string; -}; - /** * DiscussionQuestionSpec */ @@ -5481,8 +5383,10 @@ export type DiscussionSpec = { * Id */ id: string; - honorCode: HonorCodeSpec; - questionPool: DiscussionQuestionPoolSpec; + /** + * Honorcodeid + */ + honorCodeId: number; questions: DiscussionQuestionsSpec; }; @@ -5534,8 +5438,10 @@ export type DiscussionSaveSpec = { * Confirmduedays */ confirmDueDays: number; - honorCode: HonorCodeSpec; - questionPool: DiscussionQuestionPoolSpec; + /** + * Honorcodeid + */ + honorCodeId: number; }; /** @@ -5545,7 +5451,7 @@ export type DiscussionQuestionSaveSpec = { /** * Id */ - id: number; + id?: number; /** * Directive */ @@ -5577,13 +5483,13 @@ export type DiscussionQuestionSaveSpec = { }; /** - * AssignmentQuestionPoolSpec + * DiscussionQuestionsSaveSpec */ -export type AssignmentQuestionPoolSpec = { +export type DiscussionQuestionsSaveSpec = { /** - * Description + * Data */ - description: string; + data: Array; }; /** @@ -5697,8 +5603,10 @@ export type AssignmentSpec = { * Id */ id: string; - honorCode: HonorCodeSpec; - questionPool: AssignmentQuestionPoolSpec; + /** + * Honorcodeid + */ + honorCodeId: number; questions: AssignmentQuestionsSpec; }; @@ -5750,8 +5658,10 @@ export type AssignmentSaveSpec = { * Confirmduedays */ confirmDueDays: number; - honorCode: HonorCodeSpec; - questionPool: AssignmentQuestionPoolSpec; + /** + * Honorcodeid + */ + honorCodeId: number; }; /** @@ -5761,7 +5671,7 @@ export type AssignmentQuestionSaveSpec = { /** * Id */ - id: number; + id?: number; /** * Question */ @@ -5983,10 +5893,6 @@ export type CourseAssetsSpec = { * Courseinstructors */ courseInstructors: Array; - /** - * Faqitems - */ - faqItems: Array; }; /** @@ -6138,8 +6044,14 @@ export type CourseSpec = { */ effortHours: number; level: LevelChoices; - honorCode: HonorCodeSpec; - faq: FaqSpec; + /** + * Honorcodeid + */ + honorCodeId: number; + /** + * Faqid + */ + faqId: number; gradingPolicy: GradingPolicySpec; assets: CourseAssetsSpec; }; @@ -6170,42 +6082,6 @@ export type CourseSurveySpec = { endOffset: number | null; }; -/** - * FAQItemSpec - */ -export type FaqItemSpec = { - /** - * Id - */ - id: number; - /** - * Question - */ - question: string; - /** - * Answer - */ - answer: string; - /** - * Active - */ - active: boolean; -}; - -/** - * FAQSpec - */ -export type FaqSpec = { - /** - * Name - */ - name: string; - /** - * Description - */ - description: string; -}; - /** * GradingPolicySpec */ @@ -6299,8 +6175,14 @@ export type CourseSaveSpec = { */ effortHours: number; level: LevelChoices; - honorCode: HonorCodeSpec; - faq: FaqSpec; + /** + * Honorcodeid + */ + honorCodeId: number; + /** + * Faqid + */ + faqId: number; gradingPolicy: GradingPolicySpec; }; @@ -6498,33 +6380,6 @@ export type CourseInstructorSaveSpec = { */ export type RootModelListCourseInstructorSaveSpec = Array; -/** - * FAQItemSaveSpec - */ -export type FaqItemSaveSpec = { - /** - * Id - */ - id?: number; - /** - * Question - */ - question: string; - /** - * Answer - */ - answer: string; - /** - * Active - */ - active: boolean; -}; - -/** - * RootModel[list[FAQItemSaveSpec]] - */ -export type RootModelListFaqItemSaveSpec = Array; - /** * SurveyQuestionSchema */ @@ -8980,29 +8835,6 @@ export type StudioV1ContentResponses = { export type StudioV1ContentResponse = StudioV1ContentResponses[keyof StudioV1ContentResponses]; -export type StudioV1ContentSuggestionsData = { - body?: never; - path?: never; - query: { - /** - * Kind - */ - kind: 'exam' | 'survey' | 'quiz' | 'assignment' | 'discussion' | 'media' | 'course'; - }; - url: '/api/v1/studio/suggestion/content'; -}; - -export type StudioV1ContentSuggestionsResponses = { - /** - * Response - * - * OK - */ - 200: Array; -}; - -export type StudioV1ContentSuggestionsResponse = StudioV1ContentSuggestionsResponses[keyof StudioV1ContentSuggestionsResponses]; - export type StudioV1AssessmentSuggestionsData = { body?: never; path?: never; @@ -9016,105 +8848,56 @@ export type StudioV1AssessmentSuggestionsResponses = { * * OK */ - 200: Array; + 200: Array; }; export type StudioV1AssessmentSuggestionsResponse = StudioV1AssessmentSuggestionsResponses[keyof StudioV1AssessmentSuggestionsResponses]; -export type StudioV1CertificateSuggestionsData = { - body?: never; - path?: never; - query?: never; - url: '/api/v1/studio/suggestion/certificate'; -}; - -export type StudioV1CertificateSuggestionsResponses = { - /** - * Response - * - * OK - */ - 200: Array; -}; - -export type StudioV1CertificateSuggestionsResponse = StudioV1CertificateSuggestionsResponses[keyof StudioV1CertificateSuggestionsResponses]; - -export type StudioV1CategorySuggestionsData = { - body?: never; - path?: never; - query?: never; - url: '/api/v1/studio/suggestion/category'; -}; - -export type StudioV1CategorySuggestionsResponses = { - /** - * Response - * - * OK - */ - 200: Array; -}; - -export type StudioV1CategorySuggestionsResponse = StudioV1CategorySuggestionsResponses[keyof StudioV1CategorySuggestionsResponses]; - -export type StudioV1InstructorSuggestionsData = { +export type StudioV1ContentSuggestionsData = { body?: never; path?: never; - query?: never; - url: '/api/v1/studio/suggestion/instructor'; + query: { + /** + * Kind + */ + kind: 'exam' | 'survey' | 'quiz' | 'assignment' | 'discussion' | 'media' | 'course'; + }; + url: '/api/v1/studio/suggestion/content'; }; -export type StudioV1InstructorSuggestionsResponses = { +export type StudioV1ContentSuggestionsResponses = { /** * Response * * OK */ - 200: Array; + 200: Array; }; -export type StudioV1InstructorSuggestionsResponse = StudioV1InstructorSuggestionsResponses[keyof StudioV1InstructorSuggestionsResponses]; +export type StudioV1ContentSuggestionsResponse = StudioV1ContentSuggestionsResponses[keyof StudioV1ContentSuggestionsResponses]; -export type StudioV1FaqSuggestionsData = { +export type StudioV1InlineSuggestionsData = { body?: never; path?: never; - query?: never; - url: '/api/v1/studio/suggestion/faq'; -}; - -export type StudioV1FaqSuggestionsResponses = { - /** - * Response - * - * OK - */ - 200: Array; -}; - -export type StudioV1FaqSuggestionsResponse = StudioV1FaqSuggestionsResponses[keyof StudioV1FaqSuggestionsResponses]; - -export type StudioV1GetFaqItemsData = { - body?: never; - path: { + query: { /** - * Id + * Kind */ - id: number; + kind: 'honor_code' | 'faq' | 'category' | 'instructor' | 'certificate'; }; - query?: never; - url: '/api/v1/studio/faq/{id}/item'; + url: '/api/v1/studio/suggestion/inline'; }; -export type StudioV1GetFaqItemsResponses = { +export type StudioV1InlineSuggestionsResponses = { /** * Response * * OK */ - 200: Array; + 200: Array; }; -export type StudioV1GetFaqItemsResponse = StudioV1GetFaqItemsResponses[keyof StudioV1GetFaqItemsResponses]; +export type StudioV1InlineSuggestionsResponse = StudioV1InlineSuggestionsResponses[keyof StudioV1InlineSuggestionsResponses]; export type StudioV1GetExamData = { body?: never; @@ -9166,6 +8949,29 @@ export type StudioV1SaveExamResponses = { export type StudioV1SaveExamResponse = StudioV1SaveExamResponses[keyof StudioV1SaveExamResponses]; +export type StudioV1GetExamQuestionsData = { + body?: never; + path: { + /** + * Id + */ + id: string; + }; + query?: never; + url: '/api/v1/studio/exam/{id}/question'; +}; + +export type StudioV1GetExamQuestionsResponses = { + /** + * Response + * + * OK + */ + 200: Array; +}; + +export type StudioV1GetExamQuestionsResponse = StudioV1GetExamQuestionsResponses[keyof StudioV1GetExamQuestionsResponses]; + export type StudioV1SaveExamQuestionsData = { /** * MultiPartBodyParams @@ -9273,6 +9079,29 @@ export type StudioV1SaveQuizResponses = { export type StudioV1SaveQuizResponse = StudioV1SaveQuizResponses[keyof StudioV1SaveQuizResponses]; +export type StudioV1GetQuizQuestionsData = { + body?: never; + path: { + /** + * Id + */ + id: string; + }; + query?: never; + url: '/api/v1/studio/quiz/{id}/question'; +}; + +export type StudioV1GetQuizQuestionsResponses = { + /** + * Response + * + * OK + */ + 200: Array; +}; + +export type StudioV1GetQuizQuestionsResponse = StudioV1GetQuizQuestionsResponses[keyof StudioV1GetQuizQuestionsResponses]; + export type StudioV1SaveQuizQuestionsData = { /** * MultiPartBodyParams @@ -9380,6 +9209,29 @@ export type StudioV1SaveSurveyResponses = { export type StudioV1SaveSurveyResponse = StudioV1SaveSurveyResponses[keyof StudioV1SaveSurveyResponses]; +export type StudioV1GetSurveyQuestionsData = { + body?: never; + path: { + /** + * Id + */ + id: string; + }; + query?: never; + url: '/api/v1/studio/survey/{id}/question'; +}; + +export type StudioV1GetSurveyQuestionsResponses = { + /** + * Response + * + * OK + */ + 200: Array; +}; + +export type StudioV1GetSurveyQuestionsResponse = StudioV1GetSurveyQuestionsResponses[keyof StudioV1GetSurveyQuestionsResponses]; + export type StudioV1SaveSurveyQuestionsData = { /** * MultiPartBodyParams @@ -9487,6 +9339,29 @@ export type StudioV1SaveDiscussionResponses = { export type StudioV1SaveDiscussionResponse = StudioV1SaveDiscussionResponses[keyof StudioV1SaveDiscussionResponses]; +export type StudioV1GetDiscussionQuestionsData = { + body?: never; + path: { + /** + * Id + */ + id: string; + }; + query?: never; + url: '/api/v1/studio/discussion/{id}/question'; +}; + +export type StudioV1GetDiscussionQuestionsResponses = { + /** + * Response + * + * OK + */ + 200: Array; +}; + +export type StudioV1GetDiscussionQuestionsResponse = StudioV1GetDiscussionQuestionsResponses[keyof StudioV1GetDiscussionQuestionsResponses]; + export type StudioV1SaveDiscussionQuestionData = { /** * MultiPartBodyParams @@ -9498,7 +9373,7 @@ export type StudioV1SaveDiscussionQuestionData = { * Max size: 3MB */ files?: Array; - data: DiscussionQuestionSaveSpec; + data: DiscussionQuestionsSaveSpec; }; path: { /** @@ -9516,7 +9391,7 @@ export type StudioV1SaveDiscussionQuestionResponses = { * * OK */ - 200: number; + 200: Array; }; export type StudioV1SaveDiscussionQuestionResponse = StudioV1SaveDiscussionQuestionResponses[keyof StudioV1SaveDiscussionQuestionResponses]; @@ -9594,6 +9469,29 @@ export type StudioV1SaveAssignmentResponses = { export type StudioV1SaveAssignmentResponse = StudioV1SaveAssignmentResponses[keyof StudioV1SaveAssignmentResponses]; +export type StudioV1GetAssignmentQuestionsData = { + body?: never; + path: { + /** + * Id + */ + id: string; + }; + query?: never; + url: '/api/v1/studio/assignment/{id}/question'; +}; + +export type StudioV1GetAssignmentQuestionsResponses = { + /** + * Response + * + * OK + */ + 200: Array; +}; + +export type StudioV1GetAssignmentQuestionsResponse = StudioV1GetAssignmentQuestionsResponses[keyof StudioV1GetAssignmentQuestionsResponses]; + export type StudioV1SaveAssignmentQuestionData = { /** * MultiPartBodyParams @@ -10148,52 +10046,6 @@ export type StudioV1RemoveCourseInstructorResponses = { 200: unknown; }; -export type StudioV1SaveCourseFaqItemsData = { - body: RootModelListFaqItemSaveSpec; - path: { - /** - * Id - */ - id: string; - }; - query?: never; - url: '/api/v1/studio/course/{id}/faqitem'; -}; - -export type StudioV1SaveCourseFaqItemsResponses = { - /** - * Response - * - * OK - */ - 200: Array; -}; - -export type StudioV1SaveCourseFaqItemsResponse = StudioV1SaveCourseFaqItemsResponses[keyof StudioV1SaveCourseFaqItemsResponses]; - -export type StudioV1RemoveCourseFaqItemData = { - body?: never; - path: { - /** - * Id - */ - id: string; - /** - * Faq Item Id - */ - faq_item_id: number; - }; - query?: never; - url: '/api/v1/studio/course/{id}/faqitem/{faq_item_id}'; -}; - -export type StudioV1RemoveCourseFaqItemResponses = { - /** - * OK - */ - 200: unknown; -}; - export type SurveyV1GetSurveyData = { body?: never; path: { diff --git a/web/src/api/valibot.gen.ts b/web/src/api/valibot.gen.ts index 529aa53..889621d 100644 --- a/web/src/api/valibot.gen.ts +++ b/web/src/api/valibot.gen.ts @@ -2021,68 +2021,34 @@ export const vPaginatedResponseStudioContentSpec = v.object({ }); /** - * ContentSuggestionSpec - */ -export const vContentSuggestionSpec = v.object({ - id: v.string(), - title: v.string() -}); - -/** - * AssessmentSuggestion + * AssessmentSuggestionSpec */ -export const vAssessmentSuggestion = v.object({ +export const vAssessmentSuggestionSpec = v.object({ id: v.string(), - title: v.string(), + label: v.string(), itemType: vContentTypeSchema }); /** - * CertificateSuggestionSpec - */ -export const vCertificateSuggestionSpec = v.object({ - id: v.pipe(v.number(), v.integer()), - name: v.string() -}); - -/** - * CategorySuggestionSpec - */ -export const vCategorySuggestionSpec = v.object({ - id: v.pipe(v.number(), v.integer()), - fullPath: v.string() -}); - -/** - * InstructorSuggestionSpec + * ContentSuggestionSpec */ -export const vInstructorSuggestionSpec = v.object({ - id: v.pipe(v.number(), v.integer()), - name: v.string() +export const vContentSuggestionSpec = v.object({ + id: v.string(), + label: v.string() }); /** - * FAQSuggestionSpec + * InlineSuggestionSpec */ -export const vFaqSuggestionSpec = v.object({ +export const vInlineSuggestionSpec = v.object({ id: v.pipe(v.number(), v.integer()), - name: v.string() -}); - -/** - * FAQItemCopySpec - */ -export const vFaqItemCopySpec = v.object({ - question: v.string(), - answer: v.string(), - active: v.boolean() + label: v.string() }); /** * ExamQuestionPoolSpec */ export const vExamQuestionPoolSpec = v.object({ - description: v.string(), composition: v.record(v.string(), v.pipe(v.number(), v.integer())) }); @@ -2113,14 +2079,6 @@ export const vExamQuestionSpec = v.object({ */ export const vExamQuestionsSpec = v.array(vExamQuestionSpec); -/** - * HonorCodeSpec - */ -export const vHonorCodeSpec = v.object({ - title: v.string(), - code: v.string() -}); - /** * ExamSpec */ @@ -2142,7 +2100,7 @@ export const vExamSpec = v.object({ verificationRequired: v.boolean(), published: v.nullable(v.pipe(v.string(), v.isoTimestamp())), id: v.string(), - honorCode: vHonorCodeSpec, + honorCodeId: v.pipe(v.number(), v.integer()), questionPool: vExamQuestionPoolSpec, questions: vExamQuestionsSpec }); @@ -2163,7 +2121,7 @@ export const vExamSaveSpec = v.object({ gradeDueDays: v.pipe(v.number(), v.integer()), appealDeadlineDays: v.pipe(v.number(), v.integer()), confirmDueDays: v.pipe(v.number(), v.integer()), - honorCode: vHonorCodeSpec, + honorCodeId: v.pipe(v.number(), v.integer()), questionPool: vExamQuestionPoolSpec }); @@ -2171,7 +2129,7 @@ export const vExamSaveSpec = v.object({ * ExamQuestionSaveSpec */ export const vExamQuestionSaveSpec = v.object({ - id: v.pipe(v.number(), v.integer()), + id: v.optional(v.pipe(v.number(), v.integer())), format: vExamQuestionFormatChoices, question: v.string(), supplement: v.string(), @@ -2191,7 +2149,6 @@ export const vExamQuestionsSaveSpec = v.object({ * QuizQuestionPoolSpec */ export const vQuizQuestionPoolSpec = v.object({ - description: v.string(), selectCount: v.pipe(v.number(), v.integer()) }); @@ -2260,7 +2217,7 @@ export const vQuizSaveSpec = v.object({ * QuizQuestionSaveSpec */ export const vQuizQuestionSaveSpec = v.object({ - id: v.pipe(v.number(), v.integer()), + id: v.optional(v.pipe(v.number(), v.integer())), question: v.string(), supplement: v.string(), options: v.array(v.string()), @@ -2284,13 +2241,6 @@ export const vSurveyQuestionFormatChoices = v.picklist([ 'number_input' ]); -/** - * SurveyQuestionPoolSpec - */ -export const vSurveyQuestionPoolSpec = v.object({ - description: v.string() -}); - /** * SurveyQuestionSpec */ @@ -2327,7 +2277,6 @@ export const vSurveySpec = v.object({ verificationRequired: v.boolean(), published: v.nullable(v.pipe(v.string(), v.isoTimestamp())), id: v.string(), - questionPool: vSurveyQuestionPoolSpec, questions: vSurveyQuestionsSpec, completeMessage: v.string(), anonymous: v.boolean(), @@ -2343,7 +2292,6 @@ export const vSurveySaveSpec = v.object({ description: v.string(), audience: v.string(), featured: v.boolean(), - questionPool: vSurveyQuestionPoolSpec, completeMessage: v.string(), anonymous: v.boolean(), showResults: v.boolean() @@ -2353,7 +2301,7 @@ export const vSurveySaveSpec = v.object({ * SurveyQuestionSaveSpec */ export const vSurveyQuestionSaveSpec = v.object({ - id: v.pipe(v.number(), v.integer()), + id: v.optional(v.pipe(v.number(), v.integer())), format: vSurveyQuestionFormatChoices, question: v.string(), supplement: v.string(), @@ -2369,13 +2317,6 @@ export const vSurveyQuestionsSaveSpec = v.object({ data: v.array(vSurveyQuestionSaveSpec) }); -/** - * DiscussionQuestionPoolSpec - */ -export const vDiscussionQuestionPoolSpec = v.object({ - description: v.string() -}); - /** * DiscussionQuestionSpec */ @@ -2416,8 +2357,7 @@ export const vDiscussionSpec = v.object({ verificationRequired: v.boolean(), published: v.nullable(v.pipe(v.string(), v.isoTimestamp())), id: v.string(), - honorCode: vHonorCodeSpec, - questionPool: vDiscussionQuestionPoolSpec, + honorCodeId: v.pipe(v.number(), v.integer()), questions: vDiscussionQuestionsSpec }); @@ -2436,15 +2376,14 @@ export const vDiscussionSaveSpec = v.object({ gradeDueDays: v.pipe(v.number(), v.integer()), appealDeadlineDays: v.pipe(v.number(), v.integer()), confirmDueDays: v.pipe(v.number(), v.integer()), - honorCode: vHonorCodeSpec, - questionPool: vDiscussionQuestionPoolSpec + honorCodeId: v.pipe(v.number(), v.integer()) }); /** * DiscussionQuestionSaveSpec */ export const vDiscussionQuestionSaveSpec = v.object({ - id: v.pipe(v.number(), v.integer()), + id: v.optional(v.pipe(v.number(), v.integer())), directive: v.string(), supplement: v.string(), postPoint: v.pipe(v.number(), v.integer()), @@ -2455,10 +2394,10 @@ export const vDiscussionQuestionSaveSpec = v.object({ }); /** - * AssignmentQuestionPoolSpec + * DiscussionQuestionsSaveSpec */ -export const vAssignmentQuestionPoolSpec = v.object({ - description: v.string() +export const vDiscussionQuestionsSaveSpec = v.object({ + data: v.array(vDiscussionQuestionSaveSpec) }); /** @@ -2500,8 +2439,7 @@ export const vAssignmentSpec = v.object({ verificationRequired: v.boolean(), published: v.nullable(v.pipe(v.string(), v.isoTimestamp())), id: v.string(), - honorCode: vHonorCodeSpec, - questionPool: vAssignmentQuestionPoolSpec, + honorCodeId: v.pipe(v.number(), v.integer()), questions: vAssignmentQuestionsSpec }); @@ -2520,15 +2458,14 @@ export const vAssignmentSaveSpec = v.object({ gradeDueDays: v.pipe(v.number(), v.integer()), appealDeadlineDays: v.pipe(v.number(), v.integer()), confirmDueDays: v.pipe(v.number(), v.integer()), - honorCode: vHonorCodeSpec, - questionPool: vAssignmentQuestionPoolSpec + honorCodeId: v.pipe(v.number(), v.integer()) }); /** * AssignmentQuestionSaveSpec */ export const vAssignmentQuestionSaveSpec = v.object({ - id: v.pipe(v.number(), v.integer()), + id: v.optional(v.pipe(v.number(), v.integer())), question: v.string(), supplement: v.string(), attachmentFileCount: v.pipe(v.number(), v.integer()), @@ -2646,24 +2583,6 @@ export const vCourseSurveySpec = v.object({ endOffset: v.nullable(v.pipe(v.number(), v.integer())) }); -/** - * FAQItemSpec - */ -export const vFaqItemSpec = v.object({ - id: v.pipe(v.number(), v.integer()), - question: v.string(), - answer: v.string(), - active: v.boolean() -}); - -/** - * FAQSpec - */ -export const vFaqSpec = v.object({ - name: v.string(), - description: v.string() -}); - /** * GradingPolicySpec */ @@ -2694,8 +2613,7 @@ export const vCourseAssetsSpec = v.object({ courseSurveys: v.array(vCourseSurveySpec), courseCertificates: v.array(vCourseCertificateSpec), courseCategories: v.array(vCourseCategorySpec), - courseInstructors: v.array(vCourseInstructorSpec), - faqItems: v.array(vFaqItemSpec) + courseInstructors: v.array(vCourseInstructorSpec) }); /** @@ -2720,8 +2638,8 @@ export const vCourseSpec = v.object({ previewUrl: v.nullable(v.string()), effortHours: v.pipe(v.number(), v.integer()), level: vLevelChoices, - honorCode: vHonorCodeSpec, - faq: vFaqSpec, + honorCodeId: v.pipe(v.number(), v.integer()), + faqId: v.pipe(v.number(), v.integer()), gradingPolicy: vGradingPolicySpec, assets: vCourseAssetsSpec }); @@ -2742,8 +2660,8 @@ export const vCourseSaveSpec = v.object({ previewUrl: v.pipe(v.string(), v.url(), v.minLength(1), v.maxLength(2083)), effortHours: v.pipe(v.number(), v.integer()), level: vLevelChoices, - honorCode: vHonorCodeSpec, - faq: vFaqSpec, + honorCodeId: v.pipe(v.number(), v.integer()), + faqId: v.pipe(v.number(), v.integer()), gradingPolicy: vGradingPolicySpec }); @@ -2854,21 +2772,6 @@ export const vCourseInstructorSaveSpec = v.object({ */ export const vRootModelListCourseInstructorSaveSpec = v.array(vCourseInstructorSaveSpec); -/** - * FAQItemSaveSpec - */ -export const vFaqItemSaveSpec = v.object({ - id: v.optional(v.pipe(v.number(), v.integer())), - question: v.string(), - answer: v.string(), - active: v.boolean() -}); - -/** - * RootModel[list[FAQItemSaveSpec]] - */ -export const vRootModelListFaqItemSaveSpec = v.array(vFaqItemSaveSpec); - /** * SurveyQuestionSchema */ @@ -4198,6 +4101,19 @@ export const vStudioV1ContentData = v.object({ */ export const vStudioV1ContentResponse = vPaginatedResponseStudioContentSpec; +export const vStudioV1AssessmentSuggestionsData = v.object({ + body: v.optional(v.never()), + path: v.optional(v.never()), + query: v.optional(v.never()) +}); + +/** + * Response + * + * OK + */ +export const vStudioV1AssessmentSuggestionsResponse = v.array(vAssessmentSuggestionSpec); + export const vStudioV1ContentSuggestionsData = v.object({ body: v.optional(v.never()), path: v.optional(v.never()), @@ -4221,49 +4137,18 @@ export const vStudioV1ContentSuggestionsData = v.object({ */ export const vStudioV1ContentSuggestionsResponse = v.array(vContentSuggestionSpec); -export const vStudioV1AssessmentSuggestionsData = v.object({ - body: v.optional(v.never()), - path: v.optional(v.never()), - query: v.optional(v.never()) -}); - -/** - * Response - * - * OK - */ -export const vStudioV1AssessmentSuggestionsResponse = v.array(vAssessmentSuggestion); - -export const vStudioV1CertificateSuggestionsData = v.object({ - body: v.optional(v.never()), - path: v.optional(v.never()), - query: v.optional(v.never()) -}); - -/** - * Response - * - * OK - */ -export const vStudioV1CertificateSuggestionsResponse = v.array(vCertificateSuggestionSpec); - -export const vStudioV1CategorySuggestionsData = v.object({ +export const vStudioV1InlineSuggestionsData = v.object({ body: v.optional(v.never()), path: v.optional(v.never()), - query: v.optional(v.never()) -}); - -/** - * Response - * - * OK - */ -export const vStudioV1CategorySuggestionsResponse = v.array(vCategorySuggestionSpec); - -export const vStudioV1InstructorSuggestionsData = v.object({ - body: v.optional(v.never()), - path: v.optional(v.never()), - query: v.optional(v.never()) + query: v.object({ + kind: v.picklist([ + 'honor_code', + 'faq', + 'category', + 'instructor', + 'certificate' + ]) + }) }); /** @@ -4271,26 +4156,27 @@ export const vStudioV1InstructorSuggestionsData = v.object({ * * OK */ -export const vStudioV1InstructorSuggestionsResponse = v.array(vInstructorSuggestionSpec); +export const vStudioV1InlineSuggestionsResponse = v.array(vInlineSuggestionSpec); -export const vStudioV1FaqSuggestionsData = v.object({ +export const vStudioV1GetExamData = v.object({ body: v.optional(v.never()), - path: v.optional(v.never()), + path: v.object({ + id: v.string() + }), query: v.optional(v.never()) }); /** - * Response - * * OK */ -export const vStudioV1FaqSuggestionsResponse = v.array(vFaqSuggestionSpec); +export const vStudioV1GetExamResponse = vExamSpec; -export const vStudioV1GetFaqItemsData = v.object({ - body: v.optional(v.never()), - path: v.object({ - id: v.pipe(v.number(), v.integer()) +export const vStudioV1SaveExamData = v.object({ + body: v.object({ + thumbnail: v.optional(v.string()), + data: vExamSaveSpec }), + path: v.optional(v.never()), query: v.optional(v.never()) }); @@ -4299,9 +4185,9 @@ export const vStudioV1GetFaqItemsData = v.object({ * * OK */ -export const vStudioV1GetFaqItemsResponse = v.array(vFaqItemCopySpec); +export const vStudioV1SaveExamResponse = v.string(); -export const vStudioV1GetExamData = v.object({ +export const vStudioV1GetExamQuestionsData = v.object({ body: v.optional(v.never()), path: v.object({ id: v.string() @@ -4309,26 +4195,12 @@ export const vStudioV1GetExamData = v.object({ query: v.optional(v.never()) }); -/** - * OK - */ -export const vStudioV1GetExamResponse = vExamSpec; - -export const vStudioV1SaveExamData = v.object({ - body: v.object({ - thumbnail: v.optional(v.string()), - data: vExamSaveSpec - }), - path: v.optional(v.never()), - query: v.optional(v.never()) -}); - /** * Response * * OK */ -export const vStudioV1SaveExamResponse = v.string(); +export const vStudioV1GetExamQuestionsResponse = v.array(vExamQuestionSpec); export const vStudioV1SaveExamQuestionsData = v.object({ body: v.object({ @@ -4386,6 +4258,21 @@ export const vStudioV1SaveQuizData = v.object({ */ export const vStudioV1SaveQuizResponse = v.string(); +export const vStudioV1GetQuizQuestionsData = v.object({ + body: v.optional(v.never()), + path: v.object({ + id: v.string() + }), + query: v.optional(v.never()) +}); + +/** + * Response + * + * OK + */ +export const vStudioV1GetQuizQuestionsResponse = v.array(vQuizQuestionSpec); + export const vStudioV1SaveQuizQuestionsData = v.object({ body: v.object({ files: v.optional(v.array(v.string())), @@ -4442,6 +4329,21 @@ export const vStudioV1SaveSurveyData = v.object({ */ export const vStudioV1SaveSurveyResponse = v.string(); +export const vStudioV1GetSurveyQuestionsData = v.object({ + body: v.optional(v.never()), + path: v.object({ + id: v.string() + }), + query: v.optional(v.never()) +}); + +/** + * Response + * + * OK + */ +export const vStudioV1GetSurveyQuestionsResponse = v.array(vSurveyQuestionSpec); + export const vStudioV1SaveSurveyQuestionsData = v.object({ body: v.object({ files: v.optional(v.array(v.string())), @@ -4498,10 +4400,25 @@ export const vStudioV1SaveDiscussionData = v.object({ */ export const vStudioV1SaveDiscussionResponse = v.string(); +export const vStudioV1GetDiscussionQuestionsData = v.object({ + body: v.optional(v.never()), + path: v.object({ + id: v.string() + }), + query: v.optional(v.never()) +}); + +/** + * Response + * + * OK + */ +export const vStudioV1GetDiscussionQuestionsResponse = v.array(vDiscussionQuestionSpec); + export const vStudioV1SaveDiscussionQuestionData = v.object({ body: v.object({ files: v.optional(v.array(v.string())), - data: vDiscussionQuestionSaveSpec + data: vDiscussionQuestionsSaveSpec }), path: v.object({ id: v.string() @@ -4514,7 +4431,7 @@ export const vStudioV1SaveDiscussionQuestionData = v.object({ * * OK */ -export const vStudioV1SaveDiscussionQuestionResponse = v.pipe(v.number(), v.integer()); +export const vStudioV1SaveDiscussionQuestionResponse = v.array(v.pipe(v.number(), v.integer())); export const vStudioV1DeleteDiscussionQuesionData = v.object({ body: v.optional(v.never()), @@ -4554,6 +4471,21 @@ export const vStudioV1SaveAssignmentData = v.object({ */ export const vStudioV1SaveAssignmentResponse = v.string(); +export const vStudioV1GetAssignmentQuestionsData = v.object({ + body: v.optional(v.never()), + path: v.object({ + id: v.string() + }), + query: v.optional(v.never()) +}); + +/** + * Response + * + * OK + */ +export const vStudioV1GetAssignmentQuestionsResponse = v.array(vAssignmentQuestionSpec); + export const vStudioV1SaveAssignmentQuestionData = v.object({ body: v.object({ files: v.optional(v.array(v.string())), @@ -4841,30 +4773,6 @@ export const vStudioV1RemoveCourseInstructorData = v.object({ query: v.optional(v.never()) }); -export const vStudioV1SaveCourseFaqItemsData = v.object({ - body: vRootModelListFaqItemSaveSpec, - path: v.object({ - id: v.string() - }), - query: v.optional(v.never()) -}); - -/** - * Response - * - * OK - */ -export const vStudioV1SaveCourseFaqItemsResponse = v.array(v.pipe(v.number(), v.integer())); - -export const vStudioV1RemoveCourseFaqItemData = v.object({ - body: v.optional(v.never()), - path: v.object({ - id: v.string(), - faq_item_id: v.pipe(v.number(), v.integer()) - }), - query: v.optional(v.never()) -}); - export const vSurveyV1GetSurveyData = v.object({ body: v.optional(v.never()), path: v.object({ diff --git a/web/src/routes/(app)/-shared/goal/CategorySelect.tsx b/web/src/routes/(app)/-shared/goal/CategorySelect.tsx index 8e9cbe9..7d4364d 100644 --- a/web/src/routes/(app)/-shared/goal/CategorySelect.tsx +++ b/web/src/routes/(app)/-shared/goal/CategorySelect.tsx @@ -148,7 +148,6 @@ export const CategorySelect = (props: Props) => { dropdownClass="bg-base-200! max-h-64 overflow-y-auto flex-nowrap" inputClass="w-full" selectFirstOnCommit - suggestionCount={20} /> diff --git a/web/src/routes/(app)/course/-session/Outline.tsx b/web/src/routes/(app)/course/-session/Outline.tsx index e62fe4c..e666c1d 100644 --- a/web/src/routes/(app)/course/-session/Outline.tsx +++ b/web/src/routes/(app)/course/-session/Outline.tsx @@ -32,6 +32,7 @@ export const Outline = () => { ].sort((a, b) => { const dateCompare = new Date(a.startDate).getTime() - new Date(b.startDate).getTime() if (dateCompare !== 0) return dateCompare + if (a.type === 'lesson' && b.type === 'lesson') return a.number - b.number return a.type === 'lesson' ? -1 : 1 }) diff --git a/web/src/routes/(app)/dashboard/learning.tsx b/web/src/routes/(app)/dashboard/learning.tsx index 4196366..66ead9a 100644 --- a/web/src/routes/(app)/dashboard/learning.tsx +++ b/web/src/routes/(app)/dashboard/learning.tsx @@ -215,7 +215,7 @@ const ContentCard = (props: ContentCardProps) => {