From 36790172712156a27eead03cd76e2205a25d2ae0 Mon Sep 17 00:00:00 2001 From: Jonas Sander <29028262+Jonas-Sander@users.noreply.github.com> Date: Wed, 31 Jul 2024 17:57:09 +0200 Subject: [PATCH] Rework homework page for teacher and parents (#1644) This reworks the homework page for teachers and parents in a way that is very similar to the current student page. Small difference: There is no overflow button in the bottom action bar (overflow is used by students where they can select "mark all overdue homeworks as completed") I also added the `firebase_hausaufgabenheft_logik` into the `hausaufgabenheft_logik`, since I don't really see that much benefit to separate it. | Parents | Teacher | |--------|--------| | ![image](https://github.com/user-attachments/assets/3c40814a-c568-4a04-bcb2-50a29e390943) | ![image](https://github.com/user-attachments/assets/7ff7b38a-a5d9-4ca7-9969-03c69b30a3c7) | | ![image](https://github.com/user-attachments/assets/8dfbd5bd-d9ea-44ed-b638-67f15f12a346) | ![image](https://github.com/user-attachments/assets/7ba21a86-b00b-4c29-a5ae-f96d048086e9) | --- app/lib/dashboard/bloc/dashboard_bloc.dart | 2 +- app/lib/dashboard/dashboard_page.dart | 2 +- app/lib/dashboard/models/homework_view.dart | 3 +- .../homework_details/homework_details.dart | 7 +- .../homework_details_view.dart | 3 +- .../homework_details_view_factory.dart | 2 +- .../homework_dialog/homework_dialog.dart | 3 +- .../homework_dialog/homework_dialog_bloc.dart | 3 +- .../homework_dialog/open_homework_dialog.dart | 3 +- app/lib/homework/homework_page.dart | 74 ++ app/lib/homework/homework_page_new.dart | 50 -- app/lib/homework/parent/homework_page.dart | 790 ------------------ .../parent/src/homework_page_bloc.dart | 146 ---- app/lib/homework/shared/delete_homework.dart | 3 +- .../handle_homework_tile_long_press.dart | 41 + .../homework/shared/homework_archived.dart | 161 ---- app/lib/homework/shared/homework_card.dart | 13 +- .../src => shared}/homework_card_bloc.dart | 3 +- app/lib/homework/shared/shared.dart | 1 + .../student/src/completed_homework_list.dart | 8 +- .../src/homework_bottom_action_bar.dart | 89 +- .../homework/student/src/homework_tile.dart | 40 +- .../src/mark_overdue_homework_prompt.dart | 2 +- .../student/src/open_homework_list.dart | 4 +- app/lib/homework/student/src/util.dart | 2 +- .../student/student_homework_page.dart | 14 +- .../teacher_homework_bottom_action_bar.dart | 98 --- .../homework_completion_user_list_bloc.dart | 3 +- ...ork_completion_user_list_bloc_factory.dart | 3 +- .../homework_completion_user_list_page.dart | 0 .../user_has_completed_homework_view.dart | 0 ...er_and_parent_archived_homework_list.dart} | 14 +- .../teacher_and_parent_homework_tile.dart} | 46 +- ...eacher_and_parent_open_homework_list.dart} | 15 +- .../src/teacher_and_parent_src.dart | 11 + .../teacher_and_parent_homework_page.dart} | 50 +- app/lib/main/sharezone_app.dart | 3 - app/lib/main/sharezone_bloc_providers.dart | 52 +- .../navigation/models/navigation_item.dart | 2 +- .../action_requests/navigate_to_location.dart | 2 +- .../submissions/submission_permissions.dart | 2 +- app/lib/util/api/homework_api.dart | 3 +- app/pubspec.lock | 7 - app/pubspec.yaml | 2 - .../grade_details_page_test.mocks.dart | 10 +- app/test/homework/homework_dialog_test.dart | 2 +- .../homework/homework_dialog_test.mocks.dart | 3 +- ...and_parent_homework_page_widget_test.dart} | 237 +++--- .../support/support_page_test.mocks.dart | 6 +- ...st_calendrical_events_page_test.mocks.dart | 18 +- .../feedback_history_page_test.mocks.dart | 5 +- .../grade_details_page_test.mocks.dart | 10 +- .../grades_page/grades_page_test.mocks.dart | 6 +- .../term_details_page_test.mocks.dart | 10 +- ...mework_completion_user_list_page_test.dart | 8 +- ..._completion_user_list_page_test.mocks.dart | 6 +- .../change_type_of_user_test.mocks.dart | 5 +- .../support/support_page_test.mocks.dart | 6 +- .../sharezone_plus_page_test.mocks.dart | 117 ++- .../erstellung/firestore_abgaben_gateway.dart | 12 +- lib/abgabe/abgabe_client_lib/pubspec.lock | 17 +- lib/abgabe/abgabe_client_lib/pubspec.yaml | 4 +- .../.gitignore | 73 -- lib/firebase_hausaufgabenheft_logik/.metadata | 10 - .../analysis_options.yaml | 9 - .../lib/firebase_hausaufgabenheft_logik.dart | 16 - .../create_default_firestore_repository.dart | 37 - .../src/firestore_completion_dispatcher.dart | 47 -- .../src/firestore_homework_data_source.dart | 55 -- ...re_realtime_completed_homework_loader.dart | 36 - ...ating_lazy_loading_controller_factory.dart | 22 - .../pubspec.lock | 489 ----------- .../pubspec.yaml | 76 -- .../test/in_memory_homework_loader.dart | 27 - lib/hausaufgabenheft_logik/lib/color.dart | 2 +- .../lib/hausaufgabenheft_logik.dart | 29 +- .../lib/hausaufgabenheft_logik_lehrer.dart | 17 +- .../lib/hausaufgabenheft_logik_setup.dart | 9 +- .../completed_homework_list_view_factory.dart | 27 - .../src/data_source/homework_data_source.dart | 48 -- .../firebase_hausaufgabenheft_logik.dart} | 5 +- ...firebase_hausaufgabenheft_logik_setup.dart | 1 - .../src/advanceable_homework_loader.dart} | 5 +- .../create_default_firestore_repository.dart | 36 + .../firebase/src/firestore_student_api.dart | 90 ++ ...teacher_and_parents_homework_page_api.dart | 62 ++ .../lib/src/firebase}/src/homework_dto.dart | 0 .../src/homework_transformation.dart | 52 +- ...time_updating_lazy_loading_controller.dart | 17 +- .../src/teacher_homework_transformation.dart | 102 +++ .../homework_completion_dispatcher.dart | 35 - .../homework_page_completion_dispatcher.dart | 42 - .../lib/src/homework_list_extensions.dart | 42 - .../create_teacher_homework_page_bloc.dart | 17 - .../teacher_archived_homework_list_view.dart | 33 - .../lehrer/teacher_homework_page_bloc.dart | 254 ------ .../lehrer/teacher_homework_read_model.dart | 82 -- .../lib/src/models/homework.dart | 48 -- .../sort_and_subcategorizer.dart | 115 --- .../views/open_homework_list_view.dart | 86 -- .../open_homework_list_view_factory.dart | 47 -- .../src/setup/create_homework_page_bloc.dart | 55 -- .../lib/src/setup/dependencies.dart | 37 - .../lib/src/{views => shared}/color.dart | 0 .../src/shared/homework_list_extensions.dart | 22 + .../lib/src/shared/homework_page_api.dart | 68 ++ .../homework_section_view.dart} | 21 +- .../homework_sorting_cache.dart | 0 .../lazy_loading_homework_list_view.dart} | 19 +- .../lib/src/{ => shared}/models/date.dart | 0 .../lib/src/shared/models/homework.dart | 107 +++ .../models/homework_completion_status.dart | 0 .../lib/src/{ => shared}/models/models.dart | 0 .../lib/src/{ => shared}/models/subject.dart | 2 +- .../lib/src/{ => shared}/models/title.dart | 0 .../lib/src/{ => shared}/setup/config.dart | 0 .../lib/src/shared/setup/dependencies.dart | 24 + .../sort/sorts.dart} | 45 +- .../sort/src/homework_attribute_sorts.dart | 8 +- ...num_sort_object_conversion_extensions.dart | 10 +- .../sort/src/sort.dart | 32 +- .../sort/src/sort_with_operations.dart | 0 .../src/shared/sort_and_subcategorizer.dart | 77 ++ .../bloc}/events.dart | 12 +- .../bloc}/states.dart | 13 +- .../bloc}/student_homework_page_bloc.dart | 63 +- .../create_student_homework_page_bloc.dart | 43 + .../student_homework_list_extensions.dart | 26 + .../views/student_homework_section_view.dart} | 16 +- .../views/student_homework_view.dart} | 2 +- .../views/student_homework_view_factory.dart | 10 +- .../student_open_homework_list_view.dart | 48 ++ ...udent_open_homework_list_view_factory.dart | 53 ++ .../bloc}/events.dart | 11 +- .../bloc}/states.dart | 14 +- ...teacher_and_parent_homework_page_bloc.dart | 140 ++++ ...teacher_and_parent_homework_page_bloc.dart | 42 + ...r_and_parent_homework_list_extensions.dart | 22 + .../teacher_and_parent_homework_view.dart} | 8 +- ...her_and_parent_homework_view_factory.dart} | 14 +- ...er_and_parent_open_homework_list_view.dart | 48 ++ ...arent_open_homework_list_view_factory.dart | 40 + lib/hausaufgabenheft_logik/pubspec.lock | 205 ++++- lib/hausaufgabenheft_logik/pubspec.yaml | 9 + .../test/create_homework_util.dart | 11 +- .../create_student_homework_view_test.dart | 13 +- .../test/date/date_test.dart | 2 +- .../test/homework_list_test.dart | 12 +- .../test/homework_page_bloc_test.dart | 137 +-- .../test/homework_test.dart | 2 +- ...time_updating_lazy_loading_controller.dart | 14 +- .../in_memory_homework_repository.dart | 56 +- .../realtime_completed_homework_loader.dart | 8 +- .../test/lazy_loading_controller_test.dart | 33 +- .../test/subject_test.dart | 4 +- .../test/test_data/homeworks.dart | 2 +- licenses_config.yaml | 1 - 157 files changed, 2200 insertions(+), 3925 deletions(-) create mode 100644 app/lib/homework/homework_page.dart delete mode 100644 app/lib/homework/homework_page_new.dart delete mode 100644 app/lib/homework/parent/homework_page.dart delete mode 100644 app/lib/homework/parent/src/homework_page_bloc.dart create mode 100644 app/lib/homework/shared/handle_homework_tile_long_press.dart delete mode 100644 app/lib/homework/shared/homework_archived.dart rename app/lib/homework/{parent/src => shared}/homework_card_bloc.dart (94%) delete mode 100644 app/lib/homework/teacher/src/teacher_homework_bottom_action_bar.dart rename app/lib/homework/{teacher => teacher_and_parent}/homework_done_by_users_list/homework_completion_user_list_bloc.dart (97%) rename app/lib/homework/{teacher => teacher_and_parent}/homework_done_by_users_list/homework_completion_user_list_bloc_factory.dart (96%) rename app/lib/homework/{teacher => teacher_and_parent}/homework_done_by_users_list/homework_completion_user_list_page.dart (100%) rename app/lib/homework/{teacher => teacher_and_parent}/homework_done_by_users_list/user_has_completed_homework_view.dart (100%) rename app/lib/homework/{teacher/src/teacher_archived_homework_list.dart => teacher_and_parent/src/teacher_and_parent_archived_homework_list.dart} (65%) rename app/lib/homework/{teacher/src/teacher_homework_tile.dart => teacher_and_parent/src/teacher_and_parent_homework_tile.dart} (79%) rename app/lib/homework/{teacher/src/teacher_open_homework_list.dart => teacher_and_parent/src/teacher_and_parent_open_homework_list.dart} (74%) create mode 100644 app/lib/homework/teacher_and_parent/src/teacher_and_parent_src.dart rename app/lib/homework/{teacher/teacher_homework_page.dart => teacher_and_parent/teacher_and_parent_homework_page.dart} (79%) rename app/test/homework/teacher/{teacher_homework_page_widget_test.dart => teacher_and_parent_homework_page_widget_test.dart} (68%) delete mode 100644 lib/firebase_hausaufgabenheft_logik/.gitignore delete mode 100644 lib/firebase_hausaufgabenheft_logik/.metadata delete mode 100644 lib/firebase_hausaufgabenheft_logik/analysis_options.yaml delete mode 100644 lib/firebase_hausaufgabenheft_logik/lib/firebase_hausaufgabenheft_logik.dart delete mode 100644 lib/firebase_hausaufgabenheft_logik/lib/src/create_default_firestore_repository.dart delete mode 100644 lib/firebase_hausaufgabenheft_logik/lib/src/firestore_completion_dispatcher.dart delete mode 100644 lib/firebase_hausaufgabenheft_logik/lib/src/firestore_homework_data_source.dart delete mode 100644 lib/firebase_hausaufgabenheft_logik/lib/src/firestore_realtime_completed_homework_loader.dart delete mode 100644 lib/firebase_hausaufgabenheft_logik/lib/src/realtime_updating_lazy_loading_controller_factory.dart delete mode 100644 lib/firebase_hausaufgabenheft_logik/pubspec.lock delete mode 100644 lib/firebase_hausaufgabenheft_logik/pubspec.yaml delete mode 100644 lib/firebase_hausaufgabenheft_logik/test/in_memory_homework_loader.dart delete mode 100644 lib/hausaufgabenheft_logik/lib/src/completed_homeworks/views/completed_homework_list_view_factory.dart delete mode 100644 lib/hausaufgabenheft_logik/lib/src/data_source/homework_data_source.dart rename lib/hausaufgabenheft_logik/lib/src/{open_homeworks/sort_and_subcategorization/sort/homework_sorts.dart => firebase/firebase_hausaufgabenheft_logik.dart} (67%) rename lib/{firebase_hausaufgabenheft_logik/lib => hausaufgabenheft_logik/lib/src/firebase}/firebase_hausaufgabenheft_logik_setup.dart (85%) rename lib/{firebase_hausaufgabenheft_logik/lib/src/realtime_completed_homework_loader.dart => hausaufgabenheft_logik/lib/src/firebase/src/advanceable_homework_loader.dart} (73%) create mode 100644 lib/hausaufgabenheft_logik/lib/src/firebase/src/create_default_firestore_repository.dart create mode 100644 lib/hausaufgabenheft_logik/lib/src/firebase/src/firestore_student_api.dart create mode 100644 lib/hausaufgabenheft_logik/lib/src/firebase/src/firestore_teacher_and_parents_homework_page_api.dart rename lib/{firebase_hausaufgabenheft_logik/lib => hausaufgabenheft_logik/lib/src/firebase}/src/homework_dto.dart (100%) rename lib/{firebase_hausaufgabenheft_logik/lib => hausaufgabenheft_logik/lib/src/firebase}/src/homework_transformation.dart (61%) rename lib/{firebase_hausaufgabenheft_logik/lib => hausaufgabenheft_logik/lib/src/firebase}/src/realtime_updating_lazy_loading_controller.dart (85%) create mode 100644 lib/hausaufgabenheft_logik/lib/src/firebase/src/teacher_homework_transformation.dart delete mode 100644 lib/hausaufgabenheft_logik/lib/src/homework_completion/homework_completion_dispatcher.dart delete mode 100644 lib/hausaufgabenheft_logik/lib/src/homework_completion/homework_page_completion_dispatcher.dart delete mode 100644 lib/hausaufgabenheft_logik/lib/src/homework_list_extensions.dart delete mode 100644 lib/hausaufgabenheft_logik/lib/src/lehrer/create_teacher_homework_page_bloc.dart delete mode 100644 lib/hausaufgabenheft_logik/lib/src/lehrer/teacher_archived_homework_list_view.dart delete mode 100644 lib/hausaufgabenheft_logik/lib/src/lehrer/teacher_homework_page_bloc.dart delete mode 100644 lib/hausaufgabenheft_logik/lib/src/lehrer/teacher_homework_read_model.dart delete mode 100644 lib/hausaufgabenheft_logik/lib/src/models/homework.dart delete mode 100644 lib/hausaufgabenheft_logik/lib/src/open_homeworks/sort_and_subcategorization/sort_and_subcategorizer.dart delete mode 100644 lib/hausaufgabenheft_logik/lib/src/open_homeworks/views/open_homework_list_view.dart delete mode 100644 lib/hausaufgabenheft_logik/lib/src/open_homeworks/views/open_homework_list_view_factory.dart delete mode 100644 lib/hausaufgabenheft_logik/lib/src/setup/create_homework_page_bloc.dart delete mode 100644 lib/hausaufgabenheft_logik/lib/src/setup/dependencies.dart rename lib/hausaufgabenheft_logik/lib/src/{views => shared}/color.dart (100%) create mode 100644 lib/hausaufgabenheft_logik/lib/src/shared/homework_list_extensions.dart create mode 100644 lib/hausaufgabenheft_logik/lib/src/shared/homework_page_api.dart rename lib/hausaufgabenheft_logik/lib/src/{lehrer/teacher_homework_section_view.dart => shared/homework_section_view.dart} (50%) rename lib/hausaufgabenheft_logik/lib/src/{student_homework_page_bloc => shared}/homework_sorting_cache.dart (100%) rename lib/hausaufgabenheft_logik/lib/src/{completed_homeworks/views/completed_homwork_list_view.dart => shared/lazy_loading_homework_list_view.dart} (52%) rename lib/hausaufgabenheft_logik/lib/src/{ => shared}/models/date.dart (100%) create mode 100644 lib/hausaufgabenheft_logik/lib/src/shared/models/homework.dart rename lib/hausaufgabenheft_logik/lib/src/{ => shared}/models/homework_completion_status.dart (100%) rename lib/hausaufgabenheft_logik/lib/src/{ => shared}/models/models.dart (100%) rename lib/hausaufgabenheft_logik/lib/src/{ => shared}/models/subject.dart (91%) rename lib/hausaufgabenheft_logik/lib/src/{ => shared}/models/title.dart (100%) rename lib/hausaufgabenheft_logik/lib/src/{ => shared}/setup/config.dart (100%) create mode 100644 lib/hausaufgabenheft_logik/lib/src/shared/setup/dependencies.dart rename lib/hausaufgabenheft_logik/lib/src/{lehrer/teacher_open_homework_list_view.dart => shared/sort/sorts.dart} (56%) rename lib/hausaufgabenheft_logik/lib/src/{open_homeworks/sort_and_subcategorization => shared}/sort/src/homework_attribute_sorts.dart (60%) rename lib/hausaufgabenheft_logik/lib/src/{open_homeworks/sort_and_subcategorization => shared}/sort/src/homework_sort_enum_sort_object_conversion_extensions.dart (74%) rename lib/hausaufgabenheft_logik/lib/src/{open_homeworks/sort_and_subcategorization => shared}/sort/src/sort.dart (58%) rename lib/hausaufgabenheft_logik/lib/src/{open_homeworks/sort_and_subcategorization => shared}/sort/src/sort_with_operations.dart (100%) create mode 100644 lib/hausaufgabenheft_logik/lib/src/shared/sort_and_subcategorizer.dart rename lib/hausaufgabenheft_logik/lib/src/{student_homework_page_bloc => student/bloc}/events.dart (83%) rename lib/hausaufgabenheft_logik/lib/src/{student_homework_page_bloc => student/bloc}/states.dart (61%) rename lib/hausaufgabenheft_logik/lib/src/{student_homework_page_bloc => student/bloc}/student_homework_page_bloc.dart (64%) create mode 100644 lib/hausaufgabenheft_logik/lib/src/student/create_student_homework_page_bloc.dart create mode 100644 lib/hausaufgabenheft_logik/lib/src/student/student_homework_list_extensions.dart rename lib/hausaufgabenheft_logik/lib/src/{open_homeworks/views/homework_section_view.dart => student/views/student_homework_section_view.dart} (67%) rename lib/hausaufgabenheft_logik/lib/src/{views/homework_view.dart => student/views/student_homework_view.dart} (97%) rename lib/hausaufgabenheft_logik/lib/src/{ => student}/views/student_homework_view_factory.dart (87%) create mode 100644 lib/hausaufgabenheft_logik/lib/src/student/views/student_open_homework_list_view.dart create mode 100644 lib/hausaufgabenheft_logik/lib/src/student/views/student_open_homework_list_view_factory.dart rename lib/hausaufgabenheft_logik/lib/src/{lehrer => teacher_and_parent/bloc}/events.dart (76%) rename lib/hausaufgabenheft_logik/lib/src/{lehrer => teacher_and_parent/bloc}/states.dart (62%) create mode 100644 lib/hausaufgabenheft_logik/lib/src/teacher_and_parent/bloc/teacher_and_parent_homework_page_bloc.dart create mode 100644 lib/hausaufgabenheft_logik/lib/src/teacher_and_parent/create_teacher_and_parent_homework_page_bloc.dart create mode 100644 lib/hausaufgabenheft_logik/lib/src/teacher_and_parent/teacher_and_parent_homework_list_extensions.dart rename lib/hausaufgabenheft_logik/lib/src/{lehrer/teacher_homework_view.dart => teacher_and_parent/views/teacher_and_parent_homework_view.dart} (94%) rename lib/hausaufgabenheft_logik/lib/src/{lehrer/teacher_homework_view_factory.dart => teacher_and_parent/views/teacher_and_parent_homework_view_factory.dart} (85%) create mode 100644 lib/hausaufgabenheft_logik/lib/src/teacher_and_parent/views/teacher_and_parent_open_homework_list_view.dart create mode 100644 lib/hausaufgabenheft_logik/lib/src/teacher_and_parent/views/teacher_and_parent_open_homework_list_view_factory.dart rename lib/{firebase_hausaufgabenheft_logik => hausaufgabenheft_logik}/test/lazy_loading_controller_test.dart (81%) diff --git a/app/lib/dashboard/bloc/dashboard_bloc.dart b/app/lib/dashboard/bloc/dashboard_bloc.dart index 2ba2f4f79..cd7a20e40 100644 --- a/app/lib/dashboard/bloc/dashboard_bloc.dart +++ b/app/lib/dashboard/bloc/dashboard_bloc.dart @@ -12,8 +12,8 @@ import 'package:bloc_base/bloc_base.dart'; import 'package:clock/clock.dart'; import 'package:date/date.dart'; import 'package:design/design.dart'; -import 'package:firebase_hausaufgabenheft_logik/firebase_hausaufgabenheft_logik.dart'; import 'package:group_domain_models/group_domain_models.dart'; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart' hide Date; import 'package:rxdart/rxdart.dart'; import 'package:sharezone/blackboard/blackboard_item.dart'; import 'package:sharezone/blackboard/blackboard_view.dart'; diff --git a/app/lib/dashboard/dashboard_page.dart b/app/lib/dashboard/dashboard_page.dart index 0c1e8fc61..2a197fa5e 100644 --- a/app/lib/dashboard/dashboard_page.dart +++ b/app/lib/dashboard/dashboard_page.dart @@ -30,7 +30,7 @@ import 'package:sharezone/dashboard/update_reminder/update_reminder_bloc.dart'; import 'package:sharezone/dashboard/widgets/blackboard_card_dashboard.dart'; import 'package:sharezone/download_app_tip/widgets/download_app_tip_card.dart'; import 'package:sharezone/holidays/holiday_bloc.dart'; -import 'package:sharezone/homework/parent/homework_page.dart'; +import 'package:sharezone/homework/homework_page.dart'; import 'package:sharezone/homework/shared/homework_card.dart'; import 'package:sharezone/keys.dart'; import 'package:sharezone/main/application_bloc.dart'; diff --git a/app/lib/dashboard/models/homework_view.dart b/app/lib/dashboard/models/homework_view.dart index 2a6486b57..1acb3fca8 100644 --- a/app/lib/dashboard/models/homework_view.dart +++ b/app/lib/dashboard/models/homework_view.dart @@ -7,9 +7,10 @@ // SPDX-License-Identifier: EUPL-1.2 import 'package:clock/clock.dart'; -import 'package:firebase_hausaufgabenheft_logik/firebase_hausaufgabenheft_logik.dart'; + import 'package:flutter/material.dart'; import 'package:group_domain_models/group_domain_models.dart'; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; import 'package:intl/intl.dart'; import 'package:sharezone/util/api/course_gateway.dart'; diff --git a/app/lib/homework/homework_details/homework_details.dart b/app/lib/homework/homework_details/homework_details.dart index 22efea6c4..6106451ea 100644 --- a/app/lib/homework/homework_details/homework_details.dart +++ b/app/lib/homework/homework_details/homework_details.dart @@ -8,19 +8,20 @@ import 'package:bloc_provider/bloc_provider.dart'; import 'package:common_domain_models/common_domain_models.dart'; -import 'package:firebase_hausaufgabenheft_logik/firebase_hausaufgabenheft_logik.dart'; + import 'package:flutter/material.dart'; import 'package:flutter_markdown/flutter_markdown.dart'; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; import 'package:sharezone/main/application_bloc.dart'; import 'package:sharezone/comments/comments_gateway.dart'; import 'package:sharezone/comments/widgets/comment_section_builder.dart'; import 'package:sharezone/filesharing/dialog/attachment_list.dart'; -import 'package:sharezone/homework/teacher/homework_done_by_users_list/homework_completion_user_list_page.dart'; +import 'package:sharezone/homework/teacher_and_parent/homework_done_by_users_list/homework_completion_user_list_page.dart'; import 'package:sharezone/navigation/logic/navigation_bloc.dart'; import 'package:sharezone/navigation/models/navigation_item.dart'; import 'package:sharezone/homework/homework_details/homework_details_view_factory.dart'; import 'package:sharezone/homework/homework_dialog/homework_dialog.dart'; -import 'package:sharezone/homework/parent/homework_page.dart'; +import 'package:sharezone/homework/homework_page.dart'; import 'package:sharezone/report/report_icon.dart'; import 'package:sharezone/report/report_item.dart'; import 'package:sharezone/submissions/homework_list_submissions_page.dart'; diff --git a/app/lib/homework/homework_details/homework_details_view.dart b/app/lib/homework/homework_details/homework_details_view.dart index 3a7323415..e8f9ee371 100644 --- a/app/lib/homework/homework_details/homework_details_view.dart +++ b/app/lib/homework/homework_details/homework_details_view.dart @@ -7,7 +7,8 @@ // SPDX-License-Identifier: EUPL-1.2 import 'package:filesharing_logic/filesharing_logic_models.dart'; -import 'package:firebase_hausaufgabenheft_logik/firebase_hausaufgabenheft_logik.dart'; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; + import 'package:user/user.dart'; class HomeworkDetailsView { diff --git a/app/lib/homework/homework_details/homework_details_view_factory.dart b/app/lib/homework/homework_details/homework_details_view_factory.dart index d5187896b..15c730fe5 100644 --- a/app/lib/homework/homework_details/homework_details_view_factory.dart +++ b/app/lib/homework/homework_details/homework_details_view_factory.dart @@ -7,7 +7,7 @@ // SPDX-License-Identifier: EUPL-1.2 import 'package:bloc_base/bloc_base.dart'; -import 'package:firebase_hausaufgabenheft_logik/firebase_hausaufgabenheft_logik.dart'; + import 'package:group_domain_models/group_domain_models.dart'; import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; import 'package:intl/intl.dart'; diff --git a/app/lib/homework/homework_dialog/homework_dialog.dart b/app/lib/homework/homework_dialog/homework_dialog.dart index 5e5c8ef33..50736ebab 100644 --- a/app/lib/homework/homework_dialog/homework_dialog.dart +++ b/app/lib/homework/homework_dialog/homework_dialog.dart @@ -19,11 +19,12 @@ import 'package:collection/collection.dart'; import 'package:common_domain_models/common_domain_models.dart'; import 'package:date/date.dart'; import 'package:fast_immutable_collections/fast_immutable_collections.dart'; -import 'package:firebase_hausaufgabenheft_logik/firebase_hausaufgabenheft_logik.dart'; + import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_bloc/flutter_bloc.dart' as bloc_lib show BlocProvider; import 'package:flutter_bloc/flutter_bloc.dart' hide BlocProvider; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart' hide Date; import 'package:platform_check/platform_check.dart'; import 'package:provider/provider.dart'; import 'package:sharezone/filesharing/dialog/attach_file.dart'; diff --git a/app/lib/homework/homework_dialog/homework_dialog_bloc.dart b/app/lib/homework/homework_dialog/homework_dialog_bloc.dart index ada1080c6..9ba682075 100644 --- a/app/lib/homework/homework_dialog/homework_dialog_bloc.dart +++ b/app/lib/homework/homework_dialog/homework_dialog_bloc.dart @@ -18,8 +18,9 @@ import 'package:fast_immutable_collections/fast_immutable_collections.dart'; import 'package:files_basics/files_models.dart'; import 'package:files_basics/local_file.dart'; import 'package:filesharing_logic/filesharing_logic_models.dart'; -import 'package:firebase_hausaufgabenheft_logik/firebase_hausaufgabenheft_logik.dart'; + import 'package:group_domain_models/group_domain_models.dart'; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart' hide Date; import 'package:meta/meta.dart'; import 'package:sharezone/markdown/markdown_analytics.dart'; import 'package:sharezone/util/api.dart'; diff --git a/app/lib/homework/homework_dialog/open_homework_dialog.dart b/app/lib/homework/homework_dialog/open_homework_dialog.dart index b8444c96b..383bbef81 100644 --- a/app/lib/homework/homework_dialog/open_homework_dialog.dart +++ b/app/lib/homework/homework_dialog/open_homework_dialog.dart @@ -6,8 +6,9 @@ // SPDX-License-Identifier: EUPL-1.2 import 'package:common_domain_models/common_domain_models.dart'; -import 'package:firebase_hausaufgabenheft_logik/firebase_hausaufgabenheft_logik.dart'; + import 'package:flutter/material.dart'; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; import 'package:sharezone/homework/homework_dialog/homework_dialog.dart'; import 'package:sharezone_widgets/sharezone_widgets.dart'; diff --git a/app/lib/homework/homework_page.dart b/app/lib/homework/homework_page.dart new file mode 100644 index 000000000..71ef15fac --- /dev/null +++ b/app/lib/homework/homework_page.dart @@ -0,0 +1,74 @@ +// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) +// Licensed under the EUPL-1.2-or-later. +// +// You may obtain a copy of the Licence at: +// https://joinup.ec.europa.eu/software/page/eupl +// +// SPDX-License-Identifier: EUPL-1.2 + +import 'dart:async'; + +import 'package:common_domain_models/common_domain_models.dart'; +import 'package:flutter/material.dart'; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart' + hide StudentHomeworkPageBloc; +import 'package:provider/provider.dart'; +import 'package:sharezone/homework/homework_dialog/homework_dialog.dart'; +import 'package:sharezone_widgets/sharezone_widgets.dart'; +import 'package:user/user.dart'; + +import 'student/student_homework_page.dart'; +import 'teacher_and_parent/teacher_and_parent_homework_page.dart'; + +enum SortBy { date, subject } + +Map sortByAsString = { + SortBy.date: "Datum", + SortBy.subject: "Fach", +}; + +Future openHomeworkDialogAndShowConfirmationIfSuccessful( + BuildContext context, { + HomeworkDto? homework, +}) async { + final successful = await Navigator.push( + context, + IgnoreWillPopScopeWhenIosSwipeBackRoute( + builder: (context) => HomeworkDialog( + id: homework?.id != null ? HomeworkId(homework!.id) : null, + ), + settings: const RouteSettings(name: HomeworkDialog.tag), + ), + ); + if (successful == true && context.mounted) { + await showUserConfirmationOfHomeworkArrival(context: context); + } +} + +Future showUserConfirmationOfHomeworkArrival({ + required BuildContext context, +}) async { + await waitingForPopAnimation(); + if (!context.mounted) return; + showDataArrivalConfirmedSnackbar(context: context); +} + +class HomeworkPage extends StatelessWidget { + const HomeworkPage({super.key}); + static const String tag = 'homework-page'; + + @override + Widget build(BuildContext context) { + final typeOfUser = Provider.of(context); + + switch (typeOfUser) { + case TypeOfUser.student: + return const StudentHomeworkPage(); + case TypeOfUser.teacher: + case TypeOfUser.parent: + return const TeacherAndParentHomeworkPage(); + case TypeOfUser.unknown: + throw UnimplementedError(); + } + } +} diff --git a/app/lib/homework/homework_page_new.dart b/app/lib/homework/homework_page_new.dart deleted file mode 100644 index 3817ac4f9..000000000 --- a/app/lib/homework/homework_page_new.dart +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'package:flutter/material.dart'; -import 'package:sharezone/homework/parent/homework_page.dart'; -import 'package:user/user.dart'; -import 'student/student_homework_page.dart'; -import 'teacher/teacher_homework_page.dart'; - -enum HomeworkPageTypeOfUser { student, parent, teacher } - -HomeworkPageTypeOfUser typeOfUserToHomeworkPageTypeOfUserOrThrow( - TypeOfUser? typeOfUser) { - switch (typeOfUser) { - case TypeOfUser.student: - return HomeworkPageTypeOfUser.student; - case TypeOfUser.teacher: - return HomeworkPageTypeOfUser.teacher; - case TypeOfUser.parent: - return HomeworkPageTypeOfUser.parent; - default: - throw UnimplementedError(); - } -} - -class NewHomeworkPage extends StatelessWidget { - /// Can be converted from [TypeOfUser] via - /// [typeOfUserToHomeworkPageTypeOfUserOrThrow]. - final HomeworkPageTypeOfUser currentUserType; - const NewHomeworkPage({super.key, required this.currentUserType}); - - @override - Widget build(BuildContext context) { - switch (currentUserType) { - case HomeworkPageTypeOfUser.student: - return const StudentHomeworkPage(); - case HomeworkPageTypeOfUser.parent: - return const HomeworkPage(); - case HomeworkPageTypeOfUser.teacher: - return const TeacherHomeworkPage(); - default: - throw UnimplementedError(); - } - } -} diff --git a/app/lib/homework/parent/homework_page.dart b/app/lib/homework/parent/homework_page.dart deleted file mode 100644 index fbf77efb9..000000000 --- a/app/lib/homework/parent/homework_page.dart +++ /dev/null @@ -1,790 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'dart:async'; -import 'dart:developer'; - -import 'package:analytics/analytics.dart'; -import 'package:bloc_provider/bloc_provider.dart'; -import 'package:clock/clock.dart'; -import 'package:common_domain_models/common_domain_models.dart'; -import 'package:firebase_hausaufgabenheft_logik/firebase_hausaufgabenheft_logik.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; -import 'package:sharezone/homework/homework_dialog/homework_dialog.dart'; -import 'package:sharezone/homework/homework_page_new.dart'; -import 'package:sharezone/homework/parent/src/homework_page_bloc.dart'; -import 'package:sharezone/homework/shared/homework_archived.dart'; -import 'package:sharezone/homework/shared/homework_card.dart'; -import 'package:sharezone/main/application_bloc.dart'; -import 'package:sharezone/navigation/logic/navigation_bloc.dart'; -import 'package:sharezone/navigation/models/navigation_item.dart'; -import 'package:sharezone/navigation/scaffold/app_bar_configuration.dart'; -import 'package:sharezone/navigation/scaffold/sharezone_main_scaffold.dart'; -import 'package:sharezone_common/translations.dart'; -import 'package:sharezone_widgets/sharezone_widgets.dart'; -import 'package:user/user.dart'; - -enum SortBy { date, subject } - -Map sortByAsString = { - SortBy.date: "Datum", - SortBy.subject: "Fach", -}; - -Future openHomeworkDialogAndShowConfirmationIfSuccessful( - BuildContext context, { - HomeworkDto? homework, -}) async { - final successful = await Navigator.push( - context, - IgnoreWillPopScopeWhenIosSwipeBackRoute( - builder: (context) => HomeworkDialog( - id: homework?.id != null ? HomeworkId(homework!.id) : null, - ), - settings: const RouteSettings(name: HomeworkDialog.tag), - ), - ); - if (successful == true && context.mounted) { - await showUserConfirmationOfHomeworkArrival(context: context); - } -} - -/// Gibt alle Hausaufgaben zurück, bei welchen das Ablaufdatum nicht schon abgelaufen ist, sprich das -/// Datum entweder heute oder in der Zukunft ist. -List getNotArchived(List homeworkList) { - final List notArchivedHomeworks = []; - for (var homework in homeworkList) { - final int dif = homework.todoUntil.difference(clock.now()).inDays; - if (dif > -1) { - notArchivedHomeworks.add(homework); - } - } - return notArchivedHomeworks; -} - -class HomeworkPage extends StatelessWidget { - const HomeworkPage({super.key}); - static const String tag = 'homework-page'; - - @override - Widget build(BuildContext context) { - final api = BlocProvider.of(context).api; - final typeOfUser = api.user.data?.typeOfUser ?? - TypeOfUser - .student; // PROBLEM: BEIM HOTRELOAD IST MAN DADURCH IMMER EIN SCHÜLER - return _HomeworkPage(typeOfUser: typeOfUser); - } -} - -class _HomeworkPage extends StatefulWidget { - const _HomeworkPage({this.typeOfUser}); - - final TypeOfUser? typeOfUser; - - @override - _HomeworkPageState createState() => _HomeworkPageState(); -} - -class _HomeworkPageState extends State<_HomeworkPage> { - SortBy sortBy = SortBy.date; - - ScrollController? _hideButtonController; - bool _isVisible = true; - bool _isAtEdge = false; - - @override - void initState() { - super.initState(); - _hideButtonController = ScrollController(); - _hideButtonController!.addListener(() { - if (_hideButtonController!.position.pixels != 0 && - _hideButtonController!.position.maxScrollExtent - - _hideButtonController!.position.pixels < - 5) { - _isAtEdge = true; - setState(() { - _isVisible = false; - }); - } else { - if (_isAtEdge) { - _isAtEdge = false; - setState(() { - _isVisible = true; - }); - } - } - }); - } - - @override - Widget build(BuildContext context) { - final bloc = BlocProvider.of(context); - // Placeholder, may be turned to true for local development or might be - // replaced with a feature flag system later. - const newTeacherPageActivated = false; - if (widget.typeOfUser == TypeOfUser.student || - (widget.typeOfUser == TypeOfUser.teacher && newTeacherPageActivated)) { - /// We translate [TypeOfUser] (legacy) to [HomeworkPageTypeOfUser] because - /// [TypeOfUser] has types of users where no homework page exists for - /// (e.g [TypeOfUser.tutor]). - /// NewHomeworkPage only takes the types of users it knows so that there - /// is less cases to test and it is explicit that a normal [TypeOfUser] - /// can't be passed. - return NewHomeworkPage( - currentUserType: - typeOfUserToHomeworkPageTypeOfUserOrThrow(widget.typeOfUser)); - } - return PopScope( - canPop: false, - onPopInvoked: (didPop) { - if (didPop) return; - popToOverview(context); - }, - child: DefaultTabController( - length: 2, - child: SharezoneMainScaffold( - appBarConfiguration: AppBarConfiguration( - actions: [ - _PopupMenu( - onChangedSortBy: (SortBy? changedSortBy) { - if (changedSortBy == null) return; - setState(() => sortBy = changedSortBy); - }, - typeOfUser: widget.typeOfUser, - ) - ], - bottom: widget.typeOfUser == TypeOfUser.student - ? TabBar( - indicatorColor: Theme.of(context).primaryColor, - tabs: [ - // @formatter:off - Tab( - icon: const Icon(Icons.cancel), - text: HomeworkPageMessages.offeneHausaufgaben() - .toUpperCase()), - Tab( - icon: const Icon(Icons.check_circle), - text: HomeworkPageMessages.gemachteHausaufgaben() - .toUpperCase()), - // @formatter:on - ], - ) - : null, - ), - navigationItem: NavigationItem.homework, - // @formatter:off - body: StreamBuilder>( - stream: bloc.homeworkNotDone, - builder: (context, snapshotHomeworkNotDone) { - if (!snapshotHomeworkNotDone.hasData) return Container(); - if (snapshotHomeworkNotDone.hasError) { - return ShowCenteredError( - error: snapshotHomeworkNotDone.error.toString(), - ); - } - return Builder( - builder: (context) { - return StreamBuilder>( - stream: bloc.homeworkDone, - builder: (context, snapshotHomeworkDone) { - log("HomeworkNotDone length: ${snapshotHomeworkNotDone.data?.length ?? 0}"); - if (!snapshotHomeworkDone.hasData) return Container(); - if (snapshotHomeworkDone.hasError) { - return ShowCenteredError( - error: snapshotHomeworkDone.error.toString()); - } - - List? homeworkListNotDone = - snapshotHomeworkNotDone.data; - List? homeworkListDone = - snapshotHomeworkDone.data; - - if (widget.typeOfUser == TypeOfUser.teacher) { - return _TeacherScaffoldBody( - homeworkList: getNotArchived(homeworkListNotDone!), - hideButtonController: _hideButtonController, - sortBy: sortBy, - ); - } - if (widget.typeOfUser == TypeOfUser.parent) { - return _ParentsScaffoldBody( - homeworkList: getNotArchived(homeworkListNotDone!), - hideButtonController: _hideButtonController, - sortBy: sortBy, - ); - } - return _StudentScaffoldBody( - homeworkDoneList: homeworkListDone, - homeworkNotDoneList: homeworkListNotDone, - hideButtonController: _hideButtonController, - sortBy: sortBy, - ); - }, - ); - }, - ); - }), - floatingActionButton: AnimatedSwitcher( - duration: const Duration(milliseconds: 175), - transitionBuilder: (child, animation) => - ScaleTransition(scale: animation, child: child), - child: _isVisible - ? _HomeworkPageFAB(visible: _isVisible) - : const Text(""), - ), - ), - ), - ); - } -} - -class _PopupMenu extends StatelessWidget { - const _PopupMenu({this.onChangedSortBy, this.typeOfUser}); - - final ValueChanged? onChangedSortBy; - final TypeOfUser? typeOfUser; - - void onPopupSortTap({BuildContext? context, SortBy? sortBy}) { - onChangedSortBy!(sortBy); - showSnackSec( - text: "Hausaufgaben werden nach dem ${sortByAsString[sortBy]} sortiert.", - context: context, - ); - } - - @override - Widget build(BuildContext context) { - final analytics = BlocProvider.of(context).analytics; - final bloc = BlocProvider.of(context); - return PopupMenuButton( - onSelected: (String value) async { - switch (value) { - case "AddHomework": - _logHomeworkAddViaPopupMenu(analytics); - openHomeworkDialogAndShowConfirmationIfSuccessful(context); - break; - case "ArchivedHomework": - Navigator.pushNamed(context, HomeworkArchivedPage.tag); - break; - case "SortByDate": - analytics.log(NamedAnalyticsEvent(name: "homework_sort_by_date")); - onPopupSortTap(context: context, sortBy: SortBy.date); - break; - case "SortBySubject": - analytics - .log(NamedAnalyticsEvent(name: "homework_sort_by_subject")); - onPopupSortTap(context: context, sortBy: SortBy.subject); - break; - case "MarkAllOpenHomeworks": - bool? isConfirmed = - await confirmToCheckAllOverdueHomeworkDialog(context); - if (isConfirmed != null && isConfirmed) { - bloc.checkAllOverdueHomeworks(); - if (context.mounted) { - showSnackSec( - context: context, - text: "Alle überfälligen Hausaufgen wurden abgehakt!", - seconds: 2, - ); - } - } - break; - default: - log("Fehler! $value wurde beim PopupMenuButton nicht gefunden!"); - } - }, - itemBuilder: (BuildContext context) { - List> items = >[ - const PopupMenuItem( - value: 'SortByDate', - child: Text("Sortiere nach Datum"), - ), - const PopupMenuItem( - value: 'SortBySubject', - child: Text("Sortiere nach Fach"), - ), - const PopupMenuItem( - value: 'ArchivedHomework', - child: Text("Archivierte Hausaufgaben"), - ), - ]; - if (typeOfUser == TypeOfUser.student) { - items.add(const PopupMenuItem( - value: 'MarkAllOpenHomeworks', - child: Align( - alignment: Alignment.topLeft, - child: Text("Überfällige abhaken")), - )); - } - if (typeOfUser == TypeOfUser.student || - typeOfUser == TypeOfUser.teacher) { - items.add(const PopupMenuItem( - value: 'AddHomework', - child: Text("Hausaufgabe hinzufügen"), - )); - } - return items; - }, - ); - } - - void _logHomeworkAddViaPopupMenu(Analytics analytics) { - analytics.log(NamedAnalyticsEvent(name: "homework_add_via_popup_menu")); - } - - Future confirmToCheckAllOverdueHomeworkDialog(BuildContext context) { - return showLeftRightAdaptiveDialog( - context: context, - defaultValue: false, - content: !ThemePlatform.isCupertino - ? const Text( - "Möchtest du wirklich alle überfälligen Hausaufgaben als erledigt markieren?") - : null, - title: ThemePlatform.isCupertino - ? "Möchtest du wirklich alle überfälligen Hausaufgaben als erledigt markieren?" - : null, - right: const AdaptiveDialogAction( - title: "Ja", - popResult: true, - isDefaultAction: true, - ), - ); - } -} - -class _ParentsScaffoldBody extends StatelessWidget { - const _ParentsScaffoldBody( - {this.homeworkList, this.sortBy, this.hideButtonController}); - - final List? homeworkList; - final SortBy? sortBy; - final ScrollController? hideButtonController; - - @override - Widget build(BuildContext context) { - return _ParentsHomeworkPageView( - homeworkList: homeworkList, - hideButtonController: hideButtonController, - sortBy: sortBy, - ); - } -} - -class _TeacherScaffoldBody extends StatelessWidget { - const _TeacherScaffoldBody( - {this.homeworkList, this.sortBy, this.hideButtonController}); - - final List? homeworkList; - final SortBy? sortBy; - final ScrollController? hideButtonController; - - @override - Widget build(BuildContext context) { - return _TeacherHomeworkPageView( - homeworkList: homeworkList, - hideButtonController: hideButtonController, - sortBy: sortBy, - ); - } -} - -class _StudentScaffoldBody extends StatelessWidget { - const _StudentScaffoldBody({ - required this.homeworkDoneList, - required this.homeworkNotDoneList, - this.hideButtonController, - this.sortBy, - }); - - final List? homeworkDoneList; - final List? homeworkNotDoneList; - final ScrollController? hideButtonController; - final SortBy? sortBy; - - @override - Widget build(BuildContext context) { - return TabBarView(children: [ - _HomeworkPageLogic( - homeworkNotDoneList: homeworkNotDoneList, - typeOfUser: TypeOfUser.student, - hideButtonController: hideButtonController, - sortBy: sortBy, - ), - _HomeworkPageLogic( - homeworkDoneList: getNotArchived(homeworkDoneList!), - homeworkNotDoneList: homeworkNotDoneList, - typeOfUser: TypeOfUser.student, - hideButtonController: hideButtonController, - sortBy: sortBy, - ) - ]); - } -} - -class _ParentsHomeworkPageView extends StatelessWidget { - const _ParentsHomeworkPageView( - {required this.homeworkList, this.sortBy, this.hideButtonController}); - - final List? homeworkList; - final SortBy? sortBy; - final ScrollController? hideButtonController; - - @override - Widget build(BuildContext context) { - if (homeworkList!.isEmpty) return _SleepingSmileyParents(); - return _HomeworkListWithCards( - homeworkList: homeworkList, - typeOfUser: TypeOfUser.parent, - hideButtonController: hideButtonController, - ); - } -} - -class _TeacherHomeworkPageView extends StatelessWidget { - const _TeacherHomeworkPageView( - {required this.homeworkList, this.sortBy, this.hideButtonController}); - - final List? homeworkList; - final SortBy? sortBy; - final ScrollController? hideButtonController; - - @override - Widget build(BuildContext context) { - if (homeworkList!.isEmpty) return _SleepingSmileyTeacher(); - return _HomeworkListWithCards( - homeworkList: homeworkList, - typeOfUser: TypeOfUser.teacher, - hideButtonController: hideButtonController, - sortBy: sortBy, - ); - } -} - -void logHomeworkAddViaHomeworkPage(BuildContext context) { - final analytics = BlocProvider.of(context).analytics; - analytics.log(NamedAnalyticsEvent(name: "homework_add_via_fab")); -} - -class _HomeworkPageFAB extends StatelessWidget { - const _HomeworkPageFAB({this.visible}); - - final bool? visible; - - @override - Widget build(BuildContext context) { - if (!visible!) return Container(); - return ModalFloatingActionButton( - heroTag: 'sharezone-fab', - onPressed: () async { - logHomeworkAddViaHomeworkPage(context); - await openHomeworkDialogAndShowConfirmationIfSuccessful(context); - }, - tooltip: "Neue Hausaufgabe", - icon: const Icon(Icons.add), - ); - } -} - -Future showUserConfirmationOfHomeworkArrival({ - required BuildContext context, -}) async { - await waitingForPopAnimation(); - if (!context.mounted) return; - showDataArrivalConfirmedSnackbar(context: context); -} - -class _HomeworkPageLogic extends StatelessWidget { - final List? homeworkDoneList, homeworkNotDoneList; - final TypeOfUser? typeOfUser; - final ScrollController? hideButtonController; - final SortBy? sortBy; - - const _HomeworkPageLogic( - {this.homeworkDoneList, - this.homeworkNotDoneList, - this.typeOfUser, - this.hideButtonController, - this.sortBy}); - - @override - Widget build(BuildContext context) { - if (homeworkDoneList == null) { - // Show open homeworks - if (homeworkNotDoneList!.isEmpty) return const GameController(); - return _HomeworkListWithCards( - homeworkList: homeworkNotDoneList, - typeOfUser: typeOfUser, - hideButtonController: hideButtonController, - sortBy: sortBy, - ); - } else { - // Show done homeworks - if (homeworkDoneList!.isEmpty) { - // Show Motivation-Widgets - if (homeworkNotDoneList!.isEmpty) { - return const GameController(); // User has not done all homeworks - } - return const FireMotivation(); // User done all homeworks - } - return _HomeworkListWithCards( - homeworkList: homeworkDoneList, - typeOfUser: typeOfUser, - hideButtonController: hideButtonController, - sortBy: sortBy, - ); // Show done homework list - } - } -} - -class _HomeworkListWithCards extends StatelessWidget { - const _HomeworkListWithCards({ - this.homeworkList, - this.typeOfUser, - required this.hideButtonController, - this.sortBy, - }); - - final List? homeworkList; - final TypeOfUser? typeOfUser; - final ScrollController? hideButtonController; - final SortBy? sortBy; - - static const padding = EdgeInsets.fromLTRB(8, 10, 8, 8); - - @override - Widget build(BuildContext context) { - List children = []; - if (sortBy == SortBy.date) { - homeworkList!.sort((HomeworkDto a, HomeworkDto b) { - var r = a.todoUntil.compareTo(b.todoUntil); - if (r != 0) return r; - return a.subject.compareTo(b.subject); - }); - - final List overdoueList = []; - final List todayList = []; - final List tomorrowList = []; - final List dayAfterTomorrowList = []; - final List severalDaysList = []; - - DateTime today = - DateTime(clock.now().year, clock.now().month, clock.now().day); - for (var homework in homeworkList!) { - DateTime homeworkDate = DateTime(homework.todoUntil.year, - homework.todoUntil.month, homework.todoUntil.day); - - if (today.isAfter(homeworkDate)) { - overdoueList.add(homework); - } else if (today.isAtSameMomentAs(homeworkDate)) { - todayList.add(homework); - } else if (homeworkDate == today.add(const Duration(days: 1))) { - tomorrowList.add(homework); - } else if (homeworkDate == today.add(const Duration(days: 2))) { - dayAfterTomorrowList.add(homework); - } else { - severalDaysList.add(homework); - } - } - - children = [ - _HomeworkViewerInCategories( - homeworkList: overdoueList, - typeOfUser: typeOfUser, - title: "Überfällig:", - ), - _HomeworkViewerInCategories( - homeworkList: todayList, - typeOfUser: typeOfUser, - title: "Heute fällig:", - ), - _HomeworkViewerInCategories( - homeworkList: tomorrowList, - typeOfUser: typeOfUser, - title: "Morgen fällig:", - ), - _HomeworkViewerInCategories( - homeworkList: dayAfterTomorrowList, - typeOfUser: typeOfUser, - title: "Übermorgen fällig:", - ), - _HomeworkViewerInCategories( - homeworkList: severalDaysList, - typeOfUser: typeOfUser, - title: "In mehreren Tagen fällig:", - ), - ]; - } else { - homeworkList!.sort((HomeworkDto a, HomeworkDto b) { - var r = a.subject.compareTo(b.subject); - if (r != 0) return r; - return a.todoUntil.compareTo(b.todoUntil); - }); - - final homeworkSplittedIntoSubjects = >{}; - - for (var homework in homeworkList!) { - if (homeworkSplittedIntoSubjects[homework.courseID] == null) { - homeworkSplittedIntoSubjects[homework.courseID] = []; - } - - homeworkSplittedIntoSubjects[homework.courseID]!.add(homework); - } - - homeworkSplittedIntoSubjects.forEach((ref, list) { - children.add( - _HomeworkViewerInCategories( - typeOfUser: typeOfUser, - homeworkList: list, - title: list.first.subject, - ), - ); - }); - } - return SingleChildScrollView( - controller: hideButtonController, - padding: padding, - child: SafeArea(child: Column(children: children)), - ); - } -} - -class _HomeworkViewerInCategories extends StatelessWidget { - const _HomeworkViewerInCategories( - {this.homeworkList, this.typeOfUser, this.title}); - - final List? homeworkList; - final TypeOfUser? typeOfUser; - final String? title; - - @override - Widget build(BuildContext context) { - return homeworkList!.isNotEmpty - ? Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - title!, - style: const TextStyle(color: Colors.grey), - ), - const SizedBox(height: 6), - AnimationLimiter( - child: Column( - children: AnimationConfiguration.toStaggeredList( - duration: const Duration(milliseconds: 350), - childAnimationBuilder: (widget) => SlideAnimation( - verticalOffset: 25, - child: FadeInAnimation(child: widget), - ), - children: homeworkList! - .map( - (homework) => Padding( - padding: const EdgeInsets.only(bottom: 8), - child: HomeworkCard( - homework: homework, - typeOfUser: typeOfUser, - ), - ), - ) - .toList(), - ), - ), - ), - const SizedBox(height: 4), - ], - ) - : Container(); - } -} - -class _SleepingSmileyParents extends StatelessWidget { - @override - Widget build(BuildContext context) { - return const Padding( - padding: EdgeInsets.only(bottom: 48), - child: PlaceholderWidgetWithAnimation( - iconSize: Size(175, 175), - title: - "Jetzt haben die Schüler Zeit für die wirklich wichtigen Dinge! 😉😍", - description: Text( - "Die Schüler und Schülerinnen haben aktuell keine Hausaufgaben auf."), - svgPath: 'assets/icons/sleeping.svg', - animateSVG: true, - ), - ); - } -} - -class _SleepingSmileyTeacher extends StatelessWidget { - @override - Widget build(BuildContext context) { - return const PlaceholderWidgetWithAnimation( - iconSize: Size(175, 175), - title: "Keine Hausaufgaben für die Schüler und Schülerinnen? 😮😍", - description: Padding( - padding: EdgeInsets.only(top: 8), - child: _EmptyHomeworkListAddHomeworkCard(), - ), - svgPath: 'assets/icons/sleeping.svg', - animateSVG: true, - ); - } -} - -/// Show animated Game Controller -class GameController extends StatelessWidget { - const GameController({super.key}); - - @override - Widget build(BuildContext context) { - return const PlaceholderWidgetWithAnimation( - iconSize: Size(175, 175), - title: "Jetzt ist Zeit für die wirklich wichtigen Dinge im Leben! 🤘💪", - description: Column( - children: [ - Text("Sehr gut! Du hast keine Hausaufgaben zu erledigen"), - SizedBox(height: 12), - _EmptyHomeworkListAddHomeworkCard(), - ], - ), - svgPath: 'assets/icons/game-controller.svg', - animateSVG: true, - ); - } -} - -class _EmptyHomeworkListAddHomeworkCard extends StatelessWidget { - const _EmptyHomeworkListAddHomeworkCard(); - - @override - Widget build(BuildContext context) { - return CardListTile( - leading: const Icon(Icons.add_circle_outline), - centerTitle: true, - title: const Text("Hausaufgabe eintragen"), - onTap: () => openHomeworkDialogAndShowConfirmationIfSuccessful(context), - ); - } -} - -/// Show animated fire --> user should be motivated to do his homeworks -class FireMotivation extends StatelessWidget { - const FireMotivation({super.key}); - - @override - Widget build(BuildContext context) { - return const PlaceholderWidgetWithAnimation( - iconSize: Size(175, 175), - title: "AUF GEHTS! 💥👊", - description: Text( - "Du musst noch die Hausaufgaben erledigen! Also schau mich nicht weiter an und erledige die Aufgaben! Do it!"), - svgPath: 'assets/icons/fire.svg', - animateSVG: true, - ); - } -} diff --git a/app/lib/homework/parent/src/homework_page_bloc.dart b/app/lib/homework/parent/src/homework_page_bloc.dart deleted file mode 100644 index 5ce3a3284..000000000 --- a/app/lib/homework/parent/src/homework_page_bloc.dart +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'dart:async'; -import 'dart:developer'; - -import 'package:bloc_base/bloc_base.dart'; -import 'package:clock/clock.dart'; -import 'package:firebase_hausaufgabenheft_logik/firebase_hausaufgabenheft_logik.dart'; -import 'package:rxdart/subjects.dart'; -import 'package:sharezone/util/api.dart'; -import 'package:sharezone_common/api_errors.dart'; - -class HomeworkToggleDone { - final String homeworkDocumentID; - final bool newHomeworkValue; - - HomeworkToggleDone(this.homeworkDocumentID, this.newHomeworkValue); -} - -class HomeworkPageBloc extends BlocBase { - /// The [SharezoneGateway] used to get [HomeworkDto]. - final SharezoneGateway api; - - // This could maybe be in an own Bloc for homework - final _toggleIsHomeworkDoneToController = - StreamController(); - final BehaviorSubject> _homeworkListSubject = - BehaviorSubject(); - final BehaviorSubject> _homeworkDoneSubject = - BehaviorSubject(); - final BehaviorSubject> _homeworkNotDoneSubject = - BehaviorSubject(); - final _addHomeworkController = StreamController(); - final BehaviorSubject> _errorsSubject = - BehaviorSubject.seeded([]); - - /// Errors while converting [FirestoreDocument] into [HomeworkDto] from the API - /// or any Error occuring in the bloc. - Stream> get errors => _errorsSubject; - - /// Every [HomeworkDto] the user has. - Stream> get homeworkList => _homeworkListSubject; - - /// A [Sink] to add a [HomeworkDto] to the database. - Sink get addHomework => _addHomeworkController; - - /// Toggles if the [HomeworkDto] is done for the user calling it, spezified by the - /// uID in the [SharezoneGateway] - Sink get toggleIsHomeworkDoneTo => - _toggleIsHomeworkDoneToController; - - /// Every [HomeworkDto] which is done by the user, spezified by the uID in the [SharezoneGateway] - Stream> get homeworkDone => _homeworkDoneSubject; - - /// Every [HomeworkDto] which is not done by the user, spezified by the uID in the [SharezoneGateway] - Stream> get homeworkNotDone => _homeworkNotDoneSubject; - - HomeworkPageBloc(this.api) { - _homeworkListSubject.addStream(api.homework.homeworkStream); - api.homework.homeworkStream.listen( - (homeworkList) => _splitHomeworkAndAddToStreams(homeworkList), - cancelOnError: false, - onError: (e) => _handleAPIError(e)); - - _toggleIsHomeworkDoneToController.stream.listen((homeworkDone) => - api.homework.changeIsHomeworkDoneTo( - homeworkDone.homeworkDocumentID, homeworkDone.newHomeworkValue)); - - _addHomeworkController.stream - .listen((homework) => api.homework.addPrivateHomework(homework, false)); - } - - /// Attention! Side-effects. Splits [homeworkList] and adds a [List] of - /// [doneHomework] and [notDoneHomework] into [homeworkDone] and [homeworkNotDone]. - void _splitHomeworkAndAddToStreams(List homeworkList) { - final List doneHomework = []; - final List notDoneHomework = []; - - for (final homework in homeworkList) { - try { - _checkIfUserHasDoneHomework(homework) - ? doneHomework.add(homework) - : notDoneHomework.add(homework); - } on Exception catch (e) { - log("Error beim Zuweisen zu gemachten und nicht gemachten Hausaufgaben: $e", - error: e); - } - } - - _homeworkNotDoneSubject.add(notDoneHomework); - _homeworkDoneSubject.add(doneHomework); - } - - /// Returns the boolean value of the "userID - boolean" key-value pair. - bool _checkIfUserHasDoneHomework(HomeworkDto homework) { - final uID = api.uID; - final userMap = homework.forUsers; - assert(userMap.containsKey(uID), "User should be in the Map"); - return userMap[uID]!; - } - - /// Expects a [List] of [DeserializeFirestoreDocException], but tries to handle other cases, and adds it to [_errorsSubject]. - void _handleAPIError(error, [StackTrace? s]) { - log("Error während dem Konvertieren der Firestore Dokumente in Hausaufgaben: $error", - error: error, stackTrace: s); - } - - Future checkAllOverdueHomeworks() async { - List? homeworkNotDone = _homeworkNotDoneSubject.valueOrNull; - if (homeworkNotDone != null && homeworkNotDone.isNotEmpty) { - for (HomeworkDto homework in homeworkNotDone) { - final DateTime homeworkDateTime = DateTime(homework.todoUntil.year, - homework.todoUntil.month, homework.todoUntil.day); - final DateTime todayDateTime = - DateTime(clock.now().year, clock.now().month, clock.now().day); - if (homeworkDateTime.isBefore(todayDateTime)) { - api.homework.changeIsHomeworkDoneTo(homework.id, true); - } - } - } - } - - /// Take care of closing streams. - @override - Future dispose() async { - await Future.wait([ - _homeworkNotDoneSubject.drain(), - _homeworkDoneSubject.drain(), - _errorsSubject.drain(), - _homeworkListSubject.drain(), - ]); - - _homeworkNotDoneSubject.close(); - _homeworkDoneSubject.close(); - _toggleIsHomeworkDoneToController.close(); - _errorsSubject.close(); - _addHomeworkController.close(); - _homeworkListSubject.close(); - } -} diff --git a/app/lib/homework/shared/delete_homework.dart b/app/lib/homework/shared/delete_homework.dart index 6ba186e60..66a35e43e 100644 --- a/app/lib/homework/shared/delete_homework.dart +++ b/app/lib/homework/shared/delete_homework.dart @@ -7,8 +7,9 @@ // SPDX-License-Identifier: EUPL-1.2 import 'package:bloc_provider/bloc_provider.dart'; -import 'package:firebase_hausaufgabenheft_logik/firebase_hausaufgabenheft_logik.dart'; + import 'package:flutter/material.dart'; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; import 'package:sharezone/main/application_bloc.dart'; import 'package:sharezone/filesharing/file_sharing_api.dart'; import 'package:sharezone/util/api.dart'; diff --git a/app/lib/homework/shared/handle_homework_tile_long_press.dart b/app/lib/homework/shared/handle_homework_tile_long_press.dart new file mode 100644 index 000000000..6c3aac032 --- /dev/null +++ b/app/lib/homework/shared/handle_homework_tile_long_press.dart @@ -0,0 +1,41 @@ +// Copyright (c) 2024 Sharezone UG (haftungsbeschränkt) +// Licensed under the EUPL-1.2-or-later. +// +// You may obtain a copy of the Licence at: +// https://joinup.ec.europa.eu/software/page/eupl +// +// SPDX-License-Identifier: EUPL-1.2 + +import 'package:bloc_provider/bloc_provider.dart'; +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:common_domain_models/common_domain_models.dart'; +import 'package:flutter/material.dart'; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; +import 'package:sharezone/dashboard/models/homework_view.dart'; +import 'package:sharezone/main/application_bloc.dart'; + +import 'homework_card.dart'; + +Future handleHomeworkTileLongPress(BuildContext context, + {required HomeworkId homeworkId, + void Function(bool)? setHomeworkStatus}) async { + final dbModel = await getHomeworkDbModel(homeworkId); + if (!context.mounted) return; + final courseGateway = BlocProvider.of(context).api.course; + await showLongPressIfUserHasPermissions( + context, + setHomeworkStatus, + HomeworkView.fromHomework(dbModel, courseGateway), + ); +} + +/// Lädt das HomeworkDbModel, weil ein paar Funktionen noch dieses verlangen. +Future getHomeworkDbModel(HomeworkId homeworkId) async { + final CollectionReference> homeworkCollection = + FirebaseFirestore.instance.collection("Homework"); + + final homeworkDocument = await homeworkCollection.doc(homeworkId.value).get(); + final homework = + HomeworkDto.fromData(homeworkDocument.data()!, id: homeworkDocument.id); + return homework; +} diff --git a/app/lib/homework/shared/homework_archived.dart b/app/lib/homework/shared/homework_archived.dart deleted file mode 100644 index cc2195ee4..000000000 --- a/app/lib/homework/shared/homework_archived.dart +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'dart:developer'; - -import 'package:bloc_provider/bloc_provider.dart'; -import 'package:clock/clock.dart'; -import 'package:firebase_hausaufgabenheft_logik/firebase_hausaufgabenheft_logik.dart'; -import 'package:flutter/material.dart'; -import 'package:sharezone/homework/parent/homework_page.dart'; -import 'package:sharezone/homework/parent/src/homework_page_bloc.dart'; -import 'package:sharezone/homework/shared/homework_card.dart'; -import 'package:sharezone/main/application_bloc.dart'; -import 'package:sharezone_widgets/sharezone_widgets.dart'; -import 'package:user/user.dart'; - -class HomeworkArchivedPage extends StatefulWidget { - static const String tag = "homework-archived-page"; - - const HomeworkArchivedPage({super.key}); - - @override - State createState() => _HomeworkArchivedPageState(); -} - -class _HomeworkArchivedPageState extends State { - SortBy sortBy = SortBy.date; - - @override - Widget build(BuildContext context) { - final api = BlocProvider.of(context).api; - return Builder(builder: (context) { - final bloc = BlocProvider.of(context); - return Scaffold( - appBar: AppBar( - title: const Text("Archiviert"), - centerTitle: true, - actions: [ - _PopupMenu( - onChangedSortBy: (SortBy? changedSortBy) { - if (changedSortBy == null) return; - setState(() => sortBy = changedSortBy); - }, - ) - ], - ), - body: StreamBuilder( - stream: api.user.userStream, - builder: (context, userSnapshot) { - final typeOfUser = - userSnapshot.data?.typeOfUser ?? TypeOfUser.student; - return StreamBuilder>( - stream: typeOfUser == TypeOfUser.student - ? bloc.homeworkDone - : bloc.homeworkList, - builder: (context, snapshot) { - if (!snapshot.hasData) return Container(); - if (snapshot.hasError) { - return ShowCenteredError(error: snapshot.error.toString()); - } - - DateTime today = DateTime( - clock.now().year, clock.now().month, clock.now().day); - List homeworkList = - snapshot.data!.where((HomeworkDto homework) { - DateTime todoUntil = DateTime(homework.todoUntil.year, - homework.todoUntil.month, homework.todoUntil.day); - return todoUntil.difference(today).inDays < 0; - }).toList(); - log("length: ${homeworkList.length}"); - - if (homeworkList.isEmpty) { - return const Center( - child: Text("Es gibt keine archivierten Hausaufgaben.")); - } - - // Sort the Homeworks; - if (sortBy == SortBy.subject) { - homeworkList.sort((HomeworkDto a, HomeworkDto b) { - var r = a.subject.compareTo(b.subject); - if (r != 0) return r; - return b.todoUntil.compareTo(a.todoUntil); - }); - } else { - homeworkList.sort((HomeworkDto a, HomeworkDto b) { - var r = b.todoUntil.compareTo(a.todoUntil); - if (r != 0) return r; - return a.subject.compareTo(b.subject); - }); - } - - return SingleChildScrollView( - padding: const EdgeInsets.all(8), - child: Column( - children: homeworkList - .map((HomeworkDto h) => Padding( - padding: const EdgeInsets.only(bottom: 8), - child: HomeworkCard( - markedDate: false, - homework: h, - typeOfUser: typeOfUser, - ), - )) - .toList(), - ), - ); - }, - ); - }, - ), - ); - }); - } -} - -class _PopupMenu extends StatelessWidget { - const _PopupMenu({this.onChangedSortBy}); - - final ValueChanged? onChangedSortBy; - - void onPopupSortTap({BuildContext? context, SortBy? sortBy}) { - onChangedSortBy!(sortBy); - showSnackSec( - text: "Hausaufgaben werden nach dem ${sortByAsString[sortBy]} sortiert.", - context: context, - ); - } - - @override - Widget build(BuildContext context) { - return PopupMenuButton( - onSelected: (String value) { - switch (value) { - case "SortByDate": - onPopupSortTap(context: context, sortBy: SortBy.date); - break; - case "SortBySubject": - onPopupSortTap(context: context, sortBy: SortBy.subject); - break; - default: - log("Fehler! $value wurde beim PopupMenuButton nicht gefunden!"); - } - }, - itemBuilder: (BuildContext context) => const >[ - PopupMenuItem( - value: 'SortByDate', - child: Text("Sortiere nach Datum"), - ), - PopupMenuItem( - value: 'SortBySubject', - child: Text("Sortiere nach Fach"), - ), - ], - ); - } -} diff --git a/app/lib/homework/shared/homework_card.dart b/app/lib/homework/shared/homework_card.dart index 0aed6fa9f..3689a062c 100644 --- a/app/lib/homework/shared/homework_card.dart +++ b/app/lib/homework/shared/homework_card.dart @@ -10,19 +10,20 @@ import 'package:analytics/analytics.dart'; import 'package:bloc_provider/bloc_provider.dart'; import 'package:clock/clock.dart'; import 'package:common_domain_models/common_domain_models.dart'; -import 'package:firebase_hausaufgabenheft_logik/firebase_hausaufgabenheft_logik.dart'; + import 'package:flutter/material.dart'; import 'package:group_domain_models/group_domain_models.dart'; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; import 'package:intl/intl.dart'; import 'package:sharezone/dashboard/models/homework_view.dart'; import 'package:sharezone/groups/src/pages/course/course_card.dart'; import 'package:sharezone/homework/homework_details/homework_details.dart'; import 'package:sharezone/homework/homework_details/homework_details_view_factory.dart'; -import 'package:sharezone/homework/parent/homework_page.dart'; -import 'package:sharezone/homework/parent/src/homework_card_bloc.dart'; +import 'package:sharezone/homework/homework_page.dart'; +import 'package:sharezone/homework/shared/homework_card_bloc.dart'; import 'package:sharezone/homework/shared/delete_homework.dart'; import 'package:sharezone/homework/shared/homework_permissions.dart'; -import 'package:sharezone/homework/teacher/homework_done_by_users_list/homework_completion_user_list_page.dart'; +import 'package:sharezone/homework/teacher_and_parent/homework_done_by_users_list/homework_completion_user_list_page.dart'; import 'package:sharezone/main/application_bloc.dart'; import 'package:sharezone/report/page/report_page.dart'; import 'package:sharezone/report/report_icon.dart'; @@ -375,7 +376,7 @@ void _logHomeworkReportViaCardLongPress(Analytics analytics) { Future showLongPressIfUserHasPermissions( BuildContext context, - void Function(bool newHomeworkStatus) setHomeworkStatus, + void Function(bool newHomeworkStatus)? setHomeworkStatus, HomeworkView homeworkView) async { final sharezoneContext = BlocProvider.of(context); final api = sharezoneContext.api; @@ -430,7 +431,7 @@ Future showLongPressIfUserHasPermissions( _logHomeworkDoneViaCardLongPress(analytics); final result = (await confirmToMarkHomeworkAsDoneWithoutSubmission(context))!; - if (result) setHomeworkStatus(true); + if (result) setHomeworkStatus?.call(true); break; case _HomeworkTileLongPressModelSheetOption.edit: _logHomeworkEditViaCardLongPress(analytics); diff --git a/app/lib/homework/parent/src/homework_card_bloc.dart b/app/lib/homework/shared/homework_card_bloc.dart similarity index 94% rename from app/lib/homework/parent/src/homework_card_bloc.dart rename to app/lib/homework/shared/homework_card_bloc.dart index 91fd55b92..4f463fbca 100644 --- a/app/lib/homework/parent/src/homework_card_bloc.dart +++ b/app/lib/homework/shared/homework_card_bloc.dart @@ -9,7 +9,8 @@ import 'dart:async'; import 'package:bloc_base/bloc_base.dart'; -import 'package:firebase_hausaufgabenheft_logik/firebase_hausaufgabenheft_logik.dart'; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; + import 'package:rxdart/subjects.dart'; import 'package:sharezone/util/api.dart'; diff --git a/app/lib/homework/shared/shared.dart b/app/lib/homework/shared/shared.dart index 027d2316d..0e812b785 100644 --- a/app/lib/homework/shared/shared.dart +++ b/app/lib/homework/shared/shared.dart @@ -10,6 +10,7 @@ export 'animated_staggered_scroll_view.dart'; export 'animated_tab_visibility.dart'; export 'bottom_of_scrollview_visibility.dart'; export 'glowing_overscroll_color_changer.dart'; +export 'handle_homework_tile_long_press.dart'; export 'homework_fab.dart'; export 'homework_list_section.dart'; export 'homework_tab_bar.dart'; diff --git a/app/lib/homework/student/src/completed_homework_list.dart b/app/lib/homework/student/src/completed_homework_list.dart index 3226efb8a..c973ba8ec 100644 --- a/app/lib/homework/student/src/completed_homework_list.dart +++ b/app/lib/homework/student/src/completed_homework_list.dart @@ -15,8 +15,8 @@ import 'package:sharezone/homework/student/src/util.dart'; import 'homework_tile.dart'; class CompletedHomeworkList extends StatelessWidget { - final CompletedHomeworkListView view; - final HomeworkPageBloc bloc; + final LazyLoadingHomeworkListView view; + final StudentHomeworkPageBloc bloc; const CompletedHomeworkList({ super.key, @@ -27,7 +27,7 @@ class CompletedHomeworkList extends StatelessWidget { @override Widget build(BuildContext context) { return LazyLoadingHomeworkList( - loadedAllHomeworks: view.loadedAllCompletedHomeworks, + loadedAllHomeworks: view.loadedAllHomeworks, loadMoreHomeworksCallback: () => bloc.add(AdvanceCompletedHomeworks(10)), children: [ for (final hw in view.orderedHomeworks) @@ -37,7 +37,7 @@ class CompletedHomeworkList extends StatelessWidget { // Spamming the checkbox causes the homework to sometimes // get unchecked and checked again, which we do not want. if (newStatus == HomeworkStatus.open) { - final bloc = BlocProvider.of(context); + final bloc = BlocProvider.of(context); dispatchCompletionStatusChange(newStatus, hw.id, bloc); } }, diff --git a/app/lib/homework/student/src/homework_bottom_action_bar.dart b/app/lib/homework/student/src/homework_bottom_action_bar.dart index 8488a9297..a09d0f4eb 100644 --- a/app/lib/homework/student/src/homework_bottom_action_bar.dart +++ b/app/lib/homework/student/src/homework_bottom_action_bar.dart @@ -9,7 +9,6 @@ import 'package:bloc_provider/bloc_provider.dart'; import 'package:flutter/material.dart'; import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; -import 'package:rxdart/rxdart.dart'; import 'package:sharezone/navigation/logic/navigation_bloc.dart'; import 'package:sharezone/navigation/models/navigation_item.dart'; import 'package:sharezone_widgets/sharezone_widgets.dart'; @@ -18,9 +17,17 @@ class HomeworkBottomActionBar extends StatelessWidget { const HomeworkBottomActionBar({ super.key, required this.backgroundColor, + required this.onSortingChanged, + required this.onCompletedAllOverdue, + required this.showOverflowMenu, + required this.currentHomeworkSortStream, }); final Color? backgroundColor; + final Stream currentHomeworkSortStream; + final void Function(HomeworkSort newSort) onSortingChanged; + final VoidCallback onCompletedAllOverdue; + final bool showOverflowMenu; @override Widget build(BuildContext context) { @@ -30,28 +37,31 @@ class HomeworkBottomActionBar extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - _SortButton(), - IconButton( - icon: const Icon(Icons.more_vert), - onPressed: () async { - var action = - await showRoundedModalBottomSheet<_BottomSheetAction>( - context: context, - builder: (context) => const _MoreActionsBottomSheet(), - defaultValue: _BottomSheetAction.abort, - isScrollControlled: true); - if (!context.mounted) return; - - final bloc = BlocProvider.of(context); - switch (action) { - case _BottomSheetAction.completeOverdue: - bloc.add(CompletedAllOverdue()); - break; - case _BottomSheetAction.abort: - default: - } - }, + SortButton( + onSortingChanged: onSortingChanged, + currentHomeworkSortStream: currentHomeworkSortStream, ), + if (showOverflowMenu) + IconButton( + icon: const Icon(Icons.more_vert), + onPressed: () async { + var action = + await showRoundedModalBottomSheet<_BottomSheetAction>( + context: context, + builder: (context) => const _MoreActionsBottomSheet(), + defaultValue: _BottomSheetAction.abort, + isScrollControlled: true); + if (!context.mounted) return; + + switch (action) { + case _BottomSheetAction.completeOverdue: + onCompletedAllOverdue(); + break; + case _BottomSheetAction.abort: + default: + } + }, + ), ], ), ); @@ -134,13 +144,28 @@ class _MoreIdeas extends StatelessWidget { } } -class _SortButton extends StatelessWidget { +@visibleForTesting +class SortButton extends StatelessWidget { + @visibleForTesting + static const sortByDateSortButtonUiString = "Sortiere nach Datum"; + @visibleForTesting + static const sortBySubjectSortButtonUiString = "Sortiere nach Fach"; + + const SortButton({ + super.key, + required this.onSortingChanged, + required this.currentHomeworkSortStream, + }); + + final void Function(HomeworkSort newSort) onSortingChanged; + final Stream currentHomeworkSortStream; + String _sortString(HomeworkSort sort) { switch (sort) { case HomeworkSort.smallestDateSubjectAndTitle: - return 'Sortiert nach Datum'; + return sortByDateSortButtonUiString; case HomeworkSort.subjectSmallestDateAndTitleSort: - return 'Sortiert nach Fach'; + return sortBySubjectSortButtonUiString; } } @@ -155,20 +180,16 @@ class _SortButton extends StatelessWidget { @override Widget build(BuildContext context) { - // ignore: close_sinks - final bloc = BlocProvider.of(context); - - return StreamBuilder( - stream: bloc.stream.whereType(), + return StreamBuilder( + stream: currentHomeworkSortStream, builder: (context, snapshot) { - final currentSort = snapshot.data?.open.sorting ?? - HomeworkSort.smallestDateSubjectAndTitle; + final currentSort = + snapshot.data ?? HomeworkSort.smallestDateSubjectAndTitle; return Padding( padding: const EdgeInsets.only(left: 4), child: InkWell( key: const Key("change_homework_sorting"), - onTap: () => - bloc.add(OpenHwSortingChanged(_getNextSort(currentSort))), + onTap: () => onSortingChanged(_getNextSort(currentSort)), borderRadius: const BorderRadius.all(Radius.circular(5)), child: Row( children: [ diff --git a/app/lib/homework/student/src/homework_tile.dart b/app/lib/homework/student/src/homework_tile.dart index 1cabcfaff..2c317f5e3 100644 --- a/app/lib/homework/student/src/homework_tile.dart +++ b/app/lib/homework/student/src/homework_tile.dart @@ -8,18 +8,15 @@ import 'package:analytics/analytics.dart'; import 'package:bloc_provider/bloc_provider.dart'; -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:firebase_hausaufgabenheft_logik/firebase_hausaufgabenheft_logik.dart'; +import 'package:common_domain_models/common_domain_models.dart'; import 'package:flutter/material.dart'; import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; -import 'package:sharezone/main/application_bloc.dart'; -import 'package:sharezone/dashboard/models/homework_view.dart'; import 'package:sharezone/homework/homework_details/homework_details.dart'; import 'package:sharezone/homework/homework_details/homework_details_view_factory.dart'; +import 'package:sharezone/homework/shared/homework_tile_template.dart'; +import 'package:sharezone/homework/shared/shared.dart'; import 'package:sharezone/submissions/homework_create_submission_page.dart'; import 'package:sharezone/util/navigation_service.dart'; -import 'package:sharezone/homework/shared/homework_card.dart'; -import 'package:sharezone/homework/shared/homework_tile_template.dart'; import 'package:sharezone_widgets/sharezone_widgets.dart'; enum HomeworkStatus { open, completed } @@ -69,7 +66,11 @@ class _HomeworkTileState extends State { ? Colors.redAccent : Theme.of(context).textTheme.bodyMedium!.color, onTap: () => _showHomeworkDetails(context), - onLongPress: () => _showLongPressDialog(context), + onLongPress: () => handleHomeworkTileLongPress( + context, + homeworkId: HomeworkId(widget.homework.id), + setHomeworkStatus: _changeCompletionState, + ), key: Key(widget.homework.id), ); } @@ -124,31 +125,6 @@ class _HomeworkTileState extends State { name: HomeworkDetails.tag, ); } - - Future _showLongPressDialog(BuildContext context) async { - final dbModel = await getHomeworkDbModel(widget.homework); - if (!context.mounted) return; - final courseGateway = BlocProvider.of(context).api.course; - await showLongPressIfUserHasPermissions( - context, - (newStatus) => widget.onChanged( - newStatus ? HomeworkStatus.completed : HomeworkStatus.open), - HomeworkView.fromHomework(dbModel, courseGateway), - ); - } - - /// Lädt das HomeworkDbModel, weil ein paar Funktionen noch dieses verlangen. - Future getHomeworkDbModel( - StudentHomeworkView homeworkView) async { - final CollectionReference> homeworkCollection = - FirebaseFirestore.instance.collection("Homework"); - - final homeworkId = homeworkView.id; - final homeworkDocument = await homeworkCollection.doc(homeworkId).get(); - final homework = - HomeworkDto.fromData(homeworkDocument.data()!, id: homeworkDocument.id); - return homework; - } } class _SubmissionUploadButton extends StatelessWidget { diff --git a/app/lib/homework/student/src/mark_overdue_homework_prompt.dart b/app/lib/homework/student/src/mark_overdue_homework_prompt.dart index 5cc0b6e1a..c10fb1479 100644 --- a/app/lib/homework/student/src/mark_overdue_homework_prompt.dart +++ b/app/lib/homework/student/src/mark_overdue_homework_prompt.dart @@ -35,7 +35,7 @@ class _MarkOverdueHomeworkPromptState extends State { Widget build(BuildContext context) { final textTheme = Theme.of(context).textTheme; // ignore:close_sinks - final bloc = BlocProvider.of(context); + final bloc = BlocProvider.of(context); final analytics = AnalyticsProvider.ofOrNullObject(context); cache = BlocProvider.of(context); diff --git a/app/lib/homework/student/src/open_homework_list.dart b/app/lib/homework/student/src/open_homework_list.dart index 51c2c9184..b26f7edec 100644 --- a/app/lib/homework/student/src/open_homework_list.dart +++ b/app/lib/homework/student/src/open_homework_list.dart @@ -22,7 +22,7 @@ import 'util.dart'; /// Instead of [CompletedHomeworkList] this list is not intended for lazy /// loading. class OpenHomeworkList extends StatelessWidget { - final OpenHomeworkListView homeworkListView; + final StudentOpenHomeworkListView homeworkListView; final Color? overscrollColor; /// Whether to show the [MarkOverdueHomeworkPrompt] to the user. @@ -42,7 +42,7 @@ class OpenHomeworkList extends StatelessWidget { @override Widget build(BuildContext context) { - final bloc = BlocProvider.of(context); + final bloc = BlocProvider.of(context); if (homeworkListView.sections.isEmpty) return Container(); return GlowingOverscrollColorChanger( diff --git a/app/lib/homework/student/src/util.dart b/app/lib/homework/student/src/util.dart index 2140501ec..641cb7926 100644 --- a/app/lib/homework/student/src/util.dart +++ b/app/lib/homework/student/src/util.dart @@ -11,7 +11,7 @@ import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; import 'homework_tile.dart'; void dispatchCompletionStatusChange( - HomeworkStatus newStatus, String homeworkId, HomeworkPageBloc bloc) { + HomeworkStatus newStatus, String homeworkId, StudentHomeworkPageBloc bloc) { final bool newValue = newStatus == HomeworkStatus.completed; bloc.add(CompletionStatusChanged(homeworkId, newValue)); } diff --git a/app/lib/homework/student/student_homework_page.dart b/app/lib/homework/student/student_homework_page.dart index 5c10fd381..0b11458f5 100644 --- a/app/lib/homework/student/student_homework_page.dart +++ b/app/lib/homework/student/student_homework_page.dart @@ -10,6 +10,7 @@ import 'package:bloc_provider/bloc_provider.dart'; import 'package:flutter/material.dart'; import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; import 'package:provider/provider.dart'; +import 'package:rxdart/rxdart.dart'; import 'package:sharezone/homework/shared/shared.dart'; import 'package:sharezone/homework/student/src/homework_bottom_action_bar.dart'; import 'package:sharezone/navigation/logic/navigation_bloc.dart'; @@ -29,6 +30,8 @@ class StudentHomeworkPage extends StatelessWidget { @override Widget build(BuildContext context) { + final bloc = BlocProvider.of(context); + final bottomBarBackgroundColor = Theme.of(context).isDarkTheme ? Colors.grey[900] : Colors.grey[100]; return ChangeNotifierProvider( @@ -60,6 +63,13 @@ class StudentHomeworkPage extends StatelessWidget { curve: Curves.easeInOut, child: HomeworkBottomActionBar( backgroundColor: bottomBarBackgroundColor, + currentHomeworkSortStream: bloc.stream + .whereType() + .map((s) => s.open.sorting), + showOverflowMenu: true, + onCompletedAllOverdue: () => bloc.add(CompletedAllOverdue()), + onSortingChanged: (sort) => + bloc.add(OpenHwSortingChanged(sort)), ), ), ), @@ -89,9 +99,9 @@ class StudentHomeworkBody extends StatelessWidget { @override Widget build(BuildContext context) { // ignore:close_sinks - final bloc = BlocProvider.of(context); + final bloc = BlocProvider.of(context); bloc.add(LoadHomeworks()); - return StreamBuilder( + return StreamBuilder( stream: bloc.stream, initialData: bloc.state, builder: (context, snapshot) { diff --git a/app/lib/homework/teacher/src/teacher_homework_bottom_action_bar.dart b/app/lib/homework/teacher/src/teacher_homework_bottom_action_bar.dart deleted file mode 100644 index 41ecd805e..000000000 --- a/app/lib/homework/teacher/src/teacher_homework_bottom_action_bar.dart +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'package:bloc_provider/bloc_provider.dart'; -import 'package:flutter/material.dart'; -import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik_lehrer.dart'; -import 'package:rxdart/rxdart.dart'; - -class TeacherHomeworkBottomActionBar extends StatelessWidget { - const TeacherHomeworkBottomActionBar({ - super.key, - required this.backgroundColor, - }); - - final Color? backgroundColor; - - @override - Widget build(BuildContext context) { - return Material( - elevation: 0, - color: backgroundColor, - child: const Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - TeacherSortButton(), - ], - ), - ); - } -} - -class TeacherSortButton extends StatelessWidget { - @visibleForTesting - static const sortByDateSortButtonUiString = "Sortiere nach Datum"; - @visibleForTesting - static const sortBySubjectSortButtonUiString = "Sortiere nach Fach"; - - const TeacherSortButton({super.key}); - - String _sortString(HomeworkSort sort) { - switch (sort) { - case HomeworkSort.smallestDateSubjectAndTitle: - return sortByDateSortButtonUiString; - case HomeworkSort.subjectSmallestDateAndTitleSort: - return sortBySubjectSortButtonUiString; - } - } - - HomeworkSort _getNextSort(HomeworkSort current) { - switch (current) { - case HomeworkSort.smallestDateSubjectAndTitle: - return HomeworkSort.subjectSmallestDateAndTitleSort; - case HomeworkSort.subjectSmallestDateAndTitleSort: - return HomeworkSort.smallestDateSubjectAndTitle; - } - } - - @override - Widget build(BuildContext context) { - // ignore: close_sinks - final bloc = BlocProvider.of(context); - - return StreamBuilder( - stream: bloc.stream.whereType(), - builder: (context, snapshot) { - final currentSort = snapshot.data?.open.sorting ?? - HomeworkSort.subjectSmallestDateAndTitleSort; - return Padding( - padding: const EdgeInsets.only(left: 4), - child: InkWell( - key: const Key("change_homework_sorting"), - onTap: () => - bloc.add(OpenHwSortingChanged(_getNextSort(currentSort))), - borderRadius: const BorderRadius.all(Radius.circular(5)), - child: Row( - children: [ - const Padding( - padding: EdgeInsets.all(8), - child: Icon(Icons.sort), - ), - Text( - _sortString(currentSort), - key: ValueKey(_sortString(currentSort)), - ), - const SizedBox(width: 8), - ], - ), - ), - ); - }, - ); - } -} diff --git a/app/lib/homework/teacher/homework_done_by_users_list/homework_completion_user_list_bloc.dart b/app/lib/homework/teacher_and_parent/homework_done_by_users_list/homework_completion_user_list_bloc.dart similarity index 97% rename from app/lib/homework/teacher/homework_done_by_users_list/homework_completion_user_list_bloc.dart rename to app/lib/homework/teacher_and_parent/homework_done_by_users_list/homework_completion_user_list_bloc.dart index 43644feee..854988bef 100644 --- a/app/lib/homework/teacher/homework_done_by_users_list/homework_completion_user_list_bloc.dart +++ b/app/lib/homework/teacher_and_parent/homework_done_by_users_list/homework_completion_user_list_bloc.dart @@ -9,8 +9,9 @@ import 'package:bloc_base/bloc_base.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:common_domain_models/common_domain_models.dart'; -import 'package:firebase_hausaufgabenheft_logik/firebase_hausaufgabenheft_logik.dart'; + import 'package:group_domain_models/group_domain_models.dart'; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; import 'package:sharezone/homework/analytics/homework_analytics.dart'; import 'package:sharezone/util/api/homework_api.dart'; import 'package:sharezone_common/references.dart'; diff --git a/app/lib/homework/teacher/homework_done_by_users_list/homework_completion_user_list_bloc_factory.dart b/app/lib/homework/teacher_and_parent/homework_done_by_users_list/homework_completion_user_list_bloc_factory.dart similarity index 96% rename from app/lib/homework/teacher/homework_done_by_users_list/homework_completion_user_list_bloc_factory.dart rename to app/lib/homework/teacher_and_parent/homework_done_by_users_list/homework_completion_user_list_bloc_factory.dart index a3893b62f..d57546d38 100644 --- a/app/lib/homework/teacher/homework_done_by_users_list/homework_completion_user_list_bloc_factory.dart +++ b/app/lib/homework/teacher_and_parent/homework_done_by_users_list/homework_completion_user_list_bloc_factory.dart @@ -9,7 +9,8 @@ import 'package:bloc_base/bloc_base.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:common_domain_models/common_domain_models.dart'; -import 'package:firebase_hausaufgabenheft_logik/firebase_hausaufgabenheft_logik.dart'; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; + import 'package:sharezone/homework/analytics/homework_analytics.dart'; import 'package:sharezone/util/api/homework_api.dart'; diff --git a/app/lib/homework/teacher/homework_done_by_users_list/homework_completion_user_list_page.dart b/app/lib/homework/teacher_and_parent/homework_done_by_users_list/homework_completion_user_list_page.dart similarity index 100% rename from app/lib/homework/teacher/homework_done_by_users_list/homework_completion_user_list_page.dart rename to app/lib/homework/teacher_and_parent/homework_done_by_users_list/homework_completion_user_list_page.dart diff --git a/app/lib/homework/teacher/homework_done_by_users_list/user_has_completed_homework_view.dart b/app/lib/homework/teacher_and_parent/homework_done_by_users_list/user_has_completed_homework_view.dart similarity index 100% rename from app/lib/homework/teacher/homework_done_by_users_list/user_has_completed_homework_view.dart rename to app/lib/homework/teacher_and_parent/homework_done_by_users_list/user_has_completed_homework_view.dart diff --git a/app/lib/homework/teacher/src/teacher_archived_homework_list.dart b/app/lib/homework/teacher_and_parent/src/teacher_and_parent_archived_homework_list.dart similarity index 65% rename from app/lib/homework/teacher/src/teacher_archived_homework_list.dart rename to app/lib/homework/teacher_and_parent/src/teacher_and_parent_archived_homework_list.dart index 3c55ed770..5147c46db 100644 --- a/app/lib/homework/teacher/src/teacher_archived_homework_list.dart +++ b/app/lib/homework/teacher_and_parent/src/teacher_and_parent_archived_homework_list.dart @@ -10,13 +10,13 @@ import 'package:flutter/material.dart'; import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik_lehrer.dart'; import 'package:sharezone/homework/shared/shared.dart'; -import 'teacher_homework_tile.dart'; +import 'teacher_and_parent_homework_tile.dart'; -class TeacherArchivedHomeworkList extends StatelessWidget { - final TeacherArchivedHomeworkListView view; - final TeacherHomeworkPageBloc bloc; +class TeacherAndParentArchivedHomeworkList extends StatelessWidget { + final LazyLoadingHomeworkListView view; + final TeacherAndParentHomeworkPageBloc bloc; - const TeacherArchivedHomeworkList({ + const TeacherAndParentArchivedHomeworkList({ super.key, required this.view, required this.bloc, @@ -25,11 +25,11 @@ class TeacherArchivedHomeworkList extends StatelessWidget { @override Widget build(BuildContext context) { return LazyLoadingHomeworkList( - loadedAllHomeworks: view.loadedAllArchivedHomeworks, + loadedAllHomeworks: view.loadedAllHomeworks, loadMoreHomeworksCallback: () => bloc.add(AdvanceArchivedHomeworks(10)), children: [ for (final hw in view.orderedHomeworks) - TeacherHomeworkTile(homework: hw) + TeacherAndParentHomeworkTile(homework: hw) ], ); } diff --git a/app/lib/homework/teacher/src/teacher_homework_tile.dart b/app/lib/homework/teacher_and_parent/src/teacher_and_parent_homework_tile.dart similarity index 79% rename from app/lib/homework/teacher/src/teacher_homework_tile.dart rename to app/lib/homework/teacher_and_parent/src/teacher_and_parent_homework_tile.dart index 17834600e..60fb05227 100644 --- a/app/lib/homework/teacher/src/teacher_homework_tile.dart +++ b/app/lib/homework/teacher_and_parent/src/teacher_and_parent_homework_tile.dart @@ -9,23 +9,28 @@ import 'package:common_domain_models/common_domain_models.dart'; import 'package:flutter/material.dart'; import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik_lehrer.dart'; -import 'package:sharezone/homework/teacher/homework_done_by_users_list/homework_completion_user_list_page.dart'; +import 'package:provider/provider.dart'; import 'package:sharezone/homework/homework_details/homework_details.dart'; +import 'package:sharezone/homework/shared/homework_tile_template.dart'; +import 'package:sharezone/homework/shared/shared.dart'; +import 'package:sharezone/homework/teacher_and_parent/homework_done_by_users_list/homework_completion_user_list_page.dart'; import 'package:sharezone/submissions/homework_list_submissions_page.dart'; import 'package:sharezone/util/navigation_service.dart'; -import 'package:sharezone/homework/shared/homework_tile_template.dart'; import 'package:sharezone_widgets/sharezone_widgets.dart'; +import 'package:user/user.dart'; -class TeacherHomeworkTile extends StatelessWidget { - final TeacherHomeworkView homework; +class TeacherAndParentHomeworkTile extends StatelessWidget { + final TeacherAndParentHomeworkView homework; - const TeacherHomeworkTile({ + const TeacherAndParentHomeworkTile({ super.key, required this.homework, }); @override Widget build(BuildContext context) { + final isTeacher = Provider.of(context).isTeacher; + return HomeworkTileTemplate( title: homework.title, courseName: homework.subject, @@ -36,18 +41,21 @@ class TeacherHomeworkTile extends StatelessWidget { ? Colors.redAccent : Theme.of(context).textTheme.bodyMedium!.color, onTap: () => _showHomeworkDetails(context), - trailing: homework.withSubmissions - ? _SubmissionsCounter( - nrOfSubmitters: homework.nrOfStudentsCompletedOrSubmitted, - hasPermissionsToSeeSubmissions: - homework.canViewCompletionOrSubmissionList, - homeworkId: homework.id) - : _DoneHomeworksCounter( - nrOfDoneHomeworks: homework.nrOfStudentsCompletedOrSubmitted, - hasPermissionsToSeeDoneHomeworks: - homework.canViewCompletionOrSubmissionList, - homeworkId: homework.id), - onLongPress: () => _showLongPressDialog(context), + trailing: isTeacher + ? homework.withSubmissions + ? _SubmissionsCounter( + nrOfSubmitters: homework.nrOfStudentsCompletedOrSubmitted, + hasPermissionsToSeeSubmissions: + homework.canViewCompletionOrSubmissionList, + homeworkId: homework.id) + : _DoneHomeworksCounter( + nrOfDoneHomeworks: homework.nrOfStudentsCompletedOrSubmitted, + hasPermissionsToSeeDoneHomeworks: + homework.canViewCompletionOrSubmissionList, + homeworkId: homework.id) + : const SizedBox.shrink(), + onLongPress: () => + handleHomeworkTileLongPress(context, homeworkId: homework.id), key: Key('${homework.id}'), ); } @@ -60,10 +68,6 @@ class TeacherHomeworkTile extends StatelessWidget { name: HomeworkDetails.tag, ); } - - Future _showLongPressDialog(BuildContext context) async { - throw UnimplementedError(); - } } class _SubmissionsCounter extends StatelessWidget { diff --git a/app/lib/homework/teacher/src/teacher_open_homework_list.dart b/app/lib/homework/teacher_and_parent/src/teacher_and_parent_open_homework_list.dart similarity index 74% rename from app/lib/homework/teacher/src/teacher_open_homework_list.dart rename to app/lib/homework/teacher_and_parent/src/teacher_and_parent_open_homework_list.dart index 34b4e47e1..6aab8cd4a 100644 --- a/app/lib/homework/teacher/src/teacher_open_homework_list.dart +++ b/app/lib/homework/teacher_and_parent/src/teacher_and_parent_open_homework_list.dart @@ -10,18 +10,13 @@ import 'package:flutter/material.dart'; import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik_lehrer.dart'; import 'package:sharezone/homework/shared/shared.dart'; -import 'teacher_homework_tile.dart'; +import 'teacher_and_parent_homework_tile.dart'; -/// The [TeacherOpenHomeworkList] shown in the open tab of the student -/// homework page. -/// -/// Instead of [ArchivedHomeworkList] this list is not intended for lazy -/// loading. -class TeacherOpenHomeworkList extends StatelessWidget { - final TeacherOpenHomeworkListView homeworkListView; +class TeacherAndParentOpenHomeworkList extends StatelessWidget { + final TeacherAndParentOpenHomeworkListView homeworkListView; final Color? overscrollColor; - const TeacherOpenHomeworkList({ + const TeacherAndParentOpenHomeworkList({ super.key, required this.homeworkListView, required this.overscrollColor, @@ -39,7 +34,7 @@ class TeacherOpenHomeworkList extends StatelessWidget { title: section.title, children: [ for (final hw in section.homeworks) - TeacherHomeworkTile( + TeacherAndParentHomeworkTile( homework: hw, key: Key('${hw.id}'), ) diff --git a/app/lib/homework/teacher_and_parent/src/teacher_and_parent_src.dart b/app/lib/homework/teacher_and_parent/src/teacher_and_parent_src.dart new file mode 100644 index 000000000..b30cf5cf7 --- /dev/null +++ b/app/lib/homework/teacher_and_parent/src/teacher_and_parent_src.dart @@ -0,0 +1,11 @@ +// Copyright (c) 2024 Sharezone UG (haftungsbeschränkt) +// Licensed under the EUPL-1.2-or-later. +// +// You may obtain a copy of the Licence at: +// https://joinup.ec.europa.eu/software/page/eupl +// +// SPDX-License-Identifier: EUPL-1.2 + +export 'teacher_and_parent_open_homework_list.dart'; +export 'teacher_and_parent_homework_tile.dart'; +export 'teacher_and_parent_archived_homework_list.dart'; diff --git a/app/lib/homework/teacher/teacher_homework_page.dart b/app/lib/homework/teacher_and_parent/teacher_and_parent_homework_page.dart similarity index 79% rename from app/lib/homework/teacher/teacher_homework_page.dart rename to app/lib/homework/teacher_and_parent/teacher_and_parent_homework_page.dart index 6aecefe26..ddade75cd 100644 --- a/app/lib/homework/teacher/teacher_homework_page.dart +++ b/app/lib/homework/teacher_and_parent/teacher_and_parent_homework_page.dart @@ -10,7 +10,9 @@ import 'package:bloc_provider/bloc_provider.dart'; import 'package:flutter/material.dart'; import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik_lehrer.dart'; import 'package:provider/provider.dart'; +import 'package:rxdart/rxdart.dart'; import 'package:sharezone/homework/shared/shared.dart'; +import 'package:sharezone/homework/student/src/homework_bottom_action_bar.dart'; import 'package:sharezone/navigation/logic/navigation_bloc.dart'; import 'package:sharezone/navigation/models/navigation_item.dart'; import 'package:sharezone/navigation/scaffold/app_bar_configuration.dart'; @@ -18,29 +20,15 @@ import 'package:sharezone/navigation/scaffold/bottom_bar_configuration.dart'; import 'package:sharezone/navigation/scaffold/sharezone_main_scaffold.dart'; import 'package:sharezone_widgets/sharezone_widgets.dart'; -import 'src/teacher_archived_homework_list.dart'; -import 'src/teacher_homework_bottom_action_bar.dart'; -import 'src/teacher_open_homework_list.dart'; +import 'src/teacher_and_parent_src.dart'; -class TeacherHomeworkPage extends StatelessWidget { - const TeacherHomeworkPage({super.key}); +class TeacherAndParentHomeworkPage extends StatelessWidget { + const TeacherAndParentHomeworkPage({super.key}); @override Widget build(BuildContext context) { - /// - /// !!ACHTUNG!! - /// - /// Falls hier was geändert wird, dann sollte dies auch im - /// app/test/homework/teacher/teacher_homework_page_widget_test.dart - /// geändert werden. - /// Dort musste die Seite aufgrund des nicht mockbaren, hier verwendeten - /// [SharezoneMainScaffold] nachgebaut werden. - /// - /// https://gitlab.com/codingbrain/sharezone/sharezone-app/-/issues/1459 - /// https://gitlab.com/codingbrain/sharezone/sharezone-app/-/issues/1458 - /// - /// !!ACHTUNG!! - /// + final bloc = BlocProvider.of(context); + final bottomBarBackgroundColor = Theme.of(context).isDarkTheme ? Colors.grey[900] : Colors.grey[100]; return ChangeNotifierProvider( @@ -69,8 +57,16 @@ class TeacherHomeworkPage extends StatelessWidget { // Else the Sort shown in the button and the current sort // could get out of order maintainState: true, - child: TeacherHomeworkBottomActionBar( + child: HomeworkBottomActionBar( + currentHomeworkSortStream: bloc.stream + .whereType() + .map((s) => s.open.sorting), backgroundColor: bottomBarBackgroundColor, + showOverflowMenu: false, + // Not visible since we don't show the overflow menu + onCompletedAllOverdue: () => throw UnimplementedError(), + onSortingChanged: (newSort) => + bloc.add(OpenHwSortingChanged(newSort)), ), ), ), @@ -83,6 +79,8 @@ class TeacherHomeworkPage extends StatelessWidget { } } +enum HomeworkTab { open, archived } + final Color? overscrollColor = Colors.grey[600]; class TeacherHomeworkBody extends StatelessWidget { @@ -91,11 +89,11 @@ class TeacherHomeworkBody extends StatelessWidget { @override Widget build(BuildContext context) { // ignore:close_sinks - final bloc = BlocProvider.of(context); + final bloc = BlocProvider.of(context); bloc.add(LoadHomeworks()); - return StreamBuilder( + return StreamBuilder( stream: bloc.stream, - initialData: Uninitialized(), + initialData: bloc.state, builder: (context, snapshot) { final state = snapshot.hasData ? snapshot.data : Uninitialized(); @@ -106,15 +104,15 @@ class TeacherHomeworkBody extends StatelessWidget { final hasArchivedHomeworks = state.archived.numberOfHomeworks > 0; final openHomeworkWidget = hasOpenHomeworks - ? TeacherOpenHomeworkList( + ? TeacherAndParentOpenHomeworkList( homeworkListView: state.open, overscrollColor: overscrollColor, ) : _NoOpenHomeworkPlaceholder(); final completedHomeworkWidget = - hasArchivedHomeworks || !state.archived.loadedAllArchivedHomeworks - ? TeacherArchivedHomeworkList( + hasArchivedHomeworks || !state.archived.loadedAllHomeworks + ? TeacherAndParentArchivedHomeworkList( view: state.archived, bloc: bloc, ) diff --git a/app/lib/main/sharezone_app.dart b/app/lib/main/sharezone_app.dart index baacce194..5f80e19c3 100644 --- a/app/lib/main/sharezone_app.dart +++ b/app/lib/main/sharezone_app.dart @@ -29,7 +29,6 @@ import 'package:sharezone/grades/pages/grades_dialog/grades_dialog.dart'; import 'package:sharezone/groups/group_join/bloc/group_join_function.dart'; import 'package:sharezone/groups/src/pages/course/create/pages/course_template_page.dart'; import 'package:sharezone/groups/src/pages/course/group_help.dart'; -import 'package:sharezone/homework/shared/homework_archived.dart'; import 'package:sharezone/ical_links/dialog/ical_links_dialog.dart'; import 'package:sharezone/ical_links/list/ical_links_page.dart'; import 'package:sharezone/legal/privacy_policy/privacy_policy_page.dart'; @@ -168,8 +167,6 @@ class _SharezoneAppState extends State key: navigationBloc.controllerKey, ), routes: { - HomeworkArchivedPage.tag: (context) => - const HomeworkArchivedPage(), AccountPage.tag: (context) => const AccountPage(), AboutPage.tag: (context) => const AboutPage(), FeedbackPage.tag: (context) => const FeedbackPage(), diff --git a/app/lib/main/sharezone_bloc_providers.dart b/app/lib/main/sharezone_bloc_providers.dart index 810b5f9c1..48e58ccea 100644 --- a/app/lib/main/sharezone_bloc_providers.dart +++ b/app/lib/main/sharezone_bloc_providers.dart @@ -18,15 +18,14 @@ import 'package:bloc_provider/multi_bloc_provider.dart'; import 'package:clock/clock.dart'; import 'package:common_domain_models/common_domain_models.dart'; import 'package:crash_analytics/crash_analytics.dart'; -import 'package:design/design.dart'; import 'package:dio/dio.dart'; import 'package:feedback_shared_implementation/feedback_shared_implementation.dart'; import 'package:filesharing_logic/file_uploader.dart'; -import 'package:firebase_hausaufgabenheft_logik/firebase_hausaufgabenheft_logik_setup.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:group_domain_implementation/group_domain_accessors_implementation.dart'; +import 'package:group_domain_models/group_domain_models.dart'; import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik_lehrer.dart'; import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik_setup.dart'; import 'package:holidays/holidays.dart' hide State; @@ -79,7 +78,7 @@ import 'package:sharezone/groups/src/pages/course/create/gateway/course_create_g import 'package:sharezone/homework/analytics/homework_analytics.dart'; import 'package:sharezone/homework/homework_details/homework_details_view_factory.dart'; import 'package:sharezone/homework/student/src/mark_overdue_homework_prompt.dart'; -import 'package:sharezone/homework/teacher/homework_done_by_users_list/homework_completion_user_list_bloc_factory.dart'; +import 'package:sharezone/homework/teacher_and_parent/homework_done_by_users_list/homework_completion_user_list_bloc_factory.dart'; import 'package:sharezone/ical_links/dialog/ical_links_dialog_controller_factory.dart'; import 'package:sharezone/ical_links/list/ical_links_page_controller.dart'; import 'package:sharezone/ical_links/shared/ical_link_analytics.dart'; @@ -127,6 +126,7 @@ import 'package:sharezone/timetable/timetable_add/bloc/timetable_add_bloc_factor import 'package:sharezone/timetable/timetable_page/lesson/substitution_controller.dart'; import 'package:sharezone/timetable/timetable_page/school_class_filter/school_class_filter_analytics.dart'; import 'package:sharezone/util/api.dart'; +import 'package:sharezone/util/api/connections_gateway.dart'; import 'package:sharezone/util/cache/key_value_store.dart'; import 'package:sharezone/util/cache/streaming_key_value_store.dart'; import 'package:sharezone/util/firebase_auth_token_retreiver_impl.dart'; @@ -139,7 +139,6 @@ import 'package:stripe_checkout_session/stripe_checkout_session.dart'; import 'package:user/user.dart'; import '../holidays/holiday_bloc.dart'; -import '../homework/parent/src/homework_page_bloc.dart' as old; import '../notifications/is_firebase_messaging_supported.dart'; final navigationBloc = NavigationBloc(); @@ -230,15 +229,11 @@ class _SharezoneBlocProvidersState extends State { final homeworkCollection = firestore.collection("Homework"); final uid = api.uID; final crashAnalytics = getCrashAnalytics(); - final firestoreHomeworkRepository = createDefaultFirestoreRepository( + final homeworkApi = createDefaultFirestoreRepositories( homeworkCollection, uid, - (courseId) => - getCourseColorFromCourseId(api, courseId) ?? - Design.standard().color.value, + (courseId) => getCourseData(api, courseId.value), ); - final homeworkCompletionDispatcher = - FirestoreHomeworkCompletionDispatcher(homeworkCollection, () => uid); final config = HausaufgabenheftConfig( defaultCourseColorValue: Colors.lightBlue.value, @@ -260,18 +255,16 @@ class _SharezoneBlocProvidersState extends State { 20, ); final dependencies = HausaufgabenheftDependencies( - dataSource: firestoreHomeworkRepository, - completionDispatcher: homeworkCompletionDispatcher, - getOpenOverdueHomeworkIds: - firestoreHomeworkRepository.getCurrentOpenOverdueHomeworkIds, + api: homeworkApi, keyValueStore: widget.blocDependencies.keyValueStore, ); - final homeworkPageBloc = createHomeworkPageBloc(dependencies, config); + final homeworkPageBloc = + createStudentHomeworkPageBloc(dependencies, config); // Not sure if we need to call both, but without .close the linter complains _disposeCallbacks.add(homeworkPageBloc.dispose); _disposeCallbacks.add(homeworkPageBloc.close); final teacherHomeworkBloc = - createTeacherHomeworkPageBloc(dependencies, config); + createTeacherAndParentHomeworkPageBloc(dependencies, config); // Not sure if we need to call both, but without .close the linter complains _disposeCallbacks.add(teacherHomeworkBloc.dispose); _disposeCallbacks.add(teacherHomeworkBloc.close); @@ -448,6 +441,10 @@ class _SharezoneBlocProvidersState extends State { gradesService: gradesService, ), ), + StreamProvider( + create: (context) => typeOfUserStream, + initialData: TypeOfUser.unknown, + ), Provider( create: (context) => TermDetailsPageControllerFactory( gradesService: gradesService, @@ -612,11 +609,10 @@ class _SharezoneBlocProvidersState extends State { ), ), BlocProvider(bloc: NavigationAnalytics(analytics)), - BlocProvider(bloc: teacherHomeworkBloc), - BlocProvider(bloc: homeworkPageBloc), + BlocProvider(bloc: teacherHomeworkBloc), + BlocProvider(bloc: homeworkPageBloc), BlocProvider(bloc: widget.navigationService!), BlocProvider(bloc: UserTipsBloc(api.user)), - BlocProvider(bloc: old.HomeworkPageBloc(api)), BlocProvider(bloc: lessonLengthCache), BlocProvider( bloc: HomeworkCompletionUserListBlocFactory( @@ -742,8 +738,20 @@ class _SharezoneBlocProvidersState extends State { ); } - int? getCourseColorFromCourseId(SharezoneGateway api, String courseId) { - final course = api.course.getCourse(courseId); - return course?.getDesign().color.value; + Future<({int colorHexValue, bool isAdmin})> getCourseData( + SharezoneGateway api, String courseId) async { + final course = api.course.getCourse(courseId)!; + final role = _getMemberRole(api.connectionsGateway, courseId); + final isAdmin = role == MemberRole.admin || role == MemberRole.owner; + return (colorHexValue: course.getDesign().color.value, isAdmin: isAdmin); + } + + MemberRole? _getMemberRole(ConnectionsGateway gateway, String courseID) { + final connectionsData = gateway.current(); + if (connectionsData != null) { + final courses = connectionsData.courses; + return courses[courseID]?.myRole; + } + return MemberRole.none; } } diff --git a/app/lib/navigation/models/navigation_item.dart b/app/lib/navigation/models/navigation_item.dart index 965c0fe13..950fea58f 100644 --- a/app/lib/navigation/models/navigation_item.dart +++ b/app/lib/navigation/models/navigation_item.dart @@ -16,7 +16,7 @@ import 'package:sharezone/feedback/feedback_box_page.dart'; import 'package:sharezone/filesharing/file_sharing_page.dart'; import 'package:sharezone/grades/pages/grades_page/grades_page.dart'; import 'package:sharezone/groups/src/pages/course/group_page.dart'; -import 'package:sharezone/homework/parent/homework_page.dart'; +import 'package:sharezone/homework/homework_page.dart'; import 'package:sharezone/keys.dart'; import 'package:sharezone/settings/settings_page.dart'; import 'package:sharezone/sharezone_plus/page/sharezone_plus_page.dart'; diff --git a/app/lib/notifications/action_requests/navigate_to_location.dart b/app/lib/notifications/action_requests/navigate_to_location.dart index 3661ce989..08ae06294 100644 --- a/app/lib/notifications/action_requests/navigate_to_location.dart +++ b/app/lib/notifications/action_requests/navigate_to_location.dart @@ -18,7 +18,7 @@ import 'package:sharezone/grades/pages/grades_page/grades_page.dart'; import 'package:sharezone/groups/src/pages/course/group_page.dart'; import 'package:sharezone/navigation/logic/navigation_bloc.dart'; import 'package:sharezone/navigation/models/navigation_item.dart'; -import 'package:sharezone/homework/parent/homework_page.dart'; +import 'package:sharezone/homework/homework_page.dart'; import 'package:sharezone/settings/settings_page.dart'; import 'package:sharezone/sharezone_plus/page/sharezone_plus_page.dart'; import 'package:sharezone/timetable/timetable_page/timetable_page.dart'; diff --git a/app/lib/submissions/submission_permissions.dart b/app/lib/submissions/submission_permissions.dart index 7dd3dd836..68f76d36d 100644 --- a/app/lib/submissions/submission_permissions.dart +++ b/app/lib/submissions/submission_permissions.dart @@ -6,8 +6,8 @@ // // SPDX-License-Identifier: EUPL-1.2 -import 'package:firebase_hausaufgabenheft_logik/firebase_hausaufgabenheft_logik.dart'; import 'package:group_domain_models/group_domain_models.dart'; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; import 'package:sharezone/util/api/course_gateway.dart'; import 'package:user/user.dart'; diff --git a/app/lib/util/api/homework_api.dart b/app/lib/util/api/homework_api.dart index 720e423fe..0b4a67ddb 100644 --- a/app/lib/util/api/homework_api.dart +++ b/app/lib/util/api/homework_api.dart @@ -12,7 +12,8 @@ import 'dart:developer'; import 'package:clock/clock.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:filesharing_logic/filesharing_logic_models.dart'; -import 'package:firebase_hausaufgabenheft_logik/firebase_hausaufgabenheft_logik.dart'; + +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; import 'package:rxdart/rxdart.dart'; import 'package:sharezone/filesharing/file_sharing_api.dart'; import 'package:sharezone_common/api_errors.dart'; diff --git a/app/pubspec.lock b/app/pubspec.lock index 2dc783865..88f2b3819 100644 --- a/app/pubspec.lock +++ b/app/pubspec.lock @@ -751,13 +751,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.2.6+32" - firebase_hausaufgabenheft_logik: - dependency: "direct main" - description: - path: "../lib/firebase_hausaufgabenheft_logik" - relative: true - source: path - version: "0.0.1" firebase_messaging: dependency: "direct main" description: diff --git a/app/pubspec.yaml b/app/pubspec.yaml index 36b456425..bdd4ba4dd 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -78,8 +78,6 @@ dependencies: path: ../lib/filesharing/filesharing_logic firebase_auth: ^4.19.4 firebase_core: ^2.30.1 - firebase_hausaufgabenheft_logik: - path: ../lib/firebase_hausaufgabenheft_logik firebase_messaging: ^14.9.1 firebase_performance: ^0.9.4+4 firebase_storage: ^11.7.4 diff --git a/app/test/grades/pages/grade_details_page/grade_details_page_test.mocks.dart b/app/test/grades/pages/grade_details_page/grade_details_page_test.mocks.dart index f8cdfb00a..52291cd3e 100644 --- a/app/test/grades/pages/grade_details_page/grade_details_page_test.mocks.dart +++ b/app/test/grades/pages/grade_details_page/grade_details_page_test.mocks.dart @@ -3,8 +3,6 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:ui' as _i7; - import 'package:analytics/analytics.dart' as _i4; import 'package:crash_analytics/crash_analytics.dart' as _i3; import 'package:mockito/mockito.dart' as _i1; @@ -13,7 +11,7 @@ import 'package:sharezone/grades/grades_service/grades_service.dart' as _i2; import 'package:sharezone/grades/pages/grades_details_page/grade_details_page_controller.dart' as _i5; import 'package:sharezone/grades/pages/grades_details_page/grade_details_page_controller_factory.dart' - as _i8; + as _i7; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -185,7 +183,7 @@ class MockGradeDetailsPageController extends _i1.Mock ); @override - void addListener(_i7.VoidCallback? listener) => super.noSuchMethod( + void addListener(dynamic listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -194,7 +192,7 @@ class MockGradeDetailsPageController extends _i1.Mock ); @override - void removeListener(_i7.VoidCallback? listener) => super.noSuchMethod( + void removeListener(dynamic listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -216,7 +214,7 @@ class MockGradeDetailsPageController extends _i1.Mock /// /// See the documentation for Mockito's code generation for more information. class MockGradeDetailsPageControllerFactory extends _i1.Mock - implements _i8.GradeDetailsPageControllerFactory { + implements _i7.GradeDetailsPageControllerFactory { @override _i2.GradesService get gradesService => (super.noSuchMethod( Invocation.getter(#gradesService), diff --git a/app/test/homework/homework_dialog_test.dart b/app/test/homework/homework_dialog_test.dart index 7df10dd9b..644414280 100644 --- a/app/test/homework/homework_dialog_test.dart +++ b/app/test/homework/homework_dialog_test.dart @@ -19,11 +19,11 @@ import 'package:date/weekday.dart'; import 'package:files_basics/files_models.dart'; import 'package:files_basics/local_file.dart'; import 'package:filesharing_logic/filesharing_logic_models.dart'; -import 'package:firebase_hausaufgabenheft_logik/src/homework_dto.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:group_domain_models/group_domain_models.dart'; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart' hide Date; import 'package:holidays/holidays.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; diff --git a/app/test/homework/homework_dialog_test.mocks.dart b/app/test/homework/homework_dialog_test.mocks.dart index 3822dc92a..78e6fb034 100644 --- a/app/test/homework/homework_dialog_test.mocks.dart +++ b/app/test/homework/homework_dialog_test.mocks.dart @@ -14,11 +14,10 @@ import 'package:cloud_firestore_platform_interface/cloud_firestore_platform_inte import 'package:common_domain_models/common_domain_models.dart' as _i8; import 'package:design/design.dart' as _i30; import 'package:firebase_auth/firebase_auth.dart' as _i28; -import 'package:firebase_hausaufgabenheft_logik/firebase_hausaufgabenheft_logik.dart' - as _i20; import 'package:flutter/material.dart' as _i29; import 'package:group_domain_models/group_domain_accessors.dart' as _i21; import 'package:group_domain_models/group_domain_models.dart' as _i22; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart' as _i20; import 'package:mockito/mockito.dart' as _i1; import 'package:mockito/src/dummies.dart' as _i23; import 'package:shared_preferences/shared_preferences.dart' as _i6; diff --git a/app/test/homework/teacher/teacher_homework_page_widget_test.dart b/app/test/homework/teacher/teacher_and_parent_homework_page_widget_test.dart similarity index 68% rename from app/test/homework/teacher/teacher_homework_page_widget_test.dart rename to app/test/homework/teacher/teacher_and_parent_homework_page_widget_test.dart index 12999f99a..66c824c84 100644 --- a/app/test/homework/teacher/teacher_homework_page_widget_test.dart +++ b/app/test/homework/teacher/teacher_and_parent_homework_page_widget_test.dart @@ -10,6 +10,7 @@ import 'dart:collection'; import 'package:analytics/analytics.dart'; import 'package:analytics/null_analytics_backend.dart'; +import 'package:bloc/bloc.dart'; import 'package:bloc_provider/bloc_provider.dart'; import 'package:bloc_provider/multi_bloc_provider.dart'; import 'package:common_domain_models/common_domain_models.dart'; @@ -20,45 +21,55 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:hausaufgabenheft_logik/color.dart'; import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik_lehrer.dart'; import 'package:provider/provider.dart'; +import 'package:rxdart/rxdart.dart'; import 'package:sharezone/homework/shared/shared.dart'; -import 'package:sharezone/homework/teacher/src/teacher_archived_homework_list.dart'; -import 'package:sharezone/homework/teacher/src/teacher_homework_bottom_action_bar.dart'; -import 'package:sharezone/homework/teacher/src/teacher_homework_tile.dart'; -import 'package:sharezone/homework/teacher/src/teacher_open_homework_list.dart'; -import 'package:sharezone/homework/teacher/teacher_homework_page.dart'; +import 'package:sharezone/homework/student/src/homework_bottom_action_bar.dart'; +import 'package:sharezone/homework/teacher_and_parent/src/teacher_and_parent_archived_homework_list.dart'; +import 'package:sharezone/homework/teacher_and_parent/src/teacher_and_parent_homework_tile.dart'; +import 'package:sharezone/homework/teacher_and_parent/src/teacher_and_parent_open_homework_list.dart'; +import 'package:sharezone/homework/teacher_and_parent/teacher_and_parent_homework_page.dart'; import 'package:sharezone/navigation/logic/navigation_bloc.dart'; import 'package:test_randomness/test_randomness.dart'; +import 'package:user/user.dart'; -class MockTeacherHomeworkPageBloc extends TeacherHomeworkPageBloc { - final _queuedStates = Queue(); +class MockTeacherAndParentHomeworkPageBloc extends Bloc< + TeacherAndParentHomeworkPageEvent, TeacherAndParentHomeworkPageState> + implements TeacherAndParentHomeworkPageBloc { + final _queuedStates = Queue(); - final receivedEvents = []; + final receivedEvents = []; - MockTeacherHomeworkPageBloc() : super() { - on((event, emit) { + MockTeacherAndParentHomeworkPageBloc() : super(Uninitialized()) { + on((event, emit) { if (_queuedStates.isNotEmpty) { emit(_queuedStates.removeFirst()); } }); } - void emitNewState(TeacherHomeworkPageState state) { + void emitNewState(TeacherAndParentHomeworkPageState state) { _queuedStates.add(state); add(LoadHomeworks()); } @override - void onEvent(TeacherHomeworkPageEvent event) { + void onEvent(TeacherAndParentHomeworkPageEvent event) { receivedEvents.add(event); super.onEvent(event); } + + @override + void dispose() {} + + @override + int get numberOfInitialCompletedHomeworksToLoad => 10; } enum HomeworkTab { open, archived } Future pumpHomeworkPage( WidgetTester tester, { - required TeacherHomeworkPageBloc bloc, + required TeacherAndParentHomeworkPageBloc bloc, HomeworkTab initialTab = HomeworkTab.open, }) async { /// Wir müssen hier die Hausaufgaben-Seite nachbauen, weil @@ -72,39 +83,54 @@ Future pumpHomeworkPage( /// https://gitlab.com/codingbrain/sharezone/sharezone-app/-/issues/1458 await tester.pumpWidget( MaterialApp( - home: AnalyticsProvider( - /// [NullAnalyticsBackend] does nothing, just used as a replacement for - /// testing (else warnings would be printed out for tests.) - analytics: Analytics(NullAnalyticsBackend()), - child: ChangeNotifierProvider( - create: (_) => BottomOfScrollViewInvisibilityController(), - child: MultiBlocProvider( - blocProviders: [ - BlocProvider(bloc: NavigationBloc()), - BlocProvider(bloc: bloc), - ], - child: (context) => BlocProvider( - bloc: NavigationBloc(), - child: BlocProvider( - bloc: MockTeacherHomeworkPageBloc(), - child: DefaultTabController( - length: 2, - initialIndex: initialTab == HomeworkTab.open ? 0 : 1, - child: const Scaffold( - body: TeacherHomeworkBody(), - appBar: HomeworkTabBar( - tabs: [Tab(text: 'OFFEN'), Tab(text: 'ARCHIVIERT')], - ), - bottomNavigationBar: AnimatedTabVisibility( - visibleInTabIndicies: [0], - maintainState: true, - child: TeacherHomeworkBottomActionBar( - // We dont care in the tests currently - backgroundColor: flutter.Color.fromRGBO(0, 0, 0, 255), + home: Provider.value( + value: TypeOfUser.teacher, + child: AnalyticsProvider( + /// [NullAnalyticsBackend] does nothing, just used as a replacement for + /// testing (else warnings would be printed out for tests.) + analytics: Analytics(NullAnalyticsBackend()), + child: + ChangeNotifierProvider( + create: (_) => BottomOfScrollViewInvisibilityController(), + child: MultiBlocProvider( + blocProviders: [ + BlocProvider(bloc: NavigationBloc()), + BlocProvider(bloc: bloc), + ], + child: (context) => BlocProvider( + bloc: NavigationBloc(), + child: BlocProvider( + bloc: bloc, + child: DefaultTabController( + length: 2, + initialIndex: initialTab == HomeworkTab.open ? 0 : 1, + child: Scaffold( + body: const TeacherHomeworkBody(), + appBar: const HomeworkTabBar( + tabs: [Tab(text: 'OFFEN'), Tab(text: 'ARCHIVIERT')], + ), + bottomNavigationBar: AnimatedTabVisibility( + visibleInTabIndicies: const [0], + maintainState: true, + child: HomeworkBottomActionBar( + currentHomeworkSortStream: bloc.stream + .whereType() + .map((s) => s.open.sorting), + backgroundColor: + const flutter.Color.fromRGBO(0, 0, 0, 255), + + showOverflowMenu: false, + // Not visible since we don't show the overflow menu + onCompletedAllOverdue: () => + throw UnimplementedError(), + onSortingChanged: (newSort) => + bloc.add(OpenHwSortingChanged(newSort)), + ), ), + floatingActionButton: + const BottomOfScrollViewInvisibility( + child: HomeworkFab()), ), - floatingActionButton: - BottomOfScrollViewInvisibility(child: HomeworkFab()), ), ), ), @@ -117,24 +143,29 @@ Future pumpHomeworkPage( } void main() { - group('TeacherHomeworkPage', () { - late MockTeacherHomeworkPageBloc homeworkPageBloc; + group('$TeacherAndParentHomeworkPage', () { + late MockTeacherAndParentHomeworkPageBloc homeworkPageBloc; // Can't use this because of weird async behavior: // https://github.com/flutter/flutter/issues/5728 // setUp(() { - // homeworkPageBloc = MockTeacherHomeworkPageBloc(); + // homeworkPageBloc = createBloc(); // }); tearDown(() { homeworkPageBloc.close(); }); + MockTeacherAndParentHomeworkPageBloc createBloc() { + final bloc = MockTeacherAndParentHomeworkPageBloc(); + return bloc; + } + testWidgets( 'placeholder is shown on open homework page when no homeworks are to do', (tester) async { // If I comment this out (--> use the bloc from setUp) it won't work anymore - homeworkPageBloc = MockTeacherHomeworkPageBloc(); + homeworkPageBloc = createBloc(); await _pumpHomeworkPageWithNoHomeworks(tester, bloc: homeworkPageBloc, initialTab: HomeworkTab.open); @@ -145,7 +176,7 @@ void main() { testWidgets( 'placeholder is shown in archived homework page when no homework is archived', (tester) async { - homeworkPageBloc = MockTeacherHomeworkPageBloc(); + homeworkPageBloc = createBloc(); await _pumpHomeworkPageWithNoHomeworks(tester, bloc: homeworkPageBloc, initialTab: HomeworkTab.archived); @@ -156,33 +187,32 @@ void main() { testWidgets('shows open homeworks with section titles in given order', (tester) async { - homeworkPageBloc = MockTeacherHomeworkPageBloc(); - - await pumpHomeworkPage(tester, - bloc: homeworkPageBloc, initialTab: HomeworkTab.open); + homeworkPageBloc = createBloc(); - homeworkPageBloc.emitNewState(Success( - TeacherOpenHomeworkListView( + final state = Success( + TeacherAndParentOpenHomeworkListView( IList([ - TeacherHomeworkSectionView( + HomeworkSectionView( 'Section 1', IListConst([ randomHomeworkViewWith(title: 'HW in first Section'), ])), - TeacherHomeworkSectionView( + HomeworkSectionView( 'Section 2', IList([ randomHomeworkViewWith(title: 'HW in second Section'), ])), ]), sorting: HomeworkSort.subjectSmallestDateAndTitleSort), - TeacherArchivedHomeworkListView( + LazyLoadingHomeworkListView( const IListConst([]), - loadedAllArchivedHomeworks: true, + loadedAllHomeworks: true, ), - )); + ); + homeworkPageBloc.emitNewState(state); - await tester.pump(); + await pumpHomeworkPage(tester, + bloc: homeworkPageBloc, initialTab: HomeworkTab.open); final sectionTitle1Offset = tester.getCenter(find.text('Section 1')); final ha1TitleOffset = tester.getCenter(find.text('HW in first Section')); @@ -208,7 +238,7 @@ void main() { testWidgets('shows curent sorting text inside of sort button', (tester) async { - homeworkPageBloc = MockTeacherHomeworkPageBloc(); + homeworkPageBloc = createBloc(); await pumpHomeworkPage(tester, bloc: homeworkPageBloc, initialTab: HomeworkTab.open); @@ -219,32 +249,33 @@ void main() { await tester.pump(); - expect(find.text(TeacherSortButton.sortByDateSortButtonUiString), - findsOneWidget); + expect( + find.text(SortButton.sortByDateSortButtonUiString), findsOneWidget); homeworkPageBloc.emitNewState( _openHomeworksWith(HomeworkSort.subjectSmallestDateAndTitleSort)); await tester.pumpAndSettle(); - expect(find.text(TeacherSortButton.sortBySubjectSortButtonUiString), + expect(find.text(SortButton.sortBySubjectSortButtonUiString), findsOneWidget); }); Future scrollDownToEndOfArchivedHomeworkList(WidgetTester tester) { return tester.drag( find.byWidgetPredicate( - (widget) => widget is TeacherArchivedHomeworkList), + (widget) => widget is TeacherAndParentArchivedHomeworkList), const Offset(0, -5000)); } - List generateRandomHomeworks({required int count}) { + List generateRandomHomeworks( + {required int count}) { return List.generate( count, (index) => randomHomeworkViewWith(/*Random content*/)); } testWidgets('lazy-loads archived homeworks', (tester) async { - homeworkPageBloc = MockTeacherHomeworkPageBloc(); + homeworkPageBloc = createBloc(); await pumpHomeworkPage(tester, bloc: homeworkPageBloc, initialTab: HomeworkTab.archived); @@ -254,9 +285,9 @@ void main() { homeworkPageBloc.emitNewState( Success( _noOpenHomeworks, - TeacherArchivedHomeworkListView( + LazyLoadingHomeworkListView( firstHomeworkBatch, - loadedAllArchivedHomeworks: false, + loadedAllHomeworks: false, ), ), ); @@ -287,10 +318,10 @@ void main() { homeworkPageBloc.emitNewState( Success( _noOpenHomeworks, - TeacherArchivedHomeworkListView( + LazyLoadingHomeworkListView( allLoadedHomeworks, // Now all homeworks are loaded - loadedAllArchivedHomeworks: true, + loadedAllHomeworks: true, ), ), ); @@ -318,7 +349,7 @@ void main() { testWidgets( 'pressing the sort button changes sorting to subject sort when current sort is date sort', (tester) async { - homeworkPageBloc = MockTeacherHomeworkPageBloc(); + homeworkPageBloc = createBloc(); await pumpHomeworkPage(tester, bloc: homeworkPageBloc, initialTab: HomeworkTab.open); @@ -340,7 +371,7 @@ void main() { testWidgets( 'pressing sort button changes sorting to date sort when current sort is subject sort', (tester) async { - homeworkPageBloc = MockTeacherHomeworkPageBloc(); + homeworkPageBloc = createBloc(); await pumpHomeworkPage(tester, bloc: homeworkPageBloc, initialTab: HomeworkTab.open); @@ -360,21 +391,21 @@ void main() { }); Future pumpHomeworkTiles( - WidgetTester tester, List views) async { - homeworkPageBloc = MockTeacherHomeworkPageBloc(); + WidgetTester tester, List views) async { + homeworkPageBloc = createBloc(); await pumpHomeworkPage(tester, bloc: homeworkPageBloc, initialTab: HomeworkTab.open); homeworkPageBloc.emitNewState(Success( - TeacherOpenHomeworkListView( + TeacherAndParentOpenHomeworkListView( IList([ - TeacherHomeworkSectionView('Section 1', views.toIList()), + HomeworkSectionView('Section 1', views.toIList()), ]), sorting: HomeworkSort.subjectSmallestDateAndTitleSort), - TeacherArchivedHomeworkListView( + LazyLoadingHomeworkListView( const IListConst([]), - loadedAllArchivedHomeworks: true, + loadedAllHomeworks: true, ), )); @@ -402,30 +433,30 @@ void main() { ]); expect( - find.widgetWithText( - TeacherHomeworkTile, '$nrOfCompletionsForNormalHomework'), + find.widgetWithText(TeacherAndParentHomeworkTile, + '$nrOfCompletionsForNormalHomework'), findsOneWidget); expect( - find.widgetWithText( - TeacherHomeworkTile, '$nrOfCompletionsForSubmittableHomework'), + find.widgetWithText(TeacherAndParentHomeworkTile, + '$nrOfCompletionsForSubmittableHomework'), findsOneWidget); }); testWidgets( 'displays no placeholder on archived homework tab when there are no homeworks loaded locally but not all homeworks have been loaded from the backend', (tester) async { - homeworkPageBloc = MockTeacherHomeworkPageBloc(); + homeworkPageBloc = createBloc(); await pumpHomeworkPage(tester, bloc: homeworkPageBloc, initialTab: HomeworkTab.archived); homeworkPageBloc.emitNewState(Success( _noOpenHomeworks, - TeacherArchivedHomeworkListView( + LazyLoadingHomeworkListView( // No homeworks loaded already const IListConst([]), // but there are homeworks to load - loadedAllArchivedHomeworks: false, + loadedAllHomeworks: false, ), )); @@ -450,8 +481,8 @@ class _HomeworkPageFinders { } class _OpenHomeworkTabFinders { - Finder get homeworkList => find.byType(TeacherOpenHomeworkList); - Finder get bnbSortButton => find.byType(TeacherSortButton); + Finder get homeworkList => find.byType(TeacherAndParentOpenHomeworkList); + Finder get bnbSortButton => find.byType(SortButton); Finder get noHomeworkPlaceholder => // Widget is private. Not sure if this is the best way or if we should make // the Widget public and use the type directly. @@ -460,7 +491,7 @@ class _OpenHomeworkTabFinders { } class _ArchivedHomeworkListFinders { - Finder get homeworkList => find.byType(TeacherArchivedHomeworkList); + Finder get homeworkList => find.byType(TeacherAndParentArchivedHomeworkList); Finder get noHomeworkPlaceholder => find // Widget is private. Not sure if this is the best way or if we should make // the Widget public and use the type directly. @@ -473,12 +504,12 @@ bool _randomBool() { return randomBetween(0, 2).isEven; } -TeacherHomeworkView randomHomeworkViewWith({ +TeacherAndParentHomeworkView randomHomeworkViewWith({ String? title, int? nrOfStudentsCompletedOrSubmitted, bool? withSubmissions, }) { - return TeacherHomeworkView( + return TeacherAndParentHomeworkView( id: HomeworkId(randomAlphaNumeric(10)), title: title ?? 'S. ${randomBetween(1, 300)} Nr. ${randomBetween(1, 20)}', abbreviation: 'E', @@ -496,9 +527,9 @@ TeacherHomeworkView randomHomeworkViewWith({ Success _openHomeworksWith(HomeworkSort sort) { return Success( - TeacherOpenHomeworkListView( + TeacherAndParentOpenHomeworkListView( IList([ - TeacherHomeworkSectionView( + HomeworkSectionView( 'Heute', IList([ randomHomeworkViewWith(title: 'S. 32'), @@ -512,25 +543,27 @@ Success _openHomeworksWith(HomeworkSort sort) { } final _noHomeworks = Success( - TeacherOpenHomeworkListView( + TeacherAndParentOpenHomeworkListView( const IListConst([]), sorting: HomeworkSort.smallestDateSubjectAndTitle, ), - TeacherArchivedHomeworkListView( + LazyLoadingHomeworkListView( const IListConst([]), - loadedAllArchivedHomeworks: true, + loadedAllHomeworks: true, ), ); -final _noOpenHomeworks = TeacherOpenHomeworkListView(const IListConst([]), - sorting: HomeworkSort.smallestDateSubjectAndTitle); -final _noArchivedHomeworks = TeacherArchivedHomeworkListView( +final _noOpenHomeworks = TeacherAndParentOpenHomeworkListView( const IListConst([]), - loadedAllArchivedHomeworks: true); + sorting: HomeworkSort.smallestDateSubjectAndTitle); +final _noArchivedHomeworks = + LazyLoadingHomeworkListView( + const IListConst([]), + loadedAllHomeworks: true); Future _pumpHomeworkPageWithNoHomeworks( WidgetTester tester, { - required MockTeacherHomeworkPageBloc bloc, + required MockTeacherAndParentHomeworkPageBloc bloc, HomeworkTab initialTab = HomeworkTab.open, }) async { await pumpHomeworkPage(tester, bloc: bloc, initialTab: initialTab); diff --git a/app/test/settings/support/support_page_test.mocks.dart b/app/test/settings/support/support_page_test.mocks.dart index 0959b9b93..32a9e9300 100644 --- a/app/test/settings/support/support_page_test.mocks.dart +++ b/app/test/settings/support/support_page_test.mocks.dart @@ -3,8 +3,6 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:ui' as _i5; - import 'package:common_domain_models/common_domain_models.dart' as _i3; import 'package:mockito/mockito.dart' as _i1; import 'package:mockito/src/dummies.dart' as _i4; @@ -136,7 +134,7 @@ class MockSupportPageController extends _i1.Mock ); @override - void addListener(_i5.VoidCallback? listener) => super.noSuchMethod( + void addListener(dynamic listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -145,7 +143,7 @@ class MockSupportPageController extends _i1.Mock ); @override - void removeListener(_i5.VoidCallback? listener) => super.noSuchMethod( + void removeListener(dynamic listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], diff --git a/app/test_goldens/calendrical_events/page/past_calendrical_events_page_test.mocks.dart b/app/test_goldens/calendrical_events/page/past_calendrical_events_page_test.mocks.dart index 83ece4678..ecc8f6e70 100644 --- a/app/test_goldens/calendrical_events/page/past_calendrical_events_page_test.mocks.dart +++ b/app/test_goldens/calendrical_events/page/past_calendrical_events_page_test.mocks.dart @@ -3,11 +3,9 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:ui' as _i15; - import 'package:clock/clock.dart' as _i6; import 'package:date/date.dart' as _i9; -import 'package:group_domain_models/group_domain_models.dart' as _i16; +import 'package:group_domain_models/group_domain_models.dart' as _i15; import 'package:mockito/mockito.dart' as _i1; import 'package:mockito/src/dummies.dart' as _i14; import 'package:sharezone/calendrical_events/analytics/past_calendrical_events_page_analytics.dart' @@ -378,7 +376,7 @@ class MockPastCalendricalEventsPageController extends _i1.Mock ); @override - void addListener(_i15.VoidCallback? listener) => super.noSuchMethod( + void addListener(dynamic listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -387,7 +385,7 @@ class MockPastCalendricalEventsPageController extends _i1.Mock ); @override - void removeListener(_i15.VoidCallback? listener) => super.noSuchMethod( + void removeListener(dynamic listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -449,11 +447,11 @@ class MockCalendricalEvent extends _i1.Mock implements _i12.CalendricalEvent { ) as String); @override - _i16.GroupType get groupType => (super.noSuchMethod( + _i15.GroupType get groupType => (super.noSuchMethod( Invocation.getter(#groupType), - returnValue: _i16.GroupType.course, - returnValueForMissingStub: _i16.GroupType.course, - ) as _i16.GroupType); + returnValue: _i15.GroupType.course, + returnValueForMissingStub: _i15.GroupType.course, + ) as _i15.GroupType); @override _i12.EventType get eventType => (super.noSuchMethod( @@ -575,7 +573,7 @@ class MockCalendricalEvent extends _i1.Mock implements _i12.CalendricalEvent { String? eventID, String? groupID, String? authorID, - _i16.GroupType? groupType, + _i15.GroupType? groupType, _i12.EventType? eventType, _i9.Date? date, _i10.Time? startTime, diff --git a/app/test_goldens/feedback/history/feedback_history_page_test.mocks.dart b/app/test_goldens/feedback/history/feedback_history_page_test.mocks.dart index c8748fbce..9fc25dca8 100644 --- a/app/test_goldens/feedback/history/feedback_history_page_test.mocks.dart +++ b/app/test_goldens/feedback/history/feedback_history_page_test.mocks.dart @@ -4,7 +4,6 @@ // ignore_for_file: no_leading_underscores_for_library_prefixes import 'dart:async' as _i8; -import 'dart:ui' as _i9; import 'package:common_domain_models/common_domain_models.dart' as _i3; import 'package:crash_analytics/crash_analytics.dart' as _i4; @@ -178,7 +177,7 @@ class MockFeedbackHistoryPageController extends _i1.Mock ); @override - void addListener(_i9.VoidCallback? listener) => super.noSuchMethod( + void addListener(dynamic listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -187,7 +186,7 @@ class MockFeedbackHistoryPageController extends _i1.Mock ); @override - void removeListener(_i9.VoidCallback? listener) => super.noSuchMethod( + void removeListener(dynamic listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], diff --git a/app/test_goldens/grades/pages/grade_details_page/grade_details_page_test.mocks.dart b/app/test_goldens/grades/pages/grade_details_page/grade_details_page_test.mocks.dart index bbc21b7cc..fd766e2f4 100644 --- a/app/test_goldens/grades/pages/grade_details_page/grade_details_page_test.mocks.dart +++ b/app/test_goldens/grades/pages/grade_details_page/grade_details_page_test.mocks.dart @@ -3,8 +3,6 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:ui' as _i7; - import 'package:analytics/analytics.dart' as _i4; import 'package:crash_analytics/crash_analytics.dart' as _i3; import 'package:mockito/mockito.dart' as _i1; @@ -13,7 +11,7 @@ import 'package:sharezone/grades/grades_service/grades_service.dart' as _i2; import 'package:sharezone/grades/pages/grades_details_page/grade_details_page_controller.dart' as _i5; import 'package:sharezone/grades/pages/grades_details_page/grade_details_page_controller_factory.dart' - as _i8; + as _i7; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -185,7 +183,7 @@ class MockGradeDetailsPageController extends _i1.Mock ); @override - void addListener(_i7.VoidCallback? listener) => super.noSuchMethod( + void addListener(dynamic listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -194,7 +192,7 @@ class MockGradeDetailsPageController extends _i1.Mock ); @override - void removeListener(_i7.VoidCallback? listener) => super.noSuchMethod( + void removeListener(dynamic listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -216,7 +214,7 @@ class MockGradeDetailsPageController extends _i1.Mock /// /// See the documentation for Mockito's code generation for more information. class MockGradeDetailsPageControllerFactory extends _i1.Mock - implements _i8.GradeDetailsPageControllerFactory { + implements _i7.GradeDetailsPageControllerFactory { @override _i2.GradesService get gradesService => (super.noSuchMethod( Invocation.getter(#gradesService), diff --git a/app/test_goldens/grades/pages/grades_page/grades_page_test.mocks.dart b/app/test_goldens/grades/pages/grades_page/grades_page_test.mocks.dart index 512ba409c..b69d136b4 100644 --- a/app/test_goldens/grades/pages/grades_page/grades_page_test.mocks.dart +++ b/app/test_goldens/grades/pages/grades_page/grades_page_test.mocks.dart @@ -3,8 +3,6 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:ui' as _i5; - import 'package:mockito/mockito.dart' as _i1; import 'package:mockito/src/dummies.dart' as _i4; import 'package:sharezone/grades/grades_service/grades_service.dart' as _i2; @@ -91,7 +89,7 @@ class MockGradesPageController extends _i1.Mock ); @override - void addListener(_i5.VoidCallback? listener) => super.noSuchMethod( + void addListener(dynamic listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -100,7 +98,7 @@ class MockGradesPageController extends _i1.Mock ); @override - void removeListener(_i5.VoidCallback? listener) => super.noSuchMethod( + void removeListener(dynamic listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], diff --git a/app/test_goldens/grades/pages/term_details_page/term_details_page_test.mocks.dart b/app/test_goldens/grades/pages/term_details_page/term_details_page_test.mocks.dart index 204e3f948..2ca7c971b 100644 --- a/app/test_goldens/grades/pages/term_details_page/term_details_page_test.mocks.dart +++ b/app/test_goldens/grades/pages/term_details_page/term_details_page_test.mocks.dart @@ -3,8 +3,6 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:ui' as _i7; - import 'package:analytics/analytics.dart' as _i4; import 'package:crash_analytics/crash_analytics.dart' as _i3; import 'package:mockito/mockito.dart' as _i1; @@ -13,7 +11,7 @@ import 'package:sharezone/grades/grades_service/grades_service.dart' as _i2; import 'package:sharezone/grades/pages/term_details_page/term_details_page_controller.dart' as _i5; import 'package:sharezone/grades/pages/term_details_page/term_details_page_controller_factory.dart' - as _i8; + as _i7; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -185,7 +183,7 @@ class MockTermDetailsPageController extends _i1.Mock ); @override - void addListener(_i7.VoidCallback? listener) => super.noSuchMethod( + void addListener(dynamic listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -194,7 +192,7 @@ class MockTermDetailsPageController extends _i1.Mock ); @override - void removeListener(_i7.VoidCallback? listener) => super.noSuchMethod( + void removeListener(dynamic listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -216,7 +214,7 @@ class MockTermDetailsPageController extends _i1.Mock /// /// See the documentation for Mockito's code generation for more information. class MockTermDetailsPageControllerFactory extends _i1.Mock - implements _i8.TermDetailsPageControllerFactory { + implements _i7.TermDetailsPageControllerFactory { @override _i2.GradesService get gradesService => (super.noSuchMethod( Invocation.getter(#gradesService), diff --git a/app/test_goldens/homework/teacher/homework_done_by_users_list/homework_completion_user_list_page_test.dart b/app/test_goldens/homework/teacher/homework_done_by_users_list/homework_completion_user_list_page_test.dart index ae48d539f..6b759f0ea 100644 --- a/app/test_goldens/homework/teacher/homework_done_by_users_list/homework_completion_user_list_page_test.dart +++ b/app/test_goldens/homework/teacher/homework_done_by_users_list/homework_completion_user_list_page_test.dart @@ -16,10 +16,10 @@ import 'package:golden_toolkit/golden_toolkit.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; import 'package:provider/provider.dart'; -import 'package:sharezone/homework/teacher/homework_done_by_users_list/homework_completion_user_list_bloc.dart'; -import 'package:sharezone/homework/teacher/homework_done_by_users_list/homework_completion_user_list_bloc_factory.dart'; -import 'package:sharezone/homework/teacher/homework_done_by_users_list/homework_completion_user_list_page.dart'; -import 'package:sharezone/homework/teacher/homework_done_by_users_list/user_has_completed_homework_view.dart'; +import 'package:sharezone/homework/teacher_and_parent/homework_done_by_users_list/homework_completion_user_list_bloc.dart'; +import 'package:sharezone/homework/teacher_and_parent/homework_done_by_users_list/homework_completion_user_list_bloc_factory.dart'; +import 'package:sharezone/homework/teacher_and_parent/homework_done_by_users_list/homework_completion_user_list_page.dart'; +import 'package:sharezone/homework/teacher_and_parent/homework_done_by_users_list/user_has_completed_homework_view.dart'; import 'package:sharezone/sharezone_plus/subscription_service/subscription_service.dart'; import 'package:sharezone_widgets/sharezone_widgets.dart'; diff --git a/app/test_goldens/homework/teacher/homework_done_by_users_list/homework_completion_user_list_page_test.mocks.dart b/app/test_goldens/homework/teacher/homework_done_by_users_list/homework_completion_user_list_page_test.mocks.dart index ca99bf7d9..2d5fc6201 100644 --- a/app/test_goldens/homework/teacher/homework_done_by_users_list/homework_completion_user_list_page_test.mocks.dart +++ b/app/test_goldens/homework/teacher/homework_done_by_users_list/homework_completion_user_list_page_test.mocks.dart @@ -8,11 +8,11 @@ import 'dart:async' as _i6; import 'package:cloud_functions/cloud_functions.dart' as _i3; import 'package:common_domain_models/common_domain_models.dart' as _i5; import 'package:mockito/mockito.dart' as _i1; -import 'package:sharezone/homework/teacher/homework_done_by_users_list/homework_completion_user_list_bloc.dart' +import 'package:sharezone/homework/teacher_and_parent/homework_done_by_users_list/homework_completion_user_list_bloc.dart' as _i2; -import 'package:sharezone/homework/teacher/homework_done_by_users_list/homework_completion_user_list_bloc_factory.dart' +import 'package:sharezone/homework/teacher_and_parent/homework_done_by_users_list/homework_completion_user_list_bloc_factory.dart' as _i4; -import 'package:sharezone/homework/teacher/homework_done_by_users_list/user_has_completed_homework_view.dart' +import 'package:sharezone/homework/teacher_and_parent/homework_done_by_users_list/user_has_completed_homework_view.dart' as _i7; import 'package:sharezone/sharezone_plus/subscription_service/subscription_service.dart' as _i8; diff --git a/app/test_goldens/settings/change_type_of_user/change_type_of_user_test.mocks.dart b/app/test_goldens/settings/change_type_of_user/change_type_of_user_test.mocks.dart index 22445c9bb..1202bf2ec 100644 --- a/app/test_goldens/settings/change_type_of_user/change_type_of_user_test.mocks.dart +++ b/app/test_goldens/settings/change_type_of_user/change_type_of_user_test.mocks.dart @@ -4,7 +4,6 @@ // ignore_for_file: no_leading_underscores_for_library_prefixes import 'dart:async' as _i8; -import 'dart:ui' as _i9; import 'package:common_domain_models/common_domain_models.dart' as _i2; import 'package:mockito/mockito.dart' as _i1; @@ -184,7 +183,7 @@ class MockChangeTypeOfUserController extends _i1.Mock ); @override - void addListener(_i9.VoidCallback? listener) => super.noSuchMethod( + void addListener(dynamic listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -193,7 +192,7 @@ class MockChangeTypeOfUserController extends _i1.Mock ); @override - void removeListener(_i9.VoidCallback? listener) => super.noSuchMethod( + void removeListener(dynamic listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], diff --git a/app/test_goldens/settings/support/support_page_test.mocks.dart b/app/test_goldens/settings/support/support_page_test.mocks.dart index ef568d818..6fa980a69 100644 --- a/app/test_goldens/settings/support/support_page_test.mocks.dart +++ b/app/test_goldens/settings/support/support_page_test.mocks.dart @@ -3,8 +3,6 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:ui' as _i5; - import 'package:common_domain_models/common_domain_models.dart' as _i3; import 'package:mockito/mockito.dart' as _i1; import 'package:mockito/src/dummies.dart' as _i4; @@ -136,7 +134,7 @@ class MockSupportPageController extends _i1.Mock ); @override - void addListener(_i5.VoidCallback? listener) => super.noSuchMethod( + void addListener(dynamic listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -145,7 +143,7 @@ class MockSupportPageController extends _i1.Mock ); @override - void removeListener(_i5.VoidCallback? listener) => super.noSuchMethod( + void removeListener(dynamic listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], diff --git a/app/test_goldens/sharezone_plus/sharezone_plus_page_test.mocks.dart b/app/test_goldens/sharezone_plus/sharezone_plus_page_test.mocks.dart index 5c202fe38..7d38a3dd9 100644 --- a/app/test_goldens/sharezone_plus/sharezone_plus_page_test.mocks.dart +++ b/app/test_goldens/sharezone_plus/sharezone_plus_page_test.mocks.dart @@ -4,33 +4,32 @@ // ignore_for_file: no_leading_underscores_for_library_prefixes import 'dart:async' as _i24; -import 'dart:ui' as _i25; import 'package:analytics/analytics.dart' as _i5; import 'package:app_functions/app_functions.dart' as _i20; -import 'package:authentification_base/authentification.dart' as _i33; -import 'package:cloud_firestore/cloud_firestore.dart' as _i34; +import 'package:authentification_base/authentification.dart' as _i32; +import 'package:cloud_firestore/cloud_firestore.dart' as _i33; import 'package:common_domain_models/common_domain_models.dart' as _i9; import 'package:feedback_shared_implementation/feedback_shared_implementation.dart' as _i21; -import 'package:firebase_auth/firebase_auth.dart' as _i35; +import 'package:firebase_auth/firebase_auth.dart' as _i34; import 'package:flutter/material.dart' as _i1; import 'package:mockito/mockito.dart' as _i2; -import 'package:mockito/src/dummies.dart' as _i32; +import 'package:mockito/src/dummies.dart' as _i31; import 'package:rxdart/rxdart.dart' as _i3; import 'package:shared_preferences/shared_preferences.dart' as _i7; import 'package:sharezone/feedback/unread_messages/has_unread_feedback_messages_provider.dart' - as _i36; + as _i35; import 'package:sharezone/filesharing/file_sharing_api.dart' as _i12; -import 'package:sharezone/main/application_bloc.dart' as _i31; +import 'package:sharezone/main/application_bloc.dart' as _i30; import 'package:sharezone/navigation/analytics/navigation_analytics.dart' - as _i30; -import 'package:sharezone/navigation/logic/navigation_bloc.dart' as _i26; -import 'package:sharezone/navigation/models/navigation_item.dart' as _i27; + as _i29; +import 'package:sharezone/navigation/logic/navigation_bloc.dart' as _i25; +import 'package:sharezone/navigation/models/navigation_item.dart' as _i26; import 'package:sharezone/navigation/scaffold/portable/bottom_navigation_bar/navigation_experiment/navigation_experiment_cache.dart' - as _i28; + as _i27; import 'package:sharezone/navigation/scaffold/portable/bottom_navigation_bar/navigation_experiment/navigation_experiment_option.dart' - as _i29; + as _i28; import 'package:sharezone/sharezone_plus/page/sharezone_plus_page_controller.dart' as _i22; import 'package:sharezone/util/api.dart' as _i4; @@ -494,7 +493,7 @@ class MockSharezonePlusPageController extends _i2.Mock ); @override - void addListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void addListener(dynamic listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -503,7 +502,7 @@ class MockSharezonePlusPageController extends _i2.Mock ); @override - void removeListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void removeListener(dynamic listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], @@ -524,7 +523,7 @@ class MockSharezonePlusPageController extends _i2.Mock /// A class which mocks [NavigationBloc]. /// /// See the documentation for Mockito's code generation for more information. -class MockNavigationBloc extends _i2.Mock implements _i26.NavigationBloc { +class MockNavigationBloc extends _i2.Mock implements _i25.NavigationBloc { @override _i1.GlobalKey<_i1.State<_i1.StatefulWidget>> get scaffoldKey => (super.noSuchMethod( @@ -571,25 +570,25 @@ class MockNavigationBloc extends _i2.Mock implements _i26.NavigationBloc { ) as _i1.GlobalKey<_i1.State<_i1.StatefulWidget>>); @override - _i24.Stream<_i27.NavigationItem> get currentItemStream => (super.noSuchMethod( + _i24.Stream<_i26.NavigationItem> get currentItemStream => (super.noSuchMethod( Invocation.getter(#currentItemStream), - returnValue: _i24.Stream<_i27.NavigationItem>.empty(), - returnValueForMissingStub: _i24.Stream<_i27.NavigationItem>.empty(), - ) as _i24.Stream<_i27.NavigationItem>); + returnValue: _i24.Stream<_i26.NavigationItem>.empty(), + returnValueForMissingStub: _i24.Stream<_i26.NavigationItem>.empty(), + ) as _i24.Stream<_i26.NavigationItem>); @override - _i27.NavigationItem get currentItem => (super.noSuchMethod( + _i26.NavigationItem get currentItem => (super.noSuchMethod( Invocation.getter(#currentItem), - returnValue: _i27.NavigationItem.overview, - returnValueForMissingStub: _i27.NavigationItem.overview, - ) as _i27.NavigationItem); + returnValue: _i26.NavigationItem.overview, + returnValueForMissingStub: _i26.NavigationItem.overview, + ) as _i26.NavigationItem); @override - dynamic Function(_i27.NavigationItem) get navigateTo => (super.noSuchMethod( + dynamic Function(_i26.NavigationItem) get navigateTo => (super.noSuchMethod( Invocation.getter(#navigateTo), - returnValue: (_i27.NavigationItem __p0) => null, - returnValueForMissingStub: (_i27.NavigationItem __p0) => null, - ) as dynamic Function(_i27.NavigationItem)); + returnValue: (_i26.NavigationItem __p0) => null, + returnValueForMissingStub: (_i26.NavigationItem __p0) => null, + ) as dynamic Function(_i26.NavigationItem)); @override void dispose() => super.noSuchMethod( @@ -605,24 +604,24 @@ class MockNavigationBloc extends _i2.Mock implements _i26.NavigationBloc { /// /// See the documentation for Mockito's code generation for more information. class MockNavigationExperimentCache extends _i2.Mock - implements _i28.NavigationExperimentCache { + implements _i27.NavigationExperimentCache { @override - _i3.ValueStream<_i29.NavigationExperimentOption> get currentNavigation => + _i3.ValueStream<_i28.NavigationExperimentOption> get currentNavigation => (super.noSuchMethod( Invocation.getter(#currentNavigation), - returnValue: _FakeValueStream_1<_i29.NavigationExperimentOption>( + returnValue: _FakeValueStream_1<_i28.NavigationExperimentOption>( this, Invocation.getter(#currentNavigation), ), returnValueForMissingStub: - _FakeValueStream_1<_i29.NavigationExperimentOption>( + _FakeValueStream_1<_i28.NavigationExperimentOption>( this, Invocation.getter(#currentNavigation), ), - ) as _i3.ValueStream<_i29.NavigationExperimentOption>); + ) as _i3.ValueStream<_i28.NavigationExperimentOption>); @override - void setNavigation(_i29.NavigationExperimentOption? option) => + void setNavigation(_i28.NavigationExperimentOption? option) => super.noSuchMethod( Invocation.method( #setNavigation, @@ -645,9 +644,9 @@ class MockNavigationExperimentCache extends _i2.Mock /// /// See the documentation for Mockito's code generation for more information. class MockNavigationAnalytics extends _i2.Mock - implements _i30.NavigationAnalytics { + implements _i29.NavigationAnalytics { @override - void logBottomNavigationBarEvent(_i27.NavigationItem? item) => + void logBottomNavigationBarEvent(_i26.NavigationItem? item) => super.noSuchMethod( Invocation.method( #logBottomNavigationBarEvent, @@ -657,7 +656,7 @@ class MockNavigationAnalytics extends _i2.Mock ); @override - void logDrawerEvent(_i27.NavigationItem? item) => super.noSuchMethod( + void logDrawerEvent(_i26.NavigationItem? item) => super.noSuchMethod( Invocation.method( #logDrawerEvent, [item], @@ -705,7 +704,7 @@ class MockNavigationAnalytics extends _i2.Mock /// A class which mocks [SharezoneContext]. /// /// See the documentation for Mockito's code generation for more information. -class MockSharezoneContext extends _i2.Mock implements _i31.SharezoneContext { +class MockSharezoneContext extends _i2.Mock implements _i30.SharezoneContext { @override _i4.SharezoneGateway get api => (super.noSuchMethod( Invocation.getter(#api), @@ -789,11 +788,11 @@ class MockSharezoneGateway extends _i2.Mock implements _i4.SharezoneGateway { @override String get uID => (super.noSuchMethod( Invocation.getter(#uID), - returnValue: _i32.dummyValue( + returnValue: _i31.dummyValue( this, Invocation.getter(#uID), ), - returnValueForMissingStub: _i32.dummyValue( + returnValueForMissingStub: _i31.dummyValue( this, Invocation.getter(#uID), ), @@ -880,11 +879,11 @@ class MockSharezoneGateway extends _i2.Mock implements _i4.SharezoneGateway { @override String get memberID => (super.noSuchMethod( Invocation.getter(#memberID), - returnValue: _i32.dummyValue( + returnValue: _i31.dummyValue( this, Invocation.getter(#memberID), ), - returnValueForMissingStub: _i32.dummyValue( + returnValueForMissingStub: _i31.dummyValue( this, Invocation.getter(#memberID), ), @@ -973,11 +972,11 @@ class MockUserGateway extends _i2.Mock implements _i13.UserGateway { @override String get uID => (super.noSuchMethod( Invocation.getter(#uID), - returnValue: _i32.dummyValue( + returnValue: _i31.dummyValue( this, Invocation.getter(#uID), ), - returnValueForMissingStub: _i32.dummyValue( + returnValueForMissingStub: _i31.dummyValue( this, Invocation.getter(#uID), ), @@ -991,11 +990,11 @@ class MockUserGateway extends _i2.Mock implements _i13.UserGateway { ) as _i24.Stream<_i19.AppUser?>); @override - _i24.Stream<_i33.AuthUser?> get authUserStream => (super.noSuchMethod( + _i24.Stream<_i32.AuthUser?> get authUserStream => (super.noSuchMethod( Invocation.getter(#authUserStream), - returnValue: _i24.Stream<_i33.AuthUser?>.empty(), - returnValueForMissingStub: _i24.Stream<_i33.AuthUser?>.empty(), - ) as _i24.Stream<_i33.AuthUser?>); + returnValue: _i24.Stream<_i32.AuthUser?>.empty(), + returnValueForMissingStub: _i24.Stream<_i32.AuthUser?>.empty(), + ) as _i24.Stream<_i32.AuthUser?>); @override _i24.Stream get isSignedInStream => (super.noSuchMethod( @@ -1005,20 +1004,20 @@ class MockUserGateway extends _i2.Mock implements _i13.UserGateway { ) as _i24.Stream); @override - _i24.Stream<_i34.DocumentSnapshot> get userDocument => + _i24.Stream<_i33.DocumentSnapshot> get userDocument => (super.noSuchMethod( Invocation.getter(#userDocument), - returnValue: _i24.Stream<_i34.DocumentSnapshot>.empty(), + returnValue: _i24.Stream<_i33.DocumentSnapshot>.empty(), returnValueForMissingStub: - _i24.Stream<_i34.DocumentSnapshot>.empty(), - ) as _i24.Stream<_i34.DocumentSnapshot>); + _i24.Stream<_i33.DocumentSnapshot>.empty(), + ) as _i24.Stream<_i33.DocumentSnapshot>); @override - _i24.Stream<_i33.Provider?> get providerStream => (super.noSuchMethod( + _i24.Stream<_i32.Provider?> get providerStream => (super.noSuchMethod( Invocation.getter(#providerStream), - returnValue: _i24.Stream<_i33.Provider?>.empty(), - returnValueForMissingStub: _i24.Stream<_i33.Provider?>.empty(), - ) as _i24.Stream<_i33.Provider?>); + returnValue: _i24.Stream<_i32.Provider?>.empty(), + returnValueForMissingStub: _i24.Stream<_i32.Provider?>.empty(), + ) as _i24.Stream<_i32.Provider?>); @override _i24.Future<_i19.AppUser> get() => (super.noSuchMethod( @@ -1074,7 +1073,7 @@ class MockUserGateway extends _i2.Mock implements _i13.UserGateway { ) as _i24.Stream); @override - _i24.Future linkWithCredential(_i35.AuthCredential? credential) => + _i24.Future linkWithCredential(_i34.AuthCredential? credential) => (super.noSuchMethod( Invocation.method( #linkWithCredential, @@ -1278,7 +1277,7 @@ class MockUserGateway extends _i2.Mock implements _i13.UserGateway { /// /// See the documentation for Mockito's code generation for more information. class MockHasUnreadFeedbackMessagesProvider extends _i2.Mock - implements _i36.HasUnreadFeedbackMessagesProvider { + implements _i35.HasUnreadFeedbackMessagesProvider { @override _i21.FeedbackApi get feedbackApi => (super.noSuchMethod( Invocation.getter(#feedbackApi), @@ -1329,7 +1328,7 @@ class MockHasUnreadFeedbackMessagesProvider extends _i2.Mock ); @override - void addListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void addListener(dynamic listener) => super.noSuchMethod( Invocation.method( #addListener, [listener], @@ -1338,7 +1337,7 @@ class MockHasUnreadFeedbackMessagesProvider extends _i2.Mock ); @override - void removeListener(_i25.VoidCallback? listener) => super.noSuchMethod( + void removeListener(dynamic listener) => super.noSuchMethod( Invocation.method( #removeListener, [listener], diff --git a/lib/abgabe/abgabe_client_lib/lib/src/erstellung/firestore_abgaben_gateway.dart b/lib/abgabe/abgabe_client_lib/lib/src/erstellung/firestore_abgaben_gateway.dart index 5fd88a086..a3fa0f113 100644 --- a/lib/abgabe/abgabe_client_lib/lib/src/erstellung/firestore_abgaben_gateway.dart +++ b/lib/abgabe/abgabe_client_lib/lib/src/erstellung/firestore_abgaben_gateway.dart @@ -16,7 +16,8 @@ import 'package:abgabe_client_lib/src/models/models.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:common_domain_models/common_domain_models.dart'; -import 'package:firebase_hausaufgabenheft_logik/firebase_hausaufgabenheft_logik.dart'; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; + import 'package:rxdart/rxdart.dart'; class FirestoreAbgabeGateway @@ -55,9 +56,14 @@ class FirestoreAbgabeGateway return homeworkCollection .doc('$homeworkId') .snapshots() - .asyncMap((event) => tryToConvertToHomework(event, '$userId')) .whereNotNull() - .map((event) => event.todoDate); + .asyncMap((event) { + final homework = HomeworkDto.fromData( + event.data() as Map, + id: event.id, + ); + return homework.todoUntil; + }); } @override diff --git a/lib/abgabe/abgabe_client_lib/pubspec.lock b/lib/abgabe/abgabe_client_lib/pubspec.lock index 0510d2611..48d9d8b71 100644 --- a/lib/abgabe/abgabe_client_lib/pubspec.lock +++ b/lib/abgabe/abgabe_client_lib/pubspec.lock @@ -353,6 +353,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.1" + fast_immutable_collections: + dependency: transitive + description: + name: fast_immutable_collections + sha256: b910ccdc99bb38a2abbce07c5afb8f81d4e222a892e4d095a548b99814837b0c + url: "https://pub.dev" + source: hosted + version: "9.2.1" ffi: dependency: transitive description: @@ -518,13 +526,6 @@ packages: url: "https://pub.dev" source: hosted version: "3.6.32" - firebase_hausaufgabenheft_logik: - dependency: "direct main" - description: - path: "../../firebase_hausaufgabenheft_logik" - relative: true - source: path - version: "0.0.1" firebase_storage: dependency: transitive description: @@ -702,7 +703,7 @@ packages: source: hosted version: "1.4.1" hausaufgabenheft_logik: - dependency: transitive + dependency: "direct main" description: path: "../../hausaufgabenheft_logik" relative: true diff --git a/lib/abgabe/abgabe_client_lib/pubspec.yaml b/lib/abgabe/abgabe_client_lib/pubspec.yaml index 73fe4f5f9..bd66433f8 100644 --- a/lib/abgabe/abgabe_client_lib/pubspec.yaml +++ b/lib/abgabe/abgabe_client_lib/pubspec.yaml @@ -28,8 +28,8 @@ dependencies: path: ../../filesharing/files_basics filesharing_logic: path: ../../filesharing/filesharing_logic - firebase_hausaufgabenheft_logik: - path: ../../firebase_hausaufgabenheft_logik + hausaufgabenheft_logik: + path: ../../hausaufgabenheft_logik built_collection: ^5.1.0 cloud_firestore: ^4.17.2 gcloud: any diff --git a/lib/firebase_hausaufgabenheft_logik/.gitignore b/lib/firebase_hausaufgabenheft_logik/.gitignore deleted file mode 100644 index 3132dc5ff..000000000 --- a/lib/firebase_hausaufgabenheft_logik/.gitignore +++ /dev/null @@ -1,73 +0,0 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.buildlog/ -.history -.svn/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -**/doc/api/ -.dart_tool/ -.flutter-plugins -.packages -.pub-cache/ -.pub/ -build/ - -# Android related -**/android/**/gradle-wrapper.jar -**/android/.gradle -**/android/captures/ -**/android/gradlew -**/android/gradlew.bat -**/android/local.properties -**/android/**/GeneratedPluginRegistrant.java - -# iOS/XCode related -**/ios/**/*.mode1v3 -**/ios/**/*.mode2v3 -**/ios/**/*.moved-aside -**/ios/**/*.pbxuser -**/ios/**/*.perspectivev3 -**/ios/**/*sync/ -**/ios/**/.sconsign.dblite -**/ios/**/.tags* -**/ios/**/.vagrant/ -**/ios/**/DerivedData/ -**/ios/**/Icon? -**/ios/**/Pods/ -**/ios/**/.symlinks/ -**/ios/**/profile -**/ios/**/xcuserdata -**/ios/.generated/ -**/ios/Flutter/App.framework -**/ios/Flutter/Flutter.framework -**/ios/Flutter/Generated.xcconfig -**/ios/Flutter/app.flx -**/ios/Flutter/app.zip -**/ios/Flutter/flutter_assets/ -**/ios/Flutter/flutter_export_environment.sh -**/ios/ServiceDefinitions.json -**/ios/Runner/GeneratedPluginRegistrant.* - -# Exceptions to above rules. -!**/ios/**/default.mode1v3 -!**/ios/**/default.mode2v3 -!**/ios/**/default.pbxuser -!**/ios/**/default.perspectivev3 -!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages diff --git a/lib/firebase_hausaufgabenheft_logik/.metadata b/lib/firebase_hausaufgabenheft_logik/.metadata deleted file mode 100644 index f917a52ed..000000000 --- a/lib/firebase_hausaufgabenheft_logik/.metadata +++ /dev/null @@ -1,10 +0,0 @@ -# This file tracks properties of this Flutter project. -# Used by Flutter tool to assess capabilities and perform upgrades etc. -# -# This file should be version controlled and should not be manually edited. - -version: - revision: e70236e36ce1d32067dc68eb55519ec3e14b6b01 - channel: beta - -project_type: package diff --git a/lib/firebase_hausaufgabenheft_logik/analysis_options.yaml b/lib/firebase_hausaufgabenheft_logik/analysis_options.yaml deleted file mode 100644 index 1e445c14e..000000000 --- a/lib/firebase_hausaufgabenheft_logik/analysis_options.yaml +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2023 Sharezone UG (haftungsbeschränkt) -# Licensed under the EUPL-1.2-or-later. -# -# You may obtain a copy of the Licence at: -# https://joinup.ec.europa.eu/software/page/eupl -# -# SPDX-License-Identifier: EUPL-1.2 - -include: package:sharezone_lints/analysis_options.yaml diff --git a/lib/firebase_hausaufgabenheft_logik/lib/firebase_hausaufgabenheft_logik.dart b/lib/firebase_hausaufgabenheft_logik/lib/firebase_hausaufgabenheft_logik.dart deleted file mode 100644 index f9c3ae177..000000000 --- a/lib/firebase_hausaufgabenheft_logik/lib/firebase_hausaufgabenheft_logik.dart +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -library firebase_hausaufgaben_logik; - -export 'src/firestore_completion_dispatcher.dart'; -export 'src/firestore_homework_data_source.dart'; -export 'src/firestore_realtime_completed_homework_loader.dart'; -export 'src/homework_transformation.dart'; -export 'src/realtime_updating_lazy_loading_controller_factory.dart'; -export 'src/homework_dto.dart'; diff --git a/lib/firebase_hausaufgabenheft_logik/lib/src/create_default_firestore_repository.dart b/lib/firebase_hausaufgabenheft_logik/lib/src/create_default_firestore_repository.dart deleted file mode 100644 index cba41f2bd..000000000 --- a/lib/firebase_hausaufgabenheft_logik/lib/src/create_default_firestore_repository.dart +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:firebase_hausaufgabenheft_logik/src/firestore_homework_data_source.dart'; - -import 'firestore_realtime_completed_homework_loader.dart'; -import 'homework_transformation.dart'; -import 'realtime_updating_lazy_loading_controller_factory.dart'; - -FirestoreHomeworkDataSource createDefaultFirestoreRepository( - CollectionReference homeworkCollection, - String uid, - CourseColorRetriever getCourseColorFromCourseId) { - final homeworkLoader = FirestoreRealtimeCompletedHomeworkLoader( - homeworkCollection, - uid, - HomeworkTransformer(uid, - getCourseColorHexValue: getCourseColorFromCourseId), - ); - - final lazyLoadingControllerFactory = - RealtimeUpdatingLazyLoadingControllerFactory(homeworkLoader); - final firestoreHomeworkRepository = FirestoreHomeworkDataSource( - homeworkCollection, - uid, - lazyLoadingControllerFactory.create, - HomeworkTransformer(uid, - getCourseColorHexValue: getCourseColorFromCourseId), - ); - return firestoreHomeworkRepository; -} diff --git a/lib/firebase_hausaufgabenheft_logik/lib/src/firestore_completion_dispatcher.dart b/lib/firebase_hausaufgabenheft_logik/lib/src/firestore_completion_dispatcher.dart deleted file mode 100644 index e906dcfb9..000000000 --- a/lib/firebase_hausaufgabenheft_logik/lib/src/firestore_completion_dispatcher.dart +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'package:cloud_firestore/cloud_firestore.dart'; - -import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; - -class FirestoreHomeworkCompletionDispatcher - extends HomeworkCompletionDispatcher { - final CollectionReference _homeworkCollection; - final String Function() getCurrentUserId; - - FirestoreHomeworkCompletionDispatcher( - this._homeworkCollection, this.getCurrentUserId); - - @override - Future dispatch(HomeworkCompletion homeworkCompletion) async { - final uid = getCurrentUserId(); - final documentReference = - _homeworkCollection.doc(homeworkCompletion.homeworkId.toString()); - switch (homeworkCompletion.newCompletionValue) { - case CompletionStatus.completed: - documentReference.update({ - 'assignedUserArrays.completedStudentUids': - FieldValue.arrayUnion([uid]) - }); - documentReference.update({ - 'assignedUserArrays.openStudentUids': FieldValue.arrayRemove([uid]) - }); - break; - case CompletionStatus.open: - documentReference.update({ - 'assignedUserArrays.completedStudentUids': - FieldValue.arrayRemove([uid]) - }); - documentReference.update({ - 'assignedUserArrays.openStudentUids': FieldValue.arrayUnion([uid]) - }); - break; - } - } -} diff --git a/lib/firebase_hausaufgabenheft_logik/lib/src/firestore_homework_data_source.dart b/lib/firebase_hausaufgabenheft_logik/lib/src/firestore_homework_data_source.dart deleted file mode 100644 index bf6f23288..000000000 --- a/lib/firebase_hausaufgabenheft_logik/lib/src/firestore_homework_data_source.dart +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'dart:async'; - -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:common_domain_models/common_domain_models.dart'; -import 'package:fast_immutable_collections/fast_immutable_collections.dart'; -import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; -import 'homework_transformation.dart'; - -class FirestoreHomeworkDataSource extends HomeworkDataSource { - final CollectionReference _homeworkCollection; - final String uid; - final LazyLoadingController Function(int nrOfInitialHomeworksToLoad) - createLazyLoadingController; - final HomeworkTransformer _homeworkTransformer; - - FirestoreHomeworkDataSource(this._homeworkCollection, this.uid, - this.createLazyLoadingController, this._homeworkTransformer); - - @override - Stream> get openHomeworks { - return _homeworkCollection - .where("assignedUserArrays.openStudentUids", arrayContains: uid) - .snapshots() - .transform(_homeworkTransformer); - } - - Future findById(HomeworkId id) async { - final document = await _homeworkCollection.doc(id.toString()).get(); - final homework = await tryToConvertToHomework(document, uid); - return homework; - } - - Future> getCurrentOpenOverdueHomeworkIds() async { - final open = await openHomeworks.first; - final overdue = open - .where((homeworks) => homeworks.isOverdueRelativeTo(Date.now())) - .toList(); - final overdueIds = overdue.map((hws) => hws.id).toIList(); - return overdueIds; - } - - @override - LazyLoadingController getLazyLoadingCompletedHomeworksController( - int nrOfInitialHomeworkToLoad) { - return createLazyLoadingController(nrOfInitialHomeworkToLoad); - } -} diff --git a/lib/firebase_hausaufgabenheft_logik/lib/src/firestore_realtime_completed_homework_loader.dart b/lib/firebase_hausaufgabenheft_logik/lib/src/firestore_realtime_completed_homework_loader.dart deleted file mode 100644 index 572d0c792..000000000 --- a/lib/firebase_hausaufgabenheft_logik/lib/src/firestore_realtime_completed_homework_loader.dart +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:fast_immutable_collections/fast_immutable_collections.dart'; -import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; - -import 'homework_transformation.dart'; -import 'realtime_completed_homework_loader.dart'; - -class FirestoreRealtimeCompletedHomeworkLoader - extends RealtimeCompletedHomeworkLoader { - final CollectionReference _homeworkCollection; - final String _userId; - final HomeworkTransformer _homeworkTransformer; - - FirestoreRealtimeCompletedHomeworkLoader( - this._homeworkCollection, this._userId, this._homeworkTransformer); - - @override - Stream> loadMostRecentHomeworks( - int numberOfHomeworks) { - return _homeworkCollection - .where('assignedUserArrays.completedStudentUids', - arrayContains: _userId) - .orderBy('createdOn', descending: true) - .limit(numberOfHomeworks) - .snapshots() - .transform(_homeworkTransformer); - } -} diff --git a/lib/firebase_hausaufgabenheft_logik/lib/src/realtime_updating_lazy_loading_controller_factory.dart b/lib/firebase_hausaufgabenheft_logik/lib/src/realtime_updating_lazy_loading_controller_factory.dart deleted file mode 100644 index 5b1e01c05..000000000 --- a/lib/firebase_hausaufgabenheft_logik/lib/src/realtime_updating_lazy_loading_controller_factory.dart +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'realtime_completed_homework_loader.dart'; -import 'realtime_updating_lazy_loading_controller.dart'; - -class RealtimeUpdatingLazyLoadingControllerFactory { - final RealtimeCompletedHomeworkLoader _homeworkLoader; - - RealtimeUpdatingLazyLoadingControllerFactory(this._homeworkLoader); - - RealtimeUpdatingLazyLoadingController create( - int initialNumberOfHomeworksToLoad) { - return RealtimeUpdatingLazyLoadingController(_homeworkLoader, - initialNumberOfHomeworksToLoad: initialNumberOfHomeworksToLoad); - } -} diff --git a/lib/firebase_hausaufgabenheft_logik/pubspec.lock b/lib/firebase_hausaufgabenheft_logik/pubspec.lock deleted file mode 100644 index 7f904b577..000000000 --- a/lib/firebase_hausaufgabenheft_logik/pubspec.lock +++ /dev/null @@ -1,489 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - _flutterfire_internals: - dependency: transitive - description: - name: _flutterfire_internals - sha256: "3dee3db3468c5f4640a4e8aa9c1e22561c298976d8c39ed2fdd456a9a3db26e1" - url: "https://pub.dev" - source: hosted - version: "1.3.32" - args: - dependency: transitive - description: - name: args - sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 - url: "https://pub.dev" - source: hosted - version: "2.4.2" - asn1lib: - dependency: transitive - description: - name: asn1lib - sha256: "21afe4333076c02877d14f4a89df111e658a6d466cbfc802eb705eb91bd5adfd" - url: "https://pub.dev" - source: hosted - version: "1.5.0" - async: - dependency: transitive - description: - name: async - sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" - url: "https://pub.dev" - source: hosted - version: "2.11.0" - bloc: - dependency: transitive - description: - name: bloc - sha256: "3820f15f502372d979121de1f6b97bfcf1630ebff8fe1d52fb2b0bfa49be5b49" - url: "https://pub.dev" - source: hosted - version: "8.1.2" - bloc_base: - dependency: transitive - description: - path: "../bloc_base" - relative: true - source: path - version: "0.0.0" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" - url: "https://pub.dev" - source: hosted - version: "2.1.1" - characters: - dependency: transitive - description: - name: characters - sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" - url: "https://pub.dev" - source: hosted - version: "1.3.0" - clock: - dependency: "direct main" - description: - name: clock - sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf - url: "https://pub.dev" - source: hosted - version: "1.1.1" - cloud_firestore: - dependency: "direct main" - description: - name: cloud_firestore - sha256: "58ea77912e355cfd4e49f858e01d5ab4f99c7181ebd545b3fbeae25d6677dff6" - url: "https://pub.dev" - source: hosted - version: "4.17.2" - cloud_firestore_helper: - dependency: "direct main" - description: - path: "../cloud_firestore_helper" - relative: true - source: path - version: "0.0.1" - cloud_firestore_platform_interface: - dependency: transitive - description: - name: cloud_firestore_platform_interface - sha256: "9cb7d350c08c3d4987d34f418037aca3882649cdad5158440b4b932232edcf82" - url: "https://pub.dev" - source: hosted - version: "6.2.2" - cloud_firestore_web: - dependency: transitive - description: - name: cloud_firestore_web - sha256: "28db029962ebdcb8caf80f0c109f359ebcefa983b85fb62e5a220b1a577d84b5" - url: "https://pub.dev" - source: hosted - version: "3.12.2" - collection: - dependency: "direct main" - description: - name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a - url: "https://pub.dev" - source: hosted - version: "1.18.0" - common_domain_models: - dependency: "direct main" - description: - path: "../common_domain_models" - relative: true - source: path - version: "0.0.0" - convert: - dependency: transitive - description: - name: convert - sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" - url: "https://pub.dev" - source: hosted - version: "3.1.1" - crypto: - dependency: transitive - description: - name: crypto - sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab - url: "https://pub.dev" - source: hosted - version: "3.0.3" - encrypt: - dependency: transitive - description: - name: encrypt - sha256: "4fd4e4fdc21b9d7d4141823e1e6515cd94e7b8d84749504c232999fba25d9bbb" - url: "https://pub.dev" - source: hosted - version: "5.0.1" - equatable: - dependency: transitive - description: - name: equatable - sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2 - url: "https://pub.dev" - source: hosted - version: "2.0.5" - fake_async: - dependency: transitive - description: - name: fake_async - sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" - url: "https://pub.dev" - source: hosted - version: "1.3.1" - fast_immutable_collections: - dependency: "direct main" - description: - name: fast_immutable_collections - sha256: b910ccdc99bb38a2abbce07c5afb8f81d4e222a892e4d095a548b99814837b0c - url: "https://pub.dev" - source: hosted - version: "9.2.1" - firebase_core: - dependency: transitive - description: - name: firebase_core - sha256: "4aef2a23d0f3265545807d68fbc2f76a6b994ca3c778d88453b99325abd63284" - url: "https://pub.dev" - source: hosted - version: "2.30.1" - firebase_core_platform_interface: - dependency: transitive - description: - name: firebase_core_platform_interface - sha256: c437ae5d17e6b5cc7981cf6fd458a5db4d12979905f9aafd1fea930428a9fe63 - url: "https://pub.dev" - source: hosted - version: "5.0.0" - firebase_core_web: - dependency: transitive - description: - name: firebase_core_web - sha256: "67f2fcc600fc78c2f731c370a3a5e6c87ee862e3a2fba6f951eca6d5dafe5c29" - url: "https://pub.dev" - source: hosted - version: "2.16.0" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_lints: - dependency: transitive - description: - name: flutter_lints - sha256: e2a421b7e59244faef694ba7b30562e489c2b489866e505074eb005cd7060db7 - url: "https://pub.dev" - source: hosted - version: "3.0.1" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - flutter_web_plugins: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - hausaufgabenheft_logik: - dependency: "direct main" - description: - path: "../hausaufgabenheft_logik" - relative: true - source: path - version: "0.0.0" - http: - dependency: transitive - description: - name: http - sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938" - url: "https://pub.dev" - source: hosted - version: "1.2.1" - http_parser: - dependency: transitive - description: - name: http_parser - sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" - url: "https://pub.dev" - source: hosted - version: "4.0.2" - intl: - dependency: transitive - description: - name: intl - sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf - url: "https://pub.dev" - source: hosted - version: "0.19.0" - js: - dependency: transitive - description: - name: js - sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 - url: "https://pub.dev" - source: hosted - version: "0.6.7" - key_value_store: - dependency: transitive - description: - path: "../key_value_store" - relative: true - source: path - version: "0.0.1" - leak_tracker: - dependency: transitive - description: - name: leak_tracker - sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" - url: "https://pub.dev" - source: hosted - version: "10.0.4" - leak_tracker_flutter_testing: - dependency: transitive - description: - name: leak_tracker_flutter_testing - sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" - url: "https://pub.dev" - source: hosted - version: "3.0.3" - leak_tracker_testing: - dependency: transitive - description: - name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" - url: "https://pub.dev" - source: hosted - version: "3.0.1" - lints: - dependency: transitive - description: - name: lints - sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290 - url: "https://pub.dev" - source: hosted - version: "3.0.0" - logging: - dependency: transitive - description: - name: logging - sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" - url: "https://pub.dev" - source: hosted - version: "1.2.0" - matcher: - dependency: transitive - description: - name: matcher - sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb - url: "https://pub.dev" - source: hosted - version: "0.12.16+1" - material_color_utilities: - dependency: transitive - description: - name: material_color_utilities - sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" - url: "https://pub.dev" - source: hosted - version: "0.8.0" - meta: - dependency: transitive - description: - name: meta - sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" - url: "https://pub.dev" - source: hosted - version: "1.12.0" - path: - dependency: transitive - description: - name: path - sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" - url: "https://pub.dev" - source: hosted - version: "1.9.0" - plugin_platform_interface: - dependency: transitive - description: - name: plugin_platform_interface - sha256: "43798d895c929056255600343db8f049921cbec94d31ec87f1dc5c16c01935dd" - url: "https://pub.dev" - source: hosted - version: "2.1.5" - pointycastle: - dependency: transitive - description: - name: pointycastle - sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c" - url: "https://pub.dev" - source: hosted - version: "3.7.3" - random_string: - dependency: transitive - description: - name: random_string - sha256: "03b52435aae8cbdd1056cf91bfc5bf845e9706724dd35ae2e99fa14a1ef79d02" - url: "https://pub.dev" - source: hosted - version: "2.3.1" - rsa_pkcs: - dependency: transitive - description: - name: rsa_pkcs - sha256: "17a52b0c010319f0d4c7bcc635eb89e2efeaec44975b3fb45f850b350a2b0513" - url: "https://pub.dev" - source: hosted - version: "2.0.1" - rxdart: - dependency: "direct dev" - description: - name: rxdart - sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb" - url: "https://pub.dev" - source: hosted - version: "0.27.7" - sharezone_lints: - dependency: "direct dev" - description: - path: "../sharezone_lints" - relative: true - source: path - version: "1.0.0" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.99" - source_span: - dependency: transitive - description: - name: source_span - sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" - url: "https://pub.dev" - source: hosted - version: "1.10.0" - stack_trace: - dependency: transitive - description: - name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" - url: "https://pub.dev" - source: hosted - version: "1.11.1" - stream_channel: - dependency: transitive - description: - name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 - url: "https://pub.dev" - source: hosted - version: "2.1.2" - string_scanner: - dependency: transitive - description: - name: string_scanner - sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" - url: "https://pub.dev" - source: hosted - version: "1.2.0" - term_glyph: - dependency: transitive - description: - name: term_glyph - sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 - url: "https://pub.dev" - source: hosted - version: "1.2.1" - test_api: - dependency: transitive - description: - name: test_api - sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" - url: "https://pub.dev" - source: hosted - version: "0.7.0" - test_randomness: - dependency: transitive - description: - path: "../test_randomness" - relative: true - source: path - version: "0.0.1" - time: - dependency: "direct main" - description: - path: "../time" - relative: true - source: path - version: "1.0.0" - typed_data: - dependency: transitive - description: - name: typed_data - sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c - url: "https://pub.dev" - source: hosted - version: "1.3.2" - util: - dependency: transitive - description: - path: "../util" - relative: true - source: path - version: "0.0.1" - vector_math: - dependency: transitive - description: - name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" - url: "https://pub.dev" - source: hosted - version: "2.1.4" - vm_service: - dependency: transitive - description: - name: vm_service - sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" - url: "https://pub.dev" - source: hosted - version: "14.2.1" - web: - dependency: transitive - description: - name: web - sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" - url: "https://pub.dev" - source: hosted - version: "0.5.1" -sdks: - dart: ">=3.3.0 <4.0.0" - flutter: ">=3.18.0-18.0.pre.54" diff --git a/lib/firebase_hausaufgabenheft_logik/pubspec.yaml b/lib/firebase_hausaufgabenheft_logik/pubspec.yaml deleted file mode 100644 index 7aed50061..000000000 --- a/lib/firebase_hausaufgabenheft_logik/pubspec.yaml +++ /dev/null @@ -1,76 +0,0 @@ -# Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -# Licensed under the EUPL-1.2-or-later. -# -# You may obtain a copy of the Licence at: -# https://joinup.ec.europa.eu/software/page/eupl -# -# SPDX-License-Identifier: EUPL-1.2 - -name: firebase_hausaufgabenheft_logik -description: A new Flutter package project. -version: 0.0.1 -publish_to: none - -environment: - sdk: '>=3.1.0 <4.0.0' - -dependencies: - collection: ^1.17.2 - cloud_firestore_helper: - path: ../cloud_firestore_helper - hausaufgabenheft_logik: - path: ../hausaufgabenheft_logik - common_domain_models: - path: ../common_domain_models - time: - path: ../time - cloud_firestore: ^4.17.2 - fast_immutable_collections: ^9.1.5 - flutter: - sdk: flutter - clock: ^1.1.1 - -dev_dependencies: - rxdart: ^0.27.1 - flutter_test: - sdk: flutter - sharezone_lints: - path: ../sharezone_lints - - -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec - -# The following section is specific to Flutter. -flutter: - - # To add assets to your package, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - # - # For details regarding assets in packages, see - # https://flutter.dev/assets-and-images/#from-packages - # - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/assets-and-images/#resolution-aware. - - # To add custom fonts to your package, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts in packages, see - # https://flutter.dev/custom-fonts/#from-packages diff --git a/lib/firebase_hausaufgabenheft_logik/test/in_memory_homework_loader.dart b/lib/firebase_hausaufgabenheft_logik/test/in_memory_homework_loader.dart deleted file mode 100644 index e57539347..000000000 --- a/lib/firebase_hausaufgabenheft_logik/test/in_memory_homework_loader.dart +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'package:fast_immutable_collections/fast_immutable_collections.dart'; -import 'package:firebase_hausaufgabenheft_logik/src/realtime_completed_homework_loader.dart'; -import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; -import 'package:rxdart/subjects.dart'; - -class InMemoryHomeworkLoader extends RealtimeCompletedHomeworkLoader { - final BehaviorSubject> _completedHomeworksSubject; - - InMemoryHomeworkLoader(this._completedHomeworksSubject); - - @override - Stream> loadMostRecentHomeworks( - int numberOfHomeworks) { - return _completedHomeworksSubject.map((homeworks) { - if (homeworks.length < numberOfHomeworks) return homeworks; - return homeworks.sublist(0, numberOfHomeworks); - }); - } -} diff --git a/lib/hausaufgabenheft_logik/lib/color.dart b/lib/hausaufgabenheft_logik/lib/color.dart index 9584cd30e..d70cf381e 100644 --- a/lib/hausaufgabenheft_logik/lib/color.dart +++ b/lib/hausaufgabenheft_logik/lib/color.dart @@ -10,4 +10,4 @@ /// with flutters Color-class library; -export 'src/views/color.dart'; +export 'src/shared/color.dart'; diff --git a/lib/hausaufgabenheft_logik/lib/hausaufgabenheft_logik.dart b/lib/hausaufgabenheft_logik/lib/hausaufgabenheft_logik.dart index 0d6924715..a42fceea7 100644 --- a/lib/hausaufgabenheft_logik/lib/hausaufgabenheft_logik.dart +++ b/lib/hausaufgabenheft_logik/lib/hausaufgabenheft_logik.dart @@ -39,17 +39,18 @@ /// library hausaufgabenheft_logik; -export 'src/completed_homeworks/views/completed_homwork_list_view.dart'; -export 'src/data_source/homework_data_source.dart'; -export 'src/homework_completion/homework_completion_dispatcher.dart'; -export 'src/homework_list_extensions.dart'; -export 'src/models/homework.dart'; -export 'src/models/models.dart'; -export 'src/open_homeworks/sort_and_subcategorization/sort/src/sort.dart'; -export 'src/open_homeworks/sort_and_subcategorization/sort_and_subcategorizer.dart'; -export 'src/open_homeworks/views/homework_section_view.dart'; -export 'src/open_homeworks/views/open_homework_list_view.dart'; -export 'src/student_homework_page_bloc/events.dart'; -export 'src/student_homework_page_bloc/states.dart'; -export 'src/student_homework_page_bloc/student_homework_page_bloc.dart'; -export 'src/views/homework_view.dart'; +export 'src/firebase/firebase_hausaufgabenheft_logik.dart'; +export 'src/shared/homework_list_extensions.dart'; +export 'src/shared/homework_page_api.dart'; +export 'src/shared/models/homework.dart'; +export 'src/shared/models/models.dart'; +export 'src/shared/homework_section_view.dart'; +export 'src/student/views/student_homework_section_view.dart'; +export 'src/student/views/student_open_homework_list_view.dart'; +export 'src/shared/lazy_loading_homework_list_view.dart'; +export 'src/shared/sort/sorts.dart'; +export 'src/student/student_homework_list_extensions.dart'; +export 'src/student/bloc/events.dart'; +export 'src/student/bloc/states.dart'; +export 'src/student/bloc/student_homework_page_bloc.dart'; +export 'src/student/views/student_homework_view.dart'; diff --git a/lib/hausaufgabenheft_logik/lib/hausaufgabenheft_logik_lehrer.dart b/lib/hausaufgabenheft_logik/lib/hausaufgabenheft_logik_lehrer.dart index 23a0faa4c..030981d08 100644 --- a/lib/hausaufgabenheft_logik/lib/hausaufgabenheft_logik_lehrer.dart +++ b/lib/hausaufgabenheft_logik/lib/hausaufgabenheft_logik_lehrer.dart @@ -6,11 +6,14 @@ // // SPDX-License-Identifier: EUPL-1.2 -export './src/lehrer/teacher_archived_homework_list_view.dart'; -export './src/lehrer/teacher_homework_view.dart'; -export './src/lehrer/teacher_homework_page_bloc.dart'; -export './src/lehrer/teacher_homework_section_view.dart'; -export './src/lehrer/teacher_open_homework_list_view.dart'; -export './src/lehrer/create_teacher_homework_page_bloc.dart'; -export './src/lehrer/teacher_homework_read_model.dart'; +export 'src/teacher_and_parent/create_teacher_and_parent_homework_page_bloc.dart'; +export 'src/shared/sort/sorts.dart'; +export 'src/shared/lazy_loading_homework_list_view.dart'; +export 'src/teacher_and_parent/bloc/teacher_and_parent_homework_page_bloc.dart'; +export 'src/shared/models/homework.dart'; +export 'src/shared/homework_section_view.dart'; +export 'src/teacher_and_parent/views/teacher_and_parent_homework_view.dart'; +export 'src/teacher_and_parent/views/teacher_and_parent_homework_view_factory.dart'; +export 'src/teacher_and_parent/views/teacher_and_parent_open_homework_list_view.dart'; +export 'src/teacher_and_parent/views/teacher_and_parent_open_homework_list_view_factory.dart'; // export './src/lehrer/'; diff --git a/lib/hausaufgabenheft_logik/lib/hausaufgabenheft_logik_setup.dart b/lib/hausaufgabenheft_logik/lib/hausaufgabenheft_logik_setup.dart index 486d2fad9..6df29b704 100644 --- a/lib/hausaufgabenheft_logik/lib/hausaufgabenheft_logik_setup.dart +++ b/lib/hausaufgabenheft_logik/lib/hausaufgabenheft_logik_setup.dart @@ -21,7 +21,8 @@ /// ``` library; -export 'src/setup/config.dart'; -export 'src/setup/dependencies.dart'; -export 'src/setup/create_homework_page_bloc.dart'; -export 'src/student_homework_page_bloc/student_homework_page_bloc.dart'; +export 'src/shared/setup/config.dart'; +export 'src/shared/setup/dependencies.dart'; +export 'src/student/create_student_homework_page_bloc.dart'; +export 'src/student/bloc/student_homework_page_bloc.dart'; +export 'src/firebase/firebase_hausaufgabenheft_logik_setup.dart'; diff --git a/lib/hausaufgabenheft_logik/lib/src/completed_homeworks/views/completed_homework_list_view_factory.dart b/lib/hausaufgabenheft_logik/lib/src/completed_homeworks/views/completed_homework_list_view_factory.dart deleted file mode 100644 index b0a73f0fa..000000000 --- a/lib/hausaufgabenheft_logik/lib/src/completed_homeworks/views/completed_homework_list_view_factory.dart +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'package:fast_immutable_collections/fast_immutable_collections.dart'; -import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; -import '../../views/student_homework_view_factory.dart'; - -class CompletedHomeworkListViewFactory { - final StudentHomeworkViewFactory _studentHomeworkViewFactory; - - CompletedHomeworkListViewFactory(this._studentHomeworkViewFactory); - - CompletedHomeworkListView create(IList completedHomeworks, - bool loadedAllCompletedHomeworks) { - final orderedHomeworks = IList([ - for (final completedHomework in completedHomeworks) - _studentHomeworkViewFactory.createFrom(completedHomework) - ]); - return CompletedHomeworkListView(orderedHomeworks, - loadedAllCompletedHomeworks: loadedAllCompletedHomeworks); - } -} diff --git a/lib/hausaufgabenheft_logik/lib/src/data_source/homework_data_source.dart b/lib/hausaufgabenheft_logik/lib/src/data_source/homework_data_source.dart deleted file mode 100644 index bfbf52e3a..000000000 --- a/lib/hausaufgabenheft_logik/lib/src/data_source/homework_data_source.dart +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'package:fast_immutable_collections/fast_immutable_collections.dart'; -import 'package:hausaufgabenheft_logik/src/models/homework.dart'; -import 'package:collection/collection.dart' show DeepCollectionEquality; - -abstract class HomeworkDataSource { - Stream> get openHomeworks; - LazyLoadingController getLazyLoadingCompletedHomeworksController( - int nrOfInitialHomeworkToLoad); -} - -abstract class LazyLoadingController { - Stream get results; - void advanceBy(int numberOfHomeworks); -} - -class LazyLoadingResult { - final IList homeworks; - final bool moreHomeworkAvailable; - - LazyLoadingResult(this.homeworks, {required this.moreHomeworkAvailable}); - - LazyLoadingResult.empty({this.moreHomeworkAvailable = true}) - : homeworks = const IListConst([]); - - @override - String toString() { - return 'LazyLoadingResult(homeworks: $homeworks, $moreHomeworkAvailable)'; - } - - @override - bool operator ==(Object other) { - return identical(this, other) || - other is LazyLoadingResult && - const DeepCollectionEquality().equals(other.homeworks, homeworks) && - other.moreHomeworkAvailable == moreHomeworkAvailable; - } - - @override - int get hashCode => homeworks.hashCode ^ moreHomeworkAvailable.hashCode; -} diff --git a/lib/hausaufgabenheft_logik/lib/src/open_homeworks/sort_and_subcategorization/sort/homework_sorts.dart b/lib/hausaufgabenheft_logik/lib/src/firebase/firebase_hausaufgabenheft_logik.dart similarity index 67% rename from lib/hausaufgabenheft_logik/lib/src/open_homeworks/sort_and_subcategorization/sort/homework_sorts.dart rename to lib/hausaufgabenheft_logik/lib/src/firebase/firebase_hausaufgabenheft_logik.dart index b7eb8950c..32fa38b5c 100644 --- a/lib/hausaufgabenheft_logik/lib/src/open_homeworks/sort_and_subcategorization/sort/homework_sorts.dart +++ b/lib/hausaufgabenheft_logik/lib/src/firebase/firebase_hausaufgabenheft_logik.dart @@ -6,4 +6,7 @@ // // SPDX-License-Identifier: EUPL-1.2 -export 'src/sort.dart'; +library firebase_hausaufgaben_logik; + +export 'src/homework_transformation.dart'; +export 'src/homework_dto.dart'; diff --git a/lib/firebase_hausaufgabenheft_logik/lib/firebase_hausaufgabenheft_logik_setup.dart b/lib/hausaufgabenheft_logik/lib/src/firebase/firebase_hausaufgabenheft_logik_setup.dart similarity index 85% rename from lib/firebase_hausaufgabenheft_logik/lib/firebase_hausaufgabenheft_logik_setup.dart rename to lib/hausaufgabenheft_logik/lib/src/firebase/firebase_hausaufgabenheft_logik_setup.dart index 16de00548..35e8f4951 100644 --- a/lib/firebase_hausaufgabenheft_logik/lib/firebase_hausaufgabenheft_logik_setup.dart +++ b/lib/hausaufgabenheft_logik/lib/src/firebase/firebase_hausaufgabenheft_logik_setup.dart @@ -7,4 +7,3 @@ // SPDX-License-Identifier: EUPL-1.2 export 'src/create_default_firestore_repository.dart'; -export 'src/firestore_completion_dispatcher.dart'; diff --git a/lib/firebase_hausaufgabenheft_logik/lib/src/realtime_completed_homework_loader.dart b/lib/hausaufgabenheft_logik/lib/src/firebase/src/advanceable_homework_loader.dart similarity index 73% rename from lib/firebase_hausaufgabenheft_logik/lib/src/realtime_completed_homework_loader.dart rename to lib/hausaufgabenheft_logik/lib/src/firebase/src/advanceable_homework_loader.dart index fe53f0755..2abde72ad 100644 --- a/lib/firebase_hausaufgabenheft_logik/lib/src/realtime_completed_homework_loader.dart +++ b/lib/hausaufgabenheft_logik/lib/src/firebase/src/advanceable_homework_loader.dart @@ -9,7 +9,6 @@ import 'package:fast_immutable_collections/fast_immutable_collections.dart'; import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; -abstract class RealtimeCompletedHomeworkLoader { - Stream> loadMostRecentHomeworks( - int numberOfHomeworks); +abstract class AdvanceableHomeworkLoader { + Stream> loadHomeworks(int numberOfHomeworks); } diff --git a/lib/hausaufgabenheft_logik/lib/src/firebase/src/create_default_firestore_repository.dart b/lib/hausaufgabenheft_logik/lib/src/firebase/src/create_default_firestore_repository.dart new file mode 100644 index 000000000..5c59a91b4 --- /dev/null +++ b/lib/hausaufgabenheft_logik/lib/src/firebase/src/create_default_firestore_repository.dart @@ -0,0 +1,36 @@ +// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) +// Licensed under the EUPL-1.2-or-later. +// +// You may obtain a copy of the Licence at: +// https://joinup.ec.europa.eu/software/page/eupl +// +// SPDX-License-Identifier: EUPL-1.2 + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; +import 'package:hausaufgabenheft_logik/src/firebase/src/firestore_student_api.dart'; + +import 'firestore_teacher_and_parents_homework_page_api.dart'; +import 'teacher_homework_transformation.dart'; + +HomeworkPageApi createDefaultFirestoreRepositories( + CollectionReference homeworkCollection, + String uid, + CourseDataRetreiver getCourseData) { + final studentApi = FirestoreStudentHomeworkApi( + uid: uid, + homeworkCollection: homeworkCollection, + homeworkTransformer: HomeworkTransformer(uid, getCourseData: getCourseData), + ); + + final teacherAndParentApi = FirestoreTeacherAndParentsHomeworkPageApi( + homeworkCollection, + uid, + TeacherHomeworkTransformer(uid, getCourseData: getCourseData), + ); + + return HomeworkPageApi( + students: studentApi, + teachersAndParents: teacherAndParentApi, + ); +} diff --git a/lib/hausaufgabenheft_logik/lib/src/firebase/src/firestore_student_api.dart b/lib/hausaufgabenheft_logik/lib/src/firebase/src/firestore_student_api.dart new file mode 100644 index 000000000..ef5087d9e --- /dev/null +++ b/lib/hausaufgabenheft_logik/lib/src/firebase/src/firestore_student_api.dart @@ -0,0 +1,90 @@ +// Copyright (c) 2024 Sharezone UG (haftungsbeschränkt) +// Licensed under the EUPL-1.2-or-later. +// +// You may obtain a copy of the Licence at: +// https://joinup.ec.europa.eu/software/page/eupl +// +// SPDX-License-Identifier: EUPL-1.2 + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:common_domain_models/common_domain_models.dart'; +import 'package:fast_immutable_collections/fast_immutable_collections.dart'; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; +import 'package:hausaufgabenheft_logik/src/firebase/src/advanceable_homework_loader.dart'; + +import 'realtime_updating_lazy_loading_controller.dart'; + +class FirestoreStudentHomeworkApi extends StudentHomeworkPageApi + implements AdvanceableHomeworkLoader { + final CollectionReference homeworkCollection; + final String uid; + final HomeworkTransformer homeworkTransformer; + + FirestoreStudentHomeworkApi({ + required this.homeworkCollection, + required this.uid, + required this.homeworkTransformer, + }); + + @override + Future completeHomework( + HomeworkId homeworkId, CompletionStatus newCompletionStatus) async { + final documentReference = homeworkCollection.doc(homeworkId.toString()); + switch (newCompletionStatus) { + case CompletionStatus.completed: + documentReference.update({ + 'assignedUserArrays.completedStudentUids': + FieldValue.arrayUnion([uid]) + }); + documentReference.update({ + 'assignedUserArrays.openStudentUids': FieldValue.arrayRemove([uid]) + }); + break; + case CompletionStatus.open: + documentReference.update({ + 'assignedUserArrays.completedStudentUids': + FieldValue.arrayRemove([uid]) + }); + documentReference.update({ + 'assignedUserArrays.openStudentUids': FieldValue.arrayUnion([uid]) + }); + break; + } + } + + @override + LazyLoadingController + getLazyLoadingCompletedHomeworksController( + int nrOfInitialHomeworkToLoad) { + return RealtimeUpdatingLazyLoadingController(this, + initialNumberOfHomeworksToLoad: nrOfInitialHomeworkToLoad); + } + + @override + Stream> loadHomeworks(int numberOfHomeworks) { + return homeworkCollection + .where('assignedUserArrays.completedStudentUids', arrayContains: uid) + .orderBy('createdOn', descending: true) + .limit(numberOfHomeworks) + .snapshots() + .transform(homeworkTransformer); + } + + @override + Future> getOpenOverdueHomeworkIds() async { + final open = await openHomeworks.first; + final overdue = open + .where((homeworks) => homeworks.isOverdueRelativeTo(Date.now())) + .toList(); + final overdueIds = overdue.map((hws) => hws.id).toIList(); + return overdueIds; + } + + @override + Stream> get openHomeworks { + return homeworkCollection + .where("assignedUserArrays.openStudentUids", arrayContains: uid) + .snapshots() + .transform(homeworkTransformer); + } +} diff --git a/lib/hausaufgabenheft_logik/lib/src/firebase/src/firestore_teacher_and_parents_homework_page_api.dart b/lib/hausaufgabenheft_logik/lib/src/firebase/src/firestore_teacher_and_parents_homework_page_api.dart new file mode 100644 index 000000000..9038d2c6a --- /dev/null +++ b/lib/hausaufgabenheft_logik/lib/src/firebase/src/firestore_teacher_and_parents_homework_page_api.dart @@ -0,0 +1,62 @@ +// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) +// Licensed under the EUPL-1.2-or-later. +// +// You may obtain a copy of the Licence at: +// https://joinup.ec.europa.eu/software/page/eupl +// +// SPDX-License-Identifier: EUPL-1.2 + +import 'dart:async'; +import 'package:clock/clock.dart'; +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:fast_immutable_collections/fast_immutable_collections.dart'; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; +import 'package:hausaufgabenheft_logik/src/firebase/src/advanceable_homework_loader.dart'; +import 'package:hausaufgabenheft_logik/src/firebase/src/teacher_homework_transformation.dart'; + +import 'realtime_updating_lazy_loading_controller.dart'; + +class FirestoreTeacherAndParentsHomeworkPageApi + extends TeacherAndParentHomeworkPageApi + implements AdvanceableHomeworkLoader { + final CollectionReference _homeworkCollection; + final String uid; + final TeacherHomeworkTransformer _homeworkTransformer; + + FirestoreTeacherAndParentsHomeworkPageApi( + this._homeworkCollection, this.uid, this._homeworkTransformer); + + @override + LazyLoadingController + getLazyLoadingArchivedHomeworksController(int nrOfInitialHomeworkToLoad) { + return RealtimeUpdatingLazyLoadingController(this, + initialNumberOfHomeworksToLoad: nrOfInitialHomeworkToLoad); + } + + @override + Stream> loadHomeworks(int numberOfHomeworks) { + return _homeworkCollection + .where('assignedUserArrays.allAssignedUids', arrayContains: uid) + .orderBy('todoUntil', descending: true) + .limit(numberOfHomeworks) + .snapshots() + .transform(_homeworkTransformer); + } + + @override + Stream> get openHomeworks { + final startOfThisDay = clock.now().copyWith( + hour: 0, + minute: 0, + second: 0, + millisecond: 0, + microsecond: 0, + ); + + return _homeworkCollection + .where("assignedUserArrays.allAssignedUids", arrayContains: uid) + .where("todoUntil", isGreaterThanOrEqualTo: startOfThisDay) + .snapshots() + .transform(_homeworkTransformer); + } +} diff --git a/lib/firebase_hausaufgabenheft_logik/lib/src/homework_dto.dart b/lib/hausaufgabenheft_logik/lib/src/firebase/src/homework_dto.dart similarity index 100% rename from lib/firebase_hausaufgabenheft_logik/lib/src/homework_dto.dart rename to lib/hausaufgabenheft_logik/lib/src/firebase/src/homework_dto.dart diff --git a/lib/firebase_hausaufgabenheft_logik/lib/src/homework_transformation.dart b/lib/hausaufgabenheft_logik/lib/src/firebase/src/homework_transformation.dart similarity index 61% rename from lib/firebase_hausaufgabenheft_logik/lib/src/homework_transformation.dart rename to lib/hausaufgabenheft_logik/lib/src/firebase/src/homework_transformation.dart index b622337af..32c2377a7 100644 --- a/lib/firebase_hausaufgabenheft_logik/lib/src/homework_transformation.dart +++ b/lib/hausaufgabenheft_logik/lib/src/firebase/src/homework_transformation.dart @@ -15,28 +15,26 @@ import 'package:fast_immutable_collections/fast_immutable_collections.dart'; import 'package:hausaufgabenheft_logik/color.dart'; import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; -import 'homework_dto.dart'; - -typedef CourseColorRetriever = FutureOr Function(String courseId); +import 'teacher_homework_transformation.dart'; class HomeworkTransformer extends StreamTransformerBase< - QuerySnapshot>, IList> { + QuerySnapshot>, IList> { final String userId; - final CourseColorRetriever getCourseColorHexValue; + final CourseDataRetreiver getCourseData; - HomeworkTransformer(this.userId, {required this.getCourseColorHexValue}); + HomeworkTransformer(this.userId, {required this.getCourseData}); @override - Stream> bind(Stream stream) { + Stream> bind(Stream stream) { return stream.asyncMap(querySnapshotToHomeworks); } - Future> querySnapshotToHomeworks( + Future> querySnapshotToHomeworks( QuerySnapshot querySnapshot) async { - IList homeworks = const IListConst([]); + IList homeworks = const IListConst([]); for (final document in querySnapshot.docs) { final homework = await tryToConvertToHomework(document, userId, - getCourseColorHexValue: getCourseColorHexValue); + getCourseData: getCourseData); if (homework != null) { homeworks = homeworks.add(homework); } @@ -45,40 +43,30 @@ class HomeworkTransformer extends StreamTransformerBase< } } -Future tryToConvertToHomework( +Future tryToConvertToHomework( DocumentSnapshot documentSnapshot, String uid, - {CourseColorRetriever? getCourseColorHexValue}) async { - HomeworkReadModel? converted; + {required CourseDataRetreiver getCourseData}) async { + StudentHomeworkReadModel? converted; try { final homework = HomeworkDto.fromData( documentSnapshot.data() as Map, id: documentSnapshot.id); - int? courseColorHex; - if (getCourseColorHexValue != null) { - courseColorHex = await getCourseColorHexValue(homework.courseID); - } - Subject subject; - if (courseColorHex != null) { - subject = Subject( - homework.subject, - color: Color(courseColorHex), - abbreviation: homework.subjectAbbreviation, - ); - } else { - subject = Subject( - homework.subject, - abbreviation: homework.subjectAbbreviation, - ); - } + final courseId = CourseId(homework.courseID); + final data = await getCourseData(CourseId(homework.courseID)); - converted = HomeworkReadModel( + converted = StudentHomeworkReadModel( id: HomeworkId(homework.id), + courseId: courseId, todoDate: homework.todoUntil, status: homework.isDoneBy(uid) ? CompletionStatus.completed : CompletionStatus.open, - subject: subject, + subject: Subject( + homework.subject, + color: Color(data.colorHexValue), + abbreviation: homework.subjectAbbreviation, + ), withSubmissions: homework.withSubmissions, title: Title(homework.title), ); diff --git a/lib/firebase_hausaufgabenheft_logik/lib/src/realtime_updating_lazy_loading_controller.dart b/lib/hausaufgabenheft_logik/lib/src/firebase/src/realtime_updating_lazy_loading_controller.dart similarity index 85% rename from lib/firebase_hausaufgabenheft_logik/lib/src/realtime_updating_lazy_loading_controller.dart rename to lib/hausaufgabenheft_logik/lib/src/firebase/src/realtime_updating_lazy_loading_controller.dart index 7977b72d5..8541a9d80 100644 --- a/lib/firebase_hausaufgabenheft_logik/lib/src/realtime_updating_lazy_loading_controller.dart +++ b/lib/hausaufgabenheft_logik/lib/src/firebase/src/realtime_updating_lazy_loading_controller.dart @@ -9,17 +9,17 @@ import 'dart:async'; import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; -import 'realtime_completed_homework_loader.dart'; +import 'advanceable_homework_loader.dart'; -class RealtimeUpdatingLazyLoadingController extends LazyLoadingController { +class RealtimeUpdatingLazyLoadingController + extends LazyLoadingController { /// The number of homeworks that will be initially loaded on construction. /// If it is 0 then an empty LazyLoading result will be given back without /// calling the [FirebaseRealtimeCompletedHomeworkLoader]. final int initialNumberOfHomeworksToLoad; - final RealtimeCompletedHomeworkLoader _homeworkLoader; + final AdvanceableHomeworkLoader _homeworkLoader; - final StreamController _controller = - StreamController(); + final _controller = StreamController>(); int _numberOfHomeworksToAdvance = 0; /// The latest stream of lazy loading results. @@ -42,7 +42,7 @@ class RealtimeUpdatingLazyLoadingController extends LazyLoadingController { } @override - Stream get results => _controller.stream; + Stream> get results => _controller.stream; /// Advances the current number of loaded homeworks by [numberOfHomeworks]. /// @@ -62,10 +62,9 @@ class RealtimeUpdatingLazyLoadingController extends LazyLoadingController { }); } - Stream _getLazyLoadingResultStream( + Stream> _getLazyLoadingResultStream( int nrOfHomeworksToLoad) { - final homeworksStream = - _homeworkLoader.loadMostRecentHomeworks(nrOfHomeworksToLoad); + final homeworksStream = _homeworkLoader.loadHomeworks(nrOfHomeworksToLoad); final results = homeworksStream.map((homeworks) { final loadedAll = homeworks.length < nrOfHomeworksToLoad; diff --git a/lib/hausaufgabenheft_logik/lib/src/firebase/src/teacher_homework_transformation.dart b/lib/hausaufgabenheft_logik/lib/src/firebase/src/teacher_homework_transformation.dart new file mode 100644 index 000000000..9db918e6d --- /dev/null +++ b/lib/hausaufgabenheft_logik/lib/src/firebase/src/teacher_homework_transformation.dart @@ -0,0 +1,102 @@ +// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) +// Licensed under the EUPL-1.2-or-later. +// +// You may obtain a copy of the Licence at: +// https://joinup.ec.europa.eu/software/page/eupl +// +// SPDX-License-Identifier: EUPL-1.2 + +import 'dart:async'; +import 'dart:developer'; + +import 'package:clock/clock.dart'; +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:common_domain_models/common_domain_models.dart'; +import 'package:fast_immutable_collections/fast_immutable_collections.dart'; +import 'package:hausaufgabenheft_logik/color.dart'; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; + +typedef CourseDataRetreiver = Future<({int colorHexValue, bool isAdmin})> + Function(CourseId courseId); + +class TeacherHomeworkTransformer extends StreamTransformerBase< + QuerySnapshot>, IList> { + final String userId; + final CourseDataRetreiver getCourseData; + + TeacherHomeworkTransformer(this.userId, {required this.getCourseData}); + + @override + Stream> bind(Stream stream) { + return stream.asyncMap(querySnapshotToHomeworks); + } + + Future> querySnapshotToHomeworks( + QuerySnapshot querySnapshot) async { + IList homeworks = const IListConst([]); + for (final document in querySnapshot.docs) { + final homework = await tryToConvertToHomework(document, userId, + getCourseData: getCourseData); + if (homework != null) { + homeworks = homeworks.add(homework); + } + } + return homeworks; + } +} + +Future tryToConvertToHomework( + DocumentSnapshot documentSnapshot, String uid, + {required CourseDataRetreiver getCourseData}) async { + TeacherHomeworkReadModel? converted; + try { + final homework = HomeworkDto.fromData( + documentSnapshot.data() as Map, + id: documentSnapshot.id); + + final courseId = CourseId(homework.courseID); + + final data = await getCourseData(courseId); + + final startOfThisDay = clock.now().copyWith( + hour: 0, + minute: 0, + second: 0, + millisecond: 0, + microsecond: 0, + ); + + converted = TeacherHomeworkReadModel( + id: HomeworkId(homework.id), + todoDate: homework.todoUntil, + canDeleteForEveryone: data.isAdmin, + canEditForEveryone: data.isAdmin, + canViewCompletions: data.isAdmin, + canViewSubmissions: data.isAdmin, + status: homework.todoUntil.isBefore(startOfThisDay) + ? ArchivalStatus.archived + : ArchivalStatus.open, + courseId: courseId, + subject: Subject( + homework.subject, + color: Color(data.colorHexValue), + abbreviation: homework.subjectAbbreviation, + ), + withSubmissions: homework.withSubmissions, + title: Title(homework.title), + nrOfStudentsCompleted: + homework.assignedUserArrays.completedStudentUids.length, + ); + } catch (e, s) { + final errorMessage = """ + Could not convert a document into a homework object. + Homework document id: ${documentSnapshot.id} + User id: $uid + Error: $e + Stacktrace: $s + """; + log(errorMessage, error: e, stackTrace: s); + } + + return converted; +} diff --git a/lib/hausaufgabenheft_logik/lib/src/homework_completion/homework_completion_dispatcher.dart b/lib/hausaufgabenheft_logik/lib/src/homework_completion/homework_completion_dispatcher.dart deleted file mode 100644 index a2b8d2437..000000000 --- a/lib/hausaufgabenheft_logik/lib/src/homework_completion/homework_completion_dispatcher.dart +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'package:common_domain_models/common_domain_models.dart'; -import 'package:hausaufgabenheft_logik/src/models/homework_completion_status.dart'; - -/// The boundary to the outer world. -/// The only purpose for this class is to change the completion status of a -/// homework. -/// This class should be implemented in another package where it is bound to the -/// backend service used in production, e.g. Firebase. -abstract class HomeworkCompletionDispatcher { - void dispatch(HomeworkCompletion homeworkCompletion); -} - -class HomeworkCompletion { - final HomeworkId homeworkId; - final CompletionStatus newCompletionValue; - - HomeworkCompletion(this.homeworkId, this.newCompletionValue); - - @override - bool operator ==(Object other) { - return identical(this, other) || - other is HomeworkCompletion && other.homeworkId == homeworkId; - } - - @override - int get hashCode => homeworkId.hashCode; -} diff --git a/lib/hausaufgabenheft_logik/lib/src/homework_completion/homework_page_completion_dispatcher.dart b/lib/hausaufgabenheft_logik/lib/src/homework_completion/homework_page_completion_dispatcher.dart deleted file mode 100644 index 587bef3a3..000000000 --- a/lib/hausaufgabenheft_logik/lib/src/homework_completion/homework_page_completion_dispatcher.dart +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'package:common_domain_models/common_domain_models.dart'; -import 'package:fast_immutable_collections/fast_immutable_collections.dart'; -import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; - -/// The [HomeworkPageCompletionDispatcher] is a homework page sepecific input for -/// [HomeworkCompletionEvent]s. -/// -/// Delegates all incomming Events to the [HomeworkCompletionDispatcher]. -/// -/// The fundamental difference between both classes is that this class is -/// tailored to the HomeworkPage e.g. through the -/// [AllOverdueHomeworkCompletionEvent] while the [HomeworkCompletionDispatcher] -/// is not bound to the homework page. -class HomeworkPageCompletionDispatcher { - final Future> Function() getCurrentOverdueHomeworkIds; - final HomeworkCompletionDispatcher _homeworkCompletionDispatcher; - - HomeworkPageCompletionDispatcher(this._homeworkCompletionDispatcher, - {required this.getCurrentOverdueHomeworkIds}); - - Future changeCompletionStatus( - HomeworkId homeworkId, CompletionStatus newCompletionValue) async { - _homeworkCompletionDispatcher - .dispatch(HomeworkCompletion(homeworkId, newCompletionValue)); - } - - Future completeAllOverdueHomeworks() async { - final hws = await getCurrentOverdueHomeworkIds(); - for (final hw in hws) { - _homeworkCompletionDispatcher - .dispatch(HomeworkCompletion(hw, CompletionStatus.completed)); - } - } -} diff --git a/lib/hausaufgabenheft_logik/lib/src/homework_list_extensions.dart b/lib/hausaufgabenheft_logik/lib/src/homework_list_extensions.dart deleted file mode 100644 index 9e0c6fa61..000000000 --- a/lib/hausaufgabenheft_logik/lib/src/homework_list_extensions.dart +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'package:fast_immutable_collections/fast_immutable_collections.dart'; -import 'package:hausaufgabenheft_logik/src/models/homework_completion_status.dart'; - -import 'open_homeworks/sort_and_subcategorization/sort/src/sort.dart'; -import 'models/date.dart'; -import 'models/homework.dart'; -import 'models/subject.dart'; - -extension SortWith on IList { - IList sortWith(Sort sort) { - return sort.sort(this); - } -} - -extension HomeworkListExtension on IList { - IList get completed => - where((homework) => homework.status == CompletionStatus.completed) - .toIList(); - IList get open => - where((homework) => homework.status == CompletionStatus.open).toIList(); - - IList getDistinctOrderedSubjects() { - final subjects = {}; - for (final homework in this) { - subjects.add(homework.subject); - } - return subjects.toIList(); - } - - IList getOverdue([Date? now]) { - now = now ?? Date.now(); - return where((homeworks) => homeworks.isOverdueRelativeTo(now!)).toIList(); - } -} diff --git a/lib/hausaufgabenheft_logik/lib/src/lehrer/create_teacher_homework_page_bloc.dart b/lib/hausaufgabenheft_logik/lib/src/lehrer/create_teacher_homework_page_bloc.dart deleted file mode 100644 index c902b923c..000000000 --- a/lib/hausaufgabenheft_logik/lib/src/lehrer/create_teacher_homework_page_bloc.dart +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'package:hausaufgabenheft_logik/src/setup/config.dart'; -import 'package:hausaufgabenheft_logik/src/setup/dependencies.dart'; - -import '../../hausaufgabenheft_logik_lehrer.dart'; - -TeacherHomeworkPageBloc createTeacherHomeworkPageBloc( - HausaufgabenheftDependencies dependencies, HausaufgabenheftConfig config) { - return TeacherHomeworkPageBloc(); -} diff --git a/lib/hausaufgabenheft_logik/lib/src/lehrer/teacher_archived_homework_list_view.dart b/lib/hausaufgabenheft_logik/lib/src/lehrer/teacher_archived_homework_list_view.dart deleted file mode 100644 index eabbc26a4..000000000 --- a/lib/hausaufgabenheft_logik/lib/src/lehrer/teacher_archived_homework_list_view.dart +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'package:fast_immutable_collections/fast_immutable_collections.dart'; - -import 'teacher_homework_view.dart'; - -class TeacherArchivedHomeworkListView { - final bool loadedAllArchivedHomeworks; - final IList orderedHomeworks; - - TeacherArchivedHomeworkListView(this.orderedHomeworks, - {required this.loadedAllArchivedHomeworks}); - - int get numberOfHomeworks => orderedHomeworks.length; - - @override - bool operator ==(Object other) { - return identical(this, other) || - other is TeacherArchivedHomeworkListView && - other.orderedHomeworks == orderedHomeworks && - other.loadedAllArchivedHomeworks == loadedAllArchivedHomeworks; - } - - @override - int get hashCode => - orderedHomeworks.hashCode ^ loadedAllArchivedHomeworks.hashCode; -} diff --git a/lib/hausaufgabenheft_logik/lib/src/lehrer/teacher_homework_page_bloc.dart b/lib/hausaufgabenheft_logik/lib/src/lehrer/teacher_homework_page_bloc.dart deleted file mode 100644 index afc535b0e..000000000 --- a/lib/hausaufgabenheft_logik/lib/src/lehrer/teacher_homework_page_bloc.dart +++ /dev/null @@ -1,254 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'dart:async'; - -import 'package:bloc/bloc.dart'; -import 'package:bloc_base/bloc_base.dart' as bloc_base; -import 'package:common_domain_models/common_domain_models.dart'; -import 'package:fast_immutable_collections/fast_immutable_collections.dart'; -import 'package:hausaufgabenheft_logik/color.dart'; -import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik_lehrer.dart'; -import 'package:meta/meta.dart'; -import 'package:test_randomness/test_randomness.dart'; - -export 'events.dart'; -export 'states.dart'; - -class _Homeworks { - static final _noSubmissionNoPermissions = randomHomeworkViewWith( - title: 'S. 35 a)', - colorDate: false, - withSubmissions: false, - canViewCompletionOrSubmissionList: false, - canDeleteForEveryone: true, - canEditForEveryone: true, - ); - - static final _noSubmissionWithPermissions = randomHomeworkViewWith( - title: 'AB "Dichter"', - withSubmissions: false, - canViewCompletionOrSubmissionList: true, - canDeleteForEveryone: false, - canEditForEveryone: false, - ); - - static final _withSubmissionNoPermissions = randomHomeworkViewWith( - title: 'AB "trigonometrie"', - withSubmissions: true, - canViewCompletionOrSubmissionList: false, - canDeleteForEveryone: true, - canEditForEveryone: false, - ); - - static final _withSubmissionWithPermissions = randomHomeworkViewWith( - title: 'S. 23 b)', - withSubmissions: true, - canViewCompletionOrSubmissionList: true, - canDeleteForEveryone: false, - canEditForEveryone: true, - ); -} - -enum _ArchivedHwLazyLoadingState { - askedForFirstBatch, - askedForSecondBatch, - askedForAll -} - -class _States { - // ignore: unused_field - static final _uninitialized = Uninitialized(); - - // ignore: unused_field - static final _placeholder = Success( - TeacherOpenHomeworkListView(const IListConst([]), - sorting: HomeworkSort.smallestDateSubjectAndTitle), - TeacherArchivedHomeworkListView(const IListConst([]), - loadedAllArchivedHomeworks: true), - ); - - /// Answer for [_ArchivedHwLazyLoadingState.askedForFirstBatch] - static final __archivedHomeworksFirstState = TeacherArchivedHomeworkListView( - IList([ - _Homeworks._noSubmissionNoPermissions, - _Homeworks._withSubmissionWithPermissions, - ..._generateRandomHomeworks(count: 18) - ]), - loadedAllArchivedHomeworks: false); - - /// Answer for [_ArchivedHwLazyLoadingState.askedForSecondBatch] - static final __archivedHomeworksSecondState = TeacherArchivedHomeworkListView( - IList([ - ...__archivedHomeworksFirstState.orderedHomeworks, - ..._generateRandomHomeworks(count: 10) - ]), - loadedAllArchivedHomeworks: false); - - /// Answer for [_ArchivedHwLazyLoadingState.askedForAll] - static final __archivedHomeworksLoadedAllState = - TeacherArchivedHomeworkListView( - IList([ - ...__archivedHomeworksSecondState.orderedHomeworks, - ..._generateRandomHomeworks(count: 10) - ]), - loadedAllArchivedHomeworks: true); - - static TeacherArchivedHomeworkListView __getArchivedListView( - _ArchivedHwLazyLoadingState loadingState) { - switch (loadingState) { - case _ArchivedHwLazyLoadingState.askedForFirstBatch: - return __archivedHomeworksFirstState; - case _ArchivedHwLazyLoadingState.askedForSecondBatch: - return __archivedHomeworksSecondState; - case _ArchivedHwLazyLoadingState.askedForAll: - return __archivedHomeworksLoadedAllState; - } - } - - static Success _homeworksAllLoadedSortedBySubject( - _ArchivedHwLazyLoadingState loadingState) { - return Success( - TeacherOpenHomeworkListView( - IList([ - TeacherHomeworkSectionView( - 'Mathe', - IList([ - _Homeworks._noSubmissionWithPermissions, - _Homeworks._withSubmissionNoPermissions - ])) - ]), - sorting: HomeworkSort.subjectSmallestDateAndTitleSort), - __getArchivedListView(loadingState)); - } - - static Success _homeworksAllLoadedSortedByTodoDate( - _ArchivedHwLazyLoadingState loadingState) { - return Success( - TeacherOpenHomeworkListView( - IList([ - TeacherHomeworkSectionView( - 'Heute', - IList([ - _Homeworks._noSubmissionWithPermissions, - ])), - TeacherHomeworkSectionView( - 'In 3 Tagen', - IList([ - _Homeworks._withSubmissionNoPermissions, - ])) - ]), - sorting: HomeworkSort.smallestDateSubjectAndTitle), - __getArchivedListView(loadingState), - ); - } -} - -List _generateRandomHomeworks({required int count}) { - return List.generate( - count, (index) => randomHomeworkViewWith(/*Random content*/)); -} - -@visibleForTesting -TeacherHomeworkView randomHomeworkViewWith({ - String? title, - int? nrOfStudentsCompletedOrSubmitted, - bool? withSubmissions, - bool? colorDate, - bool? canViewCompletionOrSubmissionList, - bool? canDeleteForEveryone, - bool? canEditForEveryone, -}) { - bool randomBool() { - // 👈😎👉 SO SMART 👈😎👉 - return randomBetween(0, 2).isEven; - } - - String randomDate() { - final randomDay = randomBetween(0, 30); - final randomMonthNr = randomBetween(0, 12); - final randomMonth = - randomMonthNr < 10 ? '0$randomMonthNr' : '$randomMonthNr'; - - return '$randomDay.$randomMonth.2021'; - } - - final subject = randomBool() ? 'Englisch' : 'Mathe'; - return TeacherHomeworkView( - id: HomeworkId(randomAlphaNumeric(10)), - title: title ?? 'S. ${randomBetween(1, 300)} Nr. ${randomBetween(1, 20)}', - abbreviation: subject.substring(0, 1), - colorDate: colorDate ?? randomBool(), - nrOfStudentsCompletedOrSubmitted: - nrOfStudentsCompletedOrSubmitted ?? randomBetween(0, 30), - subject: subject, - subjectColor: Color.fromARGB(200, randomBetween(100, 200), 200, 255), - todoDate: randomDate(), - withSubmissions: withSubmissions ?? randomBool(), - canViewCompletionOrSubmissionList: - canViewCompletionOrSubmissionList ?? randomBool(), - canDeleteForEveryone: canDeleteForEveryone ?? randomBool(), - canEditForEveryone: canEditForEveryone ?? randomBool(), - ); -} - -/// A fake bloc for the homework page for teachers. -/// -/// Fake means that it really doesn't do much. It doesn't work yet. -/// The current implementation only makes it look as roughly how it should work -/// in the end. In reality only the fake homeworks above are returned. -/// -/// It is currently only used for local development of the new teacher homework -/// UI. The real logic will be implemented in the future. -class TeacherHomeworkPageBloc - extends Bloc - implements bloc_base.BlocBase { - TeacherHomeworkPageBloc() : super(Uninitialized()) { - on((event, emit) { - _currentSort = event.sort; - }); - on((event, emit) async { - await Future.delayed(const Duration(milliseconds: 1200)); - _advanveArchivedHwLazyLoadingState(); - }); - on((event, emit) { - // Reset so that we can inspect the lazy loading again when we change - // away and back to the homework page again. - _archivedHwLazyLoadingState = - _ArchivedHwLazyLoadingState.askedForFirstBatch; - - _currentSort == HomeworkSort.smallestDateSubjectAndTitle - ? _States._homeworksAllLoadedSortedByTodoDate( - _archivedHwLazyLoadingState) - : _States._homeworksAllLoadedSortedBySubject( - _archivedHwLazyLoadingState); - }); - } - - HomeworkSort _currentSort = HomeworkSort.smallestDateSubjectAndTitle; - _ArchivedHwLazyLoadingState _archivedHwLazyLoadingState = - _ArchivedHwLazyLoadingState.askedForFirstBatch; - - void _advanveArchivedHwLazyLoadingState() { - switch (_archivedHwLazyLoadingState) { - case _ArchivedHwLazyLoadingState.askedForFirstBatch: - _archivedHwLazyLoadingState = - _ArchivedHwLazyLoadingState.askedForSecondBatch; - break; - case _ArchivedHwLazyLoadingState.askedForSecondBatch: - _archivedHwLazyLoadingState = _ArchivedHwLazyLoadingState.askedForAll; - break; - case _ArchivedHwLazyLoadingState.askedForAll: - default: - return; - } - } - - @override - void dispose() {} -} diff --git a/lib/hausaufgabenheft_logik/lib/src/lehrer/teacher_homework_read_model.dart b/lib/hausaufgabenheft_logik/lib/src/lehrer/teacher_homework_read_model.dart deleted file mode 100644 index a9dc1d8c6..000000000 --- a/lib/hausaufgabenheft_logik/lib/src/lehrer/teacher_homework_read_model.dart +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'package:common_domain_models/common_domain_models.dart'; -import 'package:hausaufgabenheft_logik/src/models/homework.dart'; -import 'package:hausaufgabenheft_logik/src/models/models.dart'; - -/// Ein ReadModel für die Lehrer-Hausaufgaben-Seite. -/// Siehe [HomeworkReadModel]. -class TeacherHomeworkReadModel { - final HomeworkId id; - final DateTime todoDate; - final Subject subject; - final Title title; - final bool withSubmissions; - final int nrOfStudentsCompleted; - final bool canViewCompletions; - final bool canViewSubmissions; - - /// If the user has the permission to delete the homework for everyone in the - /// group. - final bool canDeleteForEveryone; - - /// If the user has the permission to edit the homework for everyone in the - /// group. - final bool canEditForEveryone; - - TeacherHomeworkReadModel({ - required this.id, - required this.todoDate, - required this.subject, - required this.title, - required this.withSubmissions, - required this.nrOfStudentsCompleted, - required this.canViewCompletions, - required this.canViewSubmissions, - required this.canDeleteForEveryone, - required this.canEditForEveryone, - }); - - /// Die Methode ist aus [HomeworkReadModel] kopiert - zusammenführen? - bool isOverdueRelativeTo(Date today) { - return Date.fromDateTime(todoDate) < today; - } - - @override - bool operator ==(Object other) { - if (identical(this, other)) return true; - - return other is TeacherHomeworkReadModel && - other.id == id && - other.todoDate == todoDate && - other.subject == subject && - other.title == title && - other.withSubmissions == withSubmissions && - other.nrOfStudentsCompleted == nrOfStudentsCompleted && - other.canViewCompletions == canViewCompletions && - other.canViewSubmissions == canViewSubmissions; - } - - @override - int get hashCode { - return id.hashCode ^ - todoDate.hashCode ^ - subject.hashCode ^ - title.hashCode ^ - withSubmissions.hashCode ^ - nrOfStudentsCompleted.hashCode ^ - canViewCompletions.hashCode ^ - canViewSubmissions.hashCode; - } - - @override - String toString() { - return 'TeacherHomeworkReadModel(id: $id, todoDate: $todoDate, subject: $subject, title: $title, withSubmissions: $withSubmissions, nrOfStudentsCompleted: $nrOfStudentsCompleted, canViewCompletions: $canViewCompletions, canViewSubmissions: $canViewSubmissions)'; - } -} diff --git a/lib/hausaufgabenheft_logik/lib/src/models/homework.dart b/lib/hausaufgabenheft_logik/lib/src/models/homework.dart deleted file mode 100644 index bac3a415c..000000000 --- a/lib/hausaufgabenheft_logik/lib/src/models/homework.dart +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'package:common_domain_models/common_domain_models.dart'; -import 'package:equatable/equatable.dart'; -import 'package:hausaufgabenheft_logik/src/models/homework_completion_status.dart'; - -import 'date.dart'; -import 'subject.dart'; -import 'title.dart'; - -/// The read model of a Homework that is specific to one user. -/// The Homework should only be used to display a homework, created specifically -/// for one user. It should not be edited and put in a repository. -/// -/// In Sharezone it used in the context of the HomeworkPage, as it is basically -/// a merge from the information of the homework-details (title, subject, ...) -/// and the specific done status of the user viewing the homework. -class HomeworkReadModel extends Equatable { - final HomeworkId id; - final DateTime todoDate; - final Subject subject; - final Title title; - final bool withSubmissions; - final CompletionStatus status; - - @override - List get props => - [id, todoDate, subject, title, withSubmissions, status]; - - const HomeworkReadModel({ - required this.id, - required this.title, - required this.subject, - required this.status, - required this.withSubmissions, - required this.todoDate, - }); - - bool isOverdueRelativeTo(Date today) { - return Date.fromDateTime(todoDate) < today; - } -} diff --git a/lib/hausaufgabenheft_logik/lib/src/open_homeworks/sort_and_subcategorization/sort_and_subcategorizer.dart b/lib/hausaufgabenheft_logik/lib/src/open_homeworks/sort_and_subcategorization/sort_and_subcategorizer.dart deleted file mode 100644 index 7ab318433..000000000 --- a/lib/hausaufgabenheft_logik/lib/src/open_homeworks/sort_and_subcategorization/sort_and_subcategorizer.dart +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'package:fast_immutable_collections/fast_immutable_collections.dart'; -import 'package:hausaufgabenheft_logik/color.dart'; -import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; -import 'package:hausaufgabenheft_logik/src/views/student_homework_view_factory.dart'; - -class HomeworkSortAndSubcategorizer { - final StudentHomeworkViewFactory _viewFactory; - final Date Function() getCurrentDate; - - HomeworkSortAndSubcategorizer({ - required Color defaultColor, - required this.getCurrentDate, - }) : _viewFactory = StudentHomeworkViewFactory( - defaultColorValue: defaultColor.value, - getCurrentDate: getCurrentDate, - ); - - IList sortAndSubcategorize( - IList homeworks, Sort sort) { - final sorted = homeworks.sortWith(sort); - - final matchingSubcategorizer = switch (sort) { - SubjectSmallestDateAndTitleSort() => - _SubjectSubcategeorizer(_viewFactory), - SmallestDateSubjectAndTitleSort() => - _TodoDateSubcategorizer(getCurrentDate(), _viewFactory), - }; - - return matchingSubcategorizer.subcategorize(sorted); - } -} - -abstract class _Subcategorizer { - IList subcategorize(IList homeworks); -} - -class _SubjectSubcategeorizer extends _Subcategorizer { - final StudentHomeworkViewFactory _viewFactory; - - _SubjectSubcategeorizer(this._viewFactory); - - @override - IList subcategorize(IList homeworks) { - final subjects = homeworks.getDistinctOrderedSubjects(); - var homeworkSections = IList(); - for (final subject in subjects) { - final IList homeworksWithSubject = - homeworks.where((h) => h.subject == subject).toIList(); - - final homeworkViewsWithSubject = - homeworksWithSubject.map((h) => _viewFactory.createFrom(h)).toIList(); - - homeworkSections = homeworkSections - .add(HomeworkSectionView(subject.name, homeworkViewsWithSubject)); - } - return homeworkSections; - } -} - -class _TodoDateSubcategorizer extends _Subcategorizer { - final Date currentDate; - final StudentHomeworkViewFactory _viewFactory; - - _TodoDateSubcategorizer(this.currentDate, this._viewFactory); - - @override - IList subcategorize(IList homeworks) { - final now = currentDate; - final tomorrow = now.addDays(1); - final in2Days = tomorrow.addDays(1); - - final IList overdueHomework = - homeworks.where((h) => Date.fromDateTime(h.todoDate) < now).toIList(); - final IList todayHomework = - homeworks.where((h) => Date.fromDateTime(h.todoDate) == now).toIList(); - final IList tomorrowHomework = homeworks - .where((h) => Date.fromDateTime(h.todoDate) == tomorrow) - .toIList(); - final IList in2DaysHomework = homeworks - .where((h) => Date.fromDateTime(h.todoDate) == in2Days) - .toIList(); - final IList futureHomework = homeworks - .where((h) => Date.fromDateTime(h.todoDate) > in2Days) - .toIList(); - - final overdueSec = HomeworkSectionView.fromModels( - 'Überfällig', overdueHomework, _viewFactory); - final todaySec = - HomeworkSectionView.fromModels('Heute', todayHomework, _viewFactory); - final tomorrowSec = HomeworkSectionView.fromModels( - 'Morgen', tomorrowHomework, _viewFactory); - final inTwoDaysSec = HomeworkSectionView.fromModels( - 'Übermorgen', in2DaysHomework, _viewFactory); - final afterTwoDaysSec = - HomeworkSectionView.fromModels('Später', futureHomework, _viewFactory); - - final sections = [ - overdueSec, - todaySec, - tomorrowSec, - inTwoDaysSec, - afterTwoDaysSec - ]; - - return sections.where((section) => section.isNotEmpty).toIList(); - } -} diff --git a/lib/hausaufgabenheft_logik/lib/src/open_homeworks/views/open_homework_list_view.dart b/lib/hausaufgabenheft_logik/lib/src/open_homeworks/views/open_homework_list_view.dart deleted file mode 100644 index 73fb74dd8..000000000 --- a/lib/hausaufgabenheft_logik/lib/src/open_homeworks/views/open_homework_list_view.dart +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'package:collection/collection.dart' show DeepCollectionEquality; -import 'package:fast_immutable_collections/fast_immutable_collections.dart'; -import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; - -import 'homework_section_view.dart'; - -class OpenHomeworkListView { - final bool showCompleteOverdueHomeworkPrompt; - final IList sections; - final HomeworkSort sorting; - - OpenHomeworkListView( - this.sections, { - required this.showCompleteOverdueHomeworkPrompt, - required this.sorting, - }) : super(); - - @override - int get hashCode => - sections.hashCode & showCompleteOverdueHomeworkPrompt.hashCode; - - int get numberOfHomeworks { - final listLengths = sections.map((s) => s.homeworks.length).toList(); - if (listLengths.isEmpty) { - return 0; - } - return listLengths.reduce((i, i2) => i + i2); - } - - @override - bool operator ==(Object other) { - return identical(this, other) || - other is OpenHomeworkListView && - showCompleteOverdueHomeworkPrompt == - other.showCompleteOverdueHomeworkPrompt && - const DeepCollectionEquality().equals(sections, other.sections); - } - - @override - String toString() => - 'OpenHomeworkListView(sections: $sections, showCompleteOverdueHomeworkPrompt: $showCompleteOverdueHomeworkPrompt)'; -} - -enum HomeworkSort { - /// Sorts the homeworks firstly by date (earliest date first). - /// If they have the same date, they will be sorted alphabetically by subject. - /// If they have the same date and subject, they will be sorted alphabetically by title. - smallestDateSubjectAndTitle, - - /// Sorts the homeworks firstly by Subject. - /// If they have the same subject, they will be sorted by date (earliest date first). - /// If they have the same date and subject, they will be sorted alphabetically by title. - subjectSmallestDateAndTitleSort, -} - -const String _subjectSmallestDateAndTitleSortAsString = - 'smallestDateSubjectAndTitle'; -const String _subjectSmallestDateAndTitleSort = - 'subjectSmallestDateAndTitleSort'; - -HomeworkSort homeworkSortFromString(String s) { - switch (s) { - case _subjectSmallestDateAndTitleSortAsString: - return HomeworkSort.smallestDateSubjectAndTitle; - case _subjectSmallestDateAndTitleSort: - return HomeworkSort.subjectSmallestDateAndTitleSort; - } - throw UnimplementedError(); -} - -String homeworkSortToString(HomeworkSort s) { - switch (s) { - case HomeworkSort.smallestDateSubjectAndTitle: - return _subjectSmallestDateAndTitleSortAsString; - case HomeworkSort.subjectSmallestDateAndTitleSort: - return _subjectSmallestDateAndTitleSort; - } -} diff --git a/lib/hausaufgabenheft_logik/lib/src/open_homeworks/views/open_homework_list_view_factory.dart b/lib/hausaufgabenheft_logik/lib/src/open_homeworks/views/open_homework_list_view_factory.dart deleted file mode 100644 index 985e6b33d..000000000 --- a/lib/hausaufgabenheft_logik/lib/src/open_homeworks/views/open_homework_list_view_factory.dart +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'package:fast_immutable_collections/fast_immutable_collections.dart'; -import 'package:hausaufgabenheft_logik/src/models/homework.dart'; -import 'package:hausaufgabenheft_logik/src/models/models.dart'; -import 'package:hausaufgabenheft_logik/src/homework_list_extensions.dart'; -import 'package:hausaufgabenheft_logik/src/open_homeworks/sort_and_subcategorization/sort/src/sort.dart'; -import 'package:hausaufgabenheft_logik/src/open_homeworks/sort_and_subcategorization/sort_and_subcategorizer.dart'; -import 'package:hausaufgabenheft_logik/src/open_homeworks/sort_and_subcategorization/sort/src/homework_sort_enum_sort_object_conversion_extensions.dart'; - -import 'open_homework_list_view.dart'; - -class OpenHomeworkListViewFactory { - final HomeworkSortAndSubcategorizer _sortAndSubcategorizer; - final Date Function() _getCurrentDate; - - OpenHomeworkListViewFactory( - this._sortAndSubcategorizer, this._getCurrentDate); - - OpenHomeworkListView create( - IList openHomeworks, Sort sort) { - final homeworkSectionViews = - _sortAndSubcategorizer.sortAndSubcategorize(openHomeworks, sort); - - final showCompleteOverdueHomeworkPrompt = - _shouldShowCompleteOverdueHomeworkPrompt(openHomeworks); - - return OpenHomeworkListView( - homeworkSectionViews, - showCompleteOverdueHomeworkPrompt: showCompleteOverdueHomeworkPrompt, - sorting: sort.toEnum(), - ); - } - - bool _shouldShowCompleteOverdueHomeworkPrompt( - IList openHomeworks) { - var now = _getCurrentDate(); - var overdueOpenHomeworks = openHomeworks.getOverdue(now); - return overdueOpenHomeworks.length > 2; - } -} diff --git a/lib/hausaufgabenheft_logik/lib/src/setup/create_homework_page_bloc.dart b/lib/hausaufgabenheft_logik/lib/src/setup/create_homework_page_bloc.dart deleted file mode 100644 index 17b660143..000000000 --- a/lib/hausaufgabenheft_logik/lib/src/setup/create_homework_page_bloc.dart +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'package:clock/clock.dart'; -import 'package:hausaufgabenheft_logik/color.dart'; -import 'package:hausaufgabenheft_logik/src/homework_completion/homework_page_completion_dispatcher.dart'; -import 'package:hausaufgabenheft_logik/src/student_homework_page_bloc/homework_sorting_cache.dart'; - -import '../completed_homeworks/views/completed_homework_list_view_factory.dart'; -import '../models/models.dart'; -import '../open_homeworks/sort_and_subcategorization/sort_and_subcategorizer.dart'; -import '../open_homeworks/views/open_homework_list_view_factory.dart'; -import '../student_homework_page_bloc/student_homework_page_bloc.dart'; -import '../views/student_homework_view_factory.dart'; -import 'config.dart'; -import 'dependencies.dart'; - -HomeworkPageBloc createHomeworkPageBloc( - HausaufgabenheftDependencies dependencies, HausaufgabenheftConfig config) { - final getCurrentDateTime = - dependencies.getCurrentDateTime ?? () => clock.now(); - getCurrentDate() => Date.fromDateTime(getCurrentDateTime()); - - final viewFactory = StudentHomeworkViewFactory( - defaultColorValue: config.defaultCourseColorValue); - final sortAndSubcategorizer = HomeworkSortAndSubcategorizer( - defaultColor: Color(config.defaultCourseColorValue), - getCurrentDate: getCurrentDate, - ); - final openHomeworkListViewFactory = - OpenHomeworkListViewFactory(sortAndSubcategorizer, getCurrentDate); - - final completedHomeworkListViewFactory = - CompletedHomeworkListViewFactory(viewFactory); - - final homeworkPageCompletionReceiver = HomeworkPageCompletionDispatcher( - dependencies.completionDispatcher, - getCurrentOverdueHomeworkIds: dependencies.getOpenOverdueHomeworkIds); - - return HomeworkPageBloc( - openHomeworkListViewFactory: openHomeworkListViewFactory, - completedHomeworkListViewFactory: completedHomeworkListViewFactory, - homeworkDataSource: dependencies.dataSource, - numberOfInitialCompletedHomeworksToLoad: - config.nrOfInitialCompletedHomeworksToLoad, - homeworkCompletionReceiver: homeworkPageCompletionReceiver, - homeworkSortingCache: HomeworkSortingCache(dependencies.keyValueStore), - getCurrentDateTime: dependencies.getCurrentDateTime ?? () => clock.now(), - ); -} diff --git a/lib/hausaufgabenheft_logik/lib/src/setup/dependencies.dart b/lib/hausaufgabenheft_logik/lib/src/setup/dependencies.dart deleted file mode 100644 index f0fc2cfa8..000000000 --- a/lib/hausaufgabenheft_logik/lib/src/setup/dependencies.dart +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) -// Licensed under the EUPL-1.2-or-later. -// -// You may obtain a copy of the Licence at: -// https://joinup.ec.europa.eu/software/page/eupl -// -// SPDX-License-Identifier: EUPL-1.2 - -import 'package:common_domain_models/common_domain_models.dart'; -import 'package:fast_immutable_collections/fast_immutable_collections.dart'; -import 'package:key_value_store/key_value_store.dart'; -import '../data_source/homework_data_source.dart'; -import '../homework_completion/homework_completion_dispatcher.dart'; - -class HausaufgabenheftDependencies { - /// Used to load open and completed homeworks - final HomeworkDataSource dataSource; - - /// Used change the completion status of a homework - final HomeworkCompletionDispatcher completionDispatcher; - - /// Used to complete all overdue homeworks at once by using the completion - /// dispatcher. - final Future> Function() getOpenOverdueHomeworkIds; - - final KeyValueStore keyValueStore; - - final DateTime Function()? getCurrentDateTime; - - HausaufgabenheftDependencies({ - required this.dataSource, - required this.completionDispatcher, - required this.getOpenOverdueHomeworkIds, - required this.keyValueStore, - this.getCurrentDateTime, - }); -} diff --git a/lib/hausaufgabenheft_logik/lib/src/views/color.dart b/lib/hausaufgabenheft_logik/lib/src/shared/color.dart similarity index 100% rename from lib/hausaufgabenheft_logik/lib/src/views/color.dart rename to lib/hausaufgabenheft_logik/lib/src/shared/color.dart diff --git a/lib/hausaufgabenheft_logik/lib/src/shared/homework_list_extensions.dart b/lib/hausaufgabenheft_logik/lib/src/shared/homework_list_extensions.dart new file mode 100644 index 000000000..f1ea32951 --- /dev/null +++ b/lib/hausaufgabenheft_logik/lib/src/shared/homework_list_extensions.dart @@ -0,0 +1,22 @@ +// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) +// Licensed under the EUPL-1.2-or-later. +// +// You may obtain a copy of the Licence at: +// https://joinup.ec.europa.eu/software/page/eupl +// +// SPDX-License-Identifier: EUPL-1.2 + +import 'package:fast_immutable_collections/fast_immutable_collections.dart'; + +import 'models/homework.dart'; +import 'models/subject.dart'; + +extension HomeworkListExtension on IList { + IList getDistinctOrderedSubjects() { + final subjects = {}; + for (final homework in this) { + subjects.add(homework.subject); + } + return subjects.toIList(); + } +} diff --git a/lib/hausaufgabenheft_logik/lib/src/shared/homework_page_api.dart b/lib/hausaufgabenheft_logik/lib/src/shared/homework_page_api.dart new file mode 100644 index 000000000..9113bdc03 --- /dev/null +++ b/lib/hausaufgabenheft_logik/lib/src/shared/homework_page_api.dart @@ -0,0 +1,68 @@ +// Copyright (c) 2024 Sharezone UG (haftungsbeschränkt) +// Licensed under the EUPL-1.2-or-later. +// +// You may obtain a copy of the Licence at: +// https://joinup.ec.europa.eu/software/page/eupl +// +// SPDX-License-Identifier: EUPL-1.2 + +import 'package:collection/collection.dart'; +import 'package:common_domain_models/common_domain_models.dart'; +import 'package:fast_immutable_collections/fast_immutable_collections.dart'; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; + +class HomeworkPageApi { + final StudentHomeworkPageApi students; + final TeacherAndParentHomeworkPageApi teachersAndParents; + + HomeworkPageApi({ + required this.students, + required this.teachersAndParents, + }); +} + +abstract class StudentHomeworkPageApi { + Stream> get openHomeworks; + LazyLoadingController + getLazyLoadingCompletedHomeworksController(int nrOfInitialHomeworkToLoad); + Future completeHomework( + HomeworkId homeworkId, CompletionStatus newCompletionStatus); + Future> getOpenOverdueHomeworkIds(); +} + +abstract class TeacherAndParentHomeworkPageApi { + Stream> get openHomeworks; + LazyLoadingController + getLazyLoadingArchivedHomeworksController(int nrOfInitialHomeworkToLoad); +} + +abstract class LazyLoadingController { + Stream> get results; + void advanceBy(int numberOfHomeworks); +} + +class LazyLoadingResult { + final IList homeworks; + final bool moreHomeworkAvailable; + + LazyLoadingResult(this.homeworks, {required this.moreHomeworkAvailable}); + + LazyLoadingResult.empty({this.moreHomeworkAvailable = true}) + : homeworks = const IListConst([]); + + @override + String toString() { + return 'LazyLoadingResult(homeworks: $homeworks, $moreHomeworkAvailable)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + other is LazyLoadingResult && + const DeepCollectionEquality().equals(other.homeworks, homeworks) && + other.moreHomeworkAvailable == moreHomeworkAvailable; + } + + @override + int get hashCode => homeworks.hashCode ^ moreHomeworkAvailable.hashCode; +} diff --git a/lib/hausaufgabenheft_logik/lib/src/lehrer/teacher_homework_section_view.dart b/lib/hausaufgabenheft_logik/lib/src/shared/homework_section_view.dart similarity index 50% rename from lib/hausaufgabenheft_logik/lib/src/lehrer/teacher_homework_section_view.dart rename to lib/hausaufgabenheft_logik/lib/src/shared/homework_section_view.dart index 94cf6af39..37f7a4c42 100644 --- a/lib/hausaufgabenheft_logik/lib/src/lehrer/teacher_homework_section_view.dart +++ b/lib/hausaufgabenheft_logik/lib/src/shared/homework_section_view.dart @@ -8,34 +8,19 @@ import 'package:equatable/equatable.dart'; import 'package:fast_immutable_collections/fast_immutable_collections.dart'; -import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik_lehrer.dart'; -import 'teacher_homework_view_factory.dart'; - -class TeacherHomeworkSectionView extends Equatable { +class HomeworkSectionView extends Equatable { final String title; - final IList homeworks; + final IList homeworks; bool get isEmpty => homeworks.isEmpty; bool get isNotEmpty => homeworks.isNotEmpty; - const TeacherHomeworkSectionView(this.title, this.homeworks); + const HomeworkSectionView(this.title, this.homeworks); @override List get props => [title, homeworks]; - factory TeacherHomeworkSectionView.fromModels( - String title, - IList homeworks, - TeacherHomeworkViewFactory viewFactory, - ) { - return TeacherHomeworkSectionView( - title, - IList([ - for (final h in homeworks) viewFactory.createFrom(h), - ])); - } - @override String toString() => 'HomeworkSection(title: $title, homeworks: $homeworks)'; } diff --git a/lib/hausaufgabenheft_logik/lib/src/student_homework_page_bloc/homework_sorting_cache.dart b/lib/hausaufgabenheft_logik/lib/src/shared/homework_sorting_cache.dart similarity index 100% rename from lib/hausaufgabenheft_logik/lib/src/student_homework_page_bloc/homework_sorting_cache.dart rename to lib/hausaufgabenheft_logik/lib/src/shared/homework_sorting_cache.dart diff --git a/lib/hausaufgabenheft_logik/lib/src/completed_homeworks/views/completed_homwork_list_view.dart b/lib/hausaufgabenheft_logik/lib/src/shared/lazy_loading_homework_list_view.dart similarity index 52% rename from lib/hausaufgabenheft_logik/lib/src/completed_homeworks/views/completed_homwork_list_view.dart rename to lib/hausaufgabenheft_logik/lib/src/shared/lazy_loading_homework_list_view.dart index 8f091879c..8410a8e97 100644 --- a/lib/hausaufgabenheft_logik/lib/src/completed_homeworks/views/completed_homwork_list_view.dart +++ b/lib/hausaufgabenheft_logik/lib/src/shared/lazy_loading_homework_list_view.dart @@ -8,26 +8,23 @@ import 'package:fast_immutable_collections/fast_immutable_collections.dart'; -import '../../views/homework_view.dart'; +class LazyLoadingHomeworkListView { + final bool loadedAllHomeworks; + final IList orderedHomeworks; -class CompletedHomeworkListView { - final bool loadedAllCompletedHomeworks; - final IList orderedHomeworks; - - CompletedHomeworkListView(this.orderedHomeworks, - {required this.loadedAllCompletedHomeworks}); + LazyLoadingHomeworkListView(this.orderedHomeworks, + {required this.loadedAllHomeworks}); int get numberOfHomeworks => orderedHomeworks.length; @override bool operator ==(Object other) { return identical(this, other) || - other is CompletedHomeworkListView && + other is LazyLoadingHomeworkListView && other.orderedHomeworks == orderedHomeworks && - other.loadedAllCompletedHomeworks == loadedAllCompletedHomeworks; + other.loadedAllHomeworks == loadedAllHomeworks; } @override - int get hashCode => - orderedHomeworks.hashCode ^ loadedAllCompletedHomeworks.hashCode; + int get hashCode => orderedHomeworks.hashCode ^ loadedAllHomeworks.hashCode; } diff --git a/lib/hausaufgabenheft_logik/lib/src/models/date.dart b/lib/hausaufgabenheft_logik/lib/src/shared/models/date.dart similarity index 100% rename from lib/hausaufgabenheft_logik/lib/src/models/date.dart rename to lib/hausaufgabenheft_logik/lib/src/shared/models/date.dart diff --git a/lib/hausaufgabenheft_logik/lib/src/shared/models/homework.dart b/lib/hausaufgabenheft_logik/lib/src/shared/models/homework.dart new file mode 100644 index 000000000..1febc85ee --- /dev/null +++ b/lib/hausaufgabenheft_logik/lib/src/shared/models/homework.dart @@ -0,0 +1,107 @@ +// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) +// Licensed under the EUPL-1.2-or-later. +// +// You may obtain a copy of the Licence at: +// https://joinup.ec.europa.eu/software/page/eupl +// +// SPDX-License-Identifier: EUPL-1.2 + +import 'package:common_domain_models/common_domain_models.dart'; +import 'package:equatable/equatable.dart'; +import 'package:hausaufgabenheft_logik/src/shared/models/homework_completion_status.dart'; + +import 'date.dart'; +import 'subject.dart'; +import 'title.dart'; + +abstract class BaseHomeworkReadModel extends Equatable { + final HomeworkId id; + final DateTime todoDate; + final Subject subject; + final Title title; + final CourseId courseId; + final bool withSubmissions; + + @override + List get props => + [id, todoDate, subject, courseId, title, withSubmissions]; + + const BaseHomeworkReadModel({ + required this.id, + required this.title, + required this.subject, + required this.courseId, + required this.withSubmissions, + required this.todoDate, + }); + + bool isOverdueRelativeTo(Date today) { + return Date.fromDateTime(todoDate) < today; + } +} + +class StudentHomeworkReadModel extends BaseHomeworkReadModel { + final CompletionStatus status; + + @override + List get props => + [id, todoDate, subject, courseId, title, withSubmissions, status]; + + const StudentHomeworkReadModel({ + required super.id, + required super.title, + required super.subject, + required this.status, + required super.withSubmissions, + required super.todoDate, + required super.courseId, + }); +} + +class TeacherHomeworkReadModel extends BaseHomeworkReadModel { + final ArchivalStatus status; + final int nrOfStudentsCompleted; + final bool canViewCompletions; + final bool canViewSubmissions; + + /// If the user has the permission to delete the homework for everyone in the + /// group. + final bool canDeleteForEveryone; + + /// If the user has the permission to edit the homework for everyone in the + /// group. + final bool canEditForEveryone; + + @override + List get props => [ + id, + todoDate, + subject, + courseId, + title, + withSubmissions, + status, + nrOfStudentsCompleted, + canViewCompletions, + canViewSubmissions, + canDeleteForEveryone, + canEditForEveryone, + ]; + + const TeacherHomeworkReadModel({ + required this.nrOfStudentsCompleted, + required this.canViewCompletions, + required this.canViewSubmissions, + required this.canDeleteForEveryone, + required this.canEditForEveryone, + required this.status, + required super.id, + required super.title, + required super.subject, + required super.courseId, + required super.withSubmissions, + required super.todoDate, + }); +} + +enum ArchivalStatus { open, archived } diff --git a/lib/hausaufgabenheft_logik/lib/src/models/homework_completion_status.dart b/lib/hausaufgabenheft_logik/lib/src/shared/models/homework_completion_status.dart similarity index 100% rename from lib/hausaufgabenheft_logik/lib/src/models/homework_completion_status.dart rename to lib/hausaufgabenheft_logik/lib/src/shared/models/homework_completion_status.dart diff --git a/lib/hausaufgabenheft_logik/lib/src/models/models.dart b/lib/hausaufgabenheft_logik/lib/src/shared/models/models.dart similarity index 100% rename from lib/hausaufgabenheft_logik/lib/src/models/models.dart rename to lib/hausaufgabenheft_logik/lib/src/shared/models/models.dart diff --git a/lib/hausaufgabenheft_logik/lib/src/models/subject.dart b/lib/hausaufgabenheft_logik/lib/src/shared/models/subject.dart similarity index 91% rename from lib/hausaufgabenheft_logik/lib/src/models/subject.dart rename to lib/hausaufgabenheft_logik/lib/src/shared/models/subject.dart index cd884845b..2d5b16235 100644 --- a/lib/hausaufgabenheft_logik/lib/src/models/subject.dart +++ b/lib/hausaufgabenheft_logik/lib/src/shared/models/subject.dart @@ -7,7 +7,7 @@ // SPDX-License-Identifier: EUPL-1.2 import 'package:equatable/equatable.dart'; -import 'package:hausaufgabenheft_logik/src/views/color.dart'; +import 'package:hausaufgabenheft_logik/src/shared/color.dart'; class Subject extends Equatable { final String name; diff --git a/lib/hausaufgabenheft_logik/lib/src/models/title.dart b/lib/hausaufgabenheft_logik/lib/src/shared/models/title.dart similarity index 100% rename from lib/hausaufgabenheft_logik/lib/src/models/title.dart rename to lib/hausaufgabenheft_logik/lib/src/shared/models/title.dart diff --git a/lib/hausaufgabenheft_logik/lib/src/setup/config.dart b/lib/hausaufgabenheft_logik/lib/src/shared/setup/config.dart similarity index 100% rename from lib/hausaufgabenheft_logik/lib/src/setup/config.dart rename to lib/hausaufgabenheft_logik/lib/src/shared/setup/config.dart diff --git a/lib/hausaufgabenheft_logik/lib/src/shared/setup/dependencies.dart b/lib/hausaufgabenheft_logik/lib/src/shared/setup/dependencies.dart new file mode 100644 index 000000000..dc0d88485 --- /dev/null +++ b/lib/hausaufgabenheft_logik/lib/src/shared/setup/dependencies.dart @@ -0,0 +1,24 @@ +// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) +// Licensed under the EUPL-1.2-or-later. +// +// You may obtain a copy of the Licence at: +// https://joinup.ec.europa.eu/software/page/eupl +// +// SPDX-License-Identifier: EUPL-1.2 + +import 'package:hausaufgabenheft_logik/src/shared/homework_page_api.dart'; +import 'package:key_value_store/key_value_store.dart'; + +class HausaufgabenheftDependencies { + final HomeworkPageApi api; + + final KeyValueStore keyValueStore; + + final DateTime Function()? getCurrentDateTime; + + HausaufgabenheftDependencies({ + required this.api, + required this.keyValueStore, + this.getCurrentDateTime, + }); +} diff --git a/lib/hausaufgabenheft_logik/lib/src/lehrer/teacher_open_homework_list_view.dart b/lib/hausaufgabenheft_logik/lib/src/shared/sort/sorts.dart similarity index 56% rename from lib/hausaufgabenheft_logik/lib/src/lehrer/teacher_open_homework_list_view.dart rename to lib/hausaufgabenheft_logik/lib/src/shared/sort/sorts.dart index c97f10112..a27701f89 100644 --- a/lib/hausaufgabenheft_logik/lib/src/lehrer/teacher_open_homework_list_view.dart +++ b/lib/hausaufgabenheft_logik/lib/src/shared/sort/sorts.dart @@ -6,47 +6,10 @@ // // SPDX-License-Identifier: EUPL-1.2 -import 'package:collection/collection.dart' show DeepCollectionEquality; -import 'package:collection/collection.dart'; -import 'package:fast_immutable_collections/fast_immutable_collections.dart'; - -import 'teacher_homework_section_view.dart'; - -class TeacherOpenHomeworkListView { - final IList sections; - final HomeworkSort sorting; - - TeacherOpenHomeworkListView( - this.sections, { - required this.sorting, - }) : super(); - - int get numberOfHomeworks { - final listLengths = sections.map((s) => s.homeworks.length).toList(); - if (listLengths.isEmpty) { - return 0; - } - return listLengths.reduce((i, i2) => i + i2); - } - - @override - String toString() => - 'OpenHomeworkListView(sorting: $sorting, sections: $sections)'; - - @override - bool operator ==(Object other) { - if (identical(this, other)) return true; - final bool Function(Object, Object) listEquals = - const DeepCollectionEquality().equals; - - return other is TeacherOpenHomeworkListView && - listEquals(other.sections, sections) && - other.sorting == sorting; - } - - @override - int get hashCode => sections.hashCode ^ sorting.hashCode; -} +export 'src/sort.dart'; +export 'src/homework_attribute_sorts.dart'; +export 'src/homework_sort_enum_sort_object_conversion_extensions.dart'; +export 'src/sort_with_operations.dart'; enum HomeworkSort { /// Sorts the homeworks firstly by date (earliest date first). diff --git a/lib/hausaufgabenheft_logik/lib/src/open_homeworks/sort_and_subcategorization/sort/src/homework_attribute_sorts.dart b/lib/hausaufgabenheft_logik/lib/src/shared/sort/src/homework_attribute_sorts.dart similarity index 60% rename from lib/hausaufgabenheft_logik/lib/src/open_homeworks/sort_and_subcategorization/sort/src/homework_attribute_sorts.dart rename to lib/hausaufgabenheft_logik/lib/src/shared/sort/src/homework_attribute_sorts.dart index 90d692fa8..2fb9dff54 100644 --- a/lib/hausaufgabenheft_logik/lib/src/open_homeworks/sort_and_subcategorization/sort/src/homework_attribute_sorts.dart +++ b/lib/hausaufgabenheft_logik/lib/src/shared/sort/src/homework_attribute_sorts.dart @@ -6,15 +6,15 @@ // // SPDX-License-Identifier: EUPL-1.2 -import 'package:hausaufgabenheft_logik/src/models/homework.dart'; +import 'package:hausaufgabenheft_logik/src/shared/models/homework.dart'; import 'sort_with_operations.dart'; -ComparisonResult dateSort(HomeworkReadModel ha1, HomeworkReadModel ha2) => +ComparisonResult dateSort(T ha1, T ha2) => ComparisonResult(ha1.todoDate.compareTo(ha2.todoDate)); -ComparisonResult subjectSort(HomeworkReadModel ha1, HomeworkReadModel ha2) => +ComparisonResult subjectSort(T ha1, T ha2) => ComparisonResult(ha1.subject.name.compareTo(ha2.subject.name)); -ComparisonResult titleSort(HomeworkReadModel ha1, HomeworkReadModel ha2) => +ComparisonResult titleSort(T ha1, T ha2) => ComparisonResult(ha1.title.compareTo(ha2.title)); diff --git a/lib/hausaufgabenheft_logik/lib/src/open_homeworks/sort_and_subcategorization/sort/src/homework_sort_enum_sort_object_conversion_extensions.dart b/lib/hausaufgabenheft_logik/lib/src/shared/sort/src/homework_sort_enum_sort_object_conversion_extensions.dart similarity index 74% rename from lib/hausaufgabenheft_logik/lib/src/open_homeworks/sort_and_subcategorization/sort/src/homework_sort_enum_sort_object_conversion_extensions.dart rename to lib/hausaufgabenheft_logik/lib/src/shared/sort/src/homework_sort_enum_sort_object_conversion_extensions.dart index f82e091d1..b3a6fead8 100644 --- a/lib/hausaufgabenheft_logik/lib/src/open_homeworks/sort_and_subcategorization/sort/src/homework_sort_enum_sort_object_conversion_extensions.dart +++ b/lib/hausaufgabenheft_logik/lib/src/shared/sort/src/homework_sort_enum_sort_object_conversion_extensions.dart @@ -6,9 +6,11 @@ // // SPDX-License-Identifier: EUPL-1.2 -import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart' + hide SmallestDateSubjectAndTitleSort, SubjectSmallestDateAndTitleSort, Sort; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik_lehrer.dart'; -extension HomeworkSortToEnumExtension on Sort { +extension HomeworkSortToEnumExtension on Sort { HomeworkSort toEnum() { if (this is SmallestDateSubjectAndTitleSort) { return HomeworkSort.smallestDateSubjectAndTitle; @@ -20,8 +22,8 @@ extension HomeworkSortToEnumExtension on Sort { } } -extension HomeworkSortEnumToSortExtension on HomeworkSort { - Sort toSortObject( +extension StudentHomeworkSortEnumToSortExtension on HomeworkSort { + Sort toSortObject( {required Date Function()? getCurrentDate}) { switch (this) { case HomeworkSort.smallestDateSubjectAndTitle: diff --git a/lib/hausaufgabenheft_logik/lib/src/open_homeworks/sort_and_subcategorization/sort/src/sort.dart b/lib/hausaufgabenheft_logik/lib/src/shared/sort/src/sort.dart similarity index 58% rename from lib/hausaufgabenheft_logik/lib/src/open_homeworks/sort_and_subcategorization/sort/src/sort.dart rename to lib/hausaufgabenheft_logik/lib/src/shared/sort/src/sort.dart index d2ed3d779..7730d429d 100644 --- a/lib/hausaufgabenheft_logik/lib/src/open_homeworks/sort_and_subcategorization/sort/src/sort.dart +++ b/lib/hausaufgabenheft_logik/lib/src/shared/sort/src/sort.dart @@ -9,17 +9,21 @@ import 'package:fast_immutable_collections/fast_immutable_collections.dart'; import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; -import 'homework_attribute_sorts.dart'; -import 'sort_with_operations.dart'; +sealed class Sort { + IList sort(IList list); +} -sealed class Sort { - IList sort(IList list); +extension SortWith on IList { + IList sortWith(Sort sort) { + return sort.sort(this); + } } /// Sorts the homeworks firstly by date (earliest date first). /// If they have the same date, they will be sorted alphabetically by subject. /// If they have the same date and subject, they will be sorted alphabetically by title. -class SmallestDateSubjectAndTitleSort extends Sort { +class SmallestDateSubjectAndTitleSort extends Sort { late Date Function() getCurrentDate; SmallestDateSubjectAndTitleSort({Date Function()? getCurrentDate}) { @@ -27,9 +31,11 @@ class SmallestDateSubjectAndTitleSort extends Sort { } @override - IList sort(IList list) { - return sortWithOperations( - list, const IListConst([dateSort, subjectSort, titleSort])); + IList sort(IList list) { + return sortWithOperations( + list, IListConst( + // ignore: prefer_const_literals_to_create_immutables + [dateSort, subjectSort, titleSort])); } @override @@ -46,11 +52,13 @@ class SmallestDateSubjectAndTitleSort extends Sort { /// Sorts the homeworks firstly by Subject. /// If they have the same subject, they will be sorted by date (earliest date first). /// If they have the same date and subject, they will be sorted alphabetically by title. -class SubjectSmallestDateAndTitleSort extends Sort { +class SubjectSmallestDateAndTitleSort extends Sort { @override - IList sort(IList list) { - return sortWithOperations( - list, const IListConst([subjectSort, dateSort, titleSort])); + IList sort(IList list) { + return sortWithOperations( + list, IListConst( + // ignore: prefer_const_literals_to_create_immutables + [subjectSort, dateSort, titleSort])); } @override diff --git a/lib/hausaufgabenheft_logik/lib/src/open_homeworks/sort_and_subcategorization/sort/src/sort_with_operations.dart b/lib/hausaufgabenheft_logik/lib/src/shared/sort/src/sort_with_operations.dart similarity index 100% rename from lib/hausaufgabenheft_logik/lib/src/open_homeworks/sort_and_subcategorization/sort/src/sort_with_operations.dart rename to lib/hausaufgabenheft_logik/lib/src/shared/sort/src/sort_with_operations.dart diff --git a/lib/hausaufgabenheft_logik/lib/src/shared/sort_and_subcategorizer.dart b/lib/hausaufgabenheft_logik/lib/src/shared/sort_and_subcategorizer.dart new file mode 100644 index 000000000..273dd025c --- /dev/null +++ b/lib/hausaufgabenheft_logik/lib/src/shared/sort_and_subcategorizer.dart @@ -0,0 +1,77 @@ +// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) +// Licensed under the EUPL-1.2-or-later. +// +// You may obtain a copy of the Licence at: +// https://joinup.ec.europa.eu/software/page/eupl +// +// SPDX-License-Identifier: EUPL-1.2 + +import 'package:fast_immutable_collections/fast_immutable_collections.dart'; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; + +class HomeworkSortAndSubcategorizer { + final Date Function() getCurrentDate; + + HomeworkSortAndSubcategorizer({ + required this.getCurrentDate, + }); + + IList> sortAndSubcategorize( + IList homeworks, Sort sort) { + final sorted = homeworks.sortWith(sort); + + return switch (sort) { + SmallestDateSubjectAndTitleSort() => _subcategorizeByDate(sorted), + SubjectSmallestDateAndTitleSort() => _subcategorizeBySubject(sorted), + }; + } + + IList> _subcategorizeByDate(IList homeworks) { + final now = getCurrentDate(); + final tomorrow = now.addDays(1); + final in2Days = tomorrow.addDays(1); + + final IList overdueHomework = + homeworks.where((h) => Date.fromDateTime(h.todoDate) < now).toIList(); + final IList todayHomework = + homeworks.where((h) => Date.fromDateTime(h.todoDate) == now).toIList(); + final IList tomorrowHomework = homeworks + .where((h) => Date.fromDateTime(h.todoDate) == tomorrow) + .toIList(); + final IList in2DaysHomework = homeworks + .where((h) => Date.fromDateTime(h.todoDate) == in2Days) + .toIList(); + final IList futureHomework = homeworks + .where((h) => Date.fromDateTime(h.todoDate) > in2Days) + .toIList(); + + final overdueSec = HomeworkSectionView('Überfällig', overdueHomework); + final todaySec = HomeworkSectionView('Heute', todayHomework); + final tomorrowSec = HomeworkSectionView('Morgen', tomorrowHomework); + final inTwoDaysSec = HomeworkSectionView('Übermorgen', in2DaysHomework); + final afterTwoDaysSec = HomeworkSectionView('Später', futureHomework); + + final sections = [ + overdueSec, + todaySec, + tomorrowSec, + inTwoDaysSec, + afterTwoDaysSec + ]; + + return sections.where((section) => section.isNotEmpty).toIList(); + } + + IList> _subcategorizeBySubject(IList homeworks) { + final subjects = homeworks.getDistinctOrderedSubjects(); + var homeworkSections = IList>(); + for (final subject in subjects) { + final IList homeworksWithSubject = + homeworks.where((h) => h.subject == subject).toIList(); + + homeworkSections = homeworkSections + .add(HomeworkSectionView(subject.name, homeworksWithSubject)); + } + return homeworkSections; + } +} diff --git a/lib/hausaufgabenheft_logik/lib/src/student_homework_page_bloc/events.dart b/lib/hausaufgabenheft_logik/lib/src/student/bloc/events.dart similarity index 83% rename from lib/hausaufgabenheft_logik/lib/src/student_homework_page_bloc/events.dart rename to lib/hausaufgabenheft_logik/lib/src/student/bloc/events.dart index 3cd9bffcc..4f8b6bfc7 100644 --- a/lib/hausaufgabenheft_logik/lib/src/student_homework_page_bloc/events.dart +++ b/lib/hausaufgabenheft_logik/lib/src/student/bloc/events.dart @@ -9,13 +9,13 @@ import 'package:equatable/equatable.dart'; import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; -abstract class HomeworkPageEvent extends Equatable { +abstract class StudentHomeworkPageEvent extends Equatable { @override List get props => []; } /// Sorts all open homeworks with the given [sort]. -class OpenHwSortingChanged extends HomeworkPageEvent { +class OpenHwSortingChanged extends StudentHomeworkPageEvent { final HomeworkSort sort; OpenHwSortingChanged(this.sort); @@ -31,7 +31,7 @@ class OpenHwSortingChanged extends HomeworkPageEvent { /// Changes the completion status of the homework with the given [homeworkId] /// to [newValue]. -class CompletionStatusChanged extends HomeworkPageEvent { +class CompletionStatusChanged extends StudentHomeworkPageEvent { final String homeworkId; final bool newValue; @@ -48,7 +48,7 @@ class CompletionStatusChanged extends HomeworkPageEvent { /// Marks the completion status of all open homeworks where the todo date lies /// before today as completed. -class CompletedAllOverdue extends HomeworkPageEvent { +class CompletedAllOverdue extends StudentHomeworkPageEvent { @override String toString() { return 'CompletedAllOverdue'; @@ -56,7 +56,7 @@ class CompletedAllOverdue extends HomeworkPageEvent { } /// Tells the bloc to start loading homeworks -class LoadHomeworks extends HomeworkPageEvent { +class LoadHomeworks extends StudentHomeworkPageEvent { @override String toString() { return 'LoadHomeworks'; @@ -70,7 +70,7 @@ class LoadHomeworks extends HomeworkPageEvent { /// New state: 10 completed homeworks loaded. /// /// If all homeworks are already loaded this won't do anything. -class AdvanceCompletedHomeworks extends HomeworkPageEvent { +class AdvanceCompletedHomeworks extends StudentHomeworkPageEvent { final int advanceBy; @override diff --git a/lib/hausaufgabenheft_logik/lib/src/student_homework_page_bloc/states.dart b/lib/hausaufgabenheft_logik/lib/src/student/bloc/states.dart similarity index 61% rename from lib/hausaufgabenheft_logik/lib/src/student_homework_page_bloc/states.dart rename to lib/hausaufgabenheft_logik/lib/src/student/bloc/states.dart index 8127eda1e..3887c1bf2 100644 --- a/lib/hausaufgabenheft_logik/lib/src/student_homework_page_bloc/states.dart +++ b/lib/hausaufgabenheft_logik/lib/src/student/bloc/states.dart @@ -7,17 +7,16 @@ // SPDX-License-Identifier: EUPL-1.2 import 'package:equatable/equatable.dart'; -import 'package:hausaufgabenheft_logik/src/completed_homeworks/views/completed_homwork_list_view.dart'; -import 'package:hausaufgabenheft_logik/src/open_homeworks/views/open_homework_list_view.dart'; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; -abstract class HomeworkPageState extends Equatable { +abstract class StudentHomeworkPageState extends Equatable { @override List get props => []; } -class Success extends HomeworkPageState { - final CompletedHomeworkListView completed; - final OpenHomeworkListView open; +class Success extends StudentHomeworkPageState { + final LazyLoadingHomeworkListView completed; + final StudentOpenHomeworkListView open; Success(this.completed, this.open); @@ -31,7 +30,7 @@ class Success extends HomeworkPageState { } /// Bloc has not yet been told to load the homeworks. -class Uninitialized extends HomeworkPageState { +class Uninitialized extends StudentHomeworkPageState { @override String toString() { return 'HomeworkPageStateUninitialized'; diff --git a/lib/hausaufgabenheft_logik/lib/src/student_homework_page_bloc/student_homework_page_bloc.dart b/lib/hausaufgabenheft_logik/lib/src/student/bloc/student_homework_page_bloc.dart similarity index 64% rename from lib/hausaufgabenheft_logik/lib/src/student_homework_page_bloc/student_homework_page_bloc.dart rename to lib/hausaufgabenheft_logik/lib/src/student/bloc/student_homework_page_bloc.dart index 351713a03..06632445e 100644 --- a/lib/hausaufgabenheft_logik/lib/src/student_homework_page_bloc/student_homework_page_bloc.dart +++ b/lib/hausaufgabenheft_logik/lib/src/student/bloc/student_homework_page_bloc.dart @@ -13,41 +13,38 @@ import 'package:bloc_base/bloc_base.dart' as bloc_base; import 'package:common_domain_models/common_domain_models.dart'; import 'package:fast_immutable_collections/fast_immutable_collections.dart'; import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; -import 'package:hausaufgabenheft_logik/src/completed_homeworks/views/completed_homework_list_view_factory.dart'; -import 'package:hausaufgabenheft_logik/src/homework_completion/homework_page_completion_dispatcher.dart'; -import 'package:hausaufgabenheft_logik/src/open_homeworks/sort_and_subcategorization/sort/src/homework_sort_enum_sort_object_conversion_extensions.dart'; -import 'package:hausaufgabenheft_logik/src/open_homeworks/views/open_homework_list_view_factory.dart'; -import 'package:hausaufgabenheft_logik/src/student_homework_page_bloc/homework_sorting_cache.dart'; +import 'package:hausaufgabenheft_logik/src/student/views/student_open_homework_list_view_factory.dart'; +import 'package:hausaufgabenheft_logik/src/shared/homework_sorting_cache.dart'; import 'package:rxdart/rxdart.dart'; -class HomeworkPageBloc extends Bloc +import '../views/student_homework_view_factory.dart'; + +class StudentHomeworkPageBloc + extends Bloc implements bloc_base.BlocBase { - final HomeworkPageCompletionDispatcher _homeworkCompletionReceiver; - final HomeworkDataSource _homeworkDataSource; + final StudentHomeworkPageApi _homeworkApi; final HomeworkSortingCache _homeworkSortingCache; final DateTime Function() _getCurrentDateTime; final int numberOfInitialCompletedHomeworksToLoad; - final CompletedHomeworkListViewFactory _completedHomeworkListViewFactory; - final OpenHomeworkListViewFactory _openHomeworkListViewFactory; - final _currentSortStream = BehaviorSubject>(); - LazyLoadingController? _lazyLoadingController; + final StudentHomeworkViewFactory _viewFactory; + final StudentOpenHomeworkListViewFactory _openHomeworkListViewFactory; + final _currentSortStream = BehaviorSubject>(); + LazyLoadingController? _lazyLoadingController; /// Whether [close] or [dispose] has been called; bool _isClosed = false; - HomeworkPageBloc({ - required HomeworkPageCompletionDispatcher homeworkCompletionReceiver, + StudentHomeworkPageBloc({ required HomeworkSortingCache homeworkSortingCache, - required HomeworkDataSource homeworkDataSource, - required CompletedHomeworkListViewFactory completedHomeworkListViewFactory, - required OpenHomeworkListViewFactory openHomeworkListViewFactory, + required StudentHomeworkPageApi homeworkApi, + required StudentHomeworkViewFactory viewFactory, + required StudentOpenHomeworkListViewFactory openHomeworkListViewFactory, required this.numberOfInitialCompletedHomeworksToLoad, required DateTime Function() getCurrentDateTime, - }) : _homeworkDataSource = homeworkDataSource, + }) : _homeworkApi = homeworkApi, _openHomeworkListViewFactory = openHomeworkListViewFactory, _homeworkSortingCache = homeworkSortingCache, - _homeworkCompletionReceiver = homeworkCompletionReceiver, - _completedHomeworkListViewFactory = completedHomeworkListViewFactory, + _viewFactory = viewFactory, _getCurrentDateTime = getCurrentDateTime, super(Uninitialized()) { on((event, emit) { @@ -82,19 +79,20 @@ class HomeworkPageBloc extends Bloc .add(sortEnum.toSortObject(getCurrentDate: _getCurrentDate)); _lazyLoadingController = - _homeworkDataSource.getLazyLoadingCompletedHomeworksController( + _homeworkApi.getLazyLoadingCompletedHomeworksController( numberOfInitialCompletedHomeworksToLoad); - _combineLatestSubscription = Rx.combineLatest3, - Sort, LazyLoadingResult, Success>( - _homeworkDataSource.openHomeworks, - _currentSortStream, + _combineLatestSubscription = Rx.combineLatest3< + IList, + Sort, + LazyLoadingResult, + Success>(_homeworkApi.openHomeworks, _currentSortStream, _lazyLoadingController!.results, (openHws, sort, lazyCompletedHwsRes) { final open = _openHomeworkListViewFactory.create(openHws, sort); - final completed = _completedHomeworkListViewFactory.create( - lazyCompletedHwsRes.homeworks, - !lazyCompletedHwsRes.moreHomeworkAvailable); + final completed = LazyLoadingHomeworkListView( + lazyCompletedHwsRes.homeworks.map(_viewFactory.createFrom).toIList(), + loadedAllHomeworks: !lazyCompletedHwsRes.moreHomeworkAvailable); return Success(completed, open); }).listen((s) { @@ -116,7 +114,7 @@ class HomeworkPageBloc extends Bloc Future _mapHomeworkChangedCompletionStatus( CompletionStatusChanged event) async { - await _homeworkCompletionReceiver.changeCompletionStatus( + await _homeworkApi.completeHomework( HomeworkId(event.homeworkId), event.newValue == true ? CompletionStatus.completed @@ -124,7 +122,10 @@ class HomeworkPageBloc extends Bloc } Future _mapHomeworkMarkOverdueToState(CompletedAllOverdue event) async { - await _homeworkCompletionReceiver.completeAllOverdueHomeworks(); + final hws = await _homeworkApi.getOpenOverdueHomeworkIds(); + for (final hw in hws) { + _homeworkApi.completeHomework(hw, CompletionStatus.completed); + } } @override @@ -148,7 +149,7 @@ class HomeworkPageBloc extends Bloc /// bloc from working (as the Stream never finishes) /// this acts a as a simple wrapper to yield the /// given value -class _Yield extends HomeworkPageEvent { +class _Yield extends StudentHomeworkPageEvent { final Success success; _Yield(this.success); diff --git a/lib/hausaufgabenheft_logik/lib/src/student/create_student_homework_page_bloc.dart b/lib/hausaufgabenheft_logik/lib/src/student/create_student_homework_page_bloc.dart new file mode 100644 index 000000000..4df8f5d03 --- /dev/null +++ b/lib/hausaufgabenheft_logik/lib/src/student/create_student_homework_page_bloc.dart @@ -0,0 +1,43 @@ +// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) +// Licensed under the EUPL-1.2-or-later. +// +// You may obtain a copy of the Licence at: +// https://joinup.ec.europa.eu/software/page/eupl +// +// SPDX-License-Identifier: EUPL-1.2 + +import 'package:clock/clock.dart'; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; +import 'package:hausaufgabenheft_logik/src/shared/homework_sorting_cache.dart'; + +import '../shared/sort_and_subcategorizer.dart'; +import 'views/student_open_homework_list_view_factory.dart'; +import 'views/student_homework_view_factory.dart'; +import '../shared/setup/config.dart'; +import '../shared/setup/dependencies.dart'; + +StudentHomeworkPageBloc createStudentHomeworkPageBloc( + HausaufgabenheftDependencies dependencies, HausaufgabenheftConfig config) { + final getCurrentDateTime = + dependencies.getCurrentDateTime ?? () => clock.now(); + getCurrentDate() => Date.fromDateTime(getCurrentDateTime()); + + final viewFactory = StudentHomeworkViewFactory( + defaultColorValue: config.defaultCourseColorValue); + final sortAndSubcategorizer = + HomeworkSortAndSubcategorizer( + getCurrentDate: getCurrentDate, + ); + final openHomeworkListViewFactory = StudentOpenHomeworkListViewFactory( + sortAndSubcategorizer, viewFactory, getCurrentDate); + + return StudentHomeworkPageBloc( + openHomeworkListViewFactory: openHomeworkListViewFactory, + viewFactory: viewFactory, + homeworkApi: dependencies.api.students, + numberOfInitialCompletedHomeworksToLoad: + config.nrOfInitialCompletedHomeworksToLoad, + homeworkSortingCache: HomeworkSortingCache(dependencies.keyValueStore), + getCurrentDateTime: dependencies.getCurrentDateTime ?? () => clock.now(), + ); +} diff --git a/lib/hausaufgabenheft_logik/lib/src/student/student_homework_list_extensions.dart b/lib/hausaufgabenheft_logik/lib/src/student/student_homework_list_extensions.dart new file mode 100644 index 000000000..7a1746fa8 --- /dev/null +++ b/lib/hausaufgabenheft_logik/lib/src/student/student_homework_list_extensions.dart @@ -0,0 +1,26 @@ +// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) +// Licensed under the EUPL-1.2-or-later. +// +// You may obtain a copy of the Licence at: +// https://joinup.ec.europa.eu/software/page/eupl +// +// SPDX-License-Identifier: EUPL-1.2 + +import 'package:fast_immutable_collections/fast_immutable_collections.dart'; +import 'package:hausaufgabenheft_logik/src/shared/models/homework_completion_status.dart'; + +import '../shared/models/date.dart'; +import '../shared/models/homework.dart'; + +extension StudentHomeworkListExtension on IList { + IList get completed => + where((homework) => homework.status == CompletionStatus.completed) + .toIList(); + IList get open => + where((homework) => homework.status == CompletionStatus.open).toIList(); + + IList getOverdue([Date? now]) { + now = now ?? Date.now(); + return where((homeworks) => homeworks.isOverdueRelativeTo(now!)).toIList(); + } +} diff --git a/lib/hausaufgabenheft_logik/lib/src/open_homeworks/views/homework_section_view.dart b/lib/hausaufgabenheft_logik/lib/src/student/views/student_homework_section_view.dart similarity index 67% rename from lib/hausaufgabenheft_logik/lib/src/open_homeworks/views/homework_section_view.dart rename to lib/hausaufgabenheft_logik/lib/src/student/views/student_homework_section_view.dart index aa7d19c7e..dc3afd32d 100644 --- a/lib/hausaufgabenheft_logik/lib/src/open_homeworks/views/homework_section_view.dart +++ b/lib/hausaufgabenheft_logik/lib/src/student/views/student_homework_section_view.dart @@ -8,28 +8,28 @@ import 'package:equatable/equatable.dart'; import 'package:fast_immutable_collections/fast_immutable_collections.dart'; -import 'package:hausaufgabenheft_logik/src/models/homework.dart'; +import 'package:hausaufgabenheft_logik/src/shared/models/homework.dart'; -import '../../views/homework_view.dart'; -import '../../views/student_homework_view_factory.dart'; +import 'student_homework_view.dart'; +import 'student_homework_view_factory.dart'; -class HomeworkSectionView extends Equatable { +class StudentHomeworkSectionView extends Equatable { final String title; final IList homeworks; bool get isEmpty => homeworks.isEmpty; bool get isNotEmpty => homeworks.isNotEmpty; - const HomeworkSectionView(this.title, this.homeworks); + const StudentHomeworkSectionView(this.title, this.homeworks); @override List get props => [title, homeworks]; - factory HomeworkSectionView.fromModels( + factory StudentHomeworkSectionView.fromModels( String title, - IList homeworks, + IList homeworks, StudentHomeworkViewFactory viewFactory) { - return HomeworkSectionView( + return StudentHomeworkSectionView( title, IList([ for (final h in homeworks) viewFactory.createFrom(h), diff --git a/lib/hausaufgabenheft_logik/lib/src/views/homework_view.dart b/lib/hausaufgabenheft_logik/lib/src/student/views/student_homework_view.dart similarity index 97% rename from lib/hausaufgabenheft_logik/lib/src/views/homework_view.dart rename to lib/hausaufgabenheft_logik/lib/src/student/views/student_homework_view.dart index 16fd43dfb..d93984bed 100644 --- a/lib/hausaufgabenheft_logik/lib/src/views/homework_view.dart +++ b/lib/hausaufgabenheft_logik/lib/src/student/views/student_homework_view.dart @@ -6,7 +6,7 @@ // // SPDX-License-Identifier: EUPL-1.2 -import 'package:hausaufgabenheft_logik/src/views/color.dart'; +import 'package:hausaufgabenheft_logik/src/shared/color.dart'; class StudentHomeworkView { final String id; diff --git a/lib/hausaufgabenheft_logik/lib/src/views/student_homework_view_factory.dart b/lib/hausaufgabenheft_logik/lib/src/student/views/student_homework_view_factory.dart similarity index 87% rename from lib/hausaufgabenheft_logik/lib/src/views/student_homework_view_factory.dart rename to lib/hausaufgabenheft_logik/lib/src/student/views/student_homework_view_factory.dart index d8deff607..b309ef73b 100644 --- a/lib/hausaufgabenheft_logik/lib/src/views/student_homework_view_factory.dart +++ b/lib/hausaufgabenheft_logik/lib/src/student/views/student_homework_view_factory.dart @@ -6,10 +6,10 @@ // // SPDX-License-Identifier: EUPL-1.2 -import 'package:hausaufgabenheft_logik/src/models/homework.dart'; -import 'package:hausaufgabenheft_logik/src/models/models.dart'; -import 'package:hausaufgabenheft_logik/src/views/color.dart'; -import 'package:hausaufgabenheft_logik/src/views/homework_view.dart'; +import 'package:hausaufgabenheft_logik/src/shared/models/homework.dart'; +import 'package:hausaufgabenheft_logik/src/shared/models/models.dart'; +import 'package:hausaufgabenheft_logik/src/shared/color.dart'; +import 'package:hausaufgabenheft_logik/src/student/views/student_homework_view.dart'; class StudentHomeworkViewFactory { late Date Function() _getCurrentDate; @@ -29,7 +29,7 @@ class StudentHomeworkViewFactory { } } - StudentHomeworkView createFrom(HomeworkReadModel homework) { + StudentHomeworkView createFrom(StudentHomeworkReadModel homework) { final twoDaysInFuture = _getCurrentDate().addDays(2); return StudentHomeworkView( id: homework.id.toString(), diff --git a/lib/hausaufgabenheft_logik/lib/src/student/views/student_open_homework_list_view.dart b/lib/hausaufgabenheft_logik/lib/src/student/views/student_open_homework_list_view.dart new file mode 100644 index 000000000..6ee7443cb --- /dev/null +++ b/lib/hausaufgabenheft_logik/lib/src/student/views/student_open_homework_list_view.dart @@ -0,0 +1,48 @@ +// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) +// Licensed under the EUPL-1.2-or-later. +// +// You may obtain a copy of the Licence at: +// https://joinup.ec.europa.eu/software/page/eupl +// +// SPDX-License-Identifier: EUPL-1.2 + +import 'package:collection/collection.dart' show DeepCollectionEquality; +import 'package:fast_immutable_collections/fast_immutable_collections.dart'; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; + +class StudentOpenHomeworkListView { + final bool showCompleteOverdueHomeworkPrompt; + final IList> sections; + final HomeworkSort sorting; + + StudentOpenHomeworkListView( + this.sections, { + required this.showCompleteOverdueHomeworkPrompt, + required this.sorting, + }) : super(); + + @override + int get hashCode => + sections.hashCode & showCompleteOverdueHomeworkPrompt.hashCode; + + int get numberOfHomeworks { + final listLengths = sections.map((s) => s.homeworks.length).toList(); + if (listLengths.isEmpty) { + return 0; + } + return listLengths.reduce((i, i2) => i + i2); + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + other is StudentOpenHomeworkListView && + showCompleteOverdueHomeworkPrompt == + other.showCompleteOverdueHomeworkPrompt && + const DeepCollectionEquality().equals(sections, other.sections); + } + + @override + String toString() => + 'OpenHomeworkListView(sections: $sections, showCompleteOverdueHomeworkPrompt: $showCompleteOverdueHomeworkPrompt)'; +} diff --git a/lib/hausaufgabenheft_logik/lib/src/student/views/student_open_homework_list_view_factory.dart b/lib/hausaufgabenheft_logik/lib/src/student/views/student_open_homework_list_view_factory.dart new file mode 100644 index 000000000..ab747a218 --- /dev/null +++ b/lib/hausaufgabenheft_logik/lib/src/student/views/student_open_homework_list_view_factory.dart @@ -0,0 +1,53 @@ +// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) +// Licensed under the EUPL-1.2-or-later. +// +// You may obtain a copy of the Licence at: +// https://joinup.ec.europa.eu/software/page/eupl +// +// SPDX-License-Identifier: EUPL-1.2 + +import 'package:fast_immutable_collections/fast_immutable_collections.dart'; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; +import 'package:hausaufgabenheft_logik/src/shared/sort_and_subcategorizer.dart'; +import 'package:hausaufgabenheft_logik/src/student/views/student_homework_view_factory.dart'; + +class StudentOpenHomeworkListViewFactory { + final HomeworkSortAndSubcategorizer + _sortAndSubcategorizer; + final StudentHomeworkViewFactory _viewFactory; + final Date Function() _getCurrentDate; + + StudentOpenHomeworkListViewFactory( + this._sortAndSubcategorizer, this._viewFactory, this._getCurrentDate); + + StudentOpenHomeworkListView create( + IList openHomeworks, + Sort sort) { + final sortedAndSubcategorized = + _sortAndSubcategorizer.sortAndSubcategorize(openHomeworks, sort); + + final views = sortedAndSubcategorized + .map((section) => HomeworkSectionView( + section.title, + section.homeworks + .map((hw) => _viewFactory.createFrom(hw)) + .toIList())) + .toIList(); + + final showCompleteOverdueHomeworkPrompt = + _shouldShowCompleteOverdueHomeworkPrompt(openHomeworks); + + return StudentOpenHomeworkListView( + views, + showCompleteOverdueHomeworkPrompt: showCompleteOverdueHomeworkPrompt, + sorting: sort.toEnum(), + ); + } + + bool _shouldShowCompleteOverdueHomeworkPrompt( + IList openHomeworks) { + var now = _getCurrentDate(); + var overdueOpenHomeworks = openHomeworks.getOverdue(now); + return overdueOpenHomeworks.length > 2; + } +} diff --git a/lib/hausaufgabenheft_logik/lib/src/lehrer/events.dart b/lib/hausaufgabenheft_logik/lib/src/teacher_and_parent/bloc/events.dart similarity index 76% rename from lib/hausaufgabenheft_logik/lib/src/lehrer/events.dart rename to lib/hausaufgabenheft_logik/lib/src/teacher_and_parent/bloc/events.dart index a2d404474..3581714a5 100644 --- a/lib/hausaufgabenheft_logik/lib/src/lehrer/events.dart +++ b/lib/hausaufgabenheft_logik/lib/src/teacher_and_parent/bloc/events.dart @@ -7,15 +7,16 @@ // SPDX-License-Identifier: EUPL-1.2 import 'package:equatable/equatable.dart'; -import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik_lehrer.dart'; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart' + show HomeworkSort; -abstract class TeacherHomeworkPageEvent extends Equatable { +abstract class TeacherAndParentHomeworkPageEvent extends Equatable { @override List get props => []; } /// Sorts all open homeworks with the given [sort]. -class OpenHwSortingChanged extends TeacherHomeworkPageEvent { +class OpenHwSortingChanged extends TeacherAndParentHomeworkPageEvent { final HomeworkSort sort; OpenHwSortingChanged(this.sort); @@ -30,7 +31,7 @@ class OpenHwSortingChanged extends TeacherHomeworkPageEvent { } /// Tells the bloc to start loading homeworks -class LoadHomeworks extends TeacherHomeworkPageEvent { +class LoadHomeworks extends TeacherAndParentHomeworkPageEvent { @override String toString() { return 'LoadHomeworks'; @@ -44,7 +45,7 @@ class LoadHomeworks extends TeacherHomeworkPageEvent { /// New state: 10 archived homeworks loaded. /// /// If all homeworks are already loaded this won't do anything. -class AdvanceArchivedHomeworks extends TeacherHomeworkPageEvent { +class AdvanceArchivedHomeworks extends TeacherAndParentHomeworkPageEvent { final int advanceBy; @override diff --git a/lib/hausaufgabenheft_logik/lib/src/lehrer/states.dart b/lib/hausaufgabenheft_logik/lib/src/teacher_and_parent/bloc/states.dart similarity index 62% rename from lib/hausaufgabenheft_logik/lib/src/lehrer/states.dart rename to lib/hausaufgabenheft_logik/lib/src/teacher_and_parent/bloc/states.dart index f8559e522..67bd4568f 100644 --- a/lib/hausaufgabenheft_logik/lib/src/lehrer/states.dart +++ b/lib/hausaufgabenheft_logik/lib/src/teacher_and_parent/bloc/states.dart @@ -7,18 +7,16 @@ // SPDX-License-Identifier: EUPL-1.2 import 'package:equatable/equatable.dart'; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik_lehrer.dart'; -import 'teacher_archived_homework_list_view.dart'; -import 'teacher_open_homework_list_view.dart'; - -abstract class TeacherHomeworkPageState extends Equatable { +abstract class TeacherAndParentHomeworkPageState extends Equatable { @override List get props => []; } -class Success extends TeacherHomeworkPageState { - final TeacherArchivedHomeworkListView archived; - final TeacherOpenHomeworkListView open; +class Success extends TeacherAndParentHomeworkPageState { + final LazyLoadingHomeworkListView archived; + final TeacherAndParentOpenHomeworkListView open; Success(this.open, this.archived); @@ -32,7 +30,7 @@ class Success extends TeacherHomeworkPageState { } /// Bloc has not yet been told to load the homeworks. -class Uninitialized extends TeacherHomeworkPageState { +class Uninitialized extends TeacherAndParentHomeworkPageState { @override String toString() { return 'HomeworkPageStateUninitialized'; diff --git a/lib/hausaufgabenheft_logik/lib/src/teacher_and_parent/bloc/teacher_and_parent_homework_page_bloc.dart b/lib/hausaufgabenheft_logik/lib/src/teacher_and_parent/bloc/teacher_and_parent_homework_page_bloc.dart new file mode 100644 index 000000000..825bfa239 --- /dev/null +++ b/lib/hausaufgabenheft_logik/lib/src/teacher_and_parent/bloc/teacher_and_parent_homework_page_bloc.dart @@ -0,0 +1,140 @@ +// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) +// Licensed under the EUPL-1.2-or-later. +// +// You may obtain a copy of the Licence at: +// https://joinup.ec.europa.eu/software/page/eupl +// +// SPDX-License-Identifier: EUPL-1.2 + +import 'dart:async'; + +import 'package:bloc/bloc.dart'; +import 'package:bloc_base/bloc_base.dart' as bloc_base; +import 'package:fast_immutable_collections/fast_immutable_collections.dart'; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart' + hide Uninitialized, LoadHomeworks, OpenHwSortingChanged, Success, Sort; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik_lehrer.dart'; +import 'package:hausaufgabenheft_logik/src/shared/homework_sorting_cache.dart'; +import 'package:rxdart/rxdart.dart'; + +export 'events.dart'; +export 'states.dart'; + +class TeacherAndParentHomeworkPageBloc extends Bloc< + TeacherAndParentHomeworkPageEvent, + TeacherAndParentHomeworkPageState> implements bloc_base.BlocBase { + final TeacherAndParentHomeworkPageApi _homeworkApi; + final HomeworkSortingCache _homeworkSortingCache; + final DateTime Function() _getCurrentDateTime; + final int numberOfInitialCompletedHomeworksToLoad; + final TeacherAndParentHomeworkViewFactory _viewFactory; + final TeacherAndParentOpenHomeworkListViewFactory + _openHomeworkListViewFactory; + final _currentSortStream = BehaviorSubject>(); + LazyLoadingController? _lazyLoadingController; + + /// Whether [close] or [dispose] has been called; + bool _isClosed = false; + + TeacherAndParentHomeworkPageBloc({ + required HomeworkSortingCache homeworkSortingCache, + required TeacherAndParentHomeworkPageApi homeworkApi, + required TeacherAndParentHomeworkViewFactory viewFactory, + required TeacherAndParentOpenHomeworkListViewFactory + openHomeworkListViewFactory, + required this.numberOfInitialCompletedHomeworksToLoad, + required DateTime Function() getCurrentDateTime, + }) : _homeworkApi = homeworkApi, + _openHomeworkListViewFactory = openHomeworkListViewFactory, + _homeworkSortingCache = homeworkSortingCache, + _viewFactory = viewFactory, + _getCurrentDateTime = getCurrentDateTime, + super(Uninitialized()) { + on((event, emit) { + _mapLoadHomeworksToState(); + }); + on((event, emit) { + _mapAdvanceArchivedHomeworks(event); + }); + on((event, emit) { + _mapFilterChangedToState(event); + }); + on<_Yield>((event, emit) { + emit(event.success); + }); + } + + Date _getCurrentDate() { + return Date.fromDateTime(_getCurrentDateTime()); + } + + StreamSubscription? _combineLatestSubscription; + Future _mapLoadHomeworksToState() async { + final sortEnum = await _homeworkSortingCache.getLastSorting() ?? + HomeworkSort.smallestDateSubjectAndTitle; + _currentSortStream + .add(sortEnum.toSortObject(getCurrentDate: _getCurrentDate)); + + _lazyLoadingController = + _homeworkApi.getLazyLoadingArchivedHomeworksController( + numberOfInitialCompletedHomeworksToLoad); + + _combineLatestSubscription = Rx.combineLatest3< + IList, + Sort, + LazyLoadingResult, + Success>(_homeworkApi.openHomeworks, _currentSortStream, + _lazyLoadingController!.results, (openHws, sort, lazyCompletedHwsRes) { + final open = _openHomeworkListViewFactory.create(openHws, sort); + + final archived = LazyLoadingHomeworkListView( + lazyCompletedHwsRes.homeworks.map(_viewFactory.createFrom).toIList(), + loadedAllHomeworks: !lazyCompletedHwsRes.moreHomeworkAvailable); + + return Success(open, archived); + }).listen((s) { + if (!_isClosed) { + add(_Yield(s)); + } + }); + } + + void _mapAdvanceArchivedHomeworks(AdvanceArchivedHomeworks event) async { + _lazyLoadingController!.advanceBy(event.advanceBy); + } + + Future _mapFilterChangedToState(OpenHwSortingChanged event) async { + await _homeworkSortingCache.setLastSorting(event.sort); + _currentSortStream + .add(event.sort.toSortObject(getCurrentDate: _getCurrentDate)); + } + + @override + Future close() { + _isClosed = true; + _currentSortStream.close(); + _combineLatestSubscription?.cancel(); + return super.close(); + } + + @override + void dispose() { + _isClosed = true; + _currentSortStream.close(); + _combineLatestSubscription?.cancel(); + } +} + +/// As you can't yield in a listen callback of a stream +/// and you can't return the stream as this stops the +/// bloc from working (as the Stream never finishes) +/// this acts a as a simple wrapper to yield the +/// given value +class _Yield extends TeacherAndParentHomeworkPageEvent { + final Success success; + + _Yield(this.success); + + @override + List get props => [success]; +} diff --git a/lib/hausaufgabenheft_logik/lib/src/teacher_and_parent/create_teacher_and_parent_homework_page_bloc.dart b/lib/hausaufgabenheft_logik/lib/src/teacher_and_parent/create_teacher_and_parent_homework_page_bloc.dart new file mode 100644 index 000000000..a1add595c --- /dev/null +++ b/lib/hausaufgabenheft_logik/lib/src/teacher_and_parent/create_teacher_and_parent_homework_page_bloc.dart @@ -0,0 +1,42 @@ +// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) +// Licensed under the EUPL-1.2-or-later. +// +// You may obtain a copy of the Licence at: +// https://joinup.ec.europa.eu/software/page/eupl +// +// SPDX-License-Identifier: EUPL-1.2 + +import 'package:clock/clock.dart'; +import 'package:hausaufgabenheft_logik/src/shared/sort_and_subcategorizer.dart'; +import 'package:hausaufgabenheft_logik/src/shared/setup/config.dart'; +import 'package:hausaufgabenheft_logik/src/shared/setup/dependencies.dart'; +import 'package:hausaufgabenheft_logik/src/shared/homework_sorting_cache.dart'; + +import '../../hausaufgabenheft_logik_lehrer.dart'; +import '../shared/models/date.dart'; + +TeacherAndParentHomeworkPageBloc createTeacherAndParentHomeworkPageBloc( + HausaufgabenheftDependencies dependencies, HausaufgabenheftConfig config) { + final getCurrentDateTime = + dependencies.getCurrentDateTime ?? () => clock.now(); + getCurrentDate() => Date.fromDateTime(getCurrentDateTime()); + + final viewFactory = TeacherAndParentHomeworkViewFactory( + defaultColorValue: config.defaultCourseColorValue); + final sortAndSubcategorizer = + HomeworkSortAndSubcategorizer( + getCurrentDate: getCurrentDate); + final openHomeworkListViewFactory = + TeacherAndParentOpenHomeworkListViewFactory( + sortAndSubcategorizer, viewFactory); + + return TeacherAndParentHomeworkPageBloc( + openHomeworkListViewFactory: openHomeworkListViewFactory, + viewFactory: viewFactory, + homeworkApi: dependencies.api.teachersAndParents, + numberOfInitialCompletedHomeworksToLoad: + config.nrOfInitialCompletedHomeworksToLoad, + homeworkSortingCache: HomeworkSortingCache(dependencies.keyValueStore), + getCurrentDateTime: dependencies.getCurrentDateTime ?? () => clock.now(), + ); +} diff --git a/lib/hausaufgabenheft_logik/lib/src/teacher_and_parent/teacher_and_parent_homework_list_extensions.dart b/lib/hausaufgabenheft_logik/lib/src/teacher_and_parent/teacher_and_parent_homework_list_extensions.dart new file mode 100644 index 000000000..1168aa156 --- /dev/null +++ b/lib/hausaufgabenheft_logik/lib/src/teacher_and_parent/teacher_and_parent_homework_list_extensions.dart @@ -0,0 +1,22 @@ +// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) +// Licensed under the EUPL-1.2-or-later. +// +// You may obtain a copy of the Licence at: +// https://joinup.ec.europa.eu/software/page/eupl +// +// SPDX-License-Identifier: EUPL-1.2 + +import 'package:fast_immutable_collections/fast_immutable_collections.dart'; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart' hide Sort; + +extension HomeworkListExtension on IList { + IList get completed => + where((homework) => homework.status == ArchivalStatus.archived).toIList(); + IList get open => + where((homework) => homework.status == ArchivalStatus.open).toIList(); + + IList getOverdue([Date? now]) { + now = now ?? Date.now(); + return where((homeworks) => homeworks.isOverdueRelativeTo(now!)).toIList(); + } +} diff --git a/lib/hausaufgabenheft_logik/lib/src/lehrer/teacher_homework_view.dart b/lib/hausaufgabenheft_logik/lib/src/teacher_and_parent/views/teacher_and_parent_homework_view.dart similarity index 94% rename from lib/hausaufgabenheft_logik/lib/src/lehrer/teacher_homework_view.dart rename to lib/hausaufgabenheft_logik/lib/src/teacher_and_parent/views/teacher_and_parent_homework_view.dart index 8d2cce3fd..90ead03c3 100644 --- a/lib/hausaufgabenheft_logik/lib/src/lehrer/teacher_homework_view.dart +++ b/lib/hausaufgabenheft_logik/lib/src/teacher_and_parent/views/teacher_and_parent_homework_view.dart @@ -7,9 +7,9 @@ // SPDX-License-Identifier: EUPL-1.2 import 'package:common_domain_models/common_domain_models.dart'; -import 'package:hausaufgabenheft_logik/src/views/color.dart'; +import 'package:hausaufgabenheft_logik/src/shared/color.dart'; -class TeacherHomeworkView { +class TeacherAndParentHomeworkView { final HomeworkId id; final String abbreviation; final bool colorDate; @@ -41,7 +41,7 @@ class TeacherHomeworkView { /// group. final bool canEditForEveryone; - TeacherHomeworkView({ + TeacherAndParentHomeworkView({ required this.id, required this.abbreviation, required this.colorDate, @@ -65,7 +65,7 @@ class TeacherHomeworkView { bool operator ==(Object other) { if (identical(this, other)) return true; - return other is TeacherHomeworkView && + return other is TeacherAndParentHomeworkView && other.id == id && other.abbreviation == abbreviation && other.colorDate == colorDate && diff --git a/lib/hausaufgabenheft_logik/lib/src/lehrer/teacher_homework_view_factory.dart b/lib/hausaufgabenheft_logik/lib/src/teacher_and_parent/views/teacher_and_parent_homework_view_factory.dart similarity index 85% rename from lib/hausaufgabenheft_logik/lib/src/lehrer/teacher_homework_view_factory.dart rename to lib/hausaufgabenheft_logik/lib/src/teacher_and_parent/views/teacher_and_parent_homework_view_factory.dart index d2c0cf138..cbe544f07 100644 --- a/lib/hausaufgabenheft_logik/lib/src/lehrer/teacher_homework_view_factory.dart +++ b/lib/hausaufgabenheft_logik/lib/src/teacher_and_parent/views/teacher_and_parent_homework_view_factory.dart @@ -6,12 +6,12 @@ // // SPDX-License-Identifier: EUPL-1.2 -import 'package:hausaufgabenheft_logik/src/models/models.dart'; -import 'package:hausaufgabenheft_logik/src/views/color.dart'; +import 'package:hausaufgabenheft_logik/src/shared/models/models.dart'; +import 'package:hausaufgabenheft_logik/src/shared/color.dart'; -import '../../hausaufgabenheft_logik_lehrer.dart'; +import '../../../hausaufgabenheft_logik_lehrer.dart'; -class TeacherHomeworkViewFactory { +class TeacherAndParentHomeworkViewFactory { late Date Function() _getCurrentDate; /// The color value from `color.value`. @@ -19,7 +19,7 @@ class TeacherHomeworkViewFactory { final int defaultColorValue; final Color defaultColor; - TeacherHomeworkViewFactory( + TeacherAndParentHomeworkViewFactory( {Date Function()? getCurrentDate, required this.defaultColorValue}) : defaultColor = Color(defaultColorValue) { if (getCurrentDate == null) { @@ -29,9 +29,9 @@ class TeacherHomeworkViewFactory { } } - TeacherHomeworkView createFrom(TeacherHomeworkReadModel homework) { + TeacherAndParentHomeworkView createFrom(TeacherHomeworkReadModel homework) { final twoDaysInFuture = _getCurrentDate().addDays(2); - return TeacherHomeworkView( + return TeacherAndParentHomeworkView( id: homework.id, title: homework.title.value, subject: homework.subject.name, diff --git a/lib/hausaufgabenheft_logik/lib/src/teacher_and_parent/views/teacher_and_parent_open_homework_list_view.dart b/lib/hausaufgabenheft_logik/lib/src/teacher_and_parent/views/teacher_and_parent_open_homework_list_view.dart new file mode 100644 index 000000000..d8594d598 --- /dev/null +++ b/lib/hausaufgabenheft_logik/lib/src/teacher_and_parent/views/teacher_and_parent_open_homework_list_view.dart @@ -0,0 +1,48 @@ +// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) +// Licensed under the EUPL-1.2-or-later. +// +// You may obtain a copy of the Licence at: +// https://joinup.ec.europa.eu/software/page/eupl +// +// SPDX-License-Identifier: EUPL-1.2 + +import 'package:collection/collection.dart' show DeepCollectionEquality; +import 'package:collection/collection.dart'; +import 'package:fast_immutable_collections/fast_immutable_collections.dart'; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik_lehrer.dart'; + +class TeacherAndParentOpenHomeworkListView { + final IList> sections; + final HomeworkSort sorting; + + TeacherAndParentOpenHomeworkListView( + this.sections, { + required this.sorting, + }) : super(); + + int get numberOfHomeworks { + final listLengths = sections.map((s) => s.homeworks.length).toList(); + if (listLengths.isEmpty) { + return 0; + } + return listLengths.reduce((i, i2) => i + i2); + } + + @override + String toString() => + 'OpenHomeworkListView(sorting: $sorting, sections: $sections)'; + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + final bool Function(Object, Object) listEquals = + const DeepCollectionEquality().equals; + + return other is TeacherAndParentOpenHomeworkListView && + listEquals(other.sections, sections) && + other.sorting == sorting; + } + + @override + int get hashCode => sections.hashCode ^ sorting.hashCode; +} diff --git a/lib/hausaufgabenheft_logik/lib/src/teacher_and_parent/views/teacher_and_parent_open_homework_list_view_factory.dart b/lib/hausaufgabenheft_logik/lib/src/teacher_and_parent/views/teacher_and_parent_open_homework_list_view_factory.dart new file mode 100644 index 000000000..051f7e922 --- /dev/null +++ b/lib/hausaufgabenheft_logik/lib/src/teacher_and_parent/views/teacher_and_parent_open_homework_list_view_factory.dart @@ -0,0 +1,40 @@ +// Copyright (c) 2022 Sharezone UG (haftungsbeschränkt) +// Licensed under the EUPL-1.2-or-later. +// +// You may obtain a copy of the Licence at: +// https://joinup.ec.europa.eu/software/page/eupl +// +// SPDX-License-Identifier: EUPL-1.2 + +import 'package:fast_immutable_collections/fast_immutable_collections.dart'; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik_lehrer.dart'; +import 'package:hausaufgabenheft_logik/src/shared/sort_and_subcategorizer.dart'; + +class TeacherAndParentOpenHomeworkListViewFactory { + final HomeworkSortAndSubcategorizer + _sortAndSubcategorizer; + final TeacherAndParentHomeworkViewFactory _viewFactory; + + TeacherAndParentOpenHomeworkListViewFactory( + this._sortAndSubcategorizer, this._viewFactory); + + TeacherAndParentOpenHomeworkListView create( + IList openHomeworks, + Sort sort) { + final sortedAndSubcategorized = + _sortAndSubcategorizer.sortAndSubcategorize(openHomeworks, sort); + + final views = sortedAndSubcategorized + .map((section) => HomeworkSectionView( + section.title, + section.homeworks + .map((hw) => _viewFactory.createFrom(hw)) + .toIList())) + .toIList(); + + return TeacherAndParentOpenHomeworkListView( + views, + sorting: sort.toEnum(), + ); + } +} diff --git a/lib/hausaufgabenheft_logik/pubspec.lock b/lib/hausaufgabenheft_logik/pubspec.lock index 6b1977698..0839dfaaf 100644 --- a/lib/hausaufgabenheft_logik/pubspec.lock +++ b/lib/hausaufgabenheft_logik/pubspec.lock @@ -9,6 +9,14 @@ packages: url: "https://pub.dev" source: hosted version: "64.0.0" + _flutterfire_internals: + dependency: transitive + description: + name: _flutterfire_internals + sha256: "37a42d06068e2fe3deddb2da079a8c4d105f241225ba27b7122b37e9865fd8f7" + url: "https://pub.dev" + source: hosted + version: "1.3.35" analyzer: dependency: transitive description: @@ -64,6 +72,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" clock: dependency: "direct main" description: @@ -72,6 +88,37 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" + cloud_firestore: + dependency: "direct main" + description: + name: cloud_firestore + sha256: a0f161b92610e078b4962d7e6ebeb66dc9cce0ada3514aeee442f68165d78185 + url: "https://pub.dev" + source: hosted + version: "4.17.5" + cloud_firestore_helper: + dependency: "direct main" + description: + path: "../cloud_firestore_helper" + relative: true + source: path + version: "0.0.1" + cloud_firestore_platform_interface: + dependency: transitive + description: + name: cloud_firestore_platform_interface + sha256: "6a55b319f8d33c307396b9104512e8130a61904528ab7bd8b5402678fca54b81" + url: "https://pub.dev" + source: hosted + version: "6.2.5" + cloud_firestore_web: + dependency: transitive + description: + name: cloud_firestore_web + sha256: "89dfa1304d3da48b3039abbb2865e3d30896ef858e569a16804a99f4362283a9" + url: "https://pub.dev" + source: hosted + version: "3.12.5" collection: dependency: "direct main" description: @@ -99,10 +146,10 @@ packages: dependency: transitive description: name: coverage - sha256: "2fb815080e44a09b85e0f2ca8a820b15053982b2e714b59267719e8a9ff17097" + sha256: "3945034e86ea203af7a056d98e98e42a5518fff200d6e8e6647e1886b07e936e" url: "https://pub.dev" source: hosted - version: "1.6.3" + version: "1.8.0" crypto: dependency: transitive description: @@ -127,6 +174,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.5" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" fast_immutable_collections: dependency: "direct main" description: @@ -143,6 +198,35 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.0" + firebase_core: + dependency: transitive + description: + name: firebase_core + sha256: "26de145bb9688a90962faec6f838247377b0b0d32cc0abecd9a4e43525fc856c" + url: "https://pub.dev" + source: hosted + version: "2.32.0" + firebase_core_platform_interface: + dependency: transitive + description: + name: firebase_core_platform_interface + sha256: "1003a5a03a61fc9a22ef49f37cbcb9e46c86313a7b2e7029b9390cf8c6fc32cb" + url: "https://pub.dev" + source: hosted + version: "5.1.0" + firebase_core_web: + dependency: transitive + description: + name: firebase_core_web + sha256: "6643fe3dbd021e6ccfb751f7882b39df355708afbdeb4130fc50f9305a9d1a3d" + url: "https://pub.dev" + source: hosted + version: "2.17.2" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" flutter_lints: dependency: transitive description: @@ -151,6 +235,16 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.1" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" frontend_server_client: dependency: transitive description: @@ -171,10 +265,10 @@ packages: dependency: transitive description: name: http - sha256: d4872660c46d929f6b8a9ef4e7a7eff7e49bbf0c4ec3f385ee32df5119175139 + sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938" url: "https://pub.dev" source: hosted - version: "1.1.2" + version: "1.2.1" http_multi_server: dependency: transitive description: @@ -191,6 +285,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.2" + intl: + dependency: transitive + description: + name: intl + sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf + url: "https://pub.dev" + source: hosted + version: "0.19.0" io: dependency: transitive description: @@ -214,6 +316,30 @@ packages: relative: true source: path version: "0.0.1" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" + url: "https://pub.dev" + source: hosted + version: "10.0.4" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" + url: "https://pub.dev" + source: hosted + version: "3.0.3" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" lints: dependency: transitive description: @@ -234,18 +360,26 @@ packages: dependency: transitive description: name: matcher - sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + url: "https://pub.dev" + source: hosted + version: "0.12.16+1" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" url: "https://pub.dev" source: hosted - version: "0.12.16" + version: "0.8.0" meta: dependency: "direct main" description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.12.0" mime: dependency: transitive description: @@ -274,10 +408,18 @@ packages: dependency: transitive description: name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" url: "https://pub.dev" source: hosted - version: "1.8.3" + version: "1.9.0" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" pointycastle: dependency: transitive description: @@ -365,6 +507,11 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.4" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" source_map_stack_trace: dependency: transitive description: @@ -425,26 +572,26 @@ packages: dependency: "direct dev" description: name: test - sha256: "9b0dd8e36af4a5b1569029949d50a52cb2a2a2fdaa20cebb96e6603b9ae241f9" + sha256: "7ee446762c2c50b3bd4ea96fe13ffac69919352bd3b4b17bac3f3465edc58073" url: "https://pub.dev" source: hosted - version: "1.24.6" + version: "1.25.2" test_api: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.7.0" test_core: dependency: transitive description: name: test_core - sha256: "4bef837e56375537055fdbbbf6dd458b1859881f4c7e6da936158f77d61ab265" + sha256: "2bc4b4ecddd75309300d8096f781c0e3280ca1ef85beda558d33fcbedc2eead4" url: "https://pub.dev" source: hosted - version: "0.5.6" + version: "0.6.0" test_randomness: dependency: "direct main" description: @@ -452,6 +599,13 @@ packages: relative: true source: path version: "0.0.1" + time: + dependency: "direct main" + description: + path: "../time" + relative: true + source: path + version: "1.0.0" typed_data: dependency: transitive description: @@ -467,14 +621,22 @@ packages: relative: true source: path version: "0.0.1" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" vm_service: dependency: transitive description: name: vm_service - sha256: c538be99af830f478718b51630ec1b6bee5e74e52c8a802d328d9e71d35d2583 + sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" url: "https://pub.dev" source: hosted - version: "11.10.0" + version: "14.2.1" watcher: dependency: transitive description: @@ -487,10 +649,10 @@ packages: dependency: transitive description: name: web - sha256: edc8a9573dd8c5a83a183dae1af2b6fd4131377404706ca4e5420474784906fa + sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" url: "https://pub.dev" source: hosted - version: "0.4.0" + version: "0.5.1" web_socket_channel: dependency: transitive description: @@ -516,4 +678,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.2.0 <4.0.0" + dart: ">=3.3.0 <4.0.0" + flutter: ">=3.18.0-18.0.pre.54" diff --git a/lib/hausaufgabenheft_logik/pubspec.yaml b/lib/hausaufgabenheft_logik/pubspec.yaml index abe6de277..ccbd10733 100644 --- a/lib/hausaufgabenheft_logik/pubspec.yaml +++ b/lib/hausaufgabenheft_logik/pubspec.yaml @@ -17,6 +17,11 @@ environment: dependencies: common_domain_models: path: ../common_domain_models + cloud_firestore_helper: + path: ../cloud_firestore_helper + cloud_firestore: ^4.17.2 + time: + path: ../time bloc: ^8.1.2 rxdart: ^0.27.1 equatable: ^2.0.5 @@ -32,6 +37,8 @@ dependencies: test_randomness: path: ../test_randomness clock: ^1.1.1 + flutter: + sdk: flutter dev_dependencies: async: ^2.11.0 @@ -39,5 +46,7 @@ dev_dependencies: # compiling the `test` package will fail. file: ^7.0.0 test: ^1.23.1 + flutter_test: + sdk: flutter sharezone_lints: path: ../sharezone_lints diff --git a/lib/hausaufgabenheft_logik/test/create_homework_util.dart b/lib/hausaufgabenheft_logik/test/create_homework_util.dart index 88a6028c4..d72ca7605 100644 --- a/lib/hausaufgabenheft_logik/test/create_homework_util.dart +++ b/lib/hausaufgabenheft_logik/test/create_homework_util.dart @@ -7,12 +7,12 @@ // SPDX-License-Identifier: EUPL-1.2 import 'package:common_domain_models/common_domain_models.dart'; -import 'package:hausaufgabenheft_logik/src/models/homework.dart'; -import 'package:hausaufgabenheft_logik/src/models/models.dart'; -import 'package:hausaufgabenheft_logik/src/views/color.dart'; +import 'package:hausaufgabenheft_logik/src/shared/models/homework.dart'; +import 'package:hausaufgabenheft_logik/src/shared/models/models.dart'; +import 'package:hausaufgabenheft_logik/src/shared/color.dart'; import 'package:test_randomness/test_randomness.dart'; -HomeworkReadModel createHomework( +StudentHomeworkReadModel createHomework( {Date todoDate = const Date(day: 1, month: 1, year: 2019), String subject = 'Subject', String title = 'Title', @@ -22,8 +22,9 @@ HomeworkReadModel createHomework( Color? subjectColor, String abbreviation = 'Abb'}) { id = id == 'willBeRandom' ? randomAlphaNumeric(5) : id; - return HomeworkReadModel( + return StudentHomeworkReadModel( id: HomeworkId(id), + courseId: const CourseId('testCourseId'), todoDate: todoDate.asDateTime(), subject: Subject(subject, color: subjectColor, abbreviation: abbreviation), title: Title(title), diff --git a/lib/hausaufgabenheft_logik/test/create_student_homework_view_test.dart b/lib/hausaufgabenheft_logik/test/create_student_homework_view_test.dart index 5753e1885..7c13d7db9 100644 --- a/lib/hausaufgabenheft_logik/test/create_student_homework_view_test.dart +++ b/lib/hausaufgabenheft_logik/test/create_student_homework_view_test.dart @@ -7,11 +7,11 @@ // SPDX-License-Identifier: EUPL-1.2 import 'package:common_domain_models/common_domain_models.dart'; -import 'package:hausaufgabenheft_logik/src/models/homework.dart'; -import 'package:hausaufgabenheft_logik/src/models/models.dart'; -import 'package:hausaufgabenheft_logik/src/views/color.dart'; -import 'package:hausaufgabenheft_logik/src/views/student_homework_view_factory.dart'; -import 'package:hausaufgabenheft_logik/src/views/homework_view.dart'; +import 'package:hausaufgabenheft_logik/src/shared/models/homework.dart'; +import 'package:hausaufgabenheft_logik/src/shared/models/models.dart'; +import 'package:hausaufgabenheft_logik/src/shared/color.dart'; +import 'package:hausaufgabenheft_logik/src/student/views/student_homework_view_factory.dart'; +import 'package:hausaufgabenheft_logik/src/student/views/student_homework_view.dart'; import 'package:test/test.dart'; import 'create_homework_util.dart'; @@ -31,10 +31,11 @@ void main() { test('Create Student homework View test', () { const white = Color.fromRGBO(255, 255, 255, 1); - final homework = HomeworkReadModel( + final homework = StudentHomeworkReadModel( id: const HomeworkId('Id'), status: CompletionStatus.open, todoDate: const Date(year: 2019, month: 1, day: 28).asDateTime(), + courseId: const CourseId('maths'), subject: Subject( 'Mathematik', color: white, diff --git a/lib/hausaufgabenheft_logik/test/date/date_test.dart b/lib/hausaufgabenheft_logik/test/date/date_test.dart index 6778063fe..5ec205179 100644 --- a/lib/hausaufgabenheft_logik/test/date/date_test.dart +++ b/lib/hausaufgabenheft_logik/test/date/date_test.dart @@ -7,7 +7,7 @@ // SPDX-License-Identifier: EUPL-1.2 import 'package:clock/clock.dart'; -import 'package:hausaufgabenheft_logik/src/models/date.dart'; +import 'package:hausaufgabenheft_logik/src/shared/models/date.dart'; import 'package:test/test.dart'; void main() { diff --git a/lib/hausaufgabenheft_logik/test/homework_list_test.dart b/lib/hausaufgabenheft_logik/test/homework_list_test.dart index 9f2ebda21..11118f963 100644 --- a/lib/hausaufgabenheft_logik/test/homework_list_test.dart +++ b/lib/hausaufgabenheft_logik/test/homework_list_test.dart @@ -55,14 +55,14 @@ void main() { homeworks.sortWith(SmallestDateSubjectAndTitleSort()), ); - final sorted = List.generate( + final sorted = List.generate( 15, (i) => createHomework( todoDate: const Date(year: 2019, month: 02, day: 03), subject: 'Subject', title: '$i'), ); - final unsorted = List.from(sorted)..shuffle(); + final unsorted = List.from(sorted)..shuffle(); testSort('does sort titles starting with numbers by their value', unsorted: unsorted, sorted: sorted, @@ -96,8 +96,8 @@ void testDateSort(String title, ListCallback sort) => testSort( ); void testSort(String title, - {required List unsorted, - required List sorted, + {required List unsorted, + required List sorted, required ListCallback sort, bool skip = false}) { test(title, () { @@ -120,5 +120,5 @@ void testTitleSort(String title, ListCallback sort) => testSort( sort: sort, ); -typedef ListCallback = IList Function( - IList); +typedef ListCallback = IList Function( + IList); diff --git a/lib/hausaufgabenheft_logik/test/homework_page_bloc_test.dart b/lib/hausaufgabenheft_logik/test/homework_page_bloc_test.dart index c03882545..730fe74c2 100644 --- a/lib/hausaufgabenheft_logik/test/homework_page_bloc_test.dart +++ b/lib/hausaufgabenheft_logik/test/homework_page_bloc_test.dart @@ -11,11 +11,12 @@ import 'dart:developer'; import 'package:bloc/bloc.dart'; import 'package:clock/clock.dart'; +import 'package:common_domain_models/src/ids/homework_id.dart'; import 'package:fast_immutable_collections/fast_immutable_collections.dart'; import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik_setup.dart'; -import 'package:hausaufgabenheft_logik/src/student_homework_page_bloc/homework_sorting_cache.dart'; -import 'package:hausaufgabenheft_logik/src/views/color.dart'; +import 'package:hausaufgabenheft_logik/src/shared/homework_sorting_cache.dart'; +import 'package:hausaufgabenheft_logik/src/shared/color.dart'; import 'package:key_value_store/in_memory_key_value_store.dart'; import 'package:key_value_store/key_value_store.dart'; import 'package:rxdart/rxdart.dart'; @@ -27,8 +28,8 @@ import 'in_memory_repo/in_memory_homework_repository.dart'; void main() { Bloc.observer = VerboseBlocObserver(); group('GIVEN a Student with Homework WHEN he opens the homework page', () { - late HomeworkPageBloc bloc; - late InMemoryHomeworkRepository repository; + late StudentHomeworkPageBloc bloc; + late InMemoryHomeworkRepository repository; late HomeworkSortingCache homeworkSortingCache; late KeyValueStore kvs; @@ -42,7 +43,7 @@ void main() { /// Adds the homeworks to the top level group repository, or if repo is /// specified into the given repository (for use in a sub-group, where /// the top level repository is not used) - Future addToRepository(List homeworks, + Future addToRepository(List homeworks, [InMemoryHomeworkRepository? repo]) async { for (var homework in homeworks) { await (repo ?? repository).add(homework); @@ -149,7 +150,7 @@ void main() { bloc.add(LoadHomeworks()); bloc.add(OpenHwSortingChanged(HomeworkSort.smallestDateSubjectAndTitle)); - final Future findState = + final Future findState = bloc.stream.firstWhere((state) { if (state is Success) { final hws = state.open.orderedHomeworks; @@ -249,7 +250,7 @@ void main() { bloc.add( OpenHwSortingChanged(HomeworkSort.subjectSmallestDateAndTitleSort)); - final Future findMatchingState = + final Future findMatchingState = bloc.stream.firstWhere((state) { if (state is Success) { final sortedOpenHWs = state.open; @@ -361,7 +362,7 @@ void main() { await addToRepository(homeworks); bloc.add(LoadHomeworks()); - final Stream invalidStates = bloc.stream.where( + final Stream invalidStates = bloc.stream.where( (state) => state is Success && state.open.showCompleteOverdueHomeworkPrompt == true); @@ -372,15 +373,16 @@ void main() { }); group('CompletedHomeworks lazy loading ', () { - HomeworkPageBloc bloc; - late InMemoryHomeworkRepository repository; + StudentHomeworkPageBloc bloc; + late InMemoryHomeworkRepository repository; setUp(() { repository = createRepositoy(); bloc = createBloc(repository); }); - List generateCompleted(int nrOfCompletedHomeworks, + List generateCompleted( + int nrOfCompletedHomeworks, {String Function(int index)? getTitle}) { String title(int i) => getTitle != null ? getTitle(i) : '$i'; @@ -398,7 +400,7 @@ void main() { bloc.add(LoadHomeworks()); final Success state = await bloc.stream.whereType().first; - expect(state.completed.loadedAllCompletedHomeworks, false); + expect(state.completed.loadedAllHomeworks, false); }); test( 'all completed loaded is true when nrOfInitialCompletedHomeworksToLoad is the bigger as the given homeworks by the repository', @@ -410,7 +412,7 @@ void main() { bloc.add(LoadHomeworks()); final Success state = await bloc.stream.whereType().first; - expect(state.completed.loadedAllCompletedHomeworks, true); + expect(state.completed.loadedAllHomeworks, true); }, ); test( @@ -422,7 +424,7 @@ void main() { bloc.add(LoadHomeworks()); - final Future expectedPromise = bloc.stream + final Future expectedPromise = bloc.stream .firstWhere((state) => state is Success && state.completed.numberOfHomeworks == 10); expect(expectedPromise, completes); @@ -438,7 +440,7 @@ void main() { bloc.add(LoadHomeworks()); bloc.add(AdvanceCompletedHomeworks(10)); - final Future findExpectedState = bloc.stream + final Future findExpectedState = bloc.stream .firstWhere((state) => state is Success && state.completed.numberOfHomeworks == @@ -479,7 +481,7 @@ void main() { }); } -extension on OpenHomeworkListView { +extension on StudentOpenHomeworkListView { List get orderedHomeworks { final listOfListOfHomeworks = sections.map((s) => s.homeworks.toList()).toList(); @@ -492,20 +494,18 @@ extension on OpenHomeworkListView { } const uid = 'uid'; -HomeworkPageBloc createBloc( - InMemoryHomeworkRepository repository, { +StudentHomeworkPageBloc createBloc( + InMemoryHomeworkRepository repository, { int nrOfInitialCompletedHomeworksToLoad = 1000, DateTime Function()? getCurrentDateTime, KeyValueStore? keyValueStore, }) { - return createHomeworkPageBloc( + return createStudentHomeworkPageBloc( HausaufgabenheftDependencies( - dataSource: repository, - completionDispatcher: RepositoryHomeworkCompletionDispatcher(repository), - getOpenOverdueHomeworkIds: () async { - final open = await repository.openHomeworks.first; - return open.getOverdue().map((hw) => hw.id).toIList(); - }, + api: HomeworkPageApi( + students: InMemoryStudentHomeworkPageApi(repo: repository), + teachersAndParents: InMemoryTeacherAndParentHomeworkPageApi( + repo: InMemoryHomeworkRepository())), keyValueStore: keyValueStore ?? InMemoryKeyValueStore(), getCurrentDateTime: getCurrentDateTime, ), @@ -516,33 +516,11 @@ HomeworkPageBloc createBloc( ); } -InMemoryHomeworkRepository createRepositoy() => InMemoryHomeworkRepository(); +InMemoryHomeworkRepository createRepositoy() => + InMemoryHomeworkRepository(); Date dateFromDay(int day) => Date(year: 2019, month: 1, day: day); -class RepositoryHomeworkCompletionDispatcher - extends HomeworkCompletionDispatcher { - final InMemoryHomeworkRepository _repository; - - RepositoryHomeworkCompletionDispatcher(this._repository); - - @override - Future dispatch(HomeworkCompletion homeworkCompletion) async { - final hw = await _repository.findById(homeworkCompletion.homeworkId); - final newHw = HomeworkReadModel( - id: hw.id, - title: hw.title, - status: hw.status == CompletionStatus.open - ? CompletionStatus.completed - : CompletionStatus.open, - subject: hw.subject, - withSubmissions: hw.withSubmissions, - todoDate: hw.todoDate, - ); - await _repository.update(newHw); - } -} - class VerboseBlocObserver extends BlocObserver { @override void onError(BlocBase bloc, Object error, StackTrace stacktrace) { @@ -563,3 +541,64 @@ class VerboseBlocObserver extends BlocObserver { super.onEvent(bloc, event); } } + +class InMemoryStudentHomeworkPageApi extends StudentHomeworkPageApi { + final InMemoryHomeworkRepository repo; + + InMemoryStudentHomeworkPageApi({required this.repo}); + + @override + Future completeHomework( + HomeworkId homeworkId, CompletionStatus newCompletionStatus) async { + final hw = await repo.findById(homeworkId); + final newHw = StudentHomeworkReadModel( + id: hw.id, + title: hw.title, + courseId: hw.courseId, + status: newCompletionStatus, + subject: hw.subject, + withSubmissions: hw.withSubmissions, + todoDate: hw.todoDate, + ); + await repo.update(newHw); + } + + @override + LazyLoadingController + getLazyLoadingCompletedHomeworksController( + int nrOfInitialHomeworkToLoad) { + return repo + .getLazyLoadingCompletedHomeworksController(nrOfInitialHomeworkToLoad); + } + + @override + Future> getOpenOverdueHomeworkIds() async { + final open = await repo.openHomeworks.first; + return open + .where((hw) => hw.todoDate.isBefore(DateTime.now())) + .map((hw) => hw.id) + .toIList(); + } + + @override + Stream> get openHomeworks => + repo.openHomeworks; +} + +class InMemoryTeacherAndParentHomeworkPageApi + extends TeacherAndParentHomeworkPageApi { + final InMemoryHomeworkRepository repo; + + InMemoryTeacherAndParentHomeworkPageApi({required this.repo}); + + @override + LazyLoadingController + getLazyLoadingArchivedHomeworksController(int nrOfInitialHomeworkToLoad) { + return repo + .getLazyLoadingCompletedHomeworksController(nrOfInitialHomeworkToLoad); + } + + @override + Stream> get openHomeworks => + repo.openHomeworks; +} diff --git a/lib/hausaufgabenheft_logik/test/homework_test.dart b/lib/hausaufgabenheft_logik/test/homework_test.dart index 17790d43f..df513b01d 100644 --- a/lib/hausaufgabenheft_logik/test/homework_test.dart +++ b/lib/hausaufgabenheft_logik/test/homework_test.dart @@ -6,7 +6,7 @@ // // SPDX-License-Identifier: EUPL-1.2 -import 'package:hausaufgabenheft_logik/src/models/date.dart'; +import 'package:hausaufgabenheft_logik/src/shared/models/date.dart'; import 'package:test/test.dart'; import 'create_homework_util.dart'; diff --git a/lib/hausaufgabenheft_logik/test/in_memory_repo/firebase_realtime_updating_lazy_loading_controller.dart b/lib/hausaufgabenheft_logik/test/in_memory_repo/firebase_realtime_updating_lazy_loading_controller.dart index 2cf120e32..1e8d17888 100644 --- a/lib/hausaufgabenheft_logik/test/in_memory_repo/firebase_realtime_updating_lazy_loading_controller.dart +++ b/lib/hausaufgabenheft_logik/test/in_memory_repo/firebase_realtime_updating_lazy_loading_controller.dart @@ -8,18 +8,18 @@ import 'dart:async'; -import 'package:hausaufgabenheft_logik/src/data_source/homework_data_source.dart'; +import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; import 'realtime_completed_homework_loader.dart'; -class RealtimeUpdatingLazyLoadingController extends LazyLoadingController { +class RealtimeUpdatingLazyLoadingController + extends LazyLoadingController { /// The number of homeworks that will be initially loaded on construction. /// If it is 0 then an empty LazyLoading result will be given back without /// calling the [FirebaseRealtimeCompletedHomeworkLoader]. final int initialNumberOfHomeworksToLoad; - final RealtimeCompletedHomeworkLoader _homeworkLoader; + final RealtimeCompletedHomeworkLoader _homeworkLoader; - final StreamController _controller = - StreamController(); + final _controller = StreamController>(); int _numberOfHomeworksToAdvance = 0; /// The latest stream of lazy loading results. @@ -42,7 +42,7 @@ class RealtimeUpdatingLazyLoadingController extends LazyLoadingController { } @override - Stream get results => _controller.stream; + Stream> get results => _controller.stream; /// Advances the current number of loaded homeworks by [numberOfHomeworks]. /// @@ -62,7 +62,7 @@ class RealtimeUpdatingLazyLoadingController extends LazyLoadingController { }); } - Stream _getLazyLoadingResultStream( + Stream> _getLazyLoadingResultStream( int nrOfHomeworksToLoad) { final homeworksStream = _homeworkLoader.loadMostRecentHomeworks(nrOfHomeworksToLoad); diff --git a/lib/hausaufgabenheft_logik/test/in_memory_repo/in_memory_homework_repository.dart b/lib/hausaufgabenheft_logik/test/in_memory_repo/in_memory_homework_repository.dart index 7c90e949f..1c4c654fb 100644 --- a/lib/hausaufgabenheft_logik/test/in_memory_repo/in_memory_homework_repository.dart +++ b/lib/hausaufgabenheft_logik/test/in_memory_repo/in_memory_homework_repository.dart @@ -15,50 +15,61 @@ import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; import 'firebase_realtime_updating_lazy_loading_controller.dart'; import 'realtime_completed_homework_loader.dart'; -class InMemoryHomeworkRepository extends HomeworkDataSource { - IList _homeworks = const IListConst([]); - IList get _openHomeworks => - _homeworks.where((h) => h.status == CompletionStatus.open).toIList(); - IList get _completedHomeworks => - _homeworks.where((h) => h.status == CompletionStatus.completed).toIList(); - - final _openHomeworkStream = BehaviorSubject>(); - final _completedHomeworkStream = BehaviorSubject>(); +class InMemoryHomeworkRepository { + IList _homeworks = IList(const []); + IList get _openHomeworks => _homeworks.where((h) { + if (h is TeacherHomeworkReadModel) { + return h.status == ArchivalStatus.open; + } else { + final hw = h as StudentHomeworkReadModel; + return hw.status == CompletionStatus.open; + } + }).toIList(); + IList get _completedHomeworks => _homeworks.where((h) { + if (h is TeacherHomeworkReadModel) { + return h.status == ArchivalStatus.archived; + } else { + final hw = h as StudentHomeworkReadModel; + return hw.status == CompletionStatus.completed; + } + }).toIList(); + + final _openHomeworkStream = BehaviorSubject>(); + final _completedHomeworkStream = BehaviorSubject>(); final Duration fakeDelay; InMemoryHomeworkRepository({this.fakeDelay = Duration.zero}) { _openHomeworkStream.add(_homeworks); } - @override - Stream> get openHomeworks => + Stream> get openHomeworks => _openHomeworkStream.stream.delay(fakeDelay); final bool _loadedAllCompleted = false; bool get loadedAllCompleted => _loadedAllCompleted; - Future add(HomeworkReadModel homework) async { + Future add(T homework) async { _homeworks = _homeworks.add(homework); addHomeworksToStreams(); } - Future delete(HomeworkReadModel homework) async { + Future delete(T homework) async { _homeworks = _homeworks.removeWhere((h) => h.id == homework.id); addHomeworksToStreams(); } - Future> getAll() async { + Future> getAll() async { await Future.delayed(fakeDelay); return _homeworks; } - Future update(HomeworkReadModel homework) async { + Future update(T homework) async { final index = _homeworks.indexWhere((h) => h.id == homework.id); _homeworks = _homeworks.replace(index, homework); addHomeworksToStreams(); } - Future findById(HomeworkId id) { + Future findById(HomeworkId id) { return Future.value(_homeworks.singleWhere((h) => h.id == id)); } @@ -67,23 +78,22 @@ class InMemoryHomeworkRepository extends HomeworkDataSource { _completedHomeworkStream.add(_completedHomeworks); } - @override - LazyLoadingController getLazyLoadingCompletedHomeworksController( + LazyLoadingController getLazyLoadingCompletedHomeworksController( int nrOfInitialHomeworkToLoad) { return RealtimeUpdatingLazyLoadingController( - InMemoryHomeworkLoader(_completedHomeworkStream), + InMemoryHomeworkLoader(_completedHomeworkStream), initialNumberOfHomeworksToLoad: nrOfInitialHomeworkToLoad); } } -class InMemoryHomeworkLoader extends RealtimeCompletedHomeworkLoader { - final BehaviorSubject> _completedHomeworksSubject; +class InMemoryHomeworkLoader + extends RealtimeCompletedHomeworkLoader { + final BehaviorSubject> _completedHomeworksSubject; InMemoryHomeworkLoader(this._completedHomeworksSubject); @override - Stream> loadMostRecentHomeworks( - int numberOfHomeworks) { + Stream> loadMostRecentHomeworks(int numberOfHomeworks) { return _completedHomeworksSubject.map((homeworks) { if (homeworks.length < numberOfHomeworks) return homeworks; return homeworks.sublist(0, numberOfHomeworks); diff --git a/lib/hausaufgabenheft_logik/test/in_memory_repo/realtime_completed_homework_loader.dart b/lib/hausaufgabenheft_logik/test/in_memory_repo/realtime_completed_homework_loader.dart index a0beb5f59..796724eab 100644 --- a/lib/hausaufgabenheft_logik/test/in_memory_repo/realtime_completed_homework_loader.dart +++ b/lib/hausaufgabenheft_logik/test/in_memory_repo/realtime_completed_homework_loader.dart @@ -7,9 +7,9 @@ // SPDX-License-Identifier: EUPL-1.2 import 'package:fast_immutable_collections/fast_immutable_collections.dart'; -import 'package:hausaufgabenheft_logik/src/models/homework.dart'; +import 'package:hausaufgabenheft_logik/src/shared/models/homework.dart'; -abstract class RealtimeCompletedHomeworkLoader { - Stream> loadMostRecentHomeworks( - int numberOfHomeworks); +abstract class RealtimeCompletedHomeworkLoader< + T extends BaseHomeworkReadModel> { + Stream> loadMostRecentHomeworks(int numberOfHomeworks); } diff --git a/lib/firebase_hausaufgabenheft_logik/test/lazy_loading_controller_test.dart b/lib/hausaufgabenheft_logik/test/lazy_loading_controller_test.dart similarity index 81% rename from lib/firebase_hausaufgabenheft_logik/test/lazy_loading_controller_test.dart rename to lib/hausaufgabenheft_logik/test/lazy_loading_controller_test.dart index 64ae882d5..e9537fd7c 100644 --- a/lib/firebase_hausaufgabenheft_logik/test/lazy_loading_controller_test.dart +++ b/lib/hausaufgabenheft_logik/test/lazy_loading_controller_test.dart @@ -11,46 +11,49 @@ import 'dart:async'; import 'package:clock/clock.dart'; import 'package:common_domain_models/common_domain_models.dart'; import 'package:fast_immutable_collections/fast_immutable_collections.dart'; -import 'package:firebase_hausaufgabenheft_logik/src/realtime_updating_lazy_loading_controller.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:hausaufgabenheft_logik/hausaufgabenheft_logik.dart'; import 'package:rxdart/subjects.dart' as rx; -import 'in_memory_homework_loader.dart'; +import 'in_memory_repo/firebase_realtime_updating_lazy_loading_controller.dart'; +import 'in_memory_repo/in_memory_homework_repository.dart'; -class ReportingInMemoryHomeworkLoader extends InMemoryHomeworkLoader { +class ReportingInMemoryHomeworkLoader + extends InMemoryHomeworkLoader { ReportingInMemoryHomeworkLoader(super.completedHomeworksSubject); bool wasInvoked = false; @override - Stream> loadMostRecentHomeworks( - int numberOfHomeworks) { + Stream> loadMostRecentHomeworks(int numberOfHomeworks) { wasInvoked = true; return super.loadMostRecentHomeworks(numberOfHomeworks); } } -IList listOfHomeworksWithLength(int length) => List.generate( +IList listOfHomeworksWithLength(int length) => + List.generate( length, - (index) => HomeworkReadModel( + (index) => StudentHomeworkReadModel( id: HomeworkId("$index"), todoDate: clock.now(), + courseId: const CourseId("testCourseId"), status: CompletionStatus.completed, subject: Subject("Mathe", abbreviation: 'Ma'), title: const Title("ABC"), withSubmissions: false), ).toIList(); -Stream> getHomeworkResultsAsStream( - Stream resultStream) => +Stream> getHomeworkResultsAsStream( + Stream> resultStream) => resultStream.map((res) => res.homeworks); void main() { group('LazyLoadingController', () { - late ReportingInMemoryHomeworkLoader homeworkLoader; - late rx.BehaviorSubject> homeworkSubject; + late ReportingInMemoryHomeworkLoader + homeworkLoader; + late rx.BehaviorSubject> homeworkSubject; - void addToDataSource(IList homeworks) { + void addToDataSource(IList homeworks) { var hws = homeworkSubject.valueOrNull; if (hws != null) { hws = hws.addAll(homeworks); @@ -61,8 +64,10 @@ void main() { } setUp(() { - homeworkSubject = rx.BehaviorSubject>(); - homeworkLoader = ReportingInMemoryHomeworkLoader(homeworkSubject); + homeworkSubject = rx.BehaviorSubject>(); + homeworkLoader = + ReportingInMemoryHomeworkLoader( + homeworkSubject); }); tearDown(() { diff --git a/lib/hausaufgabenheft_logik/test/subject_test.dart b/lib/hausaufgabenheft_logik/test/subject_test.dart index 7069db6a1..6d567d38c 100644 --- a/lib/hausaufgabenheft_logik/test/subject_test.dart +++ b/lib/hausaufgabenheft_logik/test/subject_test.dart @@ -6,8 +6,8 @@ // // SPDX-License-Identifier: EUPL-1.2 -import 'package:hausaufgabenheft_logik/src/models/subject.dart'; -import 'package:hausaufgabenheft_logik/src/views/color.dart'; +import 'package:hausaufgabenheft_logik/src/shared/models/subject.dart'; +import 'package:hausaufgabenheft_logik/src/shared/color.dart'; import 'package:test/test.dart'; void main() { diff --git a/lib/hausaufgabenheft_logik/test/test_data/homeworks.dart b/lib/hausaufgabenheft_logik/test/test_data/homeworks.dart index b6e211d7c..068f06b4b 100644 --- a/lib/hausaufgabenheft_logik/test/test_data/homeworks.dart +++ b/lib/hausaufgabenheft_logik/test/test_data/homeworks.dart @@ -6,7 +6,7 @@ // // SPDX-License-Identifier: EUPL-1.2 -import 'package:hausaufgabenheft_logik/src/models/models.dart'; +import 'package:hausaufgabenheft_logik/src/shared/models/models.dart'; import '../create_homework_util.dart'; diff --git a/licenses_config.yaml b/licenses_config.yaml index 0e67b2202..997e8f5ed 100644 --- a/licenses_config.yaml +++ b/licenses_config.yaml @@ -62,7 +62,6 @@ packageLicenseOverride: files_basics: EUPL-1.2-or-later files_usecases: EUPL-1.2-or-later filesharing_logic: EUPL-1.2-or-later - firebase_hausaufgabenheft_logik: EUPL-1.2-or-later group_domain_implementation: EUPL-1.2-or-later group_domain_models: EUPL-1.2-or-later hausaufgabenheft_logik: EUPL-1.2-or-later