From 47f9dab7c55d4953c2239ee54478235bac880f70 Mon Sep 17 00:00:00 2001 From: Carlton Whitehead Date: Sat, 22 Jun 2024 12:13:31 -0400 Subject: [PATCH] SNAPSHOT Initial dmvapp sample GUI app --- .gitignore | 25 +- admin/pom.xml | 4 +- api-client-motorsportreg-test/pom.xml | 3 +- api-client-motorsportreg/pom.xml | 3 +- buildsrc/buildsrc-kotlin-parent/pom.xml | 142 ++++++ core-kodein-di-test/pom.xml | 3 +- core-kodein-di/pom.xml | 3 +- core-test/pom.xml | 4 +- core/pom.xml | 4 +- datasource-crispy-fish-test/pom.xml | 3 +- datasource-crispy-fish/pom.xml | 4 +- datasource-motorsportreg/pom.xml | 3 +- datasource-snoozle/pom.xml | 4 +- io-kodein-di-test/pom.xml | 3 +- io-kodein-di/pom.xml | 3 +- io-test/pom.xml | 3 +- io-testsupport/pom.xml | 3 +- io/pom.xml | 4 +- pom.xml | 103 +---- .../presentation-all-kodein-di/pom.xml | 4 +- .../pom.xml | 4 +- presentation/presentation-json/pom.xml | 4 +- presentation/presentation-text/pom.xml | 4 +- presentation/presentation/pom.xml | 4 +- render-html/pom.xml | 2 +- testutil/assertk-arrowkt/pom.xml | 26 ++ .../trailer/assertk/arrowkt/ArrowktAssertk.kt | 30 ++ testutil/assertk-ktor/pom.xml | 4 +- toolkit/konstraints/pom.xml | 4 +- .../fooapp/data/service/FooService.kt | 11 - .../fooapp/domain/constraint/FooConstraint.kt | 46 -- .../domain/service/TestableFooService.kt | 48 -- .../fooapp/presentation/adapter/FooAdapter.kt | 32 -- .../fooapp/presentation/model/FooItemModel.kt | 21 - .../presenter/FooDetailPresenter.kt | 41 -- .../presenter/FooDetailPresenterTest.kt | 176 -------- .../presentation/model/FooModelAssertk.kt | 6 - .../presentation-testsupport/pom.xml | 4 +- .../presentation/model/ItemModelAssertk.kt | 11 +- .../model/LoadableModelAssertk.kt | 14 +- .../state/ItemModelStateAssertk.kt | 7 + .../state/LoadableItemStateAssertk.kt | 8 +- .../state/StatefulPresenterAssertk.kt | 7 + .../LoadableItemPresenterAssertk.kt | 2 - toolkit/presentation/presentation/pom.xml | 9 +- .../adapter/EntityModelAdapter.kt | 8 + .../adapter/LoadableItemAdapter.kt | 12 - .../presentation/model/BaseItemModel.kt | 68 ++- .../presentation/model/CommitOutcome.kt | 30 -- .../toolkit/presentation/model/ItemModel.kt | 26 +- .../toolkit/presentation/model/Loadable.kt | 73 +++ .../presentation/model/LoadableModel.kt | 55 --- .../presenter/ItemModelPresenter.kt | 10 + .../presenter/LoadableItemPresenter.kt | 54 --- .../presenter/LoadablePresenter.kt | 9 + .../presenter/PresenterCoroutineScope.kt | 6 +- .../presenter/SecondDraftPresenter.kt | 39 -- .../presenter/StatefulPresenter.kt | 9 + .../presentation/state/ItemModelState.kt | 52 +++ .../presentation/state/LoadableItemState.kt | 9 - .../presentation/state/LoadableState.kt | 56 +++ .../presentation/state/StateContainer.kt | 84 ++++ toolkit/samples/dmvapp/dmvapp-cli/pom.xml | 5 - .../toolkit/sample/dmvapp/cli/DmvAppCli.kt | 2 + .../DriversLicenseApplicationCommand.kt | 81 ++-- .../dmvapp/cli/view/DriversLicenseView.kt | 18 +- .../dmvapp/cli/view/ValidationResultView.kt | 49 ++ toolkit/samples/dmvapp/dmvapp-common/pom.xml | 8 + .../domain/entity/DriversLicense.kt | 7 - .../entity/DriversLicenseApplication.kt | 16 - .../DriversLicenseApplicationOutcome.kt | 6 - .../domain/entity/LicenseType.kt | 15 - .../DriversLicenseApplicationService.kt | 9 - .../DriversLicenseApplicationServiceImpl.kt | 31 -- ...PresentationModelToDomainEntityAdapters.kt | 15 - .../localization/EnglishUsLocalization.kt | 66 --- .../presentation/localization/Localization.kt | 19 - .../DriversLicenseApplicationPresenter.kt | 34 -- .../presenter/PresentationPresenterModule.kt | 8 - .../state/DriversLicenseApplicationState.kt | 10 - .../DriversLicenseApplicationModelFeedback.kt | 26 -- .../dmvapp/domain/entity/DriversLicense.kt | 7 + .../entity/DriversLicenseApplication.kt | 7 + .../DriversLicenseApplicationRejection.kt | 15 + .../dmvapp/domain/entity/LicenseType.kt | 15 + .../sample/dmvapp/domain/entity/Sass.kt | 7 + .../DriversLicenseApplicationService.kt | 12 + .../service/impl/DomainServiceModule.kt | 0 .../DriversLicenseApplicationServiceImpl.kt | 41 ++ .../validation/DomainValidationModule.kt | 0 .../DriversLicenseApplicationFeedback.kt | 7 +- .../DriversLicenseApplicationValidator.kt | 0 .../DriversLicenseApplicationModelAdapters.kt | 30 ++ .../adapter/PresentationAdapterModule.kt | 9 + .../localization/EnglishUsTranslation.kt | 56 +++ .../PresentationLocalizationModule.kt | 4 +- .../presentation/localization/Strings.kt | 18 + .../presentation/localization/StringsImpl.kt | 80 ++++ .../presentation/localization/Translation.kt | 53 +++ .../DriversLicenseApplicationItemModel.kt | 17 - .../model/DriversLicenseApplicationModel.kt | 0 ...DriversLicenseApplicationRejectionModel.kt | 16 + .../DriversLicenseApplicationPresenter.kt | 148 ++++++ .../presenter/PresentationPresenterModule.kt | 16 + .../state/DriversLicenseApplicationState.kt | 20 + .../DriversLicenseApplicationModelFeedback.kt | 40 ++ ...DriversLicenseApplicationModelValidator.kt | 21 +- .../PresentationValidationModule.kt | 3 +- .../trailer/toolkit/sample/dmvapp/TestDI.kt | 4 +- .../DriversLicenseApplicationAssertk.kt | 7 - ...riversLicenseApplicationServiceImplTest.kt | 35 +- .../validation/DriversLicenseValidatorTest.kt | 11 +- .../DriversLicenseApplicationPresenterTest.kt | 67 ++- ...ersLicenseApplicationModelValidatorTest.kt | 36 +- .../dmvapp/dmvapp-gui/.run/desktop.run.xml | 24 + .../dmvapp/dmvapp-gui/build.gradle.kts | 69 +++ .../dmvapp/dmvapp-gui/gradle.properties | 4 + .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 60756 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 + toolkit/samples/dmvapp/dmvapp-gui/gradlew | 234 ++++++++++ toolkit/samples/dmvapp/dmvapp-gui/gradlew.bat | 89 ++++ toolkit/samples/dmvapp/dmvapp-gui/pom.xml | 137 ++++++ .../dmvapp/dmvapp-gui/settings.gradle.kts | 16 + .../toolkit/sample/dmvapp/gui/DmvAppGui.kt | 31 ++ .../ConerTopLevelNavigationDrawer.kt | 213 +++++++++ .../gui/composable/ConerTopLevelTopAppBar.kt | 44 ++ .../gui/composable/MaterialWindowSizeClass.kt | 20 + .../gui/composable/ValidationFeedback.kt | 48 ++ .../entity/ThemeModePreference.kt | 7 + .../GuiPresentationPresenterModule.kt | 8 + .../presenter/SettingsPresenter.kt | 20 + .../gui/presentation/state/SettingsState.kt | 8 + .../sample/dmvapp/gui/screen/DmvAppScreen.kt | 8 + .../DriversLicenseApplicationForm.kt | 421 ++++++++++++++++++ ...riversLicenseApplicationRejectionDialog.kt | 58 +++ .../DriversLicenseScreen.kt | 144 ++++++ .../gui/screen/main/DmvAppMainScreen.kt | 61 +++ .../main/DmvAppNavigationDrawerScreen.kt | 97 ++++ .../gui/screen/settings/SettingsScreen.kt | 178 ++++++++ .../dmvapp/gui/theme/ConerBrandColors.kt | 9 + .../sample/dmvapp/gui/theme/ConerTheme.kt | 27 ++ .../dmvapp/gui/theme/ConerThemeColors.kt | 306 +++++++++++++ .../dmvapp/gui/util/ComposeFlowExtensions.kt | 34 ++ .../gui/util/FocusFirstFocusRequester.kt | 47 ++ .../sample/dmvapp/gui/util/LocalStrings.kt | 13 + .../dmvapp/gui/util/LocalWindowState.kt | 6 + .../dmvapp/gui/window/DmvAppMainWindow.kt | 31 ++ .../dmvapp/gui/window/DriversLicenseWindow.kt | 26 ++ .../resources/coner-icon/coner-icon_1024.png | Bin 0 -> 90565 bytes .../resources/coner-icon/coner-icon_128.png | Bin 0 -> 8741 bytes .../resources/coner-icon/coner-icon_16.png | Bin 0 -> 690 bytes .../resources/coner-icon/coner-icon_256.png | Bin 0 -> 19308 bytes .../resources/coner-icon/coner-icon_32.png | Bin 0 -> 1531 bytes .../resources/coner-icon/coner-icon_3840.png | Bin 0 -> 415999 bytes .../resources/coner-icon/coner-icon_48.png | Bin 0 -> 2638 bytes .../resources/coner-icon/coner-icon_512.png | Bin 0 -> 41866 bytes .../resources/coner-icon/coner-icon_64.png | Bin 0 -> 3820 bytes .../resources/coner-logo/coner-logo_1024.png | Bin 0 -> 45019 bytes .../resources/coner-logo/coner-logo_128.png | Bin 0 -> 4423 bytes .../resources/coner-logo/coner-logo_256.png | Bin 0 -> 9631 bytes .../resources/coner-logo/coner-logo_96.png | Bin 0 -> 3142 bytes .../DriversLicenseApplicationFormTest.kt | 212 +++++++++ .../page/DriversLicenseApplicationFormPage.kt | 30 ++ .../testutil/ValidationFeedbackTestUtils.kt | 15 + .../fooapp/fooapp-common}/pom.xml | 17 +- .../data/repository/FooRepositoryImpl.kt | 22 + .../data/repository/MutableMapRepository.kt | 54 +++ .../fooapp/data/service/FooServiceImpl.kt | 66 +++ .../sample}/fooapp/domain/entity/Foo.kt | 2 +- .../exception/AlreadyExistsException.kt | 2 +- .../domain/exception/NotFoundException.kt | 2 +- .../fooapp/domain/repository/FooRepository.kt | 5 + .../domain/repository/SimpleRepository.kt | 32 ++ .../fooapp/domain/service/FooService.kt | 36 ++ .../fooapp/domain/validation/FooFeedback.kt | 24 + .../fooapp/domain/validation/FooValidator.kt | 28 ++ .../adapter/FooEntityModelAdapter.kt | 23 + .../fooapp/presentation/model/FooItemModel.kt | 26 ++ .../fooapp/presentation/model/FooModel.kt | 9 + .../presenter/FooDetailPresenter.kt | 87 ++++ .../presentation/state/FooDetailState.kt | 14 + .../validation/FooModelFeedback.kt | 18 + .../sample/fooapp/util/StringExtensions.kt | 7 + .../fooapp/domain/entity/FooAssertk.kt | 2 +- .../presentation/model/FooModelAssertk.kt | 6 + .../presenter/FooDetailPresenterTest.kt | 217 +++++++++ .../fooapp/fooapp-parent}/pom.xml | 10 +- .../passwordapp/domain/entity/Password.kt | 4 + .../domain/state/ChangePasswordFormatState.kt | 7 +- .../validation/ChangePasswordFormFeedback.kt | 9 +- .../validation/ChangePasswordFormValidator.kt | 8 +- .../domain/validation/PasswordFeedback.kt | 4 +- .../domain/validation/PasswordValidator.kt | 13 +- .../ChangePasswordFormValidatorTest.kt | 56 +-- .../validation/PasswordValidatorTest.kt | 16 +- toolkit/samples/samples-common/pom.xml | 5 +- toolkit/toolkit/pom.xml | 23 + .../tech/coner/trailer/toolkit/Error.kt | 29 ++ .../coner/trailer/toolkit/ErrorException.kt | 4 + .../trailer/toolkit}/StringExtensions.kt | 2 +- .../validation/validation-testsupport/pom.xml | 4 +- .../testsupport/ValidationResultAssertk.kt | 10 +- toolkit/validation/validation/pom.xml | 4 +- .../trailer/toolkit/validation/Feedback.kt | 6 +- .../toolkit/validation/FeedbackDelegate.kt | 14 + .../toolkit/validation/ValidationOutcome.kt | 49 ++ .../toolkit/validation/ValidationResult.kt | 30 -- .../trailer/toolkit/validation/Validator.kt | 30 +- .../validation/adapter/PropertyAdapter.kt | 35 ++ .../adapter/ValidationOutcomeAdapter.kt | 14 + .../context/PropertyValidationRuleContext.kt | 7 + .../toolkit/validation/impl/ValidatorImpl.kt | 52 ++- .../PropertyValidationRuleContextImpl.kt | 10 + .../validation/impl/entry/ValidationEntry.kt | 47 +- .../impl/rule/ObjectValidationRuleImpl.kt | 2 +- .../impl/rule/PropertyValidationRuleImpl.kt | 8 +- .../EnglishUsValidationTranslation.kt | 9 + .../localization/ValidationStrings.kt | 7 + .../localization/ValidationStringsImpl.kt | 15 + .../localization/ValidationTranslation.kt | 8 + .../validation/rule/ObjectValidationRule.kt | 2 +- .../validation/rule/PropertyValidationRule.kt | 2 +- .../toolkit/validation/rule/ValidationRule.kt | 2 +- webapp-competition/pom.xml | 3 +- 224 files changed, 5295 insertions(+), 1344 deletions(-) create mode 100644 buildsrc/buildsrc-kotlin-parent/pom.xml create mode 100644 testutil/assertk-arrowkt/pom.xml create mode 100644 testutil/assertk-arrowkt/src/main/kotlin/tech/coner/trailer/assertk/arrowkt/ArrowktAssertk.kt delete mode 100644 toolkit/presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/data/service/FooService.kt delete mode 100644 toolkit/presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/domain/constraint/FooConstraint.kt delete mode 100644 toolkit/presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/domain/service/TestableFooService.kt delete mode 100644 toolkit/presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/presentation/adapter/FooAdapter.kt delete mode 100644 toolkit/presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/presentation/model/FooItemModel.kt delete mode 100644 toolkit/presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/presentation/presenter/FooDetailPresenter.kt delete mode 100644 toolkit/presentation/presentation-test/src/test/kotlin/tech/coner/trailer/toolkit/presentation/presenter/FooDetailPresenterTest.kt delete mode 100644 toolkit/presentation/presentation-test/src/test/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/presentation/model/FooModelAssertk.kt create mode 100644 toolkit/presentation/presentation-testsupport/src/main/kotlin/tech/coner/trailer/toolkit/presentation/state/ItemModelStateAssertk.kt create mode 100644 toolkit/presentation/presentation-testsupport/src/main/kotlin/tech/coner/trailer/toolkit/presentation/state/StatefulPresenterAssertk.kt delete mode 100644 toolkit/presentation/presentation-testsupport/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/LoadableItemPresenterAssertk.kt create mode 100644 toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/adapter/EntityModelAdapter.kt delete mode 100644 toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/adapter/LoadableItemAdapter.kt delete mode 100644 toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/model/CommitOutcome.kt create mode 100644 toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/model/Loadable.kt delete mode 100644 toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/model/LoadableModel.kt create mode 100644 toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/presenter/ItemModelPresenter.kt delete mode 100644 toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/presenter/LoadableItemPresenter.kt create mode 100644 toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/presenter/LoadablePresenter.kt delete mode 100644 toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/presenter/SecondDraftPresenter.kt create mode 100644 toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/presenter/StatefulPresenter.kt create mode 100644 toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/state/ItemModelState.kt delete mode 100644 toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/state/LoadableItemState.kt create mode 100644 toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/state/LoadableState.kt create mode 100644 toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/state/StateContainer.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-cli/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/cli/view/ValidationResultView.kt delete mode 100644 toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/domain/entity/DriversLicense.kt delete mode 100644 toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/domain/entity/DriversLicenseApplication.kt delete mode 100644 toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/domain/entity/DriversLicenseApplicationOutcome.kt delete mode 100644 toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/domain/entity/LicenseType.kt delete mode 100644 toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/domain/service/DriversLicenseApplicationService.kt delete mode 100644 toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/domain/service/impl/DriversLicenseApplicationServiceImpl.kt delete mode 100644 toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/adapter/PresentationModelToDomainEntityAdapters.kt delete mode 100644 toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/localization/EnglishUsLocalization.kt delete mode 100644 toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/localization/Localization.kt delete mode 100644 toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/presenter/DriversLicenseApplicationPresenter.kt delete mode 100644 toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/presenter/PresentationPresenterModule.kt delete mode 100644 toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/state/DriversLicenseApplicationState.kt delete mode 100644 toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/validation/DriversLicenseApplicationModelFeedback.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/entity/DriversLicense.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/entity/DriversLicenseApplication.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/entity/DriversLicenseApplicationRejection.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/entity/LicenseType.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/entity/Sass.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/service/DriversLicenseApplicationService.kt rename toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/{tech.coner.trailer.toolkit.sample.dmvapp => tech/coner/trailer/toolkit/sample/dmvapp}/domain/service/impl/DomainServiceModule.kt (100%) create mode 100644 toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/service/impl/DriversLicenseApplicationServiceImpl.kt rename toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/{tech.coner.trailer.toolkit.sample.dmvapp => tech/coner/trailer/toolkit/sample/dmvapp}/domain/validation/DomainValidationModule.kt (100%) rename toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/{tech.coner.trailer.toolkit.sample.dmvapp => tech/coner/trailer/toolkit/sample/dmvapp}/domain/validation/DriversLicenseApplicationFeedback.kt (66%) rename toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/{tech.coner.trailer.toolkit.sample.dmvapp => tech/coner/trailer/toolkit/sample/dmvapp}/domain/validation/DriversLicenseApplicationValidator.kt (100%) create mode 100644 toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/adapter/DriversLicenseApplicationModelAdapters.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/adapter/PresentationAdapterModule.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/localization/EnglishUsTranslation.kt rename toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/{tech.coner.trailer.toolkit.sample.dmvapp => tech/coner/trailer/toolkit/sample/dmvapp}/presentation/localization/PresentationLocalizationModule.kt (75%) create mode 100644 toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/localization/Strings.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/localization/StringsImpl.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/localization/Translation.kt rename toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/{tech.coner.trailer.toolkit.sample.dmvapp => tech/coner/trailer/toolkit/sample/dmvapp}/presentation/model/DriversLicenseApplicationItemModel.kt (51%) rename toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/{tech.coner.trailer.toolkit.sample.dmvapp => tech/coner/trailer/toolkit/sample/dmvapp}/presentation/model/DriversLicenseApplicationModel.kt (100%) create mode 100644 toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/model/DriversLicenseApplicationRejectionModel.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/presenter/DriversLicenseApplicationPresenter.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/presenter/PresentationPresenterModule.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/state/DriversLicenseApplicationState.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/validation/DriversLicenseApplicationModelFeedback.kt rename toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/{tech.coner.trailer.toolkit.sample.dmvapp => tech/coner/trailer/toolkit/sample/dmvapp}/presentation/validation/DriversLicenseApplicationModelValidator.kt (52%) rename toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/{tech.coner.trailer.toolkit.sample.dmvapp => tech/coner/trailer/toolkit/sample/dmvapp}/presentation/validation/PresentationValidationModule.kt (69%) delete mode 100644 toolkit/samples/dmvapp/dmvapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/entity/DriversLicenseApplicationAssertk.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/.run/desktop.run.xml create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/build.gradle.kts create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/gradle.properties create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/gradle/wrapper/gradle-wrapper.jar create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/gradle/wrapper/gradle-wrapper.properties create mode 100755 toolkit/samples/dmvapp/dmvapp-gui/gradlew create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/gradlew.bat create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/pom.xml create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/settings.gradle.kts create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/DmvAppGui.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/composable/ConerTopLevelNavigationDrawer.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/composable/ConerTopLevelTopAppBar.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/composable/MaterialWindowSizeClass.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/composable/ValidationFeedback.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/presentation/entity/ThemeModePreference.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/presentation/presenter/GuiPresentationPresenterModule.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/presentation/presenter/SettingsPresenter.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/presentation/state/SettingsState.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/screen/DmvAppScreen.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/screen/driverslicenseapplication/DriversLicenseApplicationForm.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/screen/driverslicenseapplication/DriversLicenseApplicationRejectionDialog.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/screen/driverslicenseapplication/DriversLicenseScreen.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/screen/main/DmvAppMainScreen.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/screen/main/DmvAppNavigationDrawerScreen.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/screen/settings/SettingsScreen.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/theme/ConerBrandColors.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/theme/ConerTheme.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/theme/ConerThemeColors.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/util/ComposeFlowExtensions.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/util/FocusFirstFocusRequester.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/util/LocalStrings.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/util/LocalWindowState.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/window/DmvAppMainWindow.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/window/DriversLicenseWindow.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/resources/coner-icon/coner-icon_1024.png create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/resources/coner-icon/coner-icon_128.png create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/resources/coner-icon/coner-icon_16.png create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/resources/coner-icon/coner-icon_256.png create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/resources/coner-icon/coner-icon_32.png create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/resources/coner-icon/coner-icon_3840.png create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/resources/coner-icon/coner-icon_48.png create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/resources/coner-icon/coner-icon_512.png create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/resources/coner-icon/coner-icon_64.png create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/resources/coner-logo/coner-logo_1024.png create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/resources/coner-logo/coner-logo_128.png create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/resources/coner-logo/coner-logo_256.png create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/main/resources/coner-logo/coner-logo_96.png create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/test/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/composable/DriversLicenseApplicationFormTest.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/test/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/page/DriversLicenseApplicationFormPage.kt create mode 100644 toolkit/samples/dmvapp/dmvapp-gui/src/test/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/testutil/ValidationFeedbackTestUtils.kt rename toolkit/{presentation/presentation-test => samples/fooapp/fooapp-common}/pom.xml (68%) create mode 100644 toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/data/repository/FooRepositoryImpl.kt create mode 100644 toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/data/repository/MutableMapRepository.kt create mode 100644 toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/data/service/FooServiceImpl.kt rename toolkit/{presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport => samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample}/fooapp/domain/entity/Foo.kt (71%) rename toolkit/{presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport => samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample}/fooapp/domain/exception/AlreadyExistsException.kt (56%) rename toolkit/{presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport => samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample}/fooapp/domain/exception/NotFoundException.kt (56%) create mode 100644 toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/domain/repository/FooRepository.kt create mode 100644 toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/domain/repository/SimpleRepository.kt create mode 100644 toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/domain/service/FooService.kt create mode 100644 toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/domain/validation/FooFeedback.kt create mode 100644 toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/domain/validation/FooValidator.kt create mode 100644 toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/presentation/adapter/FooEntityModelAdapter.kt create mode 100644 toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/presentation/model/FooItemModel.kt create mode 100644 toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/presentation/model/FooModel.kt create mode 100644 toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/presentation/presenter/FooDetailPresenter.kt create mode 100644 toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/presentation/state/FooDetailState.kt create mode 100644 toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/presentation/validation/FooModelFeedback.kt create mode 100644 toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/util/StringExtensions.kt rename toolkit/{presentation/presentation-test/src/test/kotlin/tech/coner/trailer/toolkit/presentation/testsupport => samples/fooapp/fooapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample}/fooapp/domain/entity/FooAssertk.kt (62%) create mode 100644 toolkit/samples/fooapp/fooapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/fooapp/presentation/model/FooModelAssertk.kt create mode 100644 toolkit/samples/fooapp/fooapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/fooapp/presentation/presenter/FooDetailPresenterTest.kt rename toolkit/{util => samples/fooapp/fooapp-parent}/pom.xml (60%) create mode 100644 toolkit/samples/passwordapp/src/main/kotlin/tech/coner/trailer/toolkit/sample/passwordapp/domain/entity/Password.kt create mode 100644 toolkit/toolkit/pom.xml create mode 100644 toolkit/toolkit/src/main/kotlin/tech/coner/trailer/toolkit/Error.kt create mode 100644 toolkit/toolkit/src/main/kotlin/tech/coner/trailer/toolkit/ErrorException.kt rename toolkit/{util/src/main/kotlin/tech/coner/trailer/toolkit/util => toolkit/src/main/kotlin/tech/coner/trailer/toolkit}/StringExtensions.kt (56%) create mode 100644 toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/FeedbackDelegate.kt create mode 100644 toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/ValidationOutcome.kt delete mode 100644 toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/ValidationResult.kt create mode 100644 toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/adapter/PropertyAdapter.kt create mode 100644 toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/adapter/ValidationOutcomeAdapter.kt create mode 100644 toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/context/PropertyValidationRuleContext.kt create mode 100644 toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/impl/context/PropertyValidationRuleContextImpl.kt create mode 100644 toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/presentation/localization/EnglishUsValidationTranslation.kt create mode 100644 toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/presentation/localization/ValidationStrings.kt create mode 100644 toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/presentation/localization/ValidationStringsImpl.kt create mode 100644 toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/presentation/localization/ValidationTranslation.kt diff --git a/.gitignore b/.gitignore index 8d9ef2c09..a0e81a534 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,27 @@ buildNumber.properties .mvn/wrapper/maven-wrapper.jar # LibreOffice lock files (.rgg especially) -.~lock* \ No newline at end of file +.~lock* + +# https://github.com/github/gitignore/blob/main/Gradle.gitignore +.gradle +**/build/ +!src/**/build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Avoid ignore Gradle wrappper properties +!gradle-wrapper.properties + +# Cache of project +.gradletasknamecache + +# Eclipse Gradle plugin generated files +# Eclipse Core +.project +# JDT-specific (Eclipse Java Development Tools) +.classpath \ No newline at end of file diff --git a/admin/pom.xml b/admin/pom.xml index 73039cf7b..230156de3 100644 --- a/admin/pom.xml +++ b/admin/pom.xml @@ -3,10 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - parent + buildsrc-kotlin-parent tech.coner.trailer 0.1.0-SNAPSHOT - ../pom.xml + ../buildsrc/buildsrc-kotlin-parent/pom.xml 4.0.0 diff --git a/api-client-motorsportreg-test/pom.xml b/api-client-motorsportreg-test/pom.xml index d1203ff18..2c84d123f 100644 --- a/api-client-motorsportreg-test/pom.xml +++ b/api-client-motorsportreg-test/pom.xml @@ -3,9 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - parent + buildsrc-kotlin-parent tech.coner.trailer 0.1.0-SNAPSHOT + ../buildsrc/buildsrc-kotlin-parent/pom.xml 4.0.0 diff --git a/api-client-motorsportreg/pom.xml b/api-client-motorsportreg/pom.xml index b759669e8..b0a91e0e9 100644 --- a/api-client-motorsportreg/pom.xml +++ b/api-client-motorsportreg/pom.xml @@ -3,9 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - parent + buildsrc-kotlin-parent tech.coner.trailer 0.1.0-SNAPSHOT + ../buildsrc/buildsrc-kotlin-parent/pom.xml 4.0.0 diff --git a/buildsrc/buildsrc-kotlin-parent/pom.xml b/buildsrc/buildsrc-kotlin-parent/pom.xml new file mode 100644 index 000000000..f1c63307c --- /dev/null +++ b/buildsrc/buildsrc-kotlin-parent/pom.xml @@ -0,0 +1,142 @@ + + + 4.0.0 + + tech.coner.trailer + parent + 0.1.0-SNAPSHOT + ../../pom.xml + + + buildsrc-kotlin-parent + + pom + + + ../../core + ../../core-test + ../../datasource-crispy-fish + ../../datasource-crispy-fish-test + ../../datasource-snoozle + ../../api-client-motorsportreg + ../../api-client-motorsportreg-test + ../../datasource-motorsportreg + ../../io + ../../io-kodein-di + ../../admin + ../../io-test + ../../presentation/presentation + ../../presentation/presentation-text + ../../presentation/presentation-all-kodein-di + ../../presentation/presentation-json + ../../io-kodein-di-test + ../../io-testsupport + ../../core-kodein-di + ../../core-kodein-di-test + ../../webapp-competition + ../../testutil/assertk-ktor + ../../presentation/presentation-all-testsupport-mockk + ../../toolkit/konstraints + ../../toolkit/presentation/presentation + ../../toolkit/presentation/presentation-testsupport + ../../toolkit/samples/samples-common + ../../toolkit/validation/validation + ../../toolkit/validation/validation-testsupport + ../../toolkit/toolkit + ../../testutil/assertk-arrowkt + + + + UTF-8 + official + 1.8 + + + + + + org.jetbrains.kotlin + kotlin-stdlib + + + org.jetbrains.kotlinx + kotlinx-coroutines-core + + + io.arrow-kt + arrow-core-jvm + + + io.arrow-kt + arrow-fx-coroutines-jvm + + + + org.jetbrains.kotlinx + kotlinx-coroutines-test-jvm + + + org.junit.jupiter + junit-jupiter + + + com.willowtreeapps.assertk + assertk-jvm + + + io.mockk + mockk-jvm + + + app.cash.turbine + turbine-jvm + + + + + + mavenCentral + https://repo1.maven.org/maven2/ + + + + + src/main/kotlin + src/test/kotlin + + + org.jetbrains.kotlin + kotlin-maven-plugin + + + compile + compile + + compile + + + + test-compile + test-compile + + test-compile + + + + + + maven-surefire-plugin + + + maven-failsafe-plugin + + + org.codehaus.mojo + exec-maven-plugin + + + + + \ No newline at end of file diff --git a/core-kodein-di-test/pom.xml b/core-kodein-di-test/pom.xml index 6536a8b97..209d8fe0d 100644 --- a/core-kodein-di-test/pom.xml +++ b/core-kodein-di-test/pom.xml @@ -3,9 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - parent + buildsrc-kotlin-parent tech.coner.trailer 0.1.0-SNAPSHOT + ../buildsrc/buildsrc-kotlin-parent/pom.xml 4.0.0 diff --git a/core-kodein-di/pom.xml b/core-kodein-di/pom.xml index c6cda81b8..ed520e126 100644 --- a/core-kodein-di/pom.xml +++ b/core-kodein-di/pom.xml @@ -3,9 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - parent + buildsrc-kotlin-parent tech.coner.trailer 0.1.0-SNAPSHOT + ../buildsrc/buildsrc-kotlin-parent/pom.xml 4.0.0 diff --git a/core-test/pom.xml b/core-test/pom.xml index 931e8f837..943e0b884 100644 --- a/core-test/pom.xml +++ b/core-test/pom.xml @@ -3,10 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - parent + buildsrc-kotlin-parent tech.coner.trailer 0.1.0-SNAPSHOT - ../pom.xml + ../buildsrc/buildsrc-kotlin-parent/pom.xml 4.0.0 diff --git a/core/pom.xml b/core/pom.xml index 510d00867..382c99b2d 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -4,9 +4,9 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> tech.coner.trailer - parent + buildsrc-kotlin-parent 0.1.0-SNAPSHOT - ../pom.xml + ../buildsrc/buildsrc-kotlin-parent/pom.xml 4.0.0 diff --git a/datasource-crispy-fish-test/pom.xml b/datasource-crispy-fish-test/pom.xml index 598c0359d..05947b890 100644 --- a/datasource-crispy-fish-test/pom.xml +++ b/datasource-crispy-fish-test/pom.xml @@ -3,9 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - parent + buildsrc-kotlin-parent tech.coner.trailer 0.1.0-SNAPSHOT + ../buildsrc/buildsrc-kotlin-parent/pom.xml 4.0.0 diff --git a/datasource-crispy-fish/pom.xml b/datasource-crispy-fish/pom.xml index 35e5dcb7a..abf504de2 100644 --- a/datasource-crispy-fish/pom.xml +++ b/datasource-crispy-fish/pom.xml @@ -4,9 +4,9 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> tech.coner.trailer - parent + buildsrc-kotlin-parent 0.1.0-SNAPSHOT - ../pom.xml + ../buildsrc/buildsrc-kotlin-parent/pom.xml 4.0.0 diff --git a/datasource-motorsportreg/pom.xml b/datasource-motorsportreg/pom.xml index 0518e08b0..0292e37f4 100644 --- a/datasource-motorsportreg/pom.xml +++ b/datasource-motorsportreg/pom.xml @@ -3,9 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - parent + buildsrc-kotlin-parent tech.coner.trailer 0.1.0-SNAPSHOT + ../buildsrc/buildsrc-kotlin-parent/pom.xml 4.0.0 diff --git a/datasource-snoozle/pom.xml b/datasource-snoozle/pom.xml index 7692f51ba..e4966c200 100644 --- a/datasource-snoozle/pom.xml +++ b/datasource-snoozle/pom.xml @@ -3,10 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - parent + buildsrc-kotlin-parent tech.coner.trailer 0.1.0-SNAPSHOT - ../pom.xml + ../buildsrc/buildsrc-kotlin-parent/pom.xml 4.0.0 diff --git a/io-kodein-di-test/pom.xml b/io-kodein-di-test/pom.xml index ebc1c305d..312c5edcd 100644 --- a/io-kodein-di-test/pom.xml +++ b/io-kodein-di-test/pom.xml @@ -3,9 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - parent + buildsrc-kotlin-parent tech.coner.trailer 0.1.0-SNAPSHOT + ../buildsrc/buildsrc-kotlin-parent/pom.xml 4.0.0 diff --git a/io-kodein-di/pom.xml b/io-kodein-di/pom.xml index 887fa16f7..87d66b25f 100644 --- a/io-kodein-di/pom.xml +++ b/io-kodein-di/pom.xml @@ -3,9 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - parent + buildsrc-kotlin-parent tech.coner.trailer 0.1.0-SNAPSHOT + ../buildsrc/buildsrc-kotlin-parent/pom.xml 4.0.0 diff --git a/io-test/pom.xml b/io-test/pom.xml index 552a2d4bd..7c79c8b42 100644 --- a/io-test/pom.xml +++ b/io-test/pom.xml @@ -3,9 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - parent + buildsrc-kotlin-parent tech.coner.trailer 0.1.0-SNAPSHOT + ../buildsrc/buildsrc-kotlin-parent/pom.xml 4.0.0 diff --git a/io-testsupport/pom.xml b/io-testsupport/pom.xml index bd4c00fb9..6199df9bd 100644 --- a/io-testsupport/pom.xml +++ b/io-testsupport/pom.xml @@ -3,9 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - parent + buildsrc-kotlin-parent tech.coner.trailer 0.1.0-SNAPSHOT + ../buildsrc/buildsrc-kotlin-parent/pom.xml 4.0.0 diff --git a/io/pom.xml b/io/pom.xml index 6d447f27c..3fe395aac 100644 --- a/io/pom.xml +++ b/io/pom.xml @@ -3,10 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - parent tech.coner.trailer + buildsrc-kotlin-parent 0.1.0-SNAPSHOT - ../pom.xml + ../buildsrc/buildsrc-kotlin-parent/pom.xml 4.0.0 diff --git a/pom.xml b/pom.xml index 12162456b..17bee4b92 100644 --- a/pom.xml +++ b/pom.xml @@ -10,50 +10,23 @@ 0.1.0-SNAPSHOT - core - core-test - datasource-crispy-fish - datasource-crispy-fish-test - datasource-snoozle - api-client-motorsportreg - api-client-motorsportreg-test - datasource-motorsportreg - io - io-kodein-di - admin - io-test - presentation/presentation - presentation/presentation-text - presentation/presentation-all-kodein-di - presentation/presentation-json - io-kodein-di-test - io-testsupport - core-kodein-di - core-kodein-di-test - webapp-competition - testutil/assertk-ktor - presentation/presentation-all-testsupport-mockk - toolkit/konstraints - toolkit/presentation/presentation - toolkit/presentation/presentation-test - toolkit/presentation/presentation-testsupport - toolkit/samples/samples-common - toolkit/validation/validation - toolkit/validation/validation-testsupport - toolkit/util + buildsrc/buildsrc-kotlin-parent + toolkit/samples/dmvapp/dmvapp-gui + ${project.version} UTF-8 17 ${maven.compiler.source} VERBOSE + 3.7.1 3.12.1 3.3.1 3.2.3 3.6.0 1.2.2 - 1.9.22 + 2.0.0 2.0 true official @@ -69,6 +42,7 @@ 1.4.14 4.2.1 2.4.0 + 1.2.4 5.10.1 0.28.0 @@ -79,39 +53,11 @@ 1.0.0 - - - org.jetbrains.kotlin - kotlin-stdlib-jdk8 - - - org.jetbrains.kotlinx - kotlinx-coroutines-core - - - - org.jetbrains.kotlinx - kotlinx-coroutines-test-jvm - - - org.junit.jupiter - junit-jupiter - - - com.willowtreeapps.assertk - assertk-jvm - - - io.mockk - mockk-jvm - - - org.jetbrains.kotlin - kotlin-stdlib-jdk8 + kotlin-stdlib ${kotlin.version} @@ -209,6 +155,16 @@ mordant-jvm ${mordant.version} + + io.arrow-kt + arrow-core-jvm + ${arrow.version} + + + io.arrow-kt + arrow-fx-coroutines-jvm + ${arrow.version} + org.junit.jupiter @@ -274,26 +230,6 @@ - ${project.basedir}/src/main/kotlin - ${project.basedir}/src/test/kotlin - - - - org.jetbrains.kotlin - kotlin-maven-plugin - - - maven-surefire-plugin - - - maven-failsafe-plugin - - - org.codehaus.mojo - exec-maven-plugin - - - @@ -343,6 +279,11 @@ maven-resources-plugin ${maven-resources-plugin.version} + + org.apache.maven.plugins + maven-dependency-plugin + ${maven-dependency-plugin.version} + org.apache.maven.plugins maven-compiler-plugin diff --git a/presentation/presentation-all-kodein-di/pom.xml b/presentation/presentation-all-kodein-di/pom.xml index 82daec4d0..86f075999 100644 --- a/presentation/presentation-all-kodein-di/pom.xml +++ b/presentation/presentation-all-kodein-di/pom.xml @@ -3,10 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - parent + buildsrc-kotlin-parent tech.coner.trailer 0.1.0-SNAPSHOT - ../../pom.xml + ../../buildsrc/buildsrc-kotlin-parent/pom.xml 4.0.0 diff --git a/presentation/presentation-all-testsupport-mockk/pom.xml b/presentation/presentation-all-testsupport-mockk/pom.xml index 890bd23e8..7840672e9 100644 --- a/presentation/presentation-all-testsupport-mockk/pom.xml +++ b/presentation/presentation-all-testsupport-mockk/pom.xml @@ -5,9 +5,9 @@ 4.0.0 tech.coner.trailer - parent + buildsrc-kotlin-parent 0.1.0-SNAPSHOT - ../../pom.xml + ../../buildsrc/buildsrc-kotlin-parent/pom.xml presentation-all-testsupport-mockk diff --git a/presentation/presentation-json/pom.xml b/presentation/presentation-json/pom.xml index 5947e1a9d..58afb75b0 100644 --- a/presentation/presentation-json/pom.xml +++ b/presentation/presentation-json/pom.xml @@ -3,10 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - parent + buildsrc-kotlin-parent tech.coner.trailer 0.1.0-SNAPSHOT - ../../pom.xml + ../../buildsrc/buildsrc-kotlin-parent/pom.xml 4.0.0 diff --git a/presentation/presentation-text/pom.xml b/presentation/presentation-text/pom.xml index 0eb9938fd..7ab27caff 100644 --- a/presentation/presentation-text/pom.xml +++ b/presentation/presentation-text/pom.xml @@ -3,10 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - parent + buildsrc-kotlin-parent tech.coner.trailer 0.1.0-SNAPSHOT - ../../pom.xml + ../../buildsrc/buildsrc-kotlin-parent/pom.xml 4.0.0 diff --git a/presentation/presentation/pom.xml b/presentation/presentation/pom.xml index e967d4ba9..89306fab7 100644 --- a/presentation/presentation/pom.xml +++ b/presentation/presentation/pom.xml @@ -3,10 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - parent + buildsrc-kotlin-parent tech.coner.trailer 0.1.0-SNAPSHOT - ../../pom.xml + ../../buildsrc/buildsrc-kotlin-parent/pom.xml 4.0.0 diff --git a/render-html/pom.xml b/render-html/pom.xml index 31ec9fe1b..9282dbbf5 100644 --- a/render-html/pom.xml +++ b/render-html/pom.xml @@ -3,7 +3,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - parent + buildsrc-kotlin-parent tech.coner.trailer 0.1.0-SNAPSHOT diff --git a/testutil/assertk-arrowkt/pom.xml b/testutil/assertk-arrowkt/pom.xml new file mode 100644 index 000000000..c78b08379 --- /dev/null +++ b/testutil/assertk-arrowkt/pom.xml @@ -0,0 +1,26 @@ + + + 4.0.0 + + tech.coner.trailer + buildsrc-kotlin-parent + 0.1.0-SNAPSHOT + ../../buildsrc/buildsrc-kotlin-parent/pom.xml + + + assertk-arrowkt + + + + com.willowtreeapps.assertk + assertk-jvm + compile + + + io.arrow-kt + arrow-core-jvm + + + \ No newline at end of file diff --git a/testutil/assertk-arrowkt/src/main/kotlin/tech/coner/trailer/assertk/arrowkt/ArrowktAssertk.kt b/testutil/assertk-arrowkt/src/main/kotlin/tech/coner/trailer/assertk/arrowkt/ArrowktAssertk.kt new file mode 100644 index 000000000..cc93594e9 --- /dev/null +++ b/testutil/assertk-arrowkt/src/main/kotlin/tech/coner/trailer/assertk/arrowkt/ArrowktAssertk.kt @@ -0,0 +1,30 @@ +package tech.coner.trailer.assertk.arrowkt + +import arrow.core.Either +import arrow.core.getOrElse +import assertk.Assert +import assertk.assertions.support.expected + +/** + * Asserts the Either value is Either.Right. You can pass in an optional lambda to run additional assertions on the right value + * + * ``` + * val name = Either.Right("...") + * assertThat(name).isRight().hasLength(3) + * ``` + */ +fun Assert>.isRight(): Assert = transform { actual -> + actual.getOrElse { expected("to be right") } +} + +/** + * Asserts the Either value is Either.Left. You can pass in an optional lambda to run additional assertions on the left value + * + * ``` + * val name = Either.Left("...") + * assertThat(name).isLeft().hasLength(3) + * ``` + */ +fun Assert>.isLeft(): Assert = transform { actual -> + actual.swap().getOrElse { expected("to be left") } +} \ No newline at end of file diff --git a/testutil/assertk-ktor/pom.xml b/testutil/assertk-ktor/pom.xml index bfcefa303..4d17d351c 100644 --- a/testutil/assertk-ktor/pom.xml +++ b/testutil/assertk-ktor/pom.xml @@ -3,10 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - parent + buildsrc-kotlin-parent tech.coner.trailer 0.1.0-SNAPSHOT - ../../pom.xml + ../../buildsrc/buildsrc-kotlin-parent/pom.xml 4.0.0 diff --git a/toolkit/konstraints/pom.xml b/toolkit/konstraints/pom.xml index dfe701a17..4b77739c1 100644 --- a/toolkit/konstraints/pom.xml +++ b/toolkit/konstraints/pom.xml @@ -5,9 +5,9 @@ 4.0.0 tech.coner.trailer - parent + buildsrc-kotlin-parent 0.1.0-SNAPSHOT - ../../pom.xml + ../../buildsrc/buildsrc-kotlin-parent/pom.xml toolkit-konstraints diff --git a/toolkit/presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/data/service/FooService.kt b/toolkit/presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/data/service/FooService.kt deleted file mode 100644 index 7246d371c..000000000 --- a/toolkit/presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/data/service/FooService.kt +++ /dev/null @@ -1,11 +0,0 @@ -package tech.coner.trailer.toolkit.presentation.testsupport.fooapp.data.service - -import tech.coner.trailer.toolkit.presentation.testsupport.fooapp.domain.entity.Foo - -interface FooService { - - suspend fun create(create: Foo): Result - suspend fun findById(id: Foo.Id): Result - suspend fun update(update: Foo): Result - suspend fun deleteById(id: Foo.Id): Result -} \ No newline at end of file diff --git a/toolkit/presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/domain/constraint/FooConstraint.kt b/toolkit/presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/domain/constraint/FooConstraint.kt deleted file mode 100644 index a1f1868b8..000000000 --- a/toolkit/presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/domain/constraint/FooConstraint.kt +++ /dev/null @@ -1,46 +0,0 @@ -package tech.coner.trailer.toolkit.presentation.testsupport.fooapp.domain.constraint - -import tech.coner.trailer.toolkit.konstraints.CompositeConstraint -import tech.coner.trailer.toolkit.presentation.testsupport.fooapp.domain.entity.Foo - -class FooConstraint : CompositeConstraint() { - - val valueIsInRange = propertyConstraint( - property = Foo::id, - assessFn = { - when (it.id.value) { - in 0..4 -> true - else -> false - } - }, - violationMessageFn = { "ID value must be in 0 to 4" } - ) - - - val nameIsLettersOnly = propertyConstraint( - property = Foo::name, - assessFn = { foo -> foo.name.all { it.isLetter() } }, - violationMessageFn = { "Name must be only letters" } - ) - - val nameMustBeThreeCharacters = propertyConstraint( - property = Foo::name, - assessFn = { foo -> foo.name.length == 3 }, - violationMessageFn = { "Name must be three letters long" } - ) - - private val vowels = "aeiouy" - private val consonants = "bcdfghjklmnpqrstvwxz" - private val namesOtherThanFooPattern = Regex("[$consonants][$vowels][$consonants]") - - val namesOtherThanFooMustFollowPatternOfConsonantVowelConsonant = propertyConstraint( - property = Foo::name, - assessFn = { foo -> - when (foo.name) { - "foo" -> true - else -> namesOtherThanFooPattern.matches(foo.name) - } - }, - violationMessageFn = { "Names other than foo must start with a consonant, followed by a vowel, and end with a consonant" } - ) -} \ No newline at end of file diff --git a/toolkit/presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/domain/service/TestableFooService.kt b/toolkit/presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/domain/service/TestableFooService.kt deleted file mode 100644 index 32ad0fc2a..000000000 --- a/toolkit/presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/domain/service/TestableFooService.kt +++ /dev/null @@ -1,48 +0,0 @@ -package tech.coner.trailer.toolkit.presentation.testsupport.fooapp.domain.service - -import tech.coner.trailer.toolkit.konstraints.Constraint -import tech.coner.trailer.toolkit.presentation.testsupport.fooapp.domain.entity.FOO_ID_BAR -import tech.coner.trailer.toolkit.presentation.testsupport.fooapp.domain.entity.FOO_ID_BAT -import tech.coner.trailer.toolkit.presentation.testsupport.fooapp.domain.entity.FOO_ID_BAZ -import tech.coner.trailer.toolkit.presentation.testsupport.fooapp.domain.entity.FOO_ID_FOO -import tech.coner.trailer.toolkit.presentation.testsupport.fooapp.domain.entity.Foo -import tech.coner.trailer.toolkit.presentation.testsupport.fooapp.domain.exception.AlreadyExistsException -import tech.coner.trailer.toolkit.presentation.testsupport.fooapp.domain.exception.NotFoundException - -class TestableFooService(private val constraint: Constraint) : - tech.coner.trailer.toolkit.presentation.testsupport.fooapp.data.service.FooService { - - private val map: MutableMap = arrayOf( - FOO_ID_FOO to "foo", - FOO_ID_BAR to "bar", - FOO_ID_BAZ to "baz", - FOO_ID_BAT to "bat", - ) - .associate { (idValue, name) -> Foo.Id(idValue).let { it to Foo(it, name) } } - .toMutableMap() - - override suspend fun create(create: Foo): Result { - if (map.containsKey(create.id)) { - return Result.failure(AlreadyExistsException()) - } - return constraint(create) - .map { map[create.id] = create; create } - } - - override suspend fun findById(id: Foo.Id): Result { - return map[id]?.let { Result.success(it) } - ?: Result.failure(NotFoundException()) - } - - override suspend fun update(update: Foo): Result { - return findById(update.id) - .mapCatching { constraint(update).getOrThrow() } - .map { map[update.id] = update; update } - } - - override suspend fun deleteById(id: Foo.Id): Result { - return map.remove(id) - ?.let { Result.success(it) } - ?: Result.failure(NotFoundException()) - } -} diff --git a/toolkit/presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/presentation/adapter/FooAdapter.kt b/toolkit/presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/presentation/adapter/FooAdapter.kt deleted file mode 100644 index 601646546..000000000 --- a/toolkit/presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/presentation/adapter/FooAdapter.kt +++ /dev/null @@ -1,32 +0,0 @@ -package tech.coner.trailer.toolkit.presentation.testsupport.fooapp.presentation.adapter - -import tech.coner.trailer.toolkit.presentation.adapter.LoadableItemAdapter -import tech.coner.trailer.toolkit.presentation.testsupport.fooapp.domain.entity.Foo -import tech.coner.trailer.toolkit.presentation.testsupport.fooapp.presentation.model.FooItemModel - -class FooAdapter : LoadableItemAdapter< - Foo.Id, - Foo, - Unit, - FooItemModel - >() { - override val argumentToModelAdapter = null - override val itemToModelAdapter: (Foo) -> FooItemModel = { FooItemModel(it, this) } - override val modelToItemAdapter: (FooItemModel) -> Foo = { - Foo( - id = it.item.id, - name = it.name.lowercase() - ) - } - - val modelNameProperty: (Foo) -> String = { it.name.capitalizeFirstChar() } - val entityNameProperty: (String) -> String = { it.lowercase() } - - private fun String.capitalizeFirstChar(): String { // TODO: adapter - return when (length) { - 0 -> this - 1 -> uppercase() - else -> let { "${it[0].uppercaseChar()}${it.substring(1)}" } - } - } -} \ No newline at end of file diff --git a/toolkit/presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/presentation/model/FooItemModel.kt b/toolkit/presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/presentation/model/FooItemModel.kt deleted file mode 100644 index ed1aa7d76..000000000 --- a/toolkit/presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/presentation/model/FooItemModel.kt +++ /dev/null @@ -1,21 +0,0 @@ -package tech.coner.trailer.toolkit.presentation.testsupport.fooapp.presentation.model - -import kotlinx.coroutines.runBlocking -import tech.coner.trailer.toolkit.presentation.model.BaseItemModel -import tech.coner.trailer.toolkit.presentation.testsupport.fooapp.domain.constraint.FooConstraint -import tech.coner.trailer.toolkit.presentation.testsupport.fooapp.domain.entity.Foo -import tech.coner.trailer.toolkit.presentation.testsupport.fooapp.presentation.adapter.FooAdapter - -class FooItemModel( - override val initialItem: Foo, - private val adapter: FooAdapter, -) : BaseItemModel() { - override val constraints = - FooConstraint() - - var name: String - get() = adapter.modelNameProperty(pendingItem) - set(value) = runBlocking { mutatePendingItem { it.copy(name = adapter.entityNameProperty(value)) } } - -} - diff --git a/toolkit/presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/presentation/presenter/FooDetailPresenter.kt b/toolkit/presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/presentation/presenter/FooDetailPresenter.kt deleted file mode 100644 index 664a1376c..000000000 --- a/toolkit/presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/presentation/presenter/FooDetailPresenter.kt +++ /dev/null @@ -1,41 +0,0 @@ -package tech.coner.trailer.toolkit.presentation.testsupport.fooapp.presentation.presenter - -import kotlin.coroutines.CoroutineContext -import kotlin.time.Duration.Companion.seconds -import kotlinx.coroutines.delay -import tech.coner.trailer.toolkit.presentation.model.LoadableModel -import tech.coner.trailer.toolkit.presentation.presenter.LoadableItemPresenter -import tech.coner.trailer.toolkit.presentation.state.LoadableItemState -import tech.coner.trailer.toolkit.presentation.testsupport.fooapp.domain.entity.Foo -import tech.coner.trailer.toolkit.presentation.testsupport.fooapp.presentation.adapter.FooAdapter -import tech.coner.trailer.toolkit.presentation.testsupport.fooapp.presentation.model.FooItemModel - -class FooDetailPresenter( - override val argument: Foo.Id, - private val service: tech.coner.trailer.toolkit.presentation.testsupport.fooapp.data.service.FooService, - override val coroutineContext: CoroutineContext -) : LoadableItemPresenter< - Foo.Id, - Foo, - Unit, - FooItemModel - >() { - override val adapter = FooAdapter() - - override suspend fun performLoad(): Result { - return service.findById(argument) - .onSuccess { foo -> - // faking a partial load - update { - LoadableItemState( - LoadableModel.Loading( - partial = adapter.itemToModelAdapter( - foo.copy(name = "${foo.name[0]}") - ) - ) - ) - } - delay(1.seconds) - } - } -} \ No newline at end of file diff --git a/toolkit/presentation/presentation-test/src/test/kotlin/tech/coner/trailer/toolkit/presentation/presenter/FooDetailPresenterTest.kt b/toolkit/presentation/presentation-test/src/test/kotlin/tech/coner/trailer/toolkit/presentation/presenter/FooDetailPresenterTest.kt deleted file mode 100644 index 73e653c7b..000000000 --- a/toolkit/presentation/presentation-test/src/test/kotlin/tech/coner/trailer/toolkit/presentation/presenter/FooDetailPresenterTest.kt +++ /dev/null @@ -1,176 +0,0 @@ -package tech.coner.trailer.toolkit.presentation.presenter - -import app.cash.turbine.test -import assertk.all -import assertk.assertThat -import assertk.assertions.isEmpty -import assertk.assertions.isEqualTo -import assertk.assertions.isFalse -import assertk.assertions.isInstanceOf -import assertk.assertions.isNotNull -import assertk.assertions.isNull -import assertk.assertions.isTrue -import assertk.assertions.length -import kotlinx.coroutines.CoroutineName -import kotlinx.coroutines.Job -import kotlinx.coroutines.launch -import kotlinx.coroutines.test.TestScope -import kotlinx.coroutines.test.runTest -import org.junit.jupiter.api.Test -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.ValueSource -import tech.coner.trailer.toolkit.presentation.model.cause -import tech.coner.trailer.toolkit.presentation.model.isDirty -import tech.coner.trailer.toolkit.presentation.model.isEmpty -import tech.coner.trailer.toolkit.presentation.model.isLoadFailed -import tech.coner.trailer.toolkit.presentation.model.isLoaded -import tech.coner.trailer.toolkit.presentation.model.isLoading -import tech.coner.trailer.toolkit.presentation.model.isValid -import tech.coner.trailer.toolkit.presentation.model.item -import tech.coner.trailer.toolkit.presentation.model.partial -import tech.coner.trailer.toolkit.presentation.model.violations -import tech.coner.trailer.toolkit.presentation.state.loadable -import tech.coner.trailer.toolkit.presentation.testsupport.fooapp.domain.constraint.FooConstraint -import tech.coner.trailer.toolkit.presentation.testsupport.fooapp.domain.entity.FOO_ID_FOO -import tech.coner.trailer.toolkit.presentation.testsupport.fooapp.domain.entity.Foo -import tech.coner.trailer.toolkit.presentation.testsupport.fooapp.domain.entity.name -import tech.coner.trailer.toolkit.presentation.testsupport.fooapp.domain.exception.NotFoundException -import tech.coner.trailer.toolkit.presentation.testsupport.fooapp.domain.service.TestableFooService -import tech.coner.trailer.toolkit.presentation.testsupport.fooapp.presentation.model.name -import tech.coner.trailer.toolkit.presentation.testsupport.fooapp.presentation.presenter.FooDetailPresenter - -class FooDetailPresenterTest { - - @Test - fun itsModelFlowShouldBeAdaptedFromInitialState() = runTest { - val id = Foo.Id(FOO_ID_FOO) - val presenter = createPresenter(id) - - presenter.stateFlow.test { - assertThat(expectMostRecentItem()) - .loadable() - .isEmpty() - } - } - - @Test - fun itsModelFlowShouldEmitWhenLoadingAndLoaded() = runTest { - val id = Foo.Id(FOO_ID_FOO) - val presenter = createPresenter(id) - - presenter.stateFlow.test { - skipItems(1) - - presenter.load() - - assertThat(awaitItem()) - .loadable() - .isLoading() - .partial() - .isNull() - assertThat(awaitItem()) - .loadable() - .isLoading() - .partial() - .isNotNull() - .item() - .name() - .length() - .isEqualTo(1) - assertThat(awaitItem()) - .loadable() - .isLoaded() - .item() - .item() - .name() - .isEqualTo("foo") - } - } - - @Test - fun itsModelFlowShouldEmitWhenLoadingAndLoadFailed() = runTest { - val id = Foo.Id(Int.MAX_VALUE) - val presenter = createPresenter(id) - - presenter.stateFlow.test { - skipItems(1) - - presenter.load() - - assertThat(awaitItem()) - .loadable() - .isLoading() - assertThat(awaitItem()) - .loadable() - .isLoadFailed() - .cause() - .isNotNull() - .isInstanceOf() - } - } - - @Test - fun whenItsModelNameChangedValidItsItemModelShouldBeValid() = runTest { - val id = Foo.Id(FOO_ID_FOO) - val presenter = createPresenter(id) - launch { presenter.load() } - val model = presenter.awaitModelLoadedOrThrow() - - model.item.name = "bax" - model.item.validate() - - assertThat(model.item).all { - name().isEqualTo("Bax") - isValid().isTrue() - isDirty().isTrue() - } - } - - @Test - fun whenItsModelNameChangedInvalidItsItemModelShouldBeInvalid() = runTest { - val id = Foo.Id(FOO_ID_FOO) - val presenter = createPresenter(id) - launch { presenter.load() } - val model = presenter.awaitModelLoadedOrThrow() - - model.item.name = "boo" - model.item.validate() - - assertThat(model.item).all { - name().isEqualTo("Boo") - isValid().isFalse() - isDirty().isTrue() - } - } - - @ParameterizedTest - @ValueSource(strings = ["Bar", "Baz", "Bat", "Cat", "Dat", "Far", "Ber", "Fir", "Nor", "Dur", "Xyr"]) - fun whenItsModelNameChangedValidItsItemModelShouldValidateValid(newName: String) = runTest { - val id = Foo.Id(FOO_ID_FOO) - val presenter = createPresenter(id) - launch { presenter.load() } - val model = presenter.awaitModelLoadedOrThrow() - - with (model.item) { - name = newName - validate() - } - - assertThat(model.item).all { - name().isEqualTo(newName) - isValid().isTrue() - violations().isEmpty() - isDirty().isTrue() - } - } -} - -private fun TestScope.createPresenter(argument: Foo.Id): FooDetailPresenter { - return FooDetailPresenter( - argument = argument, - service = TestableFooService( - constraint = FooConstraint() - ), - coroutineContext = coroutineContext + Job() + CoroutineName("FooDetailPresenter") - ) -} diff --git a/toolkit/presentation/presentation-test/src/test/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/presentation/model/FooModelAssertk.kt b/toolkit/presentation/presentation-test/src/test/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/presentation/model/FooModelAssertk.kt deleted file mode 100644 index 45f4d110f..000000000 --- a/toolkit/presentation/presentation-test/src/test/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/presentation/model/FooModelAssertk.kt +++ /dev/null @@ -1,6 +0,0 @@ -package tech.coner.trailer.toolkit.presentation.testsupport.fooapp.presentation.model - -import assertk.Assert -import assertk.assertions.prop - -fun Assert.name() = prop(FooItemModel::name) \ No newline at end of file diff --git a/toolkit/presentation/presentation-testsupport/pom.xml b/toolkit/presentation/presentation-testsupport/pom.xml index 2419cb405..90670303e 100644 --- a/toolkit/presentation/presentation-testsupport/pom.xml +++ b/toolkit/presentation/presentation-testsupport/pom.xml @@ -5,9 +5,9 @@ 4.0.0 tech.coner.trailer - parent + buildsrc-kotlin-parent 0.1.0-SNAPSHOT - ../../../pom.xml + ../../../buildsrc/buildsrc-kotlin-parent/pom.xml toolkit-presentation-testsupport diff --git a/toolkit/presentation/presentation-testsupport/src/main/kotlin/tech/coner/trailer/toolkit/presentation/model/ItemModelAssertk.kt b/toolkit/presentation/presentation-testsupport/src/main/kotlin/tech/coner/trailer/toolkit/presentation/model/ItemModelAssertk.kt index 50bc6549f..a7d2ecde2 100644 --- a/toolkit/presentation/presentation-testsupport/src/main/kotlin/tech/coner/trailer/toolkit/presentation/model/ItemModelAssertk.kt +++ b/toolkit/presentation/presentation-testsupport/src/main/kotlin/tech/coner/trailer/toolkit/presentation/model/ItemModelAssertk.kt @@ -2,13 +2,14 @@ package tech.coner.trailer.toolkit.presentation.model import assertk.Assert import assertk.assertions.prop +import tech.coner.trailer.toolkit.validation.Feedback -fun Assert>.item() = prop(ItemModel::item) +fun > Assert>.item() = prop(ItemModel::item) -fun Assert>.pendingItem() = prop(ItemModel::pendingItem) +fun > Assert>.pendingItem() = prop(ItemModel::pendingItem) -fun Assert>.violations() = prop(ItemModel::pendingItemValidation) +fun > Assert>.pendingItemValidation() = prop(ItemModel::pendingItemValidation) -fun Assert>.isValid() = prop(ItemModel::isPendingItemValid) +fun > Assert>.isValid() = prop(ItemModel::isPendingItemValid) -fun Assert>.isDirty() = prop(ItemModel::isPendingItemDirty) \ No newline at end of file +fun > Assert>.isDirty() = prop(ItemModel::isPendingItemDirty) \ No newline at end of file diff --git a/toolkit/presentation/presentation-testsupport/src/main/kotlin/tech/coner/trailer/toolkit/presentation/model/LoadableModelAssertk.kt b/toolkit/presentation/presentation-testsupport/src/main/kotlin/tech/coner/trailer/toolkit/presentation/model/LoadableModelAssertk.kt index 9642f6798..9e499872b 100644 --- a/toolkit/presentation/presentation-testsupport/src/main/kotlin/tech/coner/trailer/toolkit/presentation/model/LoadableModelAssertk.kt +++ b/toolkit/presentation/presentation-testsupport/src/main/kotlin/tech/coner/trailer/toolkit/presentation/model/LoadableModelAssertk.kt @@ -3,14 +3,14 @@ package tech.coner.trailer.toolkit.presentation.model import assertk.Assert import assertk.assertions.isInstanceOf import assertk.assertions.prop +import tech.coner.trailer.toolkit.validation.Feedback -fun > Assert>.isEmpty() = isInstanceOf>() +fun , FEEDBACK : Feedback> Assert>.isEmpty() = isInstanceOf>() -fun > Assert>.isLoading() = isInstanceOf>() -fun > Assert>.partial() = prop(LoadableModel.Loading::partial) +fun , FEEDBACK : Feedback> Assert>.isLoading() = isInstanceOf>() +fun , FEEDBACK : Feedback> Assert>.partial() = prop(Loadable.Loading::partial) -fun > Assert>.isLoaded() = isInstanceOf>() -fun > Assert>.item() = prop(LoadableModel.Loaded::item) +fun , FEEDBACK : Feedback> Assert>.isLoaded() = isInstanceOf>() +fun , FEEDBACK : Feedback> Assert>.either() = prop(Loadable.Loaded::either) -fun > Assert>.isLoadFailed() = isInstanceOf>() -fun > Assert>.cause() = prop(LoadableModel.LoadFailed::cause) +// TODO: convenient API for asserting loaded either success or failure diff --git a/toolkit/presentation/presentation-testsupport/src/main/kotlin/tech/coner/trailer/toolkit/presentation/state/ItemModelStateAssertk.kt b/toolkit/presentation/presentation-testsupport/src/main/kotlin/tech/coner/trailer/toolkit/presentation/state/ItemModelStateAssertk.kt new file mode 100644 index 000000000..5ef47079c --- /dev/null +++ b/toolkit/presentation/presentation-testsupport/src/main/kotlin/tech/coner/trailer/toolkit/presentation/state/ItemModelStateAssertk.kt @@ -0,0 +1,7 @@ +package tech.coner.trailer.toolkit.presentation.state + +import assertk.Assert +import assertk.assertions.prop +import tech.coner.trailer.toolkit.validation.Feedback + +fun > Assert>.itemModel() = prop(ItemModelState::itemModel) \ No newline at end of file diff --git a/toolkit/presentation/presentation-testsupport/src/main/kotlin/tech/coner/trailer/toolkit/presentation/state/LoadableItemStateAssertk.kt b/toolkit/presentation/presentation-testsupport/src/main/kotlin/tech/coner/trailer/toolkit/presentation/state/LoadableItemStateAssertk.kt index 52ff64963..528e2a6ff 100644 --- a/toolkit/presentation/presentation-testsupport/src/main/kotlin/tech/coner/trailer/toolkit/presentation/state/LoadableItemStateAssertk.kt +++ b/toolkit/presentation/presentation-testsupport/src/main/kotlin/tech/coner/trailer/toolkit/presentation/state/LoadableItemStateAssertk.kt @@ -3,5 +3,11 @@ package tech.coner.trailer.toolkit.presentation.state import assertk.Assert import assertk.assertions.prop import tech.coner.trailer.toolkit.presentation.model.ItemModel +import tech.coner.trailer.toolkit.validation.Feedback -fun > Assert>.loadable() = prop(LoadableItemState::loadable) \ No newline at end of file +fun , FAILURE, ITEM, ITEM_MODEL : ItemModel, FEEDBACK : Feedback> + Assert.loadable() = prop(LoadableState::loadable) + +fun , FAILURE, ITEM, ITEM_MODEL : ItemModel, FEEDBACK : Feedback, PROPERTY> + Assert>.value() + = prop(MutableLoadedPropertyDelegate::value) \ No newline at end of file diff --git a/toolkit/presentation/presentation-testsupport/src/main/kotlin/tech/coner/trailer/toolkit/presentation/state/StatefulPresenterAssertk.kt b/toolkit/presentation/presentation-testsupport/src/main/kotlin/tech/coner/trailer/toolkit/presentation/state/StatefulPresenterAssertk.kt new file mode 100644 index 000000000..9aa96a22a --- /dev/null +++ b/toolkit/presentation/presentation-testsupport/src/main/kotlin/tech/coner/trailer/toolkit/presentation/state/StatefulPresenterAssertk.kt @@ -0,0 +1,7 @@ +package tech.coner.trailer.toolkit.presentation.state + +import assertk.Assert +import assertk.assertions.prop +import tech.coner.trailer.toolkit.presentation.presenter.StatefulPresenter + +fun Assert>.state() = prop(StatefulPresenter::state) \ No newline at end of file diff --git a/toolkit/presentation/presentation-testsupport/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/LoadableItemPresenterAssertk.kt b/toolkit/presentation/presentation-testsupport/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/LoadableItemPresenterAssertk.kt deleted file mode 100644 index 9dd5acf0f..000000000 --- a/toolkit/presentation/presentation-testsupport/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/LoadableItemPresenterAssertk.kt +++ /dev/null @@ -1,2 +0,0 @@ -package tech.coner.trailer.toolkit.presentation.testsupport - diff --git a/toolkit/presentation/presentation/pom.xml b/toolkit/presentation/presentation/pom.xml index 6c412d6d5..b845a5201 100644 --- a/toolkit/presentation/presentation/pom.xml +++ b/toolkit/presentation/presentation/pom.xml @@ -5,15 +5,20 @@ 4.0.0 tech.coner.trailer - parent + buildsrc-kotlin-parent 0.1.0-SNAPSHOT - ../../../pom.xml + ../../../buildsrc/buildsrc-kotlin-parent/pom.xml toolkit-presentation + + tech.coner.trailer + toolkit + 0.1.0-SNAPSHOT + tech.coner.trailer toolkit-validation diff --git a/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/adapter/EntityModelAdapter.kt b/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/adapter/EntityModelAdapter.kt new file mode 100644 index 000000000..296c650f6 --- /dev/null +++ b/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/adapter/EntityModelAdapter.kt @@ -0,0 +1,8 @@ +package tech.coner.trailer.toolkit.presentation.adapter + +abstract class EntityModelAdapter { + + abstract val entityToModelAdapter: (ITEM) -> MODEL + abstract val modelToEntityAdapter: (MODEL) -> ITEM +} + diff --git a/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/adapter/LoadableItemAdapter.kt b/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/adapter/LoadableItemAdapter.kt deleted file mode 100644 index fb77dc83f..000000000 --- a/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/adapter/LoadableItemAdapter.kt +++ /dev/null @@ -1,12 +0,0 @@ -package tech.coner.trailer.toolkit.presentation.adapter - -import tech.coner.trailer.toolkit.presentation.model.ItemModel -import tech.coner.trailer.toolkit.validation.Feedback - -abstract class LoadableItemAdapter - where ITEM_MODEL : ItemModel { - - abstract val itemToModelAdapter: (ITEM) -> ITEM_MODEL - abstract val modelToItemAdapter: (ITEM_MODEL) -> ITEM -} - diff --git a/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/model/BaseItemModel.kt b/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/model/BaseItemModel.kt index 8f011ba30..d3c072293 100644 --- a/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/model/BaseItemModel.kt +++ b/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/model/BaseItemModel.kt @@ -1,15 +1,22 @@ package tech.coner.trailer.toolkit.presentation.model +import arrow.core.Either +import arrow.core.raise.either +import arrow.core.raise.ensure +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.update import tech.coner.trailer.toolkit.validation.Feedback -import tech.coner.trailer.toolkit.validation.ValidationResult +import tech.coner.trailer.toolkit.validation.ValidationOutcome import tech.coner.trailer.toolkit.validation.Validator abstract class BaseItemModel : ItemModel - where VALIDATOR_FEEDBACK : Feedback { + where VALIDATOR_FEEDBACK : Feedback { abstract val validator: Validator abstract val validatorContext: VALIDATOR_CONTEXT @@ -24,43 +31,70 @@ abstract class BaseItemModel final override val pendingItemFlow by lazy { _pendingItemFlow.asStateFlow() } final override var pendingItem: ITEM get() = pendingItemFlow.value - set(value) = mutatePendingItem { value } + set(value) = updatePendingItem { value } private val _pendingItemValidationFlow by lazy { - MutableStateFlow>( - ValidationResult(emptyMap()) - ) + MutableStateFlow>(ValidationOutcome(emptyList())) + } + final override val pendingItemValidationFlow: StateFlow> by lazy { + _pendingItemValidationFlow.asStateFlow() } - final override val pendingItemValidationFlow by lazy { _pendingItemValidationFlow.asStateFlow() } final override val pendingItemValidation get() = _pendingItemValidationFlow.value - final override fun mutatePendingItem(forceValidate: Boolean?, mutatePendingItemFn: (ITEM) -> ITEM) { - _pendingItemFlow.update { pending -> mutatePendingItemFn(pending) } - if (forceValidate == true) { + final override fun updatePendingItem(forceValidate: Boolean?, updateFn: (ITEM) -> ITEM) { + val pendingItemHadFeedback = _pendingItemValidationFlow.value.feedback.isNotEmpty() + _pendingItemFlow.update { pending -> + updateFn(pending) + } + if (forceValidate == true || pendingItemHadFeedback) { validate() } } final override val isPendingItemValid get() = _pendingItemValidationFlow.value.isValid + final override val isPendingItemValidFlow by lazy { + _pendingItemValidationFlow.map { it.isValid } + } final override val isPendingItemDirty get() = item != pendingItem + final override val isPendingItemDirtyFlow: Flow by lazy { + pendingItemFlow + .map { item != it } + } - final override fun validate(): ValidationResult { + override val canReset: Boolean get() = pendingItem != item || _pendingItemValidationFlow.value.feedback.isNotEmpty() + override val canResetFlow: Flow by lazy { + combine( + _pendingItemFlow, + _pendingItemValidationFlow, + ) { pendingItem, pendingItemValidation -> + pendingItem != item || pendingItemValidation.feedback.isNotEmpty() + } + } + + final override fun validate(): ValidationOutcome { return validator(validatorContext, pendingItem) .also { _pendingItemValidationFlow.value = it } } - override fun commit(requireValid: Boolean): CommitOutcome { + + + override fun commit(requireValid: Boolean): Either, ITEM> = either { val validationResult = validate() if (requireValid) { - if (!validationResult.isValid) { - return CommitOutcome.Failure(pendingItem, validationResult) + ensure(validationResult.isValid) { + validationResult } } - return pendingItem + pendingItem .also { _itemFlow.value = it } - .let { CommitOutcome.Success(it, validationResult) } } -} \ No newline at end of file + + override fun reset() { + _itemFlow.value = initialItem + _pendingItemFlow.value = initialItem + _pendingItemValidationFlow.value = ValidationOutcome(emptyList()) + } +} diff --git a/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/model/CommitOutcome.kt b/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/model/CommitOutcome.kt deleted file mode 100644 index 3d86761b4..000000000 --- a/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/model/CommitOutcome.kt +++ /dev/null @@ -1,30 +0,0 @@ -package tech.coner.trailer.toolkit.presentation.model - -import tech.coner.trailer.toolkit.validation.Feedback -import tech.coner.trailer.toolkit.validation.ValidationResult - -sealed class CommitOutcome { - - abstract val item: ITEM - abstract val feedback: ValidationResult? - - data class Success( - override val item: ITEM, - override val feedback: ValidationResult? - ) : CommitOutcome() - - data class Failure( - override val item: ITEM, - override val feedback: ValidationResult - ) : CommitOutcome() - - fun onSuccess(fn: (Success) -> Unit): CommitOutcome { - if (this is Success) fn(this) - return this - } - - fun onFailure(fn: (Failure) -> Unit): CommitOutcome { - if (this is Failure) fn(this) - return this - } -} \ No newline at end of file diff --git a/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/model/ItemModel.kt b/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/model/ItemModel.kt index a3b75ec46..4673fec38 100644 --- a/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/model/ItemModel.kt +++ b/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/model/ItemModel.kt @@ -1,27 +1,35 @@ package tech.coner.trailer.toolkit.presentation.model +import arrow.core.Either import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow import tech.coner.trailer.toolkit.validation.Feedback -import tech.coner.trailer.toolkit.validation.ValidationResult +import tech.coner.trailer.toolkit.validation.ValidationOutcome -interface ItemModel : Model { - val itemFlow: StateFlow +interface ItemModel> : Model { val item: ITEM + val itemFlow: StateFlow - val pendingItemFlow: StateFlow var pendingItem: ITEM + val pendingItemFlow: StateFlow val isPendingItemDirty: Boolean + val isPendingItemDirtyFlow: Flow - val pendingItemValidationFlow: Flow> - val pendingItemValidation: ValidationResult + val pendingItemValidation: ValidationOutcome + val pendingItemValidationFlow: StateFlow> val isPendingItemValid: Boolean + val isPendingItemValidFlow: Flow + + val canReset: Boolean + val canResetFlow: Flow + + fun updatePendingItem(forceValidate: Boolean? = null, updateFn: (ITEM) -> ITEM) - fun mutatePendingItem(forceValidate: Boolean? = null, mutatePendingItemFn: (ITEM) -> ITEM) + fun validate(): ValidationOutcome - fun validate(): ValidationResult + fun commit(requireValid: Boolean = true): Either, ITEM> - fun commit(requireValid: Boolean = true): CommitOutcome + fun reset() } \ No newline at end of file diff --git a/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/model/Loadable.kt b/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/model/Loadable.kt new file mode 100644 index 000000000..6d666a7eb --- /dev/null +++ b/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/model/Loadable.kt @@ -0,0 +1,73 @@ +package tech.coner.trailer.toolkit.presentation.model + +import arrow.core.Either +import tech.coner.trailer.toolkit.validation.Feedback + +sealed interface Loadable, FEEDBACK : Feedback> + : Model { + + /** + * Initial model corresponding to the presenter having initial state, + * prior to starting to load anything, or if it was fully reset. + */ + class Empty, FEEDBACK : Feedback> + : Loadable { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + return true + } + + override fun hashCode(): Int { + return javaClass.hashCode() + } + } + + /** + * Model indicates the item is loading. + * + * @property partial Partial model representing incomplete loading + * state. For long or complex load operations, use to convey details + * of loading in progress. Adapters may optionally specify this value. + * It may be helpful to implement the partial model with a different + * type than the loaded item. + */ + data class Loading, FEEDBACK : Feedback>( + val partial: ITEM_MODEL? = null + ) : Loadable + + /** + * Indicates a load operation completed, either in failure or success. + */ + data class Loaded, FEEDBACK : Feedback>( + val either: Either + ) + : Loadable + + data class FailedExceptionally, FEEDBACK : Feedback>( + val throwable: Throwable + ) + : Loadable +} + +inline fun , FEEDBACK : Feedback> Loadable.letLoadedSuccess( + block: (ITEM_MODEL) -> R +): R? { + return when (this) { + is Loadable.Loaded -> either.getOrNull()?.let(block) + is Loadable.Empty, + is Loadable.Loading, + is Loadable.FailedExceptionally -> null + } +} + +inline fun , FEEDBACK : Feedback> Loadable.whenLoadedSuccess( + block: (ITEM_MODEL) -> Unit +) { + when (this) { + is Loadable.Loaded -> either.getOrNull()?.also(block) + is Loadable.Empty, + is Loadable.Loading, + is Loadable.FailedExceptionally -> { /* no-op */ } + } +} \ No newline at end of file diff --git a/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/model/LoadableModel.kt b/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/model/LoadableModel.kt deleted file mode 100644 index 2262b47e2..000000000 --- a/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/model/LoadableModel.kt +++ /dev/null @@ -1,55 +0,0 @@ -package tech.coner.trailer.toolkit.presentation.model - -import tech.coner.trailer.toolkit.validation.Feedback - -sealed class LoadableModel, FEEDBACK : Feedback> - : Model { - - /** - * Initial model corresponding to the presenter having initial state, - * prior to starting to load anything, or if it was fully reset. - */ - class Empty, FEEDBACK : Feedback> : LoadableModel() { - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (javaClass != other?.javaClass) return false - return true - } - - override fun hashCode(): Int { - return javaClass.hashCode() - } - } - - /** - * Model indicates the item is loading. - * - * @property partial Partial model representing incomplete loading - * state. For long or complex load operations, use to convey details - * of loading in progress. Adapters may optionally specify this value. - * It may be helpful to implement the partial model with a different - * type than the loaded item. - */ - data class Loading, FEEDBACK : Feedback>( - val partial: ITEM_MODEL? = null - ) : LoadableModel() - - /** - * Model indicates the item has loaded. - * - * @property item the item resulting from the load operation. - */ - data class Loaded, FEEDBACK : Feedback>( - val item: ITEM_MODEL - ) : LoadableModel() - - /** - * Model indicates the load operation failed. - * - * @property cause the cause of the failure, if known - */ - data class LoadFailed, FEEDBACK : Feedback>( - val cause: Throwable - ) : LoadableModel() - -} \ No newline at end of file diff --git a/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/presenter/ItemModelPresenter.kt b/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/presenter/ItemModelPresenter.kt new file mode 100644 index 000000000..222d6cd0c --- /dev/null +++ b/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/presenter/ItemModelPresenter.kt @@ -0,0 +1,10 @@ +package tech.coner.trailer.toolkit.presentation.presenter + +interface ItemModelPresenter { + + suspend fun reset() + + suspend fun commit() + + suspend fun validate() +} \ No newline at end of file diff --git a/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/presenter/LoadableItemPresenter.kt b/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/presenter/LoadableItemPresenter.kt deleted file mode 100644 index 0afe3cec3..000000000 --- a/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/presenter/LoadableItemPresenter.kt +++ /dev/null @@ -1,54 +0,0 @@ -package tech.coner.trailer.toolkit.presentation.presenter - -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.flow.map -import tech.coner.trailer.toolkit.presentation.adapter.LoadableItemAdapter -import tech.coner.trailer.toolkit.presentation.model.ItemModel -import tech.coner.trailer.toolkit.presentation.model.LoadableModel -import tech.coner.trailer.toolkit.presentation.model.Model -import tech.coner.trailer.toolkit.presentation.state.LoadableItemState -import tech.coner.trailer.toolkit.validation.Feedback - -abstract class LoadableItemPresenter( - override val initialState: LoadableItemState = LoadableItemState(LoadableModel.Empty()) -) - : SecondDraftPresenter< - LoadableItemState - >(), CoroutineScope - where ITEM_MODEL : ItemModel { - - protected abstract val adapter: LoadableItemAdapter - - suspend fun load() { - update { old -> old.copy(LoadableModel.Loading()) } - performLoad() - .onSuccess { loaded -> update { old -> old.copy(LoadableModel.Loaded(adapter.itemToModelAdapter(loaded))) } } - .onFailure { failed -> update { old -> old.copy(LoadableModel.LoadFailed(failed)) } } - } - - protected abstract suspend fun performLoad(): Result - - suspend fun awaitModelLoadedOrFailed(): LoadableModel { - return stateFlow - .map { it.loadable } - .first { - when (it) { - is LoadableModel.Loaded, is LoadableModel.LoadFailed -> true - else -> false - } - } - } - - suspend fun awaitModelLoadedOrThrow(): LoadableModel.Loaded { - return stateFlow - .map { it.loadable } - .first { - when (it) { - is LoadableModel.Loaded -> true - is LoadableModel.LoadFailed -> throw it.cause - else -> false - } - } as LoadableModel.Loaded - } -} \ No newline at end of file diff --git a/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/presenter/LoadablePresenter.kt b/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/presenter/LoadablePresenter.kt new file mode 100644 index 000000000..46550e701 --- /dev/null +++ b/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/presenter/LoadablePresenter.kt @@ -0,0 +1,9 @@ +package tech.coner.trailer.toolkit.presentation.presenter + +import arrow.core.Either +import kotlinx.coroutines.Deferred + +interface LoadablePresenter { + + suspend fun load(): Deferred>> +} \ No newline at end of file diff --git a/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/presenter/PresenterCoroutineScope.kt b/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/presenter/PresenterCoroutineScope.kt index 18107f767..6853ff59b 100644 --- a/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/presenter/PresenterCoroutineScope.kt +++ b/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/presenter/PresenterCoroutineScope.kt @@ -1,5 +1,9 @@ package tech.coner.trailer.toolkit.presentation.presenter import kotlinx.coroutines.CoroutineScope +import kotlin.coroutines.CoroutineContext -class PresenterCoroutineScope(coroutineScope: CoroutineScope) : CoroutineScope by coroutineScope +class PresenterCoroutineScope(coroutineScope: CoroutineScope) : CoroutineScope by coroutineScope { + + constructor(coroutineContext: CoroutineContext) : this(CoroutineScope(coroutineContext)) +} diff --git a/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/presenter/SecondDraftPresenter.kt b/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/presenter/SecondDraftPresenter.kt deleted file mode 100644 index f161a3a88..000000000 --- a/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/presenter/SecondDraftPresenter.kt +++ /dev/null @@ -1,39 +0,0 @@ -package tech.coner.trailer.toolkit.presentation.presenter - -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.update -import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.sync.withLock -import tech.coner.trailer.toolkit.presentation.model.Model -import tech.coner.trailer.toolkit.presentation.state.State - -abstract class SecondDraftPresenter - where STATE : State { - - abstract val initialState: STATE - private val _stateMutex = Mutex() - private val _stateFlow: MutableStateFlow by lazy { MutableStateFlow(initialState) } - val stateFlow: StateFlow by lazy { _stateFlow.asStateFlow() } - val state: STATE - get() = runBlocking { - _stateMutex.withLock { - _stateFlow.value - } - } - - protected suspend fun update(reduceFn: (old: STATE) -> STATE) { - _stateMutex.withLock { - _stateFlow.update(reduceFn) - } - } - - interface WithArgument { - - val argument: ARGUMENT - val argumentModel: ARGUMENT_MODEL - - } -} \ No newline at end of file diff --git a/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/presenter/StatefulPresenter.kt b/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/presenter/StatefulPresenter.kt new file mode 100644 index 000000000..93f7420f7 --- /dev/null +++ b/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/presenter/StatefulPresenter.kt @@ -0,0 +1,9 @@ +package tech.coner.trailer.toolkit.presentation.presenter + +import kotlinx.coroutines.flow.StateFlow + +interface StatefulPresenter { + + val state: S + val stateFlow: StateFlow +} \ No newline at end of file diff --git a/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/state/ItemModelState.kt b/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/state/ItemModelState.kt new file mode 100644 index 000000000..ba9966cd6 --- /dev/null +++ b/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/state/ItemModelState.kt @@ -0,0 +1,52 @@ +package tech.coner.trailer.toolkit.presentation.state + +import kotlin.reflect.KProperty1 +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.map +import tech.coner.trailer.toolkit.presentation.model.ItemModel +import tech.coner.trailer.toolkit.validation.Feedback +import tech.coner.trailer.toolkit.validation.ValidationOutcome + +interface ItemModelState> : State { + val itemModel: ItemModel +} + +class MutableItemModelPropertyDelegate +, ITEM, FEEDBACK : Feedback, PROPERTY>( + private val stateContainer: StateContainer, + private val getFn: ITEM.() -> PROPERTY, + private val updateFn: ITEM.(PROPERTY) -> ITEM, + private val property: KProperty1 +) { + var value: PROPERTY + get() = stateContainer.state.itemModel.pendingItem.let(getFn) + set(value) { + stateContainer.state.itemModel.updatePendingItem { updateFn(it, value) } + } + val valueFlow: Flow = stateContainer.stateFlow + .flatMapLatest { it.itemModel.pendingItemFlow } + .map(getFn) + + val feedback: List + get() = stateContainer.state.itemModel.pendingItemValidation.feedbackByProperty[property] + ?: emptyList() + val feedbackFlow: Flow> = stateContainer.stateFlow + .flatMapLatest { + flow { + emit(ValidationOutcome(emptyList())) + it.itemModel.pendingItemValidationFlow.collect(this) + } + } + .map { it.feedbackByProperty[property] ?: emptyList() } +} + +fun , ITEM, FEEDBACK : Feedback, PROPERTY> + StateContainer.mutableItemModelProperty( + getFn: ITEM.() -> PROPERTY, + updateFn: ITEM.(PROPERTY) -> ITEM, + property: KProperty1 +): MutableItemModelPropertyDelegate { + return MutableItemModelPropertyDelegate(this, getFn, updateFn, property) +} diff --git a/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/state/LoadableItemState.kt b/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/state/LoadableItemState.kt deleted file mode 100644 index f9a9b8b81..000000000 --- a/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/state/LoadableItemState.kt +++ /dev/null @@ -1,9 +0,0 @@ -package tech.coner.trailer.toolkit.presentation.state - -import tech.coner.trailer.toolkit.presentation.model.ItemModel -import tech.coner.trailer.toolkit.presentation.model.LoadableModel -import tech.coner.trailer.toolkit.validation.Feedback - -data class LoadableItemState, FEEDBACK : Feedback>( - val loadable: LoadableModel -) : State diff --git a/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/state/LoadableState.kt b/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/state/LoadableState.kt new file mode 100644 index 000000000..050e370b1 --- /dev/null +++ b/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/state/LoadableState.kt @@ -0,0 +1,56 @@ +package tech.coner.trailer.toolkit.presentation.state + +import kotlinx.coroutines.flow.* +import tech.coner.trailer.toolkit.presentation.model.ItemModel +import tech.coner.trailer.toolkit.presentation.model.Loadable +import tech.coner.trailer.toolkit.presentation.model.letLoadedSuccess +import tech.coner.trailer.toolkit.presentation.model.whenLoadedSuccess +import tech.coner.trailer.toolkit.validation.Feedback +import kotlin.reflect.KProperty1 + +interface LoadableState, FEEDBACK : Feedback>: State { + val loadable: Loadable +} + +class MutableLoadedPropertyDelegate + , FAILURE, ITEM, ITEM_MODEL : ItemModel, FEEDBACK : Feedback, PROPERTY>( + private val stateContainer: StateContainer, + private val getFn: ITEM.() -> PROPERTY, + private val updateFn: ITEM.(PROPERTY) -> ITEM, + private val property: KProperty1 +) { + var value: PROPERTY + get() = stateContainer.state.loadable.letLoadedSuccess { it.pendingItem?.let(getFn) } + // let's see if this causes race conditions in the sample app + // might need to add an extra property for null->default value + ?: throw IllegalStateException("Accessing successfully loaded state but not successfully loaded") + set(value) { + stateContainer.state.loadable.whenLoadedSuccess { loaded -> + loaded.updatePendingItem { updateFn(it, value) } + } + } + val valueFlow: Flow = stateContainer.stateFlow + .map { if (it.loadable is Loadable.Loaded) it.loadable as Loadable.Loaded else null } + .flatMapLatest { it?.either?.getOrNull()?.pendingItemFlow ?: flowOf(null) } + .map { it?.let(getFn) } + + val feedback: List + get() = stateContainer.state.loadable.letLoadedSuccess { it.pendingItemValidation.feedbackByProperty[property] } + ?: emptyList() + val feedbackFlow: Flow> = stateContainer.stateFlow + .map { if (it.loadable is Loadable.Loaded) it.loadable as Loadable.Loaded else null } + .flatMapLatest { + it?.letLoadedSuccess { itemModel -> flowOf(itemModel.pendingItemValidation.feedbackByProperty[property]) } + ?: flowOf(emptyList()) + } + .map { it ?: emptyList() } +} + +fun , FAILURE, ITEM, ITEM_MODEL : ItemModel, FEEDBACK : Feedback, PROPERTY> + StateContainer.mutableLoadedProperty( + getFn: ITEM.() -> PROPERTY, + updateFn: ITEM.(PROPERTY) -> ITEM, + property: KProperty1 +): MutableLoadedPropertyDelegate { + return MutableLoadedPropertyDelegate(this, getFn, updateFn, property) +} diff --git a/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/state/StateContainer.kt b/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/state/StateContainer.kt new file mode 100644 index 000000000..8fb0bfb4d --- /dev/null +++ b/toolkit/presentation/presentation/src/main/kotlin/tech/coner/trailer/toolkit/presentation/state/StateContainer.kt @@ -0,0 +1,84 @@ +package tech.coner.trailer.toolkit.presentation.state + +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock +import tech.coner.trailer.toolkit.presentation.state.StateContainer.ReducedStateInspector + +class StateContainer( + val initialState: STATE, + private val isReducedStateLegal: ReducedStateInspector = ReducedStateInspector { _, _ -> true } +) { + + private val _stateMutex = Mutex() + private val _stateFlow: MutableStateFlow by lazy { MutableStateFlow(initialState) } + val stateFlow: StateFlow by lazy { _stateFlow.asStateFlow() } + val state: STATE + get() = runBlocking { + _stateMutex.withLock { + _stateFlow.value + } + } + + suspend fun update(reduceFn: (old: STATE) -> STATE) { + _stateMutex.withLock { + val oldState = _stateFlow.value + val reducedState = reduceFn(oldState) + check(isReducedStateLegal(oldState = oldState, reducedState = reducedState)) + _stateFlow.emit(reducedState) + } + } + + /** + * Inspects reduced state for legality. + * + * StateContainer will invoke this interface with the old and reduced state when updating to check it for legality. + * + * Use this as a last-ditch safety measure to prevent your app entering an illegal state. Be prepared to handle + * the IllegalStateException or else your app may crash. + * + * This is not the place to perform expensive validations. This will be invoked on every call to + * `StateContainer.update` with a mutex lock. Keep it simple, light, fast, and safe. + */ + fun interface ReducedStateInspector { + + operator fun invoke(oldState: STATE, reducedState: STATE): Boolean + } + + open inner class StatePropertyContainer( + private val getValue: STATE.() -> PROPERTY + ) { + val immutableValue: PROPERTY + get() = state.getValue() + val flow: Flow = stateFlow.map(getValue) + } + + fun stateProperty( + getValue: STATE.() -> PROPERTY + ): StatePropertyContainer { + return StatePropertyContainer(getValue) + } + + + inner class MutableStatePropertyContainer( + getValue: STATE.() -> PROPERTY, + private val updateState: STATE.(PROPERTY) -> STATE + ) : StatePropertyContainer(getValue) { + + var value: PROPERTY + get() = immutableValue + set(value) { runBlocking { update { it.updateState(value) } } } + } + + fun mutableStateProperty( + getValue: STATE.() -> PROPERTY, + updateState: STATE.(newValue: PROPERTY) -> STATE + ): MutableStatePropertyContainer { + return MutableStatePropertyContainer(getValue, updateState) + } +} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-cli/pom.xml b/toolkit/samples/dmvapp/dmvapp-cli/pom.xml index d41b54f06..ddf59acf6 100644 --- a/toolkit/samples/dmvapp/dmvapp-cli/pom.xml +++ b/toolkit/samples/dmvapp/dmvapp-cli/pom.xml @@ -18,11 +18,6 @@ toolkit-sample-dmvapp-common 0.1.0-SNAPSHOT - - tech.coner.trailer - toolkit-util - 0.1.0-SNAPSHOT - com.github.ajalt.clikt clikt-jvm diff --git a/toolkit/samples/dmvapp/dmvapp-cli/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/cli/DmvAppCli.kt b/toolkit/samples/dmvapp/dmvapp-cli/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/cli/DmvAppCli.kt index 74f5c392c..afc9b8248 100644 --- a/toolkit/samples/dmvapp/dmvapp-cli/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/cli/DmvAppCli.kt +++ b/toolkit/samples/dmvapp/dmvapp-cli/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/cli/DmvAppCli.kt @@ -7,6 +7,7 @@ import tech.coner.trailer.toolkit.sample.dmvapp.cli.command.cliCommandModule import tech.coner.trailer.toolkit.sample.dmvapp.cli.view.cliViewModule import tech.coner.trailer.toolkit.sample.dmvapp.domain.service.impl.domainServiceModule import tech.coner.trailer.toolkit.sample.dmvapp.domain.validation.domainValidationModule +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.adapter.presentationAdapterModule import tech.coner.trailer.toolkit.sample.dmvapp.presentation.localization.presentationLocalizationModule import tech.coner.trailer.toolkit.sample.dmvapp.presentation.presenter.presentationPresenterModule import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.presentationValidationModule @@ -24,6 +25,7 @@ private val di = DI { domainValidationModule, presentationLocalizationModule, presentationPresenterModule, + presentationAdapterModule, presentationValidationModule ) } \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-cli/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/cli/command/DriversLicenseApplicationCommand.kt b/toolkit/samples/dmvapp/dmvapp-cli/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/cli/command/DriversLicenseApplicationCommand.kt index 4f069b78a..eeeb69083 100644 --- a/toolkit/samples/dmvapp/dmvapp-cli/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/cli/command/DriversLicenseApplicationCommand.kt +++ b/toolkit/samples/dmvapp/dmvapp-cli/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/cli/command/DriversLicenseApplicationCommand.kt @@ -1,27 +1,36 @@ package tech.coner.trailer.toolkit.sample.dmvapp.cli.command -import com.github.ajalt.clikt.core.Abort import com.github.ajalt.clikt.core.CliktCommand +import com.github.ajalt.clikt.core.terminal import com.github.ajalt.clikt.parameters.options.option import com.github.ajalt.clikt.parameters.options.required import com.github.ajalt.clikt.parameters.types.choice import com.github.ajalt.clikt.parameters.types.int +import kotlin.random.Random +import kotlin.time.Duration.Companion.milliseconds import kotlinx.coroutines.CoroutineName import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.async +import kotlinx.coroutines.delay +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking +import tech.coner.trailer.toolkit.dashify import tech.coner.trailer.toolkit.sample.dmvapp.cli.view.DriversLicenseView +import tech.coner.trailer.toolkit.sample.dmvapp.cli.view.ValidationResultView +import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.DriversLicenseApplicationRejection import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.LicenseType -import tech.coner.trailer.toolkit.sample.dmvapp.presentation.localization.Localization +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.localization.Strings import tech.coner.trailer.toolkit.sample.dmvapp.presentation.model.DriversLicenseApplicationModel +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.model.DriversLicenseApplicationRejectionModel import tech.coner.trailer.toolkit.sample.dmvapp.presentation.presenter.DriversLicenseApplicationPresenter import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelFeedback -import tech.coner.trailer.toolkit.util.dashify -import tech.coner.trailer.toolkit.validation.ValidationResult +import tech.coner.trailer.toolkit.validation.ValidationOutcome class DriversLicenseApplicationCommand( private val presenter: DriversLicenseApplicationPresenter, - private val localization: Localization, + private val strings: Strings, private val driversLicenseView: DriversLicenseView, ) : CliktCommand( name = "drivers-license-application" @@ -33,32 +42,50 @@ class DriversLicenseApplicationCommand( .int() .required() private val licenseType: LicenseType by option() - .choice(localization.licenseTypeLabels.associate { it.second.dashify() to it.first }) + .choice(strings.licenseTypeLabels.associate { it.second.dashify() to it.first }) .required() - override fun run() { - val model = presenter.state.model - model.name = name - model.age = age - model.licenseType = licenseType - model.commit() - .onFailure { - it.feedback.echo() - throw Abort() - } - runBlocking { presenter.processApplication() } - ?.also { - echo(localization.driversLicenseGranted) - echo(driversLicenseView(it.driversLicense!!)) + override fun run(): Unit = runBlocking { + presenter.name.value = name + presenter.age.value = age + presenter.licenseType.value = licenseType + + val processing = async { + val progress = launch { + echo("Processing...", trailingNewline = false) + while (isActive) { + echo('.', trailingNewline = false) + delay(Random.nextInt(100, 1000).milliseconds) + } } - } + presenter.submitApplication() + .also { progress.cancel() } + } - private fun ValidationResult.echo() { - if (feedback.isEmpty()) return - feedback - .map { (_, feedbacks) -> - feedbacks.joinToString(separator = System.lineSeparator()) { "[${it.severity.name.lowercase()}]: ${localization.label(it)}" } + processing.await().getOrThrow() + .also { echo() } + .onLeft { rejection -> + when (rejection) { + is DriversLicenseApplicationRejectionModel.Invalid -> rejection.validationOutcome.widget() + is DriversLicenseApplicationRejectionModel.Sassed -> strings[rejection.sass] + } + .also { echo(terminal.render(it), err = true) } + } + .onRight { + echo(strings.driversLicenseGranted) + echo(driversLicenseView(it)) } - .forEach { echo(it, err = true) } } + + private fun ValidationOutcome.widget() = + ValidationResultView( + terminal = terminal, + strings = strings, + fieldStringsMap = mapOf( + DriversLicenseApplicationModel::name to strings.driversLicenseNameField, + DriversLicenseApplicationModel::age to strings.driversLicenseAgeField, + DriversLicenseApplicationModel::licenseType to strings.driversLicenseLicenseTypeField, + ), + messageFn = { strings[it] } + ).invoke(this) } \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-cli/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/cli/view/DriversLicenseView.kt b/toolkit/samples/dmvapp/dmvapp-cli/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/cli/view/DriversLicenseView.kt index 248552d4c..3c768afb5 100644 --- a/toolkit/samples/dmvapp/dmvapp-cli/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/cli/view/DriversLicenseView.kt +++ b/toolkit/samples/dmvapp/dmvapp-cli/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/cli/view/DriversLicenseView.kt @@ -5,26 +5,26 @@ import com.github.ajalt.mordant.rendering.VerticalAlign import com.github.ajalt.mordant.table.Borders import com.github.ajalt.mordant.table.table import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.DriversLicense -import tech.coner.trailer.toolkit.sample.dmvapp.presentation.localization.Localization +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.localization.Strings class DriversLicenseView( - private val localization: Localization + private val strings: Strings ) { operator fun invoke(driversLicense: DriversLicense) = table { header { row { - cell(localization.dmvLabel) { + cell(strings.dmvLabel) { cellBorders = Borders.LEFT_TOP columnSpan = 2 } - cell(localization.driversLicenseHeading) { + cell(strings.driversLicenseHeading) { align = TextAlign.RIGHT cellBorders = Borders.TOP_RIGHT } } row { - cell(localization.dmvMotto) { + cell(strings.dmvMotto) { cellBorders = Borders.LEFT_RIGHT_BOTTOM columnSpan = 3 } @@ -32,18 +32,18 @@ class DriversLicenseView( } body { row { - cell(localization.driversLicensePhotoPlaceholder) { + cell(strings.driversLicensePhotoPlaceholder) { rowSpan = 3 align = TextAlign.CENTER verticalAlign = VerticalAlign.MIDDLE } - cells(localization.driversLicenseNameField, driversLicense.name) + cells(strings.driversLicenseNameField, driversLicense.name) } row { - cells(localization.driversLicenseAgeWhenAppliedField, driversLicense.ageWhenApplied) + cells(strings.driversLicenseAgeField, driversLicense.age) } row { - cells(localization.driversLicenseLicenseTypeField, localization.licenseTypesByObject[driversLicense.licenseType]) + cells(strings.driversLicenseLicenseTypeField, strings.licenseTypesByObject[driversLicense.licenseType]) } } } diff --git a/toolkit/samples/dmvapp/dmvapp-cli/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/cli/view/ValidationResultView.kt b/toolkit/samples/dmvapp/dmvapp-cli/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/cli/view/ValidationResultView.kt new file mode 100644 index 000000000..b93930e3c --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-cli/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/cli/view/ValidationResultView.kt @@ -0,0 +1,49 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.cli.view + +import com.github.ajalt.mordant.rendering.TextColors +import com.github.ajalt.mordant.table.Table +import com.github.ajalt.mordant.table.table +import com.github.ajalt.mordant.terminal.Terminal +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.localization.Strings +import tech.coner.trailer.toolkit.validation.Feedback +import tech.coner.trailer.toolkit.validation.Severity +import tech.coner.trailer.toolkit.validation.ValidationOutcome +import kotlin.reflect.KProperty1 + +class ValidationResultView> ( + private val terminal: Terminal, + private val strings: Strings, + private val fieldStringsMap: Map, String>, + private val messageFn: (FEEDBACK) -> String, +) { + operator fun invoke( + validationOutcome: ValidationOutcome, + ): Table { + return table { + body { + validationOutcome.feedbackByProperty.forEach { (property, feedbacks) -> + feedbacks.forEachIndexed { index, feedback -> + row { + if (index == 0) { + cell(fieldStringsMap[property]) { + columnSpan = feedbacks.size + } + } + cell(strings.validation[feedback.severity]) { + style( + color = when (feedback.severity) { + Severity.Error -> TextColors.red + Severity.Warning -> TextColors.yellow + Severity.Success -> TextColors.green + Severity.Info -> TextColors.blue + } + ) + } + cell(messageFn(feedback)) + } + } + } + } + } + } +} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-common/pom.xml b/toolkit/samples/dmvapp/dmvapp-common/pom.xml index cdbc2b07f..243eef151 100644 --- a/toolkit/samples/dmvapp/dmvapp-common/pom.xml +++ b/toolkit/samples/dmvapp/dmvapp-common/pom.xml @@ -12,4 +12,12 @@ toolkit-sample-dmvapp-common + + + tech.coner.trailer + assertk-arrowkt + 0.1.0-SNAPSHOT + + + \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/domain/entity/DriversLicense.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/domain/entity/DriversLicense.kt deleted file mode 100644 index c6934a177..000000000 --- a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/domain/entity/DriversLicense.kt +++ /dev/null @@ -1,7 +0,0 @@ -package tech.coner.trailer.toolkit.sample.dmvapp.domain.entity - -data class DriversLicense( - val name: String, - val ageWhenApplied: Int, - val licenseType: tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.LicenseType -) \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/domain/entity/DriversLicenseApplication.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/domain/entity/DriversLicenseApplication.kt deleted file mode 100644 index 8b3024ebe..000000000 --- a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/domain/entity/DriversLicenseApplication.kt +++ /dev/null @@ -1,16 +0,0 @@ -package tech.coner.trailer.toolkit.sample.dmvapp.domain.entity - -import kotlin.reflect.KProperty1 -import tech.coner.trailer.toolkit.sample.dmvapp.domain.validation.DriversLicenseApplicationFeedback - -data class DriversLicenseApplication( - val name: String, - val age: Int, - val licenseType: tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.LicenseType, -) { - - data class Outcome( - val driversLicense: tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.DriversLicense?, - val feedback: Map?, List> - ) -} diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/domain/entity/DriversLicenseApplicationOutcome.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/domain/entity/DriversLicenseApplicationOutcome.kt deleted file mode 100644 index 8f95e8b8e..000000000 --- a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/domain/entity/DriversLicenseApplicationOutcome.kt +++ /dev/null @@ -1,6 +0,0 @@ -package tech.coner.trailer.toolkit.sample.dmvapp.domain.entity - -class DriversLicenseApplicationOutcome( - -) { -} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/domain/entity/LicenseType.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/domain/entity/LicenseType.kt deleted file mode 100644 index 8eed554fb..000000000 --- a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/domain/entity/LicenseType.kt +++ /dev/null @@ -1,15 +0,0 @@ -package tech.coner.trailer.toolkit.sample.dmvapp.domain.entity - -sealed class LicenseType { - data object GraduatedLearnerPermit : tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.LicenseType() { - const val MIN_AGE = 15 - const val MAX_AGE_INCLUSIVE = 17 - val AGE_RANGE = tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.LicenseType.GraduatedLearnerPermit.MIN_AGE..tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.LicenseType.GraduatedLearnerPermit.MAX_AGE_INCLUSIVE - } - data object LearnerPermit : tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.LicenseType() { - const val MIN_AGE = 18 - } - data object FullLicense : tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.LicenseType() { - const val MIN_AGE = 18 - } -} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/domain/service/DriversLicenseApplicationService.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/domain/service/DriversLicenseApplicationService.kt deleted file mode 100644 index e0dbdf492..000000000 --- a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/domain/service/DriversLicenseApplicationService.kt +++ /dev/null @@ -1,9 +0,0 @@ -package tech.coner.trailer.toolkit.sample.dmvapp.domain.service - -import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.DriversLicenseApplication - -interface DriversLicenseApplicationService { - - suspend fun process(application: DriversLicenseApplication): DriversLicenseApplication.Outcome - -} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/domain/service/impl/DriversLicenseApplicationServiceImpl.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/domain/service/impl/DriversLicenseApplicationServiceImpl.kt deleted file mode 100644 index 7c2df64a9..000000000 --- a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/domain/service/impl/DriversLicenseApplicationServiceImpl.kt +++ /dev/null @@ -1,31 +0,0 @@ -package tech.coner.trailer.toolkit.sample.dmvapp.domain.service.impl - -import kotlin.time.Duration.Companion.seconds -import kotlinx.coroutines.delay -import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.DriversLicense -import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.DriversLicenseApplication -import tech.coner.trailer.toolkit.sample.dmvapp.domain.service.DriversLicenseApplicationService -import tech.coner.trailer.toolkit.sample.dmvapp.domain.validation.DriversLicenseClerk -import tech.coner.trailer.toolkit.validation.invoke - -internal class DriversLicenseApplicationServiceImpl( - private val clerk: DriversLicenseClerk -) : DriversLicenseApplicationService { - - override suspend fun process(application: DriversLicenseApplication): DriversLicenseApplication.Outcome { - return clerk(application) - .also { if (it.isInvalid) delay(3.seconds) } - .let { - DriversLicenseApplication.Outcome( - driversLicense = it.whenValid { - DriversLicense( - name = application.name, - ageWhenApplied = application.age, - licenseType = application.licenseType - ) - }, - feedback = it.feedback - ) - } - } -} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/adapter/PresentationModelToDomainEntityAdapters.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/adapter/PresentationModelToDomainEntityAdapters.kt deleted file mode 100644 index 8e665c734..000000000 --- a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/adapter/PresentationModelToDomainEntityAdapters.kt +++ /dev/null @@ -1,15 +0,0 @@ -package tech.coner.trailer.toolkit.sample.dmvapp.presentation.adapter - -import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.DriversLicenseApplication -import tech.coner.trailer.toolkit.sample.dmvapp.presentation.model.DriversLicenseApplicationModel - -fun DriversLicenseApplicationModel.toDomainEntity(): DriversLicenseApplication? { - return when { - name != null && age != null && licenseType != null -> DriversLicenseApplication( - name = name, - age = age, - licenseType = licenseType - ) - else -> null - } -} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/localization/EnglishUsLocalization.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/localization/EnglishUsLocalization.kt deleted file mode 100644 index 6f1b7dc94..000000000 --- a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/localization/EnglishUsLocalization.kt +++ /dev/null @@ -1,66 +0,0 @@ -package tech.coner.trailer.toolkit.sample.dmvapp.presentation.localization - -import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.LicenseType.FullLicense -import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.LicenseType.GraduatedLearnerPermit -import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.LicenseType.LearnerPermit -import tech.coner.trailer.toolkit.sample.dmvapp.domain.validation.DriversLicenseApplicationFeedback -import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelFeedback -import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelFeedback.AgeIsRequired -import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelFeedback.DelegatedFeedback -import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelFeedback.LicenseTypeIsRequired -import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelFeedback.NameIsRequired - -class EnglishUsLocalization : Localization { - - override val dmvLabel: String get() = "Coner Trailer DMV" - override val dmvMotto: String get() = "Officiale sine auctoritate" - override val licenseTypeLabels = listOf( - GraduatedLearnerPermit to "Graduated Learner Permit" , - LearnerPermit to "Learner Permit", - FullLicense to "Full License" - ) - override val licenseTypesByObject = licenseTypeLabels.toMap() - - override fun label(model: DriversLicenseApplicationModelFeedback) = model.label - - private val DriversLicenseApplicationModelFeedback.label: String - get() = when (this) { - NameIsRequired -> "Name is required" - AgeIsRequired -> "Age is required" - LicenseTypeIsRequired -> "License Type is required" - is DelegatedFeedback -> feedback.label - } - - private val DriversLicenseApplicationFeedback.label: String - get() = when (this) { - DriversLicenseApplicationFeedback.NameMustNotBeBlank -> "Name must not be blank" - is DriversLicenseApplicationFeedback.TooYoung -> { - val suggestion = when { - reapplyWhenAge != null && suggestOtherLicenseType != null -> "Apply for ${licenseTypesByObject[suggestOtherLicenseType]} when you turn $reapplyWhenAge." - reapplyWhenAge != null -> "Reapply when you turn $reapplyWhenAge." - suggestOtherLicenseType != null -> "Reapply for ${licenseTypesByObject[suggestOtherLicenseType]}." - else -> null - } - val tooYoung = "You are too young." - when { - suggestion != null -> "$tooYoung $suggestion" - else -> tooYoung - } - } - is DriversLicenseApplicationFeedback.TooOld -> { - val tooOld = "You are too old." - when { - suggestOtherLicenseType != null -> "$tooOld Reapply for ${licenseTypesByObject[suggestOtherLicenseType]}." - else -> tooOld - } - } - } - - override val driversLicenseGranted: String get() = "Granted drivers license!" - override val driversLicenseHeading: String get() = "Drivers License" - override val driversLicensePhotoPlaceholder: String get() = "[photo]" - override val driversLicenseNameField: String get() = "Name" - override val driversLicenseAgeWhenAppliedField: String get() = "Age" - override val driversLicenseLicenseTypeField: String get() = "License Type" - -} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/localization/Localization.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/localization/Localization.kt deleted file mode 100644 index 45654db6f..000000000 --- a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/localization/Localization.kt +++ /dev/null @@ -1,19 +0,0 @@ -package tech.coner.trailer.toolkit.sample.dmvapp.presentation.localization - -import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.LicenseType -import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelFeedback - -interface Localization { - - fun label(model: DriversLicenseApplicationModelFeedback): String - val dmvLabel: String - val dmvMotto: String - val licenseTypeLabels: List> - val licenseTypesByObject: Map - val driversLicenseGranted: String - val driversLicenseHeading: String - val driversLicensePhotoPlaceholder: String - val driversLicenseNameField: String - val driversLicenseAgeWhenAppliedField: String - val driversLicenseLicenseTypeField: String -} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/presenter/DriversLicenseApplicationPresenter.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/presenter/DriversLicenseApplicationPresenter.kt deleted file mode 100644 index d5a4d2351..000000000 --- a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/presenter/DriversLicenseApplicationPresenter.kt +++ /dev/null @@ -1,34 +0,0 @@ -package tech.coner.trailer.toolkit.sample.dmvapp.presentation.presenter - -import org.kodein.di.DI -import org.kodein.di.DIAware -import org.kodein.di.instance -import tech.coner.trailer.toolkit.presentation.presenter.SecondDraftPresenter -import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.DriversLicenseApplication -import tech.coner.trailer.toolkit.sample.dmvapp.domain.service.DriversLicenseApplicationService -import tech.coner.trailer.toolkit.sample.dmvapp.presentation.adapter.toDomainEntity -import tech.coner.trailer.toolkit.sample.dmvapp.presentation.model.DriversLicenseApplicationItemModel -import tech.coner.trailer.toolkit.sample.dmvapp.presentation.state.DriversLicenseApplicationState -import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelValidator - -class DriversLicenseApplicationPresenter( - override val di: DI, - initialState: DriversLicenseApplicationState? = null, -) : SecondDraftPresenter(), DIAware { - - private val service: DriversLicenseApplicationService by instance() - private val validator: DriversLicenseApplicationModelValidator by instance() - - override val initialState = initialState - ?: DriversLicenseApplicationState( - model = DriversLicenseApplicationItemModel( - validator = validator - ) - ) - - suspend fun processApplication(): DriversLicenseApplication.Outcome? { - return state.model.item.toDomainEntity() - ?.let { service.process(it) } - ?.also { outcome -> update { it.copy(outcome = outcome) } } - } -} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/presenter/PresentationPresenterModule.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/presenter/PresentationPresenterModule.kt deleted file mode 100644 index 460a7e45c..000000000 --- a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/presenter/PresentationPresenterModule.kt +++ /dev/null @@ -1,8 +0,0 @@ -package tech.coner.trailer.toolkit.sample.dmvapp.presentation.presenter - -import org.kodein.di.DI -import org.kodein.di.bindSingleton - -val presentationPresenterModule by DI.Module { - bindSingleton { DriversLicenseApplicationPresenter(di) } -} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/state/DriversLicenseApplicationState.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/state/DriversLicenseApplicationState.kt deleted file mode 100644 index fe5a987ef..000000000 --- a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/state/DriversLicenseApplicationState.kt +++ /dev/null @@ -1,10 +0,0 @@ -package tech.coner.trailer.toolkit.sample.dmvapp.presentation.state - -import tech.coner.trailer.toolkit.presentation.state.State -import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.DriversLicenseApplication -import tech.coner.trailer.toolkit.sample.dmvapp.presentation.model.DriversLicenseApplicationItemModel - -data class DriversLicenseApplicationState( - val model: DriversLicenseApplicationItemModel, - val outcome: DriversLicenseApplication.Outcome? = null -) : State diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/validation/DriversLicenseApplicationModelFeedback.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/validation/DriversLicenseApplicationModelFeedback.kt deleted file mode 100644 index 18f05f13f..000000000 --- a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/validation/DriversLicenseApplicationModelFeedback.kt +++ /dev/null @@ -1,26 +0,0 @@ -package tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation - -import tech.coner.trailer.toolkit.sample.dmvapp.domain.validation.DriversLicenseApplicationFeedback -import tech.coner.trailer.toolkit.validation.Feedback -import tech.coner.trailer.toolkit.validation.Severity -import tech.coner.trailer.toolkit.validation.Severity.Error - -sealed class DriversLicenseApplicationModelFeedback : Feedback { - - data object NameIsRequired : DriversLicenseApplicationModelFeedback() { - override val severity = Error - } - data object AgeIsRequired : DriversLicenseApplicationModelFeedback() { - override val severity = Error - } - data object LicenseTypeIsRequired : DriversLicenseApplicationModelFeedback() { - override val severity = Error - } - - data class DelegatedFeedback( - val feedback: DriversLicenseApplicationFeedback - ) : DriversLicenseApplicationModelFeedback() { - override val severity: Severity - get() = feedback.severity - } -} diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/entity/DriversLicense.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/entity/DriversLicense.kt new file mode 100644 index 000000000..757e48d1d --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/entity/DriversLicense.kt @@ -0,0 +1,7 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.domain.entity + +data class DriversLicense( + val name: String, + val age: Int, + val licenseType: LicenseType +) \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/entity/DriversLicenseApplication.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/entity/DriversLicenseApplication.kt new file mode 100644 index 000000000..14d393386 --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/entity/DriversLicenseApplication.kt @@ -0,0 +1,7 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.domain.entity + +data class DriversLicenseApplication( + val name: String, + val age: Int, + val licenseType: LicenseType, +) diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/entity/DriversLicenseApplicationRejection.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/entity/DriversLicenseApplicationRejection.kt new file mode 100644 index 000000000..3ed304bec --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/entity/DriversLicenseApplicationRejection.kt @@ -0,0 +1,15 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.domain.entity + +import tech.coner.trailer.toolkit.sample.dmvapp.domain.validation.DriversLicenseApplicationFeedback +import tech.coner.trailer.toolkit.validation.ValidationOutcome + +sealed interface DriversLicenseApplicationRejection { + + data class Invalid( + val validationOutcome: ValidationOutcome + ) : DriversLicenseApplicationRejection + + data class Sassed( + val sass: Sass + ) : DriversLicenseApplicationRejection +} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/entity/LicenseType.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/entity/LicenseType.kt new file mode 100644 index 000000000..469d5a2df --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/entity/LicenseType.kt @@ -0,0 +1,15 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.domain.entity + +sealed class LicenseType { + data object GraduatedLearnerPermit : LicenseType() { + const val MIN_AGE = 15 + const val MAX_AGE_INCLUSIVE = 17 + val AGE_RANGE = MIN_AGE..MAX_AGE_INCLUSIVE + } + data object LearnerPermit : LicenseType() { + const val MIN_AGE = 18 + } + data object FullLicense : LicenseType() { + const val MIN_AGE = 18 + } +} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/entity/Sass.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/entity/Sass.kt new file mode 100644 index 000000000..07c665a20 --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/entity/Sass.kt @@ -0,0 +1,7 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.domain.entity + +enum class Sass { + + LEAVING_FOR_BREAK, + MEAL_DELIVERY_JUST_ARRIVED, +} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/service/DriversLicenseApplicationService.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/service/DriversLicenseApplicationService.kt new file mode 100644 index 000000000..7ff85f35d --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/service/DriversLicenseApplicationService.kt @@ -0,0 +1,12 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.domain.service + +import arrow.core.Either +import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.DriversLicense +import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.DriversLicenseApplication +import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.DriversLicenseApplicationRejection + +interface DriversLicenseApplicationService { + + suspend fun submit(application: DriversLicenseApplication): Result> + +} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/domain/service/impl/DomainServiceModule.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/service/impl/DomainServiceModule.kt similarity index 100% rename from toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/domain/service/impl/DomainServiceModule.kt rename to toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/service/impl/DomainServiceModule.kt diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/service/impl/DriversLicenseApplicationServiceImpl.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/service/impl/DriversLicenseApplicationServiceImpl.kt new file mode 100644 index 000000000..a014e4e2d --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/service/impl/DriversLicenseApplicationServiceImpl.kt @@ -0,0 +1,41 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.domain.service.impl + +import arrow.core.Either +import arrow.core.raise.either +import arrow.core.raise.ensure +import kotlin.random.Random +import kotlin.time.Duration.Companion.milliseconds +import kotlin.time.Duration.Companion.seconds +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.delay +import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.DriversLicense +import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.DriversLicenseApplication +import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.DriversLicenseApplicationRejection +import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.Sass +import tech.coner.trailer.toolkit.sample.dmvapp.domain.service.DriversLicenseApplicationService +import tech.coner.trailer.toolkit.sample.dmvapp.domain.validation.DriversLicenseClerk +import tech.coner.trailer.toolkit.validation.invoke + +internal class DriversLicenseApplicationServiceImpl( + private val clerk: DriversLicenseClerk +) : DriversLicenseApplicationService { + + override suspend fun submit(application: DriversLicenseApplication): Result> = coroutineScope { + runCatching { + either { + delay(Random.nextDouble(1000.0, 10000.0).milliseconds) + clerk(application) + .also { if (it.isInvalid) delay(5.seconds) } + .also { ensure(it.isValid) { DriversLicenseApplicationRejection.Invalid(it) } } + .let { + DriversLicense( + name = application.name, + age = application.age, + licenseType = application.licenseType + ) + } + } + } + } + +} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/domain/validation/DomainValidationModule.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/validation/DomainValidationModule.kt similarity index 100% rename from toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/domain/validation/DomainValidationModule.kt rename to toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/validation/DomainValidationModule.kt diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/domain/validation/DriversLicenseApplicationFeedback.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/validation/DriversLicenseApplicationFeedback.kt similarity index 66% rename from toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/domain/validation/DriversLicenseApplicationFeedback.kt rename to toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/validation/DriversLicenseApplicationFeedback.kt index da51431ff..2105a38fd 100644 --- a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/domain/validation/DriversLicenseApplicationFeedback.kt +++ b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/validation/DriversLicenseApplicationFeedback.kt @@ -1,23 +1,28 @@ package tech.coner.trailer.toolkit.sample.dmvapp.domain.validation +import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.DriversLicenseApplication import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.LicenseType import tech.coner.trailer.toolkit.validation.Feedback import tech.coner.trailer.toolkit.validation.Severity +import kotlin.reflect.KProperty1 -sealed class DriversLicenseApplicationFeedback : Feedback { +sealed class DriversLicenseApplicationFeedback : Feedback { data object NameMustNotBeBlank : DriversLicenseApplicationFeedback() { + override val property = DriversLicenseApplication::name override val severity = Severity.Error } data class TooYoung( val suggestOtherLicenseType: LicenseType? = null, val reapplyWhenAge: Int? = null ) : DriversLicenseApplicationFeedback() { + override val property = DriversLicenseApplication::age override val severity = Severity.Error } data class TooOld( val suggestOtherLicenseType: LicenseType? ) : DriversLicenseApplicationFeedback() { + override val property = DriversLicenseApplication::age override val severity = Severity.Error } } \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/domain/validation/DriversLicenseApplicationValidator.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/validation/DriversLicenseApplicationValidator.kt similarity index 100% rename from toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/domain/validation/DriversLicenseApplicationValidator.kt rename to toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/validation/DriversLicenseApplicationValidator.kt diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/adapter/DriversLicenseApplicationModelAdapters.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/adapter/DriversLicenseApplicationModelAdapters.kt new file mode 100644 index 000000000..9d2dd5377 --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/adapter/DriversLicenseApplicationModelAdapters.kt @@ -0,0 +1,30 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.presentation.adapter + +import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.DriversLicenseApplication +import tech.coner.trailer.toolkit.sample.dmvapp.domain.validation.DriversLicenseApplicationFeedback +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.model.DriversLicenseApplicationModel +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelFeedback +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelFeedback.DelegatedFeedback +import tech.coner.trailer.toolkit.validation.ValidationOutcome +import tech.coner.trailer.toolkit.validation.adapter.map + + +class DriversLicenseApplicationModelAdapters { + + /** + * Adapter function converts presentation model to domain entity + * + * The conversion can fail if the presentation model is invalid. Validate first. + */ + fun toDomainEntity(model: DriversLicenseApplicationModel): Result = runCatching { + DriversLicenseApplication( + name = model.name!!, + age = model.age!!, + licenseType = model.licenseType!! + ) + } + + val domainEntityValidationAdapter: (ValidationOutcome) -> ValidationOutcome = { + it.map { feedback -> DelegatedFeedback(feedback) } + } +} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/adapter/PresentationAdapterModule.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/adapter/PresentationAdapterModule.kt new file mode 100644 index 000000000..aee9b483f --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/adapter/PresentationAdapterModule.kt @@ -0,0 +1,9 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.presentation.adapter + +import org.kodein.di.DI +import org.kodein.di.bindSingleton +import org.kodein.di.new + +val presentationAdapterModule by DI.Module { + bindSingleton { new(::DriversLicenseApplicationModelAdapters) } +} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/localization/EnglishUsTranslation.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/localization/EnglishUsTranslation.kt new file mode 100644 index 000000000..48d34de71 --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/localization/EnglishUsTranslation.kt @@ -0,0 +1,56 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.presentation.localization + +import tech.coner.trailer.toolkit.validation.presentation.localization.EnglishUsValidationTranslation +import tech.coner.trailer.toolkit.validation.presentation.localization.ValidationStringsImpl + +class EnglishUsTranslation() : Translation { + + override val conerLogoContentDescription: String get() = "Coner Logo" + override val dmvLabel: String get() = "Division of Motor Vehicles" + override val dmvMotto: String get() = "Officiale sine auctoritate" + + override val settings get() = "Settings" + override val menuContentDescription get() = "Menu" + override val settingsThemeTitle: String get() = "Theme" + override val settingsThemeModeTitle: String get() = "Mode" + override val settingsThemeModeAuto: String get() = "Auto" + override val settingsThemeModeLight: String get() = "Use Light Theme" + override val settingsThemeModeDark: String get() = "Use Dark Theme" + + override val driversLicenseGranted: String get() = "Granted drivers license!" + override val driversLicenseHeading: String get() = "Drivers License" + override val driversLicenseNameField: String get() = "Name" + override val driversLicenseNameFeedbackRequired get() = "Name is required" + override val driversLicenseNameFeedbackNotBlank get() = "Name must not be blank" + override val driversLicenseAgeField: String get() = "Age" + override val driversLicenseAgeFeedbackRequired get() = "Age is required" + override val driversLicenseAgeFeedbackTooYoung get() = "You are too young." + override val driversLicenseAgeFeedbackTooYoungSuggestOtherLicenseTypeWhenAgedFormat + get() = "Apply for %1\$s when you turn %2\$d" + override val driversLicenseAgeFeedbackTooYoungSuggestReapplyWhenAgedFormat + get() = "Reapply when you turn %1\$s." + override val driversLicenseAgeFeedbackTooYoungSuggestOtherLicenseTypeFormat + get() = "Reapply for %1\$s." + override val driversLicenseAgeFeedbackTooYoungSuggestionFormat + get() = "%1\$s %2\$s" + override val driversLicenseAgeFeedbackTooOld get() = "You are too old." + override val driversLicenseAgeFeedbackTooOldSuggestOtherLicenseTypeFormat: String + get() = "%1\$s Reapply for %2\$s." + override val driversLicenseLicenseTypeField: String get() = "License Type" + override val driversLicenseLicenseTypeGraduatedLearnerPermit get() = "Graduated Learner Permit" + override val driversLicenseLicenseTypeLearnerPermit get() = "Learner Permit" + override val driversLicenseLicenseTypeFullLicense get() = "Full License" + override val driversLicenseLicenseTypeFeedbackRequired get() = "License Type is required" + override val driversLicensePhotoPlaceholder: String get() = "[photo]" + override val driversLicenseApplicationHeading: String get() = "Drivers License Application" + override val driversLicenseApplicationFormReset: String get() = "Reset" + override val driversLicenseApplicationFormApply: String get() = "Apply" + override val driversLicenseApplicationRejectionTitle: String get() = "Rejected" + override val sassFormat get() = "%1\$s Try again another time." + override val sassLeavingForBreak get() = "The clerk was just stepping out for a break." + override val sassMealDeliveryJustArrived: String get() = "The clerk's meal delivery just arrived and they're not about to let it get cold." + + override val validation = ValidationStringsImpl(EnglishUsValidationTranslation()) + + override val ok get() = "OK" +} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/localization/PresentationLocalizationModule.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/localization/PresentationLocalizationModule.kt similarity index 75% rename from toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/localization/PresentationLocalizationModule.kt rename to toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/localization/PresentationLocalizationModule.kt index f773f1df1..1c691c829 100644 --- a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/localization/PresentationLocalizationModule.kt +++ b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/localization/PresentationLocalizationModule.kt @@ -5,5 +5,5 @@ import org.kodein.di.bindSingleton import org.kodein.di.new val presentationLocalizationModule by DI.Module { - bindSingleton { new(::EnglishUsLocalization) } -} \ No newline at end of file + bindSingleton { StringsImpl(EnglishUsTranslation()) } +} diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/localization/Strings.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/localization/Strings.kt new file mode 100644 index 000000000..c7877651f --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/localization/Strings.kt @@ -0,0 +1,18 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.presentation.localization + +import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.LicenseType +import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.Sass +import tech.coner.trailer.toolkit.sample.dmvapp.domain.validation.DriversLicenseApplicationFeedback +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelFeedback + +interface Strings : Translation { + + val licenseTypeLabels: List> + val licenseTypesByObject: Map + operator fun get(licenseType: LicenseType): String + fun getNullable(licenseType: LicenseType?): String + + operator fun get(feedback: DriversLicenseApplicationModelFeedback): String + operator fun get(feedback: DriversLicenseApplicationFeedback): String + operator fun get(sass: Sass): String +} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/localization/StringsImpl.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/localization/StringsImpl.kt new file mode 100644 index 000000000..6d0552782 --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/localization/StringsImpl.kt @@ -0,0 +1,80 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.presentation.localization + +import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.LicenseType +import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.LicenseType.FullLicense +import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.LicenseType.GraduatedLearnerPermit +import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.LicenseType.LearnerPermit +import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.Sass +import tech.coner.trailer.toolkit.sample.dmvapp.domain.validation.DriversLicenseApplicationFeedback +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelFeedback +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelFeedback.AgeIsRequired +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelFeedback.DelegatedFeedback +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelFeedback.LicenseTypeIsRequired +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelFeedback.NameIsRequired + +class StringsImpl(translation: Translation) : Strings, + Translation by translation { + + override val licenseTypeLabels = listOf( + GraduatedLearnerPermit to driversLicenseLicenseTypeGraduatedLearnerPermit, + LearnerPermit to driversLicenseLicenseTypeLearnerPermit, + FullLicense to driversLicenseLicenseTypeFullLicense + ) + override val licenseTypesByObject = licenseTypeLabels.toMap() + + override fun get(licenseType: LicenseType) = licenseTypesByObject[licenseType] + ?: throw Exception("No string defined for $licenseType") + + override fun getNullable(licenseType: LicenseType?) = licenseType?.let { get(it) } ?: "" + + override fun get(feedback: DriversLicenseApplicationModelFeedback) = when (feedback) { + NameIsRequired -> driversLicenseNameFeedbackRequired + AgeIsRequired -> driversLicenseAgeFeedbackRequired + LicenseTypeIsRequired -> driversLicenseLicenseTypeFeedbackRequired + is DelegatedFeedback -> get(feedback.feedback) + } + + override fun get(feedback: DriversLicenseApplicationFeedback) = with (feedback) { + when (this) { + DriversLicenseApplicationFeedback.NameMustNotBeBlank -> driversLicenseNameFeedbackNotBlank + is DriversLicenseApplicationFeedback.TooYoung -> { + val suggestion = when { + reapplyWhenAge != null && suggestOtherLicenseType != null -> + driversLicenseAgeFeedbackTooYoungSuggestOtherLicenseTypeWhenAgedFormat.format( + get(suggestOtherLicenseType), + reapplyWhenAge + ) + reapplyWhenAge != null -> + driversLicenseAgeFeedbackTooYoungSuggestReapplyWhenAgedFormat.format( + reapplyWhenAge + ) + suggestOtherLicenseType != null -> + driversLicenseAgeFeedbackTooYoungSuggestOtherLicenseTypeFormat.format( + get(suggestOtherLicenseType) + ) + else -> null + } + val tooYoung = driversLicenseAgeFeedbackTooYoung + suggestion + ?.let { driversLicenseAgeFeedbackTooYoungSuggestionFormat.format(tooYoung, suggestion) } + ?: tooYoung + } + + is DriversLicenseApplicationFeedback.TooOld -> { + val tooOld = driversLicenseAgeFeedbackTooOld + suggestOtherLicenseType + ?.let { + driversLicenseAgeFeedbackTooOldSuggestOtherLicenseTypeFormat.format(tooOld, get(suggestOtherLicenseType)) + } + ?: tooOld + } + } + } + + override fun get(sass: Sass): String = sassFormat.format( + when (sass) { + Sass.LEAVING_FOR_BREAK -> sassLeavingForBreak + Sass.MEAL_DELIVERY_JUST_ARRIVED -> sassMealDeliveryJustArrived + } + ) +} diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/localization/Translation.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/localization/Translation.kt new file mode 100644 index 000000000..a0969d5dc --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/localization/Translation.kt @@ -0,0 +1,53 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.presentation.localization + +import tech.coner.trailer.toolkit.validation.presentation.localization.ValidationStrings + +interface Translation { + + val conerLogoContentDescription: String + val dmvLabel: String + val dmvMotto: String + + val driversLicenseHeading: String + val driversLicenseNameField: String + val driversLicenseNameFeedbackRequired: String + val driversLicenseNameFeedbackNotBlank: String + val driversLicenseAgeField: String + val driversLicenseAgeFeedbackRequired: String + val driversLicenseAgeFeedbackTooYoung: String + val driversLicenseAgeFeedbackTooYoungSuggestOtherLicenseTypeWhenAgedFormat: String + val driversLicenseAgeFeedbackTooYoungSuggestReapplyWhenAgedFormat: String + val driversLicenseAgeFeedbackTooYoungSuggestOtherLicenseTypeFormat: String + val driversLicenseAgeFeedbackTooYoungSuggestionFormat: String + val driversLicenseAgeFeedbackTooOld: String + val driversLicenseAgeFeedbackTooOldSuggestOtherLicenseTypeFormat: String + val driversLicenseLicenseTypeField: String + val driversLicenseLicenseTypeGraduatedLearnerPermit: String + val driversLicenseLicenseTypeLearnerPermit: String + val driversLicenseLicenseTypeFullLicense: String + val driversLicenseLicenseTypeFeedbackRequired: String + val driversLicensePhotoPlaceholder: String + val driversLicenseApplicationHeading: String + val driversLicenseApplicationFormReset: String + val driversLicenseApplicationFormApply: String + + val driversLicenseApplicationRejectionTitle: String + + val sassFormat: String + val sassLeavingForBreak: String + val sassMealDeliveryJustArrived: String + + val driversLicenseGranted: String + + val menuContentDescription: String + val settings: String + val settingsThemeTitle: String + val settingsThemeModeTitle: String + val settingsThemeModeAuto: String + val settingsThemeModeLight: String + val settingsThemeModeDark: String + + val validation: ValidationStrings + + val ok: String +} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/model/DriversLicenseApplicationItemModel.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/model/DriversLicenseApplicationItemModel.kt similarity index 51% rename from toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/model/DriversLicenseApplicationItemModel.kt rename to toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/model/DriversLicenseApplicationItemModel.kt index aa10659ff..cb331416c 100644 --- a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/model/DriversLicenseApplicationItemModel.kt +++ b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/model/DriversLicenseApplicationItemModel.kt @@ -1,8 +1,6 @@ package tech.coner.trailer.toolkit.sample.dmvapp.presentation.model -import kotlinx.coroutines.flow.map import tech.coner.trailer.toolkit.presentation.model.BaseItemModel -import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.LicenseType import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelFeedback import tech.coner.trailer.toolkit.validation.Validator @@ -13,19 +11,4 @@ class DriversLicenseApplicationItemModel( override val initialItem: DriversLicenseApplicationModel = DriversLicenseApplicationModel() override val validatorContext = Unit - var name: String? - get() = pendingItem.name - set(value) = mutatePendingItem { it.copy(name = value) } - val nameFlow = pendingItemFlow.map { it.name } - - var age: Int? - get() = pendingItem.age - set(value) = mutatePendingItem { it.copy(age = value) } - val ageFlow = pendingItemFlow.map { it.age } - - var licenseType: LicenseType? - get() = pendingItem.licenseType - set(value) = mutatePendingItem { it.copy(licenseType = value) } - val licenseTypeFlow = pendingItemFlow.map { it.licenseType } - } diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/model/DriversLicenseApplicationModel.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/model/DriversLicenseApplicationModel.kt similarity index 100% rename from toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/model/DriversLicenseApplicationModel.kt rename to toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/model/DriversLicenseApplicationModel.kt diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/model/DriversLicenseApplicationRejectionModel.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/model/DriversLicenseApplicationRejectionModel.kt new file mode 100644 index 000000000..9e5b90b1b --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/model/DriversLicenseApplicationRejectionModel.kt @@ -0,0 +1,16 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.presentation.model + +import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.Sass +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelFeedback +import tech.coner.trailer.toolkit.validation.ValidationOutcome + +sealed interface DriversLicenseApplicationRejectionModel { + + data class Invalid( + val validationOutcome: ValidationOutcome + ) : DriversLicenseApplicationRejectionModel + + data class Sassed( + val sass: Sass + ) : DriversLicenseApplicationRejectionModel +} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/presenter/DriversLicenseApplicationPresenter.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/presenter/DriversLicenseApplicationPresenter.kt new file mode 100644 index 000000000..fdc043323 --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/presenter/DriversLicenseApplicationPresenter.kt @@ -0,0 +1,148 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.presentation.presenter + +import arrow.core.Either +import arrow.core.raise.either +import kotlinx.coroutines.cancel +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.flatMapLatest +import tech.coner.trailer.toolkit.presentation.presenter.ItemModelPresenter +import tech.coner.trailer.toolkit.presentation.presenter.StatefulPresenter +import tech.coner.trailer.toolkit.presentation.state.StateContainer +import tech.coner.trailer.toolkit.presentation.state.mutableItemModelProperty +import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.DriversLicense +import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.DriversLicenseApplicationRejection +import tech.coner.trailer.toolkit.sample.dmvapp.domain.service.DriversLicenseApplicationService +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.adapter.DriversLicenseApplicationModelAdapters +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.localization.Strings +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.model.DriversLicenseApplicationItemModel +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.model.DriversLicenseApplicationModel +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.model.DriversLicenseApplicationRejectionModel +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.state.DriversLicenseApplicationState +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelFeedback +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelValidator +import tech.coner.trailer.toolkit.validation.ValidationOutcome + +class DriversLicenseApplicationPresenter( + private val initialState: DriversLicenseApplicationState? = null, + private val adapters: DriversLicenseApplicationModelAdapters, + private val service: DriversLicenseApplicationService, + private val validator: DriversLicenseApplicationModelValidator, + private val strings: Strings, +) : StatefulPresenter, + ItemModelPresenter { + + private val stateContainer = StateContainer( + initialState = initialState ?: DriversLicenseApplicationState( + itemModel = DriversLicenseApplicationItemModel( + validator = validator + ) + ), + ) + override val state: DriversLicenseApplicationState get() = stateContainer.state + override val stateFlow: StateFlow get() = stateContainer.stateFlow + + suspend fun submitApplication(): Result> = coroutineScope { + runCatching { + either { + if (state.processing) cancel() + stateContainer.update { + it.copy(processing = true) + } + either { + state.itemModel.commit() + .mapLeft { DriversLicenseApplicationRejectionModel.Invalid(it) } + .bind() + } + .map { + service.submit(adapters.toDomainEntity(it).getOrThrow()).getOrThrow() + .mapLeft { rejection -> + when (rejection) { + is DriversLicenseApplicationRejection.Invalid -> DriversLicenseApplicationRejectionModel.Invalid( + adapters.domainEntityValidationAdapter(rejection.validationOutcome) + ) + is DriversLicenseApplicationRejection.Sassed -> DriversLicenseApplicationRejectionModel.Sassed( + rejection.sass + ) + } + + } + .also { outcome -> stateContainer.update { state -> state.copy(outcome = outcome) } } + .bind() + } + .bind() + } + } + .also { stateContainer.update { it.copy(processing = false) } } + } + + suspend fun clearOutcome() { + stateContainer.update { it.copy(outcome = null) } + } + + override suspend fun reset() { + stateContainer.update { + initialState + ?: DriversLicenseApplicationState( + itemModel = DriversLicenseApplicationItemModel( + validator = validator + ) + ) + } + } + + override suspend fun commit() { + state.itemModel.commit() + } + + override suspend fun validate() { + state.itemModel.validate() + } + + val validationResult get() = state.itemModel.pendingItemValidation + val validationOutcomeFlow: Flow> get() = stateFlow + .flatMapLatest { it.itemModel.pendingItemValidationFlow } + + val name = stateContainer.mutableItemModelProperty( + getFn = { name }, + updateFn = { copy(name = it) }, + property = DriversLicenseApplicationModel::name + ) + + val age = stateContainer.mutableItemModelProperty( + getFn = { age }, + updateFn = { copy(age = it) }, + property = DriversLicenseApplicationModel::age + ) + + val licenseType = stateContainer.mutableItemModelProperty( + getFn = { licenseType }, + updateFn = { copy(licenseType = it) }, + property = DriversLicenseApplicationModel::licenseType + ) + + val processingApplication = stateContainer.mutableStateProperty( + getValue = { processing }, + updateState = { copy(processing = it) } + ) + val fieldsEditable = stateContainer.stateProperty { fieldsEditable } + + val canResetFlow: Flow by lazy { + stateFlow + .flatMapLatest { it.itemModel.canResetFlow } + .combine(processingApplication.flow) { itemModelCanReset, processing -> + itemModelCanReset && !processing + } + .distinctUntilChanged() + } + + val canApplyFlow: Flow = stateFlow + .combine( + stateFlow.flatMapLatest { it.itemModel.pendingItemValidationFlow } + ) { state, pendingItemValidation -> + !state.processing && state.outcome == null && pendingItemValidation.isValid + } +} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/presenter/PresentationPresenterModule.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/presenter/PresentationPresenterModule.kt new file mode 100644 index 000000000..81984d880 --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/presenter/PresentationPresenterModule.kt @@ -0,0 +1,16 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.presentation.presenter + +import org.kodein.di.* +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.adapter.DriversLicenseApplicationModelAdapters + +val presentationPresenterModule by DI.Module { + bindSingleton { + DriversLicenseApplicationPresenter( + initialState = null, + adapters = DriversLicenseApplicationModelAdapters(), + service = instance(), + validator = instance(), + strings = instance() + ) + } +} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/state/DriversLicenseApplicationState.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/state/DriversLicenseApplicationState.kt new file mode 100644 index 000000000..1b7bcbda1 --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/state/DriversLicenseApplicationState.kt @@ -0,0 +1,20 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.presentation.state + +import arrow.core.Either +import tech.coner.trailer.toolkit.presentation.state.ItemModelState +import tech.coner.trailer.toolkit.presentation.state.State +import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.DriversLicense +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.model.DriversLicenseApplicationItemModel +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.model.DriversLicenseApplicationModel +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.model.DriversLicenseApplicationRejectionModel +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelFeedback + +data class DriversLicenseApplicationState( + override val itemModel: DriversLicenseApplicationItemModel, + val processing: Boolean = false, + val outcome: Either? = null +) : State, + ItemModelState { + + val fieldsEditable: Boolean get() = !processing && (outcome == null || outcome.isLeft()) +} diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/validation/DriversLicenseApplicationModelFeedback.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/validation/DriversLicenseApplicationModelFeedback.kt new file mode 100644 index 000000000..5e828cba0 --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/validation/DriversLicenseApplicationModelFeedback.kt @@ -0,0 +1,40 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation + +import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.DriversLicenseApplication +import tech.coner.trailer.toolkit.sample.dmvapp.domain.validation.DriversLicenseApplicationFeedback +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.model.DriversLicenseApplicationModel +import tech.coner.trailer.toolkit.validation.Feedback +import tech.coner.trailer.toolkit.validation.FeedbackDelegate +import tech.coner.trailer.toolkit.validation.Severity +import tech.coner.trailer.toolkit.validation.Severity.Error +import tech.coner.trailer.toolkit.validation.adapter.propertyAdapterOf +import kotlin.reflect.KProperty1 + +sealed class DriversLicenseApplicationModelFeedback : Feedback { + + data object NameIsRequired : DriversLicenseApplicationModelFeedback() { + override val property = DriversLicenseApplicationModel::name + override val severity = Error + } + data object AgeIsRequired : DriversLicenseApplicationModelFeedback() { + override val property = DriversLicenseApplicationModel::age + override val severity = Error + } + data object LicenseTypeIsRequired : DriversLicenseApplicationModelFeedback() { + override val property = DriversLicenseApplicationModel::licenseType + override val severity = Error + } + + data class DelegatedFeedback( + val feedback: DriversLicenseApplicationFeedback + ) : DriversLicenseApplicationModelFeedback(), + Feedback by FeedbackDelegate( + feedback, + propertyAdapterOf( + DriversLicenseApplication::name to DriversLicenseApplicationModel::name, + DriversLicenseApplication::age to DriversLicenseApplicationModel::age, + DriversLicenseApplication::licenseType to DriversLicenseApplicationModel::licenseType, + null to null + ) + ) +} diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/validation/DriversLicenseApplicationModelValidator.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/validation/DriversLicenseApplicationModelValidator.kt similarity index 52% rename from toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/validation/DriversLicenseApplicationModelValidator.kt rename to toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/validation/DriversLicenseApplicationModelValidator.kt index bb13edd92..38c49c135 100644 --- a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/validation/DriversLicenseApplicationModelValidator.kt +++ b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/validation/DriversLicenseApplicationModelValidator.kt @@ -1,13 +1,9 @@ package tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation -import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.DriversLicenseApplication import tech.coner.trailer.toolkit.sample.dmvapp.domain.validation.DriversLicenseClerk -import tech.coner.trailer.toolkit.sample.dmvapp.presentation.adapter.toDomainEntity +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.adapter.DriversLicenseApplicationModelAdapters import tech.coner.trailer.toolkit.sample.dmvapp.presentation.model.DriversLicenseApplicationModel -import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelFeedback.AgeIsRequired -import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelFeedback.DelegatedFeedback -import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelFeedback.LicenseTypeIsRequired -import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelFeedback.NameIsRequired +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelFeedback.* import tech.coner.trailer.toolkit.validation.Severity import tech.coner.trailer.toolkit.validation.Validator import tech.coner.trailer.toolkit.validation.input @@ -15,20 +11,17 @@ import tech.coner.trailer.toolkit.validation.input typealias DriversLicenseApplicationModelValidator = Validator fun DriversLicenseApplicationModelValidator( - driversLicenseClerk: DriversLicenseClerk + driversLicenseClerk: DriversLicenseClerk, + driversLicenseApplicationModelAdapters: DriversLicenseApplicationModelAdapters, ): DriversLicenseApplicationModelValidator = Validator { - DriversLicenseApplicationModel::name { if (it == null) NameIsRequired else null } + + DriversLicenseApplicationModel::name { if (it.isNullOrBlank()) NameIsRequired else null } DriversLicenseApplicationModel::age { if (it == null) AgeIsRequired else null } DriversLicenseApplicationModel::licenseType { licenseType -> LicenseTypeIsRequired.takeIf { licenseType == null } } returnEarlyIfAny { it.severity == Severity.Error } input( validator = driversLicenseClerk, - mapInputFn = { it.toDomainEntity()!! }, - mapFeedbackKeys = mapOf( - DriversLicenseApplication::name to DriversLicenseApplicationModel::name, - DriversLicenseApplication::age to DriversLicenseApplicationModel::age, - DriversLicenseApplication::licenseType to DriversLicenseApplicationModel::licenseType - ), + mapInputFn = { driversLicenseApplicationModelAdapters.toDomainEntity(it).getOrThrow() }, mapFeedbackObjectFn = { DelegatedFeedback(it) } ) } diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/validation/PresentationValidationModule.kt b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/validation/PresentationValidationModule.kt similarity index 69% rename from toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/validation/PresentationValidationModule.kt rename to toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/validation/PresentationValidationModule.kt index 975b84a63..021cbdd50 100644 --- a/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech.coner.trailer.toolkit.sample.dmvapp/presentation/validation/PresentationValidationModule.kt +++ b/toolkit/samples/dmvapp/dmvapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/validation/PresentationValidationModule.kt @@ -3,7 +3,8 @@ package tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation import org.kodein.di.DI import org.kodein.di.bindSingleton import org.kodein.di.instance +import org.kodein.di.new val presentationValidationModule by DI.Module { - bindSingleton { DriversLicenseApplicationModelValidator(instance()) } + bindSingleton { new(::DriversLicenseApplicationModelValidator) } } \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/TestDI.kt b/toolkit/samples/dmvapp/dmvapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/TestDI.kt index 00548cd27..4143f5e6a 100644 --- a/toolkit/samples/dmvapp/dmvapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/TestDI.kt +++ b/toolkit/samples/dmvapp/dmvapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/TestDI.kt @@ -3,16 +3,18 @@ package tech.coner.trailer.toolkit.sample.dmvapp import org.kodein.di.DI import tech.coner.trailer.toolkit.sample.dmvapp.domain.service.impl.domainServiceModule import tech.coner.trailer.toolkit.sample.dmvapp.domain.validation.domainValidationModule +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.adapter.presentationAdapterModule import tech.coner.trailer.toolkit.sample.dmvapp.presentation.localization.presentationLocalizationModule import tech.coner.trailer.toolkit.sample.dmvapp.presentation.presenter.presentationPresenterModule import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.presentationValidationModule -val testDi = DI { +val testDi get() = DI { importAll( domainServiceModule, domainValidationModule, presentationLocalizationModule, presentationPresenterModule, + presentationAdapterModule, presentationValidationModule ) } \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/entity/DriversLicenseApplicationAssertk.kt b/toolkit/samples/dmvapp/dmvapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/entity/DriversLicenseApplicationAssertk.kt deleted file mode 100644 index 518de79e5..000000000 --- a/toolkit/samples/dmvapp/dmvapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/entity/DriversLicenseApplicationAssertk.kt +++ /dev/null @@ -1,7 +0,0 @@ -package tech.coner.trailer.toolkit.sample.dmvapp.domain.entity - -import assertk.Assert -import assertk.assertions.prop - -fun Assert.driversLicense() = prop(DriversLicenseApplication.Outcome::driversLicense) -fun Assert.feedback() = prop(DriversLicenseApplication.Outcome::feedback) diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/service/impl/DriversLicenseApplicationServiceImplTest.kt b/toolkit/samples/dmvapp/dmvapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/service/impl/DriversLicenseApplicationServiceImplTest.kt index ea0e662f3..e83c3199e 100644 --- a/toolkit/samples/dmvapp/dmvapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/service/impl/DriversLicenseApplicationServiceImplTest.kt +++ b/toolkit/samples/dmvapp/dmvapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/service/impl/DriversLicenseApplicationServiceImplTest.kt @@ -1,5 +1,6 @@ package tech.coner.trailer.toolkit.sample.dmvapp.domain.service.impl +import arrow.core.Either import assertk.assertThat import assertk.assertions.isEqualTo import kotlinx.coroutines.test.runTest @@ -7,10 +8,12 @@ import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.EnumSource import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.DriversLicense import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.DriversLicenseApplication +import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.DriversLicenseApplicationRejection import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.LicenseType.FullLicense import tech.coner.trailer.toolkit.sample.dmvapp.domain.service.DriversLicenseApplicationService import tech.coner.trailer.toolkit.sample.dmvapp.domain.validation.DriversLicenseApplicationFeedback.NameMustNotBeBlank import tech.coner.trailer.toolkit.sample.dmvapp.domain.validation.DriversLicenseClerk +import tech.coner.trailer.toolkit.validation.ValidationOutcome class DriversLicenseApplicationServiceImplTest { @@ -20,7 +23,7 @@ class DriversLicenseApplicationServiceImplTest { enum class ProcessScenario( val application: DriversLicenseApplication, - val expected: DriversLicenseApplication.Outcome + val expected: Result> ) { VALID( application = DriversLicenseApplication( @@ -28,13 +31,14 @@ class DriversLicenseApplicationServiceImplTest { age = 18, licenseType = FullLicense ), - expected = DriversLicenseApplication.Outcome( - driversLicense = DriversLicense( - name = "not blank", - ageWhenApplied = 18, - licenseType = FullLicense - ), - feedback = emptyMap() + expected = Result.success( + Either.Right( + DriversLicense( + name = "not blank", + age = 18, + licenseType = FullLicense + ), + ) ) ), INVALID( @@ -43,10 +47,13 @@ class DriversLicenseApplicationServiceImplTest { age = 18, licenseType = FullLicense ), - expected = DriversLicenseApplication.Outcome( - driversLicense = null, - feedback = mapOf( - DriversLicenseApplication::name to listOf(NameMustNotBeBlank) + expected = Result.success( + Either.Left( + DriversLicenseApplicationRejection.Invalid( + ValidationOutcome( + listOf(NameMustNotBeBlank) + ) + ) ) ) ) @@ -54,8 +61,8 @@ class DriversLicenseApplicationServiceImplTest { @ParameterizedTest @EnumSource(ProcessScenario::class) - fun itShouldProcessDriversLicenseApplication(scenario: ProcessScenario) = runTest { - val actual = service.process(scenario.application) + fun itShouldSubmitDriversLicenseApplication(scenario: ProcessScenario) = runTest { + val actual = service.submit(scenario.application) assertThat(actual).isEqualTo(scenario.expected) } diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/validation/DriversLicenseValidatorTest.kt b/toolkit/samples/dmvapp/dmvapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/validation/DriversLicenseValidatorTest.kt index 3365c59ff..38fdae983 100644 --- a/toolkit/samples/dmvapp/dmvapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/validation/DriversLicenseValidatorTest.kt +++ b/toolkit/samples/dmvapp/dmvapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/domain/validation/DriversLicenseValidatorTest.kt @@ -3,8 +3,7 @@ package tech.coner.trailer.toolkit.sample.dmvapp.domain.validation import assertk.all import assertk.assertThat -import assertk.assertions.hasSize -import assertk.assertions.isEqualTo +import assertk.assertions.* import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.EnumSource import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.DriversLicenseApplication @@ -14,6 +13,7 @@ import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.LicenseType.Learne import tech.coner.trailer.toolkit.sample.dmvapp.domain.validation.DriversLicenseApplicationFeedback.TooYoung import tech.coner.trailer.toolkit.validation.invoke import tech.coner.trailer.toolkit.validation.testsupport.feedback +import tech.coner.trailer.toolkit.validation.testsupport.feedbackByProperty import tech.coner.trailer.toolkit.validation.testsupport.isInvalid import tech.coner.trailer.toolkit.validation.testsupport.isValid @@ -136,8 +136,11 @@ class DriversLicenseValidatorTest { else -> 0 } ) - transform { it[DriversLicenseApplication::age] } - .isEqualTo(scenario.expectedAgeFeedback) + } + feedbackByProperty().all { + scenario.expectedAgeFeedback + ?.also { key(DriversLicenseApplication::age).isEqualTo(it) } + ?: doesNotContainKey(DriversLicenseApplication::age) } isValid().isEqualTo(scenario.expectedValid) diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/presenter/DriversLicenseApplicationPresenterTest.kt b/toolkit/samples/dmvapp/dmvapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/presenter/DriversLicenseApplicationPresenterTest.kt index b502bf9f7..31bf68ee2 100644 --- a/toolkit/samples/dmvapp/dmvapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/presenter/DriversLicenseApplicationPresenterTest.kt +++ b/toolkit/samples/dmvapp/dmvapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/presenter/DriversLicenseApplicationPresenterTest.kt @@ -2,80 +2,71 @@ package tech.coner.trailer.toolkit.sample.dmvapp.presentation.presenter import assertk.all import assertk.assertThat -import assertk.assertions.isEmpty import assertk.assertions.isEqualTo -import assertk.assertions.isFalse import assertk.assertions.isNotNull -import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.jupiter.api.Test -import org.junit.jupiter.api.fail +import org.kodein.di.DIAware +import org.kodein.di.instance +import tech.coner.trailer.assertk.arrowkt.isRight import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.DriversLicense import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.LicenseType.FullLicense -import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.driversLicense -import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.feedback import tech.coner.trailer.toolkit.sample.dmvapp.presentation.model.DriversLicenseApplicationModel import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelFeedback.AgeIsRequired import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelFeedback.LicenseTypeIsRequired import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelFeedback.NameIsRequired import tech.coner.trailer.toolkit.sample.dmvapp.testDi import tech.coner.trailer.toolkit.validation.testsupport.feedback +import tech.coner.trailer.toolkit.validation.testsupport.feedbackByProperty +import tech.coner.trailer.toolkit.validation.testsupport.isInvalid import tech.coner.trailer.toolkit.validation.testsupport.isValid -class DriversLicenseApplicationPresenterTest { +class DriversLicenseApplicationPresenterTest: DIAware by testDi { - private val presenter = DriversLicenseApplicationPresenter( - di = testDi - ) + private val presenter: DriversLicenseApplicationPresenter by instance() @Test fun itShouldProcessValidApplication() = runTest { val license = DriversLicense( name = "experienced driver", - ageWhenApplied = 42, + age = 42, licenseType = FullLicense ) - with(presenter.state.model) { - name = license.name - age = license.ageWhenApplied - licenseType = license.licenseType + with(presenter) { + name.value = license.name + age.value = license.age + licenseType.value = license.licenseType - commit() - .onSuccess { - runBlocking { - presenter.processApplication() - } - } + submitApplication() } assertThat(presenter.state.outcome) .isNotNull() - .all { - driversLicense().isEqualTo(license) - feedback().isEmpty() - } + .isRight() + .isEqualTo(license) } @Test fun itShouldHandleInvalidApplication() = runTest { - with(presenter.state.model) { + with(presenter) { // model's initial values aren't valid - commit() - .onSuccess { - fail("unexpected: commit invoked successFn") - } + submitApplication() + runCurrent() } - assertThat(presenter.state.model.pendingItemValidation).all { - isValid().isFalse() - feedback().isEqualTo( - mapOf( - DriversLicenseApplicationModel::name to listOf(NameIsRequired), - DriversLicenseApplicationModel::age to listOf(AgeIsRequired), - DriversLicenseApplicationModel::licenseType to listOf(LicenseTypeIsRequired) + assertThat(presenter.validationResult) + .isNotNull() + .all { + isInvalid() + feedbackByProperty().isEqualTo( + mapOf( + DriversLicenseApplicationModel::name to listOf(NameIsRequired), + DriversLicenseApplicationModel::age to listOf(AgeIsRequired), + DriversLicenseApplicationModel::licenseType to listOf(LicenseTypeIsRequired) + ) ) - ) } } } \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/validation/DriversLicenseApplicationModelValidatorTest.kt b/toolkit/samples/dmvapp/dmvapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/validation/DriversLicenseApplicationModelValidatorTest.kt index 702c87090..36b62eb9d 100644 --- a/toolkit/samples/dmvapp/dmvapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/validation/DriversLicenseApplicationModelValidatorTest.kt +++ b/toolkit/samples/dmvapp/dmvapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/presentation/validation/DriversLicenseApplicationModelValidatorTest.kt @@ -10,11 +10,14 @@ import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.LicenseType import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.LicenseType.FullLicense import tech.coner.trailer.toolkit.sample.dmvapp.domain.validation.DriversLicenseApplicationFeedback.TooYoung import tech.coner.trailer.toolkit.sample.dmvapp.domain.validation.DriversLicenseClerk +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.adapter.DriversLicenseApplicationModelAdapters import tech.coner.trailer.toolkit.sample.dmvapp.presentation.model.DriversLicenseApplicationModel +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelFeedback import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelFeedback.AgeIsRequired import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelFeedback.DelegatedFeedback import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelFeedback.LicenseTypeIsRequired import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelFeedback.NameIsRequired +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelValidator import tech.coner.trailer.toolkit.validation.invoke import tech.coner.trailer.toolkit.validation.testsupport.feedback import tech.coner.trailer.toolkit.validation.testsupport.isInvalid @@ -23,20 +26,21 @@ import tech.coner.trailer.toolkit.validation.testsupport.isValid class DriversLicenseApplicationModelValidatorTest { private val validator = DriversLicenseApplicationModelValidator( - driversLicenseClerk = DriversLicenseClerk() + driversLicenseClerk = DriversLicenseClerk(), + driversLicenseApplicationModelAdapters = DriversLicenseApplicationModelAdapters() ) enum class Scenario( val input: DriversLicenseApplicationModel, - val expectedFeedback: Map, List> = emptyMap(), + val expectedFeedback: List = emptyList(), val expectedIsValid: Boolean ) { FAIL_MODEL_FROM_DEFAULT_CONSTRUCTOR( input = DriversLicenseApplicationModel(), - expectedFeedback = mapOf( - DriversLicenseApplicationModel::name to listOf(NameIsRequired), - DriversLicenseApplicationModel::age to listOf(AgeIsRequired), - DriversLicenseApplicationModel::licenseType to listOf(LicenseTypeIsRequired) + expectedFeedback = listOf( + NameIsRequired, + AgeIsRequired, + LicenseTypeIsRequired, ), expectedIsValid = false ), @@ -47,8 +51,8 @@ class DriversLicenseApplicationModelValidatorTest { age = 42, licenseType = FullLicense ), - expectedFeedback = mapOf( - DriversLicenseApplicationModel::name to listOf(NameIsRequired) + expectedFeedback = listOf( + NameIsRequired ), expectedIsValid = false ), @@ -59,8 +63,8 @@ class DriversLicenseApplicationModelValidatorTest { age = null, licenseType = FullLicense ), - expectedFeedback = mapOf( - DriversLicenseApplicationModel::age to listOf(AgeIsRequired) + expectedFeedback = listOf( + AgeIsRequired ), expectedIsValid = false ), @@ -71,8 +75,8 @@ class DriversLicenseApplicationModelValidatorTest { age = 42, licenseType = null ), - expectedFeedback = mapOf( - DriversLicenseApplicationModel::licenseType to listOf(LicenseTypeIsRequired) + expectedFeedback = listOf( + LicenseTypeIsRequired ), expectedIsValid = false ), @@ -83,10 +87,8 @@ class DriversLicenseApplicationModelValidatorTest { age = 15, licenseType = FullLicense ), - expectedFeedback = mapOf( - DriversLicenseApplicationModel::age to listOf( - DelegatedFeedback(TooYoung(suggestOtherLicenseType = LicenseType.GraduatedLearnerPermit)) - ) + expectedFeedback = listOf( + DelegatedFeedback(TooYoung(suggestOtherLicenseType = LicenseType.GraduatedLearnerPermit)) ), expectedIsValid = false ), @@ -97,7 +99,7 @@ class DriversLicenseApplicationModelValidatorTest { age = 40, licenseType = FullLicense ), - expectedFeedback = emptyMap(), + expectedFeedback = emptyList(), expectedIsValid = true ) } diff --git a/toolkit/samples/dmvapp/dmvapp-gui/.run/desktop.run.xml b/toolkit/samples/dmvapp/dmvapp-gui/.run/desktop.run.xml new file mode 100644 index 000000000..c7e694b9b --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-gui/.run/desktop.run.xml @@ -0,0 +1,24 @@ + + + + + + + true + true + false + false + + + \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-gui/build.gradle.kts b/toolkit/samples/dmvapp/dmvapp-gui/build.gradle.kts new file mode 100644 index 000000000..d57f7d523 --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-gui/build.gradle.kts @@ -0,0 +1,69 @@ + +import java.nio.file.Paths +import java.util.Properties +import kotlin.io.path.inputStream +import org.jetbrains.compose.desktop.application.dsl.TargetFormat + +plugins { + kotlin("jvm") + id("org.jetbrains.compose") + id("org.jetbrains.kotlin.plugin.compose") +} + +val mavenProperties: Properties = file(Paths.get("target", "project.properties")) + .inputStream() + .buffered() + .use { + Properties() + .apply { load(it) } + } + +version = mavenProperties["coner-trailer.version"] + ?: throw IllegalStateException("coner-trailer.version property missing from mavenProperties") + +repositories { + maven("target/dependencies") + mavenCentral() + maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") + google() +} + +dependencies { + implementation("tech.coner.trailer:toolkit-sample-dmvapp-common:$version") + + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-swing:${mavenProperties["kotlinx-coroutines.version"]}") + implementation(compose.desktop.currentOs) + implementation(compose.material3) + implementation(compose.materialIconsExtended) + implementation("tech.annexflow.compose:constraintlayout-compose-multiplatform:0.4.0") + implementation("com.materialkolor:material-kolor:1.7.0") + implementation("org.kodein.di:kodein-di-framework-compose:${mavenProperties["kodein-di.version"]}") + implementation("com.bumble.appyx:appyx-navigation-desktop:2.0.0") + + testImplementation(kotlin("test")) + @OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class) + testImplementation(compose.uiTest) + testImplementation(compose.desktop.currentOs) +} + +kotlin { + compilerOptions { + optIn.addAll( + "androidx.compose.foundation.ExperimentalFoundationApi", + "androidx.compose.material3.ExperimentalMaterial3Api", + "androidx.compose.ui.test.ExperimentalTestApi" + ) + } +} + +compose.desktop { + application { + mainClass = "tech.coner.trailer.toolkit.sample.dmvapp.gui.DmvAppGuiKt" + + nativeDistributions { + targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb) + packageName = "toolkit-sample-dmvapp-gui" + packageVersion = "1.0.0" + } + } +} diff --git a/toolkit/samples/dmvapp/dmvapp-gui/gradle.properties b/toolkit/samples/dmvapp/dmvapp-gui/gradle.properties new file mode 100644 index 000000000..1b291c2c4 --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-gui/gradle.properties @@ -0,0 +1,4 @@ +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +kotlin.code.style=official +kotlin.version=2.0.0 +compose.version=1.6.10 diff --git a/toolkit/samples/dmvapp/dmvapp-gui/gradle/wrapper/gradle-wrapper.jar b/toolkit/samples/dmvapp/dmvapp-gui/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..249e5832f090a2944b7473328c07c9755baa3196 GIT binary patch literal 60756 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 !U!23G^mDmVCRZ=noJ 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

U3o|tBw5ekG*G);5|ZL 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 HcK)caVfjayd8>BnSw|Gz9`$ z>IdQ%elerYI2|0QrH(Vj=^+1T+YyVRcKnzMY73QC)KoMh0xB|yZ7eF^Bzy=aAtWKm z<&s=(Z|`<*-(UZ@i$+K;$pPs&(`V*pXWx%!pXdGf?eEI9 z-B0dso&IiXVrxr`KLCIam3PEuKo-Pf({k;L-uroxdx}Sv`qoL3#XsG_4$C}o%?Z_< z)nj7wPhRUvk45#imgR?vheU=gd@6y0Kj3j ztf+JOBR#Y4GWI#fsc#>u3r?}=PNyUY0Kgc_Gj#KiU!uY-=ZrvCf?i6;XBipUNq9US z-@JtjY2BtxzTUD#B7t8nsAzmz4*IM@GOD|B>^)H}hBzdSzi>}jUe6BjF1wRTV z{!pk`7EX4{GoJrRUS7UU1OaMIm)^YMaK!1KPzDtiv+Cnd>qSwV)0docj^E6m(XiC~ z)_?Z_^~4F4PaH@{Mp4Km33omgkOS9xEDQje;~dY_#X=1+0w)j?1aa|L=jxS{Jx+g? zgak*^%6;u;UOyS0nII~a1ZF&1@@@6k5izi2$&#^ERaH%E*REBTE?w#Y0LB;?=K=sE z2xdAh85zhHF~hGUV_sK+u<{$d^Of0N&!ik{zwQ528>(A(qPwE^-ryuH-raJ|U*{Db zUH9IWyl_t>Z{x;|XL}8Nxb=hP>9OX~h856>Mbl}?XcJSPboY~XLwj_p$2E|60C=P< zr?A*zX*$2WrX$+5AkT_vQzo~*`R1Em0NAmmvS<5KE7hxIU1`ubIMLB`S~8je4g^(` z004C{(r$LjO1k#4D2zLJo4;lLjBJ4FEX2x66zGz(j}Otm%p;hT2gQ*w~#n z`1bvx#Py%6a^xAQ;#g-WyjNAV^4@ma+KpI`$zC0dFXJ<@Ut!gi(;Tyc24Pb>>sU8u z%&1Iw7@_H0dsjz17N6Q%#tB%oUu~$<_(TA)bp10>Gh)}>+g^C#OCM9U%F(m z4Gd8R#2K+LK<7B8hFCm)JRFX;2SeRsq7ki>bM85xv`r^0uhr_##%Ml(v@ft;WU>bs zfWH8!2k?r|CN#b`!y%uFntc5kz3atE$_2uPg2ou9U)5;!4H~~5!0Dm(8*s{rXc`f1 zC89ToXcG~AOhlh7Tej@5-|wHIs_Iwc$B*AKp}eB@*(MgbGD{R@d93!AnkX_{@gD_^ z*n>x+2OBg#cR1qH8UQc>z>NT|29OP4|K`n`d$w-fIYOuGK_0tzjA(P&B{X%&DA(v86|;1VLD*#JHR@C1N0 zj4=_w*8m;_&<@~b0E+;a00ghhwm;&R=iZVhDOIgT_~Q;E@nosuaZ49IqCw+We^w7g z45G&Z@+h~&aQ6YV_Dqbf9Ikn-V&#UFEqs8 z=}ypf_ZL`QWmzJvIIe}tavZh=ISG5dRlupJN&jfpLs=GvhkWv=fL(xU68?G4P>Bt1 z>GUGq3|tRj9e`@a*irx=0$70Lr||Mr-35GOWZ};hZgKHr0h>n_fZB+Of9rPCh1BkV z%%wZVNcK?@!wHpR!`XQ2kqB?@()qJt6L0q!kV|5~2jCQdFBoHg2ha-O0|0*n@Hl`0 z*LjYJJ3O-R{L@z`#S`Bn)^%{Qy!13XV9ukPCh=@!gIt^fb zs@Mx)$q*^>3uLx^u|GTVx2blzuSn_i+k{%TB>WnH{j!Me3nFq7QOo}Q`x`}3yf;;R z9{}fYc;48s;q~ABb_Lya`|Y=0dX;HFM2v`bJ@?#mb@=`x>kS$3+(<-0BD(F;Doi3> z6k-4-dc9r?5$TLEAQ?V~ivR#OF4Mn3>0V?K=RA_1pWnM)88Ud$Aeqw$015_cmTAnH;9y8+An0&7K5)5Q7aK7mNE#@;NS=O?&Oo-? z?Y(R&NN(QKM07mW-VUG|z_`?X2>=B^H-IbvQ6j1Z;6QTE^cpAy@cD=tV2l|=;Ye7IRZq1;E^X>dP*TrRVe=@POzdt)Pht z{P9IKj{yFS<|MD@0s>)-!@l4=xLxCbACkDr>bhz;TDp3eI$MA|JUlq89c*39Or0z^ z9G$JwkHttqpjRLTnb(@08HW&$j2ANt;Iq}?BM%?Ws;ck#f_QM&G#~#|M5Gm=ag!=W zr^%S{G4y^HR3k8338AwImgB4BuJ%Bp!^6#2Ac!CBvC1>}kOBRTL69e9QYo~1qPz5#3$EO`CL{|Nyz>L6PRW(;*Y z+yk7D%w>%KT(qV*>okyuJh8G(6MAJdAzA(@MOXQ%brs;}SP(EAGjft}-9Wh&}Ne zQHmlj8Kk@4X@0B2mF^zLT#ExkNFLBI~STP-%(K4Lk(r1*U!Q)jN^KI*LJ|q z8)VJ6G|ciifw(jaLV?Ec4ePctZwgqPEMrrVLbVyJ(sI1PUi?2ADpDh_nYscwkKo%e zS{MvjNd-%Ianj)4jAO1 z2h(>FGxn5}w|UyOPF`K?trSqK_OCJaYMNRR5elGJA@X%fCTLFnMO5!!GzzVDDkInt zE=C7Li`P|V7Gk4hJ)~G`Eqoq$Ma~eqh>g<$(LV6DvuZ1bl!h)nR*^MQ>f*_|g+@d$ zPrSgDzO*(AvH(xNm*k>`bf3Hx(S2`DKV#>+`8>)k*s(BI;WOf9L6QL(Yw)S+%Ht{Q zw{G@!lDi1HOWuYkQ@(wPfUp3b3p7~sd$mE2A|0aW4GO{i>P&Ph7Ee0ZBTN)}f?f03 zw4L4(r{YMNvb{P#$uhJ0kv#n?7BMDWZOiWv(yNohl8Wb~ee@Q2VQ1R~aNVh~!e2ae?>vk=#4;EJUx0=h#`5LcQR|AB(Q><^{O3F>B zG7>i=7$N$?%fHM6me=x`FTVz-g89LpOoZDrQ9>g~&;aAk+<8w0rGFfzSg1j>O|jdx zKK2y!R&>?0jtsf!>lYo5JC+r0iF!JzQ+jKufm0JUcKiF>9umYf!jSE3&vAQ$gC?Nx zL2cmJcu9JhA9Nrf;HKQb*=VMI&(lf-adDq{1la52ih$^{Z8D^XF(uFvsNSRRZQ8!MD-@>cO~p@gONwJkE=t z4uZThoj}`r{ae}8FW+A(or_L{yHPqU&b~8@cL>l5va)=^EignhdNif3al}8OY`@}4 zFnV#$j_H=BtA9d$DHM1H);T*8@Z`$q3`LcLT`RE+>{gKOC5Q75LduuNYb769-$fTP zaTf2cWvMQq(od{9stlMtf$OS<-V@TZ^3z)cm}x{2RAGNE8Ro1TUz>&IG5=+HMX>q~ zj`5T#XY@T=NL(2_a0(yb+6~VlFFD=`va*qGnMixvttu|IonDCBw;H_o@ZpInW@sD5 ztR|Ob>R?8IQbJSw-JAOyjP*8B!H)SUBG=ttQ8JuSJB3*hr$*A1U@r<)Ct)JsDb*gln9#7!b6q!SqFJw=}FVJwkSxa2`S|#ZgiD(}} zy7cA*i|NlCSryjm3cR$85^U>i5G-GflVGvZPJ+!0%t)uc_V=EAo@L8(TgIE{M=|%K z+zStfdAnrKW5o==yB!)TJ~=p$UEXq+mT-wK4gbaDB_k7`MoEo2C1E^$;j0jmO#KF) zMw$olRY*kA6EwLxAF=sWSJ`Q|E~5o=we3TLpci!E*u7pL^m?|E<+Su`)3T5lFT<6! zgSEbzOPRm>+$K9^49a!=g>=Llf^5C7j`C|&uV)DSA`n5+5xTc1?SeB7sV|^Qx{L&7 zeA}zQ*>489KY4YB3U-^ihbx#)Ov7*EU@{Av=GBFTZ6~?8Df707HkI{`sCxWHGE8*} zHUn>gedM&>Ut;|;GSn1oJnl6BeR@T<^LLK}Jt9Kq3vpa?qni(_?SXj6Vl=kW@6*YQ zkCwzDSd|*Ykt3EzJJ*eZjUr+_hN{@^B?g)%rXEp()2(nSYb?I^sAW8j6*{H7W8F~LP~URx zBSzWr6Ys1i!9ZRbacPM@f z_vVw4iC0XzB!!)oj*I8TdRa*)#H_Z-UX!Q*Q4EV;SyWx^v%!VuGF*zh!>3cHo!GTh zbk!w<+I=Q(PFNC!#2T0R z0sP~%=AK05qGt1b&jkKRDN+WT-oa$!&Xj=mZ1bBodn6~gsy`7Tkt?uj6*9qrXoT&0 z-h`$iCs(}^V4E1OQ?lIZJe}WS@A%46c0Ku9>M}2fXaN~!XxEW@WpPniYBZ6Mat*O( zYwH(DicdIh5M$c*N5mDryo8)Nv}UptT#Q2!wCQ@f3PVg`+YrSlY9JV9(_nQ}jD%66=-jzkGXf@ed>5tn-o!K*8vYZ;O z;e=^vUy=^sJ)u*3C$a`TW4KOQt9v>GCkDacKYQ}c135L30f%bV3;J`E!lBtfG8CIv zQj$3wDc@S*alF*=)03*7;gt2C3eoxPt$NiD3lMx~uFDSaP5eO62I9bjAy7<|G)|Re zFyysNYzk8CqJj;twstCAtTjD67nb((yM8XaTN5QY#`XVA#!Jl$t%`BPchaINU7cK< z6yTl@Ri<2R4ZN|D<dAZ_h-sur-B~2Z|k67Lu`Z+NF#Z*joE`whGgMELEYtJiOd} zwn)-BZ`(6`NSq0pe_HtENX)y6cG?$ZC@AV|1P9m80O#HkmD(G`*-js*v0>;GJJNlW zTLWFXgdaW14(?i}UAYt0s1ltb{~Z&TR$jSr;F8P}bh9{S0WmFd$6gVq5PPmb< zX`M@5ST%|W6dD$WgA*6dA%nz+_qW0eeF4`NiHD}ikm$}CFlveP``iK zyVnsLzp7%4WQnA#@bJ|L!5#QSbjq>Y(IYo#t=&{a7aID8_eUDBpHYzc^zvkT&bIDa z5}e_Y--AU9I;1ANf;RBSqDuad2CIrwL^gP zzlFYa{=wG;epdFw+lh;QK}Ddp1)#JO?dFw$m#nU>oE=Wc$KsNQwr;Cx&gacLJsoVp zZ+w>Y)F>x$cS-rWDtLmkRXq-bo{KWX~{ z?L0!|g?Yy@f-`${`swM5r2NVlw(46Ut^~ylp)-HJfEe5Df;czGh;ZA!!xFluK9&K_ ze6#4n`i#)x_IhVR6*1N&8oH2%`jJmM>4$Sv7s@&4_?JM}HQzO3DGhV}7X$y?-pUVe z4;BvMfaX)r3kj9#@pwzi8G{z_#p7}_Z(Z>*}2)KZKK|F5lkxUYK7u_L4l(O>-u)V zQ9Fn*dBejF=&L&1cX&pmW)powlvSogiy)E743(vV-rm`#Z@!)%o4;z~_>zm+pE~(o zz^}ySk$=m8K`6S(4{LJpb}wDaAYE0M7`Z$xnVd`@EvOIL94Z;>%0)x}sWv{6Q^UkG&*JOfSFi&nc|cpu13Mhq?XHbruiJSTH^t6AG=W|r|?Bv=6JF_0LQ%j3-@CaiSJBWF7r1i1giV9^&hVE2Lx zcAmE%-7c7wb9||f;&IoiuwG}!TdC7xJ(Z3B9^M?}D61YTF9vhSz=oNx7hLlQoWaWB z_V7o>o&<{bK=NC!bF{Uy+aum%pBzD_)lhC#J3_BN4M2AStv-uRbp1P4A_w1lgbcjh zVC0k(MdW@;xIaZDi#Xqtj*ci0XxiQew7d(GU4LBsDGWdQN09k_J?^ooIX1Av)CZEx z5i28h$Bp;3qT|+|gQKIre`bi?%D!(etJX>wdAw-IuFBB-=g_^ zZ$aCx9+Rbi;`vw!YAgZ*-!ItLf8XAowN#$Um{_&~D(sCdg#2JUGlH9B9^^|3?602A zmq?nfv;zUonE%=DCwHvY-YsG1VQcVVk;hqW$?3Qgib~>fCp;3AwfzMJjlw@Jsl5f> zmtxeRw9l{6a)uA-vJp`B5V9l7Z5xvcAAGcUy@T)iT1D zn@)w+pYlI<$Pnc(DxHGaW{!1RXq*2r|F#m3a|k*Kazx02d0IlkM`PRWHiwrcW<^i$ z1L4Jx^IocDafQK>w|N6GYNPKFBr;h@JKtkqRAo$qFkgJ}UY8K6mr9`(!1R-_k#n&o zvG>2b6}}Dhf%k{ z!`V<-zjc4&ATLiyMWA$FjrQ1W2t@YgG8~=_>=?tOD5DAk0IF4_nPq{taS9+@?$GJw z)@Ta3<-wB9$3NllqX^q1YFQDnFk7>J5~0q^`_aKkX_g5bxR%a*lwWx|vu3DZ!W1Dq z)%R_KqY3(FCSfUjCKT!^N?|mBf{UbKWRz?=#Oy%wiGC<&35yHAaiQp3#{9qEgu6ld zbn)rX2K5Km`w+0Xx{9-i{Xul2PP5+n5<>9tv?o=(t&A7Vzm)17sqD?@!SC8#O4+9E zpdu&oZmo%EUHAPbQ{6}hf<&Z;;fR|5TX!iaaBo{83G~W4l823b=Jpp}gZhg`Tc`1u zw00y+-W)MJ30M{rmnCz0H9nwffeOY=O)Zv<%z1g9A}rk1y-W^KMo|Wf%YCQs{O>ex z>BhfiUQHsHAj+z}o0`(VQou%Z>U%{d@R+=9V-lja^>rK;_PYx3$E+QNYTlsegsfvG zUS^w8yqkS1o!d13Few73N<53Nr?4!ztALFxGI4l4I15HrBh2UG<-MZKJ-!)v(&o9k z!EDE0os`0R3o9hv_>k|v`xf0A@?MzAD|kfnl@Pz`$qSjpI3=JR#Qz1m)f0)Ddzs%s zU@6jD>r|CD^%%&FCG+@f!sADt^~=AUd$RT^`36NBU!>s#!C9nl{eyWPJ!w%hvD-iL`~)?cx+A2E`B z?ih+<6LT;6QULZMb3k}Xc?FmKzZ=l|CJ-d$i28G2YisMAAqz6sUy@tyiAlZX@1Z0w)Ny(M*c2l^!?-Xw=^6Y_3`Qsf>Iz z;rh$VcN1z1?cVW{M@3OSn>g=hw%4uFZC+kY!W}O-MK8uuLUPN^EeiK6KVtTQS_Y%- zAS%15U}nJe4+FTcgfcK8nrg3Meep@`T!FpgJ}+Uujhe}0Hk0d`oACr_XVscV_ za%xJ{(B*GG-u2N^U%TJ^d`Ez!sQcm1ni`(nHvMHIqNAcsDj%{Y9|M6^HpRZO%T{dN z^ckLkvXZwDBgb~Uo0gLK&Vaas!Hf zM<(Yo0lDmqZbkEsnv7-$6A}^0Y5o%Txvp~FdY8y!t57kv}y86{iWq;hkmGU)LXOTMN3iyPBdSP zA6Bq+vo6Shbxn^+90k&wZnx7He%lh?toS%ClLiF7{(^jVzxte|D*5<56oWXY1S08> zqFwK_EgCK~PUyuE>^amg&ub@_Kb7a?UUBSN#~b7i_`RL(Um+oRu^(D%HD-CSJ;L^( zE~2%yRd-fF=ksT7Rk1TfD!)s-&0e>TrK9UR>`~7hTzwm?1y9cHVTP#z%f#CVwVRe# zt2rKvA&xJlUjCEIRPp&h@3oRzj+>+M6;pVe&2=e|x!ukO7;7CMBF8N!5=sou>lZ*i z*x?i%F4z>OLFKYC&p+ncw`9yu-*ud`k0m12N`@v31A5*iVKLM)6vfx!1u^l(Fz*rh923}~eYXHbN{#U8@g(4FYqBJsTnuT?{!D2L zMFEqeyUWOZk}KWqQ?E6NO4sZTj%!i0^3;)%ZeX2WSVD&qP>|1rAZ74Bcr4I?JfoB$ z#0{qvsq*?Y+)xUqRd)oQ|BghF!zRi>Ed5XIU$uH{n_99HhTT-L80T&}2!se4(JYGp zN(@PR=m}O;;^)oYvr*BL@k-;4z@ftgLsL^~#T1TwW69?v2i3!houf#wFk*sK8t+V_ zX`qWUJK}=EEq?AGKCJpAtb*1W3~`8vh|c#*EAO@rPQKn<9rQ(UwnucWpNe`MgwK#W zs;=CE_N-O9oZ-#&2vtVMDUch7i)un%7n6tL(u8Hf^=5cVX=xoL=@_Z?#!+SeWFY}e z@yC406-aFCTRnBg(2$aAPdUn|p!|O1vbZE|ZhU?+GHfK`ex`{}dkzWHvnFr{uFIYN zaOfY-9vUCL9{=@bsos9cvf)FbPo{5PEQM(Ae6^XdbDm318_6xUQFeL; z$!Cbe*xMH``WVREIxuDhYdiSY`a99rTyqEa|1+bkT{@-L81ON)Px5%LJVsK=!GQxu z0{V0HEa|PjR|Ac(M-P9hve^qQ?lR{>i-T);B@~`$mQv3DfH>h=Yz4~BSoVqV{bB86 z?an2Sj~qqV z4)H(!bZA}s~mq+ZS9O6#Ac zBcXt$URz0SU}g^fhv9{d%<<7PlgEeb*hhelDr+Fyuj( zNZ2ek|3Y@XW{6|yE!Bv=bI%JMD24v#yq+I_+`kl;@EB-C>tPpx2qxWp;0nmpRE!y5 z^f^^2Xq4HaFP36S;?wxgmBb4{rKv(yMnS=bscIk~0>hX7<#)^{?p2?J$%wGXl7l?tOEutNiBa=xQx30g~u=($S?a1^rtj$+`n z0);^(W1g|^Np;##A`lW&fjCVkB&#LI6#20q8lo3;w%0r|O-MVqSNiW1FnGtAM=Bu> zg;iBtuV)k}Ei5ej`>yGB$U%fo^Y+P^au7%9v|}!?Ozz-b)W27J`39!(^;+rRG691K z^T#|u?{#(MKYaL5Xr=|gG6Oh|VMV6GDO26iFjMAcI4Ow)T&9mO+whf+1U22+%rk-C644ui`6G4WbP?$K9Q(DII z3k&ZlY+dQi1VHcE8M=Dykr%b>?%0zML3jzU@R9EUS0ZFCw|eoivk#vBVSYU{H z+^LquncJ?_xUyx=c9i-^y<`!L=K+dPUx%&JhxY-+H_VjSeX522e9TT84;=rkT?65X1i0yn-LVH*g zS8;D7%WX$56{P&fdU6D1J>|7JA|tHUdN!jsQcp*;HLd`fjL`YIMmSbXb(J+om)*#PQDa&rpuL!`S`d0+uxm?#N=c-IXPta zmdyHkf&GI6AQDY)jv64Mk4dwf%-Byp!p1K5rJcH;V=S zSnbqHV&ya{yu)R`Smy_%dQw7#ux+tsj+lrHlU0aKDQrc|< zC0_iH91kG*h#T2sS8}-PL^dfzyr6kqhxh>S0+^kD=K;sOfvZAZH7^e=*j~`nfZSqT zl{c(x9M+CumsV{JrMTQ5HPl)RC09wLWM+}kpB}}|x(ObxDg*L!a-?q-hZLuvN6cP%;oNFf z+q#d<+sX9`6SD+sPZ0ZudwDQcd_A05G*cnxH(|idy0r+L_<3g?b|$36Nze|93f*d& zvQA2$Lv8?A9afPAoGOd7ZpMlVJwIF&m-5=_->VR@f9Q@T;dLc@z8Dpan<>?)^?&rP z=yji%JymQfp?7_9p%Cwbau~92giNrb1zd~>rV6_-{Qmu0 z4YDJ{krD+v3w?(sq?FQo!G&Ut!W!=@8zY}1eiiZGOC2?jVOqP0mbIy+mF;QvOZC7B zsUj{1eGW*B;$0Q*J_t{H(_GnO$8E=8_Di{;OXNlWY>N~WR{Zf4ao~+-T3$hNYRoP1 z0JgZxM&@-rs@OhTX*^bK))!24xg+_UD*3REqo#E&qu=1Lbw0!yC-MWdI)4uo&)(cP ziN&MavNE=(ySa`Uo0$?RtmmDNY4>yHJk?I?((Z@zf7lzACy!L3l{q-)T8#$)5i@vY z?4y>Q+)O!Be;6q6*+D^C$4*@ejT&+JenC~L1U?|$sDD~abnSox=zvTVr|V7eA!C#G z{~bs~Sh0G%yJFL=0>$;sL(Z;`AyG?5+W_f`fKry1mm7GlhqeNI1Co_3?jvy0dVvja z1?>8(YUI3iMPC99;99zjiKl3&iYEb~I5j`NtMjb^TQJdrmz%kd@>C+N_pG-!8J>3k zFH%-9st^juw@b+5bQN(oRft@519(i`v7i6x7pn0I zQ>Dd)3IL0&em-6M6CrWn-qQ4NKIC-+@pv3%j_kwH2%qZ{T@$J15iPc+x&yCcVd zAs`=nbZi1APHf~ER9ex@lCi{(VAfR<7zCISMa;QfzvOTsx--kyUR_eMGy@lzlSih9 z1BgQO0Fdcqk_0^|#qSIPed^~QS`o@v4_qA;Y!J?1&+7#%VW%~zLNm%Z#`97M$nHjcT$9|qAQtXuRg()o0Ox{FPVIv)@T<^@5VH^q=zmto)xZa!_!Ay>ek@E)QQ<5Y z$6Jg#Jj#98L1ELY2}xqr@jqJyNE@{d-v>Y$!QN{=@!b)HSkBxpjQRJz&@sSMm`De` zX_?IZ#e@zx#1g=b{ySNc}JM7;7QQPFdvHKPEa|_Y-v(L|2KWC-^0n< zbjJv!JOy33X}{@Na;v)hEmu-jhUq>iYtJOVPHU%@+oV z1~oyO?{Ytrp2D4)d8;_Yu7hn%RH`tdGA)g=m*Q$JPg5!-xtNI+Q<~sy=PI@Wo^}F2 z!R6_K-$x3vrwVd&bC=G}IyicT;!Kd_aW5-*bFFBSb z`!suST*&~Cgc5Gr4m%=bbv87~Q&izYY1{Md6Hm8($01>y@~%;3Kl<>9;;i;cyza}t zFZ|*47~KyjA?thE6%_l=2G6%+0i)qm{x7*K?Acsz>V0x#qlnJ-3bXGh0xl=s4h#%@ z&Fg0ecgst>GG&A|0Tp;NUXyLF~Ex(bkhESaKgU(81 z?11Z&xV3{xO4*O?R4E8!3`K_~O3;M+)_14`6#%~U^l=D4E|eu6gULk+-$zyb8@RpokmU<3ZDgH5)_`fAWgxul@l3(Pfj-!6;+ zb5IqgvCZmFM_0z3d9VB7r%TnZ{#zfKWw*|(LtXu@Q&Lhcx~QJwmzSXrC+VUd4q%r! z$tNK#Ev?L0y>e|z@7-VWk>~JlLC<>e3QV-LU$UPr3;p|ynH@i><~r=JROz`T$HIpl ziH_@ZJA#xW=J#=wK)nIiV`xx@4f+R<<($B-yz%XsT~t4@X{2G0M5JDiv?qJgU8OnYKLSvHU&>zS%tHUi?H)wREET7LaeyHu6XJ< z56*m3j_cUVVR;H?jlbkHJHcbCQs8dE8N2o&QE%K8^k`Y z1U!0yyB?1FwD@Vd(h;aXg7Bb%*9vDujvA&#Q{DZVNqEc*a`~{y(lamp#+IHT{TYs| za#yvJSqSq?u;a!$9sZ5fP|uu8PD}dgR|nFpfoG***=JdHo}1XAb)Z|^QCC~-@Br6- z7USr;1Vw0lyk7E;>FD{mJ}OGP-+dcFISc*bD7r3s(wcZs(NZyW_PjLLuiQgYqE@+0 z{a~~Z4|-*e79ff*{g%{N;5_@;1+zLmf;btowliXk^bU`ig;re|)49msa0XKR*?PIH zHU?)uSfaEYN6b#jt?M^PS0;j$+^(eaP2u0OE9&aZ@R{9n=h>Fp8UFd z9$VaeKs9G0*|^j|f&RuOankwRS}lq8QYitk`0=o$@|!9*x7f_h3H6~W<@;FK^|)N} zXrR7~z^Uf!0}j0biYw%_@p1|?NlH!?hMTpH;m zIK3rr2UOt&o?>ERTF-jP{QD{a0O%B@hoywo;;hhZSqp{%BEe`)y#Rin0FO8Fx z@!)|W#IrR}MR&@r1G>UwX!b|-msvSH54FAi=8=QAg=n_qbG?6c3EKtxdsQ!~Y={wv z;VZj;qBEFKw;McBbCxs|p?k!QY+tMCQDb?%v2vphG@ zAYl(PI>uL`?gR8GA&bz4^&!CtRv`P~(aJeZDlk?9k|1ZS7auT@)wR$xAt*@w@O$6A z@arg$%c}F%Y%c>;g6H^l^piMA@5WY-6%TFHU4sk_OxE*Rh{;G@vke2l4VYs^;_ENg ze0{M3bc-!f@^n3YKfq~R;FI+w6?}k>3DX-~JmG0m*z;emz=W-U#{=Upmd^(cUw#7O zq0o04i5}vYH{FEe&7%MxQGo-2_dhgn!%3YgVh)SW-_v(ps9vggK?S~|d9f{^vT%Xd z$#SVuZ9YP+o`>t{ZYuAxh&V9>1U4rr(AETHvZ-*oZ$M)&uklSl90QB=p%N9;pzv2P9EQ&Ee9Xo!#z9N{dg*}4m) zQ)@5uAGr!6Y4Q9f)krrq_2yRxH@BK=mmE=&LFu$iospdP>o;c>(wLS0)suCkv_*r z!HEZ;$QuIWvGZf~nzLUj;wQ(_6zw>oE03vMs#jkwK_Rm6Ak(^!zJ@dTaw~i@W$(8& zNs{*U^(BE}cfQfht7`W*Ut=0dAm1C1e8WQk@Z|t}tNizvfH`^( zS`8(_#e|kK?qKCmDl8y01t4dK17J630^*)936!Ya4~xdzK3i*TZH{q=TZFeJ#uxt= z-%Mw^%l$>bJt_3IU{kXmIqQ|@>Dp@mJq&O3L@6jMTkKC4N5A9_{`DrD$94BTItIpP zk<58J0di~vP-q*0o^3vE!)eyp zMk_`gx3m9g0R_MH-@pK%4=qIbv3sL-&;0HA zL2p~gsUkRSSNUZob}?0IPlpnng&P7c&Fa7YWO15VbLAk3A3SN8JKM>0n?@P0L zj$r?w9x#cE^!xl%di|NF&tUT6 zbq0cR#S>)=Tk`_@Sl;+JXOFX;c6-}KG>z2(bCbK(GvUx_=$k2*O3H-ZNZN9-fS=#y z2GgybNFznnwAF{(mOwzWJg<9Gjq=TwOCo>>TB*k zu>u|8&B+rZYz3PVI|UrqmIRvUOfCeQnT~Maq5?F}G-LqUoYTV34e4f|goc;pK!%#V zafD~*UAu7J{dOAaSE?ZW?f^}0`}XOxPs4+mquJJp$26Ak{9n@0N~qT0@x9se=nMD@{Blo`b(`=8$s}mOd za$o?03E*saqm!au7a%f)Gyha`k=Clho~{Za&KCVv-^D`*QMIL%HlZlK19^GI|6r?j0MkOMA zvF@M9?Qd!-XND>)IZ>8cf6)nieV07bt%Fi{7V~TGdp_e+dCklw8c|WvHLF%5PC&EZ zgGoA%^&{dF6S;4_o^E$wUkVBe>&f~K>lH1>G^|68i*M9R%C8)wrZ6K!z6{gGV+NW6 zLbwd;i_H9hsTyzh&DH%0q2&s-sb3TOGoNmxbMvrsEia|0v6?!B6+d`|ACaX6LfctK<*jX`4A)FQ#^` z6c+$N%CtaM>z(wY-8;c9MgV)kAq0Lw!EpwFM3re*Sk?ag^71eOju;q7vtEEU{X^Wx zT{l}b1gM}LX2r;uf-}1TzW}{B5fMc5!EF3iT!g>Y>M_#Z@%+@ZEgb8LvYx-EKvaTA z6RBWZxY5ppB?VKSekqweXs+6Q?CwBEr+A1}pMk!a!+S++Sfm!9F>QP00 zkCT;=;zIWoh{yf)(Qvw8Tv%9G(ZQ~B6ZE>FLs?s!NXN*_V)`a3NjY7BA1?F!DM=(J z9c}vW^%Z!p=xa%!1d!PA$^%6QEz(|`oAD(=P({<*#6GNy){qJ!E4_~uPJ}nBu^aC9 z;Hm}xIfS=TAKsAshRh##RAwA77G_r1#BVR3b3jmmU1^#5u=q#AI78!MbqXW1_OgN^ z!{$u1-sk36<=N2Kc#J;9;G_KJv#|11BOp_e@R*|(W;jQh-tbQXP0@$6{nu*9puXU^ zLIs?E>~;cu9)U}YUwG$<>R{aSuasz|c2k1)0atAf7xhx_r7y}9#$iU<&MWaI{Hu)q z-*q)!SHD?H8KzrWn@gn=GLZ*+hFC4zoV?G@c_TAi;0*=oAd;ZnwCAVx`(v}6(af;9 z>fgVUU|Or&!7LJ_UT8&(5(k)rIQjnegO=}->)TD;)AdGhEsJaefKMmT8@Eoltj=8( z0*+&Bh@Wc`D(Mq4j3a({HU^s{EXqi89rw0UbOyYzkUke zkeGHPpmO8#d6@O~1j?r0AP%?LqQ}z+jEn$xw4_Ac$Y>OhS4nH{?B}b3fNT=WTG2>j zX(96w=yL#5qwY5Pa``{1WN%B!&Ea23$-2^CisOSKKFtHuU(>5uVvY<)M$p@10V9dD z`8Mec%Ow25)L(lqO7$2! z{Hva0qfjUWiZ4aaGT@a)YAP8YhMoI?Vo`2|R%A}aTE_@;M2pGnr zG<9=DJ6f-@H)iX}MA)H?bz@~r2JaI(XWmQ-mxCv0TmEkLyWPLl>cTht>gmNPo7 zGP}i#PM*ntWCZ*k&a95d2iY3aF63lRW6FkRKVX*SGb`(l!fgM=P3I<&-`9**Kb%P8 zqf4Zpeb^w+c=8XdX}bgH2$@yI@mb)8zuIxV?Adi;)6i0MV5mM*nHc-;07>XDyYstE zs_s9QH@#m*9G=CEeX57FHI=MyY)C8>~GDOh?lA50{&2HTb?;YX3+l z@B@t>hvptNzX7#esYD(F6M{M4C{JbJ5dw)z4O;b%u)QHkUnXH}Fe78L!=q{ZX0>GY z`v;nLZ#I-7J;gTG`<6<|D_u}` z6dMgh0}Q%H$W0=FfO-9nl_ko{=9WIoi``-*g=#ew)xYQ7z$As)pU6R)wWx|?!rH-3 zYBJy!i1rnr$B%f^2kKjW&qDuQr>B<|^n!sMGlYrp*L>kt>r zZraa;ADryg*!5+dRHBN7%#@#Gdme_Zlc1#w@|bppgnYk;CD4EJ_t*e8 zFVD;mbCazpHc>>6)}OE;AF&BOz{uLf^bcVXbS@Ve$EaVHd8Gl?C%DYTq*GP-ba<1tD5zt z5yU}wIl|d&eW#4a()gp6m%ATTP8Mpz0Rd|21R8ov6ebj7YlOXf13D}i>Q=%d{kH*$ zqYVm>o#S~`iNNVnhq4y%5hv-gn$|JgCikg`pyF+b$62?&MYBxHR;v#)jW-;Rz$8qp ztrw#+aQgvWCcn72cLm_M0IV$0_^Oo83&pAXt>(o!<13?}T07vOJPMH$)Gc ze@f#fNI(S57FrS>E4$L;Ti^@h0d2elm6dx;71g$#0Au)hHxp+@pqku;=m9S3IyMjbT*rwGz;6(so23k!asdRpj`VwK%I)JwCB zRGq+Qa=P>(i?bDdj({Y&m2VxE0_*qcJGS*$7XqJ^E|@d&i2=$Pd`js>e0m9(bMWx5 zUd;2xiQVkc(_G+481dp;VAKcZ9L9ci-#31`#Etg>>J^!Xh`+V}<_f4&m$`7s}e%o0ttI>=#;yy6Y?&|@j4c@&Cf3``d!l~wE z6%{D1`+^AClCoDqKmM0_QH3rlXj>s3w6n*dejDAP<=Xd7cT3{JB`x|#f)`6-;2Pb^#pP(&?^@Q23yo1toTNiDKI4(kaosTMyS?$ z;k3JWp4_a$pRy>)%(R`TUbSRLd_q)0-kjW+LIT)I?$Qz$`&dAs03Po(it1>l01xDR z`^dJGAU%^IHd(t46J^=;LX6$@hu2ZGe@4qC*M0f}nW~l+3@lN`g{P&F0vJVDSQwK+ zB1jUEl;88#Rt zlPf%qrjy|fx<*mJ6A_u3zv`!9x+1e6xj-)XkZgEo)U)@2YS+Tf-RELSY*D*Kfn*AD z>#xFFnLQDAk$j5+2kaOqb==mIbTA?$7fVi(A`-r_m14ZzOXi5#2ss7*1AyfZHoU%* zt6zg#9}zAGOc`@8?>Gx1iotMF8QUPuT|2xqGv06ZQI3`Z>%4{iUcGOLF?FrAlImsV z=qaxSnp_iUu2i`%Ru&#pvsV4$rkmXkUP}6l2`)P!077S!0>v9G04>e6U-NUcLpL1A z0+1SiO}8J^zZ87Jb$y@$u1X~As;~#CGzPOR^S=vKi9Jmq+*^B>XKFpGC(6kV$*@$5 z145~~zO5oX^|PV*l2WTsq0rhs2hpBj6Z}(fTDJ?pr)bxh6YlRX*cC_$jtuv^zpyzSo442bN5zB= zGy8(?_xnEuszA?r#ljaIn~P3=E&5(zrk4!oENXbKwGnA*y5?)3<9%oLc1fC6CsVrV zHz3E7xI5~KpcMR$Nz8n-Yw(ydlq$S-E-Tyt-*>4t8=?f#EZSgPD)`y zdfQ&GG-c8dmE*1Ym*ch-7kA~TBBbY*=jI(7SJvOK+XS?d2ezUE*T;x4upW&3;1H@jlyiqQ6b>P>ByJV?|QWEj{=DLd;d*DnB> zN~Og(^FiCKZB=#kQ+gf8qGEP+v=X0?08|H5^z~_($CDiO=WT@nfmj0ovU_v&(ZEy3 z$GvpbmXqw1lt@0#;-Wcye@0aLO`Y;daiczJPWSFVE^Nr!Rd@ldM99007zRoJ*xj9j zo|XURja@VW(EQ~7{`vyDfNak0{%EVH{m>#gW9x>zFu#jfwG%TAX^A|g*&Z+SZ>q;81gFT&G_hr9EEIGBNqOZ15OzOhnqF_zT~D$u);XMW?qB z6MH9S%LAwcu}$tcjYV97k#_Br>^sVhe?HXz^nCu5e9ri46 zlKsV*fT}{guK3qyqN3G^KM2nI_dYb-m&IIMHe_;|=E*Jsp5{}TpwUe=<=$^k1_1bF z5HOGSwsL@|Nc=DFZ1%^bv zd;(I3z~hBcJlfJC$rsOjxg}pUJ-$K$y?Ihg)i-|BTOhevLD@Wb*^yYfQ^3i^k|T~{ z_3*66Uzi}Vz9et{WNFWlFmwJqW%3%K!!yxAk{%1U-K*pLQvLGF`34e~Z$J!+{fVrg z=*;pYp5*V*DmGG+GsNzD8~E%al_eZY8Qu=;!Z9P~v2 zUncsCFq>&A5Bqu4aE*7$R#RY(?|0FfK{3gI`uu$RxO{hXmS0EFI{{ITjzSYC6Sy*SU7raiIS7vYd+?IDRFpi z?c>+OwzYpn{k_q?!|^uTL1%#kY8aS;e&i|iG~2B7-%&rbeZN{Sz;J<_6&sVqaAP51 zzK~&!)yKt*krBh(HudBg-@LxJcQLB|DdpOKAayt$PBzo(dLSA%IPZACHqy14(gat> z()5BD+N*aG`Xw;Uc;~7WxV}p$ZJ_a+m5JAl0yANueEOvW@{}|ozZ%KurM-%zc=L>` ziTe+=*e~Hj!@EyIW$CrZglJ?%NQd>y zB0GyS_u77)ZHRi(*bhB)efL1Pws*XsSVv-I_1DjX-v$TBQD3Lu2b1ovmaDEGv|{OnSfe0y^v=$S4YNB* zE?O!ez~-;WKw=8wAa)(8EV0FoA<;b$ljT}u-J^HpZT=fMYWwZBfF*9Hw;t?{KWS)9 z%t)GOe}0!;U*AcA$6@P5H)U0najo31zO^QxUnkfHv9fe8RMj>zhS2z-^fELq_+?>r zoldJnifwh>3^8Rm$vf38~ zjG$w>Q%1}w^xumEGS`f~kyPzVF+XgA$`q5vSu|>%HQ`Ydm6a6X%WE)`H8Ftfm@*%I zrRdJLRBDj3(g^C2V+Pp#ApX;FOjsJN$pgH1wdyRvXzqG%{~l#X_{eBy@5XS04Q!Og zPoS*)1*6X3Wq92~d6@@&1B`##JC6i-Yv{Aa_GGOLpY zs1R_e#?w!-yr*6kUA<6=W;55l3J6K!a;1QiR^e@9p?r%L5USJvu;t-Y|C@XJ=&}0x zx14Vd4QM?OEsKA#<9z@65L9D{o@LMgJ%KeAM9>kqqOec5N!dV^vipZ2Ohn#oO-;u* zSTX-tGGs{fE#wj4-*1V5$AR}yUtJ8;s(+z$5F7g)<=SVqa~8bCGLKLD((GR!zw4_p z3}2ry7+(;pFfl{buc|7aXS`XX&f5o(a9$fg%r=qVg%F9a$_{_n)CGb7JmtY#Cy?#aj&GL zq!?cgi)usonXiUhDc_2#GrHJa=F3^|2j#HTS}x8bqvliGlh7YmG=A)vE})y#R6JTy zXY0mhZi96_0n^bfuY`o4rlOQ!rR)#?LSJh!C2H+3UJ>=2)u}v+r6n;wEu}O^WhjcjRm&sk<#gHXiJWoeD}U;uLTUAHa&q@{wQhKS5>{S zl}Godo5}-jDxUR7za_xRp@IMkdAAyER~v%Rljg9$w?YM0DI56n zx+1%B{cXGSrz7&mtX+e+D#E}#MebD?xQ=8qB$ex;dH%gYU^lTR+jm~!sb+ZVs_p| zKbzynV2lG&;yvmxq7QH?;Jr)P))F6-A4N-pf=w@3(EBVt? z`{;4SYQSB#i((+RyaEs2P{h)U{*qV^xni{k&I*R^UZmXqbV|9DhE^>BhXUf#Ow!o` z4|1QxLH8+*hsk`V`bqXR)1oC4wH8Yqi)(2u`ER;6u_bhMrk$R@C0XamkozHhzZ44u z0n$_Ry17&ENE#~9{}ze`+Jb8r89Si z>d_(D`hrs;)9u_>{OC|Zv%rAk20whqdDR8P7=wTtAlXq^k=Y&GoyVtG}S) z_tXt4_!DMDu_aT z;l;$Uc)exrqM>pk{mkiTThll=9$N@LtMrB`XLKCTj(vXh^oGPYom@jSr&N?W9z7Ml zNhHr6w~u@?%z;lTyWO~3Tx5W|poU!ALN2~AhZ-yAXtZ##oQE?%) zT-vakx?ty@pP{;X@0!w3DH&i4x8;qFmu_YB--um)eL5y$q6j3BRy@O)Ufz6xhpv&L z{H&byLj6DUu4l=W>gY++^v}<)L*?QsHDGmmJLddYmb)b9 zeKW$i5Bja^#2kxOQkym=b@J^ z(KvdN$j6MGdz6%qLMTbnEqOhhrKh-7cna=6=dSRn^~azcxvw5fdgBi_h0GkXcW2(l zoNG2yroLGjT><YM;bGki1#E6u2SO0SuJT>5O-^x|~m;^wP> z1@cvNTm!Y;X*|E#NdIhfJRZ>p*a{=IUP3O4cAeGNg)DidSq>^+KXeyVV!;Q{NLHlp z;x>t2e?r4JNbr?WX}}-bPN;!pSFj+x3JlCMRThKucWly!v-e$-K~$(~F2&Ow4DU1{=le}#d+2zV0S z(obNs5*YVr2e#WN6f2^7dbp7Bl|vTrtR4n{fB=kYWa;xE>@1Hsd7ae5mHz&lmxO4f zP5d($ko_ZHqMI`VdO*q=&mb+xR&xw{3PktBMukE*FLLcgd=&4_o7sB-cjREfSQkP!ZiQEloGi}yfIMzBDfKOdLY}k` zDsqxZBW@`d{AT41wjNo*oz>T|g2#PCw{(%r(}P?G0;*?N(X~m<;^+qY3s3Ch}LC!?})+!pKb`1%ChkSs7l1s?jV9QRClKD&Llo zRBY`Wfs3hP-YY7$@upci!ig2T=r zv<6(q;O#zB2^2=h!+Oq2G;J`7ptA4dF4sAOZdMwT&XIsjn?pRvguzYacwtycyiME0I_>r-a(zqxRGPYi-E@G5+ zeI_M$X><1-0n_{S=%=4Wk|p#FL=<4sb*3Zvs)=+otQ@Uj6QBME@2i3tz(hu#SCN1xNXCtq#l| zKa7^?IcG-x7cTtN^(Ye>T+Po-zouKy;bs>E4(-~(;8(zimLrs?>A>5YNQF8F!Wsbm|VOoXw}FCVix;_!Xvp5+Q18!uuU#R2vyPaX)5 zGY_I&v-k;2-K!lVPa1R94$&}VgWOYfXgCxLx&NA!4`FDBU_9e_h}1fcJv2KE8qSVhp1o75bC472*o;s0lwh_9>2BiZ##G6-l*9T z2*Y3C=9SwZ{sulI^zY*L(-Gc}MSXxzSXU=KGHwYNnG80^5Uqx^PoNesf5K_VXX{Iy zq$HLx<)X$4B0E6n>x@kuh==&NsHAIA7;EZ`#Wp{p*7WKHdU!Xzo7}~K`jj9O`WxwY zJr78~{)Bf*Nn0KzT{KGl-Qi)eRcxV&J1&EAc(bAGjw;@tM- zm2U>JPg*8rq0@QsVi7wQw%>*u`le>^4_ub~J=iPTeEiTyLSNgj;;C~2WMK-?{xkp@ zPGt|F>gl&c_wYV@SDm%}s!zpAWF=`5T{od%=Qqw4hF^a@Zv_v*%Y6$gNU~tx&_9Q- zH~IQW0QHnb$bRVnbgThOu3ybtKNS$}ItQ(;MIYZIUit@Wb-GJ=P1Xc!Uty5SdYcft zI_9^0_Jo({$OCIM5|+s!b6*q0)jsfIv9yoNdZ*Q*BDZo+rAhvL{z8mAe-$g_P3)t_ zw2<-v&)f~s%u2LF$4S(e!j@@d^k101-&3MMzhD1GQbu9!5o_q8Td!$t!8tcul6Iyt z563vH?biQI5`pzbQJ1&Ppo49ZCul zV9@9Q%Y=*9qig?7ahiOzK_mlmu#Mrz9*^%o;FnxnAbk7F%f5un?$?A58|AW)^*Q$L zoQd#BTPQC?4opH2*{^ecJ~Xhio2r5n#PITONN#kgMflO$`NJ1N@o8`-x|6dFPZkYG zlU3DPVPegM21nLN_hr;n(s z>4G)YyE4;2tg~~JNH}x0*Z^Xu`B8u}QOj~SRY+i>o|+0zE|WZMGB1Z_0vhux`qN zrtppj zi!m4!Q&PkeC#Qt=7p6AES*fFxWyvn`_UluTB@B|z{`%5DnJM?nr-3|-xzUGZp&Bdm|To#$vNWtQ2((o$T20OJ7N{96c) zq&n5Aiq4O^?NZnu1e?U9BH$%R6)2$iN8V~~uje+R9sYg52f$RQ$)ck@cl{scvzX^* zyMS6sd|`kBHJgg4lGNF4fZfzo{YOEe8tU16esY?`1=-XexWi*1so6&BobYZcZbh?L|rBK+UGU5vB->a589Epff!HUX_{> zRRkK7+FSg(d%#MKE|j;gxWgao_Y0!fo_(7((sSIQeWgg7TURHPd{^70as8hGly5rM zIlMK{<80S_!3&2=U!RQpxK?Fxa0rvg*O$DUiyeRhZAQ76kz`GnvO0F8Mjq3-FP5Di z2mJ{kSNmmip&Yk4h)s!V&cNH9%*H1sq^e7Ygt^Eul!#+hx0b#F zzIhziN54pA_9~>3;=$>!0bP!PP=aC}>>iOS$3VDDy}Uh~i4IEjYbb8=6>N>Drv6NT zanyD0lc79{Nv^ZAdi;iieCy#Khly@}YxnNV$B#QUKo=;|t##3eyZ+~x_TxjDC}o0D zHnf3#86VAy=E2Ax>L#Qb*{Q|(Q1b%TD*gk0h2DVFAl^HviVB#~1dcAhAebs!+O5rn zuBMmZQIZ=Exz^5Vp(rxcT#`QW`O2Q@KIVA3k55EWrjk+%{U|D7{d9F+Nl9)|%>>m^ zgCuSAv}E79F-~&j@I+m*d|v1bEoKPSz5fSR0*nMSqz=^;s2e5uLbyTh!2;oX({gD9 zj<4`WgV_J#St9|L)TLK!X`a|e>E!K~#^b1mREI%YhkE^_#OZSd?O9^oBSKeew8F6c z>Vco)0@df}+$Nt}UL2&qptUoxD4afIJ6?8aREXq5ju^nd%|70yh0<$;#}=70 z%@RdH?pI_)D8C0vbjY|F(v#3Ks{VweISm(y1K;wq2c~$mE)sXz;?)Q_G{U$BiY*K1cUX z?zl9IE40{V&aFo^N!Xg;!1o=(2R;OMm_*o9L@45r1`j982J;8lhsn#0Tn5XB0L1eQ zs?W&*H47yOQxKpGBM5`EW`D@#qzuytWc=F^EAJ%2E5Tx?LE3FIhjizyqtNv*Vpy>L zqX0>*74TK@ab|{8k6~mK06|6+coDqOExxj+s&AWeFfVn_1*jm89ZRyI+ytsg z%bmm@4L`LW=1BOX&2qJjTotkAVSY1EUc-auqeM1)m#4byeScH}mZP|GXbGU2&7pod z-}Rg5>oa7Wb4m!#p+GMkDi9r-ehy0Y=5VS{*`cvrc(!~oLHT%&P;K0ppOPmzf=&~3S2d!9C2Z8^1D z+xjC7$pyPTpHdy!~mw1bv8e%k}2NiD|E`B-*->HrWO8E)RG z$WT4{yaOV4V#dm@hnMOS?U>^A4IJV8$S{AVP_Bwf#{NNn+Y2_=d_Eyq>>Ei5RbmE$ zuiP?z^{Jg{g8ho_QFUnS2}QG6M?hJS)9PKuIN974or=qn;$%4Bs`9J|jwD?9GjRvVdyK#F6p0g2D?7uL;8SGu2@(hz7eJP>u8Q z&Wj#u%hkS@q4Es^LI)28KU747ci{~M)Gl#-xC4!uP07XBvzvQV+#}iX^kf{pVP=O| zh^ddfVTdko&{X70g-@Qw1D93UQKY8S4)LDuwi&4lqMg6KR;@?*@FTmX?eeST5&`{F zoFlF=gR|)croGo)@r+}omXW-!$sv5oFR(yS)H`OXddXAJyZWjcwoc$Qn8gK9vo+W= ziZGAwou$OoD9<-Fmr1g?lbqFB1Ax~oIzVcRhhL}qjrV!|rIQgoqP8~%bu+?t>M%AV z+3c;u^$Q1}-30h5lYwE==mg8>!5F=`m%N?XN8JiN#DrG^Qy^aiHT{pzWViOq5?NdY zr0T7~Qbi=s3EwrI6U25f{D5vZhsNhQ4w3s{=qAFieU`Bi`<_4fVUh@FhsAA$WPhoS zx`Nw}s%>Q5d0wt#PKYO@!LpRc=;N!rs!4L9w#FvLNvAfDZ%_VuROY_Ix%e!&FD4X+ zB-YUZx{wW1QIoh7M|`?zhWr~8*^Ec#Hi>Y$O(%?1hx}tBEPNKb&u}747$!LA!wpqW zv0KxDd0MpP7tkS*eRcHrbVVU%zWCEk;pu+encS^|>w2AYcleoZ7X3qGMLt(&&>@TR z=gCOWGOI&Uo=Gc!-XlqlYMjDxOjMJ#X}CdxM5+_RKB1F zUJ$LxAP3)$Jpq)eGGHgoG(sD(zZu{! z><=z%=~Z?GY31Ada26n`tieboe-m}Bh2R;620ZudLNYLz={RB1DIKQSUx!ii7M!L#diUrDzQp&C&M+);>37a>DX^~~T*Fo0gx~_x^K%Qz zEeagWR~Wr9zu23}#6$})8FTYIG!cI`Gk81Fjdo9wwt9`rq)qR3B9HHj;Q4FddQ*hd zNw#RGA~x}u<2}&eR^r$ZrtwG;(OE8ZgCzzsBBf#R!zQ?h2z}x3J{^V=A))(&^=`X6S8@~fNIqNuLc!y;t!U81Is|XW zOO=*Lh5HiJt^H72lXlt~b+HcF%!X`A8jx*-P1vQeQK(xsxXX(EF@C&riOUqG63lDr zpNB`W8r)?`ro(+-Kv8C|ikX~H=>B{nNC0!DZrU2B+#rzZURGIQT!Wj9SQ(;Z8auaA^?Zz4rJhUwKRiV41?7ajjN#;iXPAl8+18Ew*IM z(X{)YzYV1G+KO%t;!)p>K0cW|et|iH30Wx;l$xp$ZKhW}*8>71aVxJow^r#%xHOV( zG)>_I+#nAE$fpx`;;poy3mQ*5xwvx$n*3Mt)&fjPALXxni-u~^llZWc^?}Blo#JtK zOmu1}OxgPTQgm3T76gwl)-JTqgyF=MP*ffgMH*|7zRS^cD{yfrR`~rp)-!J1K7gnS zbb(X{PE{6J30#rB>cA&zb5YU>)S+Ia#5j7qU|TL{wpuYPmD>>TO)LTDYKEe-Svlm*0~?t z4N<#VZ_d@His~?=^$s_4&SXOmkRQ--4|4c(qo2PcH+ev%4yLgj_B=+=VBr4yeT?1! zV6?_8@4&Wg*BfPUx@D@|nJeVGlce_dg~#Yur^qx)@PtT?j0KUwNq zH$6kX=f9TWB^uloWx88&fRls9abqw$Cx>x;`f00Aq$MW&kHu~P!J_C&AaN+<2T#Q9 z)9630@O;eFIllN_1unp1p22}Q;8ez!Xl8p>zS0#H;deMCXNo)gG!|uzQ0^E$RS_+_{^dcY8Xx!T&(mm3GhNhcYf!5 z0tWi}%YTYFvje)v{U#XaPs9A|>}NdDe*`WE^FPn#2e_Lf0KF97=Lg6vZqon6vG|5F zVLvaQZH~87e&6z4ns`8m!OO9hXB+Fln?rYAwE3HAip1|Fb6jlSd7|aYq7Pym7YvA) z`S!iLYBlX~Ha}WOE{=!>M0xA@7HiM)Txtyf1HLal<^dpc07sLy-~&S^Kp>N-w&wdp zMFh|SebpFV^gLW>g06J3py4Z1t8dkng7sCrYn}V?DE2m@ZxdqoR(wq4;>*kTviP%_ zk#7RtIvWjto*K^C2HGFu{?fl9+Z|$DKo?HzLTURi8BXvCw`Wm#pZ#W)@qWM??0_T6 zx9v-4sm@sTTWy}sq5XQuZp>o{ASmj89zy-YR<-#WK-!IT24Tl#xFU=~`0N%XBr+nj zc6|>WGjHe50X7w_&cg4k(EFR35F>SmGhY1mB_8)07?5upXs-;sqtURh*p>3qZ621> zsL7bN($aDl7ed!O3j6xZ5QH%~{-ufS~hWccfl1f)Bs5_xzR?$_T|i@-}(@ z0b+~RMz>Z==z@R0i{3vwHz#^F`sRs;X(yrK9}%q^z0rqP9kxFu(nbDaCGi*x1GFaZ zc#}nfwt>L{U}lqznE4DRAm*o4d21rTzjBE=^7GTis(*k(HUHz!Spw;s(M%_+X`rU2 zSIv>Ub98{BDPm)^QfKpuwgl&g2XA{|8~$BKEJvY_%Ar7WDjJT_C7jNXJZJ_DLx_+7 z1Sikr+hAT+geMnA^67C|v|Qajf-{hdD#JWvk*wM-TMzRlujrsK@VxtG`XA+67Wn1r)6e_gqQA?035pGqXvfrz%jEilBx2xhqju|%3rH8hd~FN6pAAZ z7a%t|Ac(E6Xe1d%i@JKaY#-@Q;2=&kjaUJscRiFbD%7>V7&cP5tz=Sqgb(I1Tw|6n zir8*@yMt*m=*hq@y4a&tC)?nXo(X7p@A{Dp49E}N^p2`=eTdHaQaYcCJ9oCS6o4x& z|7v&UqZpVfjQ;6wioTq!@y~E|IgbV_xlZLObgDyNJQqDbHH!aq?VoR@zpulJt;rzi zLca&noQw;marKI1pc2`g`m&hGU^RmpQaqJOiphjKSO^(G15Zw0@M(|cGpi0wL%ZuI zcXZfvXA5ER0Y-Tm{{2vF@&PJz1a95raRMiwzMgg70J9xFh{A%5@A9j?S-|w&eOY$4 z5e+Xkf=b+&k7y1djjd}K5$2*C$1f-?RzM>Q7ppL)Z0;rMi0_Ad06ZA9o-8>pMrB3IhXVQli zp*xS9%n;h}a*ep&mNB2=`hYQE9mCej!|{@^Of~ zS`Pv@BD;6@n?yu)HA$A;{Be#FhUXHgZoab4_!h70eLi^yNZriLb<=GmUl`rWWr@}w zfETqKpc*-F26#{YoRCWdeoCMF9$DcSOtQYrromgxPR5Y3-M}g0>jt) z{vbP{;6}4j>AdaWQ(4dJKNJ6&F*Q~M0t4sjQQdOc<6Wu>e*(svw>JJB-KR=}h3V)# z;ZK(WvM*ZMyZSZ-=f86b)C?zImz(kQ4rKR+zg0)_(aFsd#y&@IdPKsL$D8kcqGcd> zB5300F=Or5!1z4}8IQi#aWbFD;+BF5sH(N)aOSfnRA(^M2_Hp#!LQMrNWc zQGG+acb-FpWuMn_xPtzybOkqDj}JNoGl%j1J{ce*JXj)KU8Dip)tMfYJA7VW9oWbs zF5qdlMc7zmZA;2ZCp5@O#sw|$3aN{#s|1AjE`8$b*C!}aD0sr~8aV4$u?iIOi~!m8 zaP&`T)G6h<%Wu*U=HMRzNWfPpQMu zD!ceguJAA-l|9(Qb(>UOen7z55Q9MVskg!Ykh+m5MFxel@=PD7rwAbZ1NOkJGZ||Q zHll*Ex|Bw%S^RB&M-5Nr9WF&p278Gsi|+a>IwGzDh8SZk*XVkJDHnd2{$%uTXA+h3 zEB~#nxlDri|^#P1SWki|NP}Lo^L!)=~mynQHF$+7+6=r zb7k*>NCU5bD$U2z<}s-u_+`t};{$3~j}l))Qy+yzw<%-%5rls8XKI?6`HUb;C#iJb ztmgrT)hNFZBch&%2jZA|n1 z_5b2mub9pvdt@(nFU&{rMvZCIfA1j6e^Llst+A^(0zxBm6mYauxYtWm7b9#Nq(2{i zHBuUT>u=CyhOWVG>VX~h3Ubk5n~E$Ru^&i(VR6aF@~k><#b=M$n_VAGnfVr)vxywd zEV^m2hZp)fq&+oMse+&T?>o-~@&|hvRL`W%d}4x#&JpR8Q>POuNkcMV&LxNQ>$&R1 z(ic^|P@t9c^847Q10h|BsR3c;L|%Grkv7bcq1>gB1%#z>=ZQZq@m{_9fw2N$Je7}NM?1?K`9AQ1UNzbp(76emWK zM8i>9BYM6}W4-8i4%37u&kkFuputUYHr73QnyK8PnY!lEQAE()`u!aq!}NYqtB^PQ zUUQ-MJB+a*E;FHrOS$}Hk0QMFGq=wsgRcMF{HsK2N)zoLP`TjBV+b#JZ(4sUsY~(C zU+?+n@r9A;?Y?Z=vQ)Lixb0u)uBg}TN|@t5^RLr*=M{Q>xkfNS{(V`d7zs0A}X%`gtB4!A07x;`Zq^Z&JPz{eVzPbJJH;m%2 zwz`Y1{s)IYvg1eawrhErGD+;vFJuvp#|S8^nT-*23Oj<}2=OnbKK z|AmC|*O-#TK+ryCmT)Q^r=WK83+u>SGqifiYBRxOft!5fM?S`5^=vQdz?}A{IPEoG zp!(@L$i4Z1%yBYxg*-@^Tv4Kil~nWo{Pj(84CJd!mT;v(i32_G@vHPmMEivNn2u_TPq)>TEt767Pg<6! z3>)jT=-Xg9&fgf>&BB755cdY_*O(!=YYWJ%9sQ;&-h9l7rnUBAEf^VeoZgyo@#i}7*& zaYypPOVt1ucTv zG9*Wb9+iiee${$?M^a2>kf`A3+r{0^`?o)AwLH<45_RE^As`=*0$G2n>nr@})vK8QeR<1IQHv($>n6GV`vq?hDpDmLGql{}Y6+)l{{--O`zSwocK)&1@r`Txyx)b&-DlAlw>gdv@fKNl7JKV?f>$>0MPoe}# zTjL#B+gQE}@}ShSyjn#Nag(d-s&qZC#9fhgHLH&t0m9<3kiOG!?s*9gOY!>A&S z4rU0yxLY<$aU*T4H+(LNW}6!ERV9pNtiZNTt7_*nD}6KFgq_;L8tV+p79l=Dx2Aq< zw2$KIV1C{&lw(-gOwy1z5*V^H%sR5Gz5zr!wzJ6(H8M#=WL_S>L*nE-uJ$lg zKF;h_{Y^;T%oGpMFeP*<>_#n!I6FDVd?C72_A~M(=EzMmRId2-b}p?Cs`x^_$|E}$ zP_gk3-3uBr)Y=(+@f8?86o;l$AQB$KKBm2`#66kAi${mj3cXU}1n(tEvn=Y^L8XKo z3|m0*bmCtsQi1Gb#Nxp(qZ27wBdEd3({C21YSx*}l}hU6{E!7>E4AR@n|HLcBRhUa zhyC=?8o~T2V_W?B6VPJ>5#R(&6ld!4w$0R$DYqw|}(d}90%s z<&FH+Z^nKg7zSoLuI$vAW?t6^&cl`Ky-d9@(KmQG4C|VEU z+uql%I$o+9TET8r%n-%IaUL12Bb{X)zkE*(ZH{3(CI2w_OFtfI*zltP*85J`*?y-C zPwBnH)^ZAygFi=<+=dh`ncfmK2o}|XZ@9SIEgwtV5772*i=2O#ES8aoJDgo>C`%c} zq)Lx)^0>jm$J*RKNRb;a5OiRIi*>RS0}jQo>!y9Ud#fOgnw_t>2# zY{}mjX@AB*nXMS3T`Gu$fevY0+*j8)LR1Y>hP;UUx$MO<0rRl?m>0I=ZkjsxyKF= zE#r&<=6Gn|@@m>rIVP6MbfDXB{${T5^lz{@SUTcwpYe6U2X7!WHztU^t^DIWWkiNF z%m=q7j`fEp3lX|wP`NSc&B%hBoTu1SJ2UYsbCCTx`?qZ|DuNJ3!AqS7@uR8g)?`SJ zu(C|~KGWq?V#NjrwL->h=Jbkjy7ie^Uce0VN3q0|0){~gCg z6wGA&LcI4q6#Mkiz=^5Ck7PQ6T6n&zyda5mAyc zEIfJ0I9az-B3F97Qlk}VXCol39dyDra8=#=oFiVDNt(W-<*ush`jg=W1Du?3!AA4UKfH*O*}iGy*00>u{yu|f=>8G;swu$q+;pun92sA6{aE z*;-HPtzDPw^Z9i{ZSMup-fZNlx@hAB>a-Hu+NsG&oa!j1l93S*_U`-4QT)cn+9!O@ zAe4J(7@a+D!|K{$7;U6m7)e#(+E~n*dD2`X7g%7m_p9w(```1e4ME^9RO|KI-T%V^ zAR2x0uwFm)^ZMki>1hh+y2|+AccKB)lHm*A$VVCI-{Nj-+9LLy{^gWBl#o!-@UI7Dhv3?u7H^xrZG2HyANJjQHq(IA z*xm#YhJWs{H~!#_5ENA)6$JExp5fN`azUIld)>igP?DjF((Nz#=>m!VspsCEk3<1D zoVsvP4vcGsTL_jHgxfrM}0Zrj`h7%Mh7ViwXdiwHR2TW+srR9_UbNAO-PCWxJ zkC=tFqWdF%!n$Dog>B1QMzl{xc-bh>Gu)Jm@S&BXZ{Xah3V%T5g-iUN(4MPCp}t%% zVO;ZMhn2J7)TLp_8IOv?Lw(rNm7Kp7O_7%C@eh)FUUbt!m69H`k2h9DJZ{x|gFpu6 zUa7wZ?;d~l3^;E4gDRJ{s$T({yH%EVsNw~WsD^gS9yLHbmn5%FX1hen=M4v&=`CBsHJGVyUpC6Fw2WOU5Nmtppug{q-Ad75QC^~$D9^j;k+7i zZ2K2VEMYnRJw5~cwxgse0E#YTlcZy z&6jtO{zyKlkUCT$Rm2mtW4i;XP#!XqnsV8-K90c3Zslf5yW7TcdI}{4zL=Ft)(|C3V9D z8$5ZFnA-QpmCAxNn$NxrjmKxq!Gq&wGQT*-4~Yr}qC&!5wYimUm!loFK#@M8kks3x z)lTVyTN874K*FmcWNqnv^vb1LasQ-IF0Z0YKoBV*U%=2P`YuiBKxc+??)P)@r5c?N=khbU>a!#krGI^5RKWj%L1fF`v%VS z67@=*apQIC&|Sm|t&c!n{IO||DAyC><3GP3QWaF5qEdHcGkjyIaQ?h?O*KmG<>8=Pi|hh7J& zDSXeO8+}IjY%RdXy)#ij;r&ohyXC_$4_z? zVRQ6|SMsOHLE+r~zlN|b0`(2q=JE-UUS#atoswG{W`0uD^+CJiM_*Sl9qBVmt(Y64 zp3%uWDWYyDJ8iFW(s%p!L3mo}&xo!6|Lg3$zna>fzn>5Ur3XZs6ho6<1qBh5fP|)m z-XjVKNRi$`xhjNSLoa#>(wm_QNW9bwp%_4#6sd+@rNj4lKkNAip0ifg$`3oq$u2W{ z&YpR{P$LdMgZ^jDgNff!`Mya(-&z-CP7Z~Y+c!WbKuI))81bV{bKZa(hddH1w+jA?!U zTLZ{XNh(Ky(CKrUx>NGOsg*7a2&-QDBm!x{Bb0cz-|gc?=WPYxARuLYlS0c)d_ds> z#1(XQQ>tZKeeol324|!RKmQr1@RgFP$k;6% zyjRoG63l<>vX35bI#=J_-AqM_vcO~?!hfiQD9(m6s0ju=i1IsMfp>lNkN;(0BH=_8 zXMj#V1n6$&_h0lRS}B~ZRX>c5SlO@^DKz>BUlfN17{TM2l0;y#z==1p{^0QRyscB= zi;8=)3xa<(h{|o%U?$(oENxW--f{3Vl6S@jV1Z$#HhfFJF{1qNi=Ns#B854^umz39 zR-TQ+$L95y?xCxO`JXZ4io~kLBZ=18f|fU4R(Y%T@Wlwm2S;l900$?Q>mrIpI3k>P z{_KVY(C56+CWSt#P{u#n_Dkj@@Vg*t?UEPrOi!KNI^D*mx}#z=3JmgscmFkO zKf9#-OD1G1Rc=D%cl-1`ah(Gs%#%`@d9Ju1eja%J-PDx%hxp+)6A%e#D1I9s*SdY( z4$x`Q%~pte9)B-lSYJ6VIy!-Ek5N#OT!ux8w!s%473E#b`Y*(pJ$Y)dUSDpt`ejK> zZAH(fWD|~i1Xpm}fhI)vfZv7iYL|3)=AYuXj)qETRe&6lnvnCf6#I^+5&ayqOHT5c z(a~Sohr{W)b4u*HGO+rik43Otz+#`)T4zF=WbVS>M)Cyquq_O!erj@~iGO~G61yCD z9Z>3Lnb+y!;~Ir5-GU~W!$?Ww@n6Y;I(GDz4d6GPRtKuSVpUge4+1UOSd!H785E6e zLkFhXf5ZmJE>|Yy&^rJ&!S4Lz+rZi~$q_iz5qTxAP&hx4+3Aw2n^TyI>{N#{FeRzR zXt{n)&;;^#Fn1^t*Z4%#tIbD0_bQ8ZFO@t1_BjrBDVSK3&S|Yf3sXIFFmy~w_T(AX zu?kDJvYkuJk0SdA1(pH*FMru$DWJzb5!@gsPy|-`i+o+pp;Gt_T<8ynrQCM*ooj{{ z`Pb$sU*EgfQg@c5N{0DMaEx3FQ4sd`&rmE99fNt*yO{KH6DV-Wzj#9!zi)J0;bxzg z8@X#FB?L2#>48BrMPPF9MNjBG8z2EHoBFwHH1Dx7Y+hpj)IeM0F-EHd11Gtjm6eq} z7c|QRj%L%Jzqz=oAe+5xZF()LCj|D%bR}Ons>f9M(rV`T(rftW*JXK_y9O}F`C$da zu4fwX&DO&iv%O21UMrSB{!Dp?>M15pG^6ionBe$(4T_eOc26T-J{WCaus0g0 zirpJWL7jU4hIp8Mn9WBz`+cUDz6RwGfvMn^3+r6Bj#u($H&&XwRw6VO1?FP9GORQ~ zIi12W7dMuxZ;mRC93BPGRs+^UwyPF&_~P}(J@Xb5k-}XaxKQ-;?tVGOYT{Tqef*uC zi1KFRf-e`i5x_P4ZD(q+qQrA)Kizw76yJwz&B0hPt?-|rR(1v*_SfB8ZGRmW0i6dt zj~s4V187o!!tcM`aiQksney`Ti(>R!vr2uglt2FT0TL#w1wWH{&;^AamtoFSVi?pE z3aGV3jLl&4(4=%y(^~8HKeWv%=e8bSufSl>pgW5ndfmO#PR)3LGP|&GkeYr>bWhT| z5O?j8X)8B)K1iV8eJKQm=-;t&JYp~0&qviM=OINzwvZDKSqUCf+^pN z37suNn0~YhiKmFy+T*Mv1QE`=GOF>ThT0_*Oi8?jay!S9E>#-}m!SX> z*IPB%Ccf-+VZhU82iu!5PB1N#%{jFdfGPDC8zqsX90N&N-GIKRqUr^{Z)qMtzpjTI z`9tq@eF*H7E!exP627lfLK!PV@q)AW@cJArgUMr&LK=0rX5rqE7r@mEIontD+x%fx zB;NPTXLeIONSmSWDcWk~DuIh59)!V&-`)>;`roQ^DfRmT$Tf%l03S_ng|MxqT4{pI zseKo>Pf8P5l4zg-d@)_NaGVKT_rq)qQrlh+{y=M~vLRq^d3yO$6;SpvE2>~kg5E1$ zE*|jY?fqJ3%qt870zz)+1lE3mclGQGQFK2Dsl9<11K}RRg+SPnoGJ9dC7`aK@c-3H(AQalH^sb{P=<D}}vsU^*A083i!>I8hPCYlw0eY`|XbW(< zH~AGLw*NBoYXP*v&}aLXK*uUh^zYQZu(zLMom0HmSh@NbzQ_*ETu~E7)h#;UfX{e7 zfpv;8E5c}1?`hs(P4d!M6oVmI*Yy1s;uLB4fSkOfr?;D$wH;OgRzPxpfPODYiumjW#ho>@^Sdkg~3m^58}H&{IoM#ZCl+>6nJ^X@jw< zFicJZCp4V)AUuZlKeGu$BUYk*jR48;b(0lEPcK$P4Y(U5RAO}$VJT%$={b|j?gx-TA8HB!qAjgPmt zR`Ty@zgY`Aw+SOn2ehMe1Us*mk_>DBgIVI3&op;%1C8*(ZfIqVTQ&g@NyO>_1wp?( zyRWx=@P5VqU9zT%sM8pxQSgb9!*{kHpyKH#L1NM_-^J-U<+Xw~>P#hes310%-+f{8 z)(FNsN54-6(F!mnC1KF>aLaJ_lr9eTOhE%Vyb0){wjm|A`=%Eipwe8ia#kFvRaXz^ zTrV}y37ZOg6MiQgVZD5M!iHCv;~$!oNZF6fqakM9Df_;8ssBLHdBgb=PLTeK9|rea zP=$}IlgzUz8=BiSEQ_}SZpvV%;dnIt zw=sPbR(o*7Uq#(Y&Lx=(()={LCG^ixaB*FkqNt4&R^EhE=+k8;N*)y4K%Sv_s(m7U5XB*i zAZImB>bXhD;rg`w)U2R#a^pv4xiw|%V2PQ4lRCojJIBIzOrv#~=8c;oWPOxT#2K+1 z0ZhbYB!b%e0(`T`J7^?BXn}{u-wfsQxLwqSG0D3O_t2;7R|~-h-dUR~php#9EaL7U z0jz4*yu?~4Ip@+aIYiRwoa(uRiL-9bhkf1s!6n2u@v`1qL1T%vz7UysQQv+3&$_dw zBv*fVT{#y&+~dC`iQW%K>R4YxdVH{T<_ZLSX8qxCctP}70wfab0#SyXrdvOe!@GgG zAl;x#ESYvEzqc~Q+&!#8&ULE_WC`xilLUrM0%eWT_$Z~W)c{9xZOehmCBRemKW4!7 zQqB4f^-8vop%_d?l{eT(@{M4wl#>GaTk)wwtZQ0(c;>?KBU8Dx{ICSDoE$H!@rj^x z<9c8gf_XcJZfZY>P(z?sYxQHy$gE=|1rR@Lo|X(d_Er{fNQ3<4+JCpOtL}G~R~%ng zi-XOxB3J|@whAE4h~VW&HGB3PyOXSEyE@1@caDahzB&P6$$fMqYI6( zHTBqiG%C0&!@*$*6i*ydnH*IP1CEMCNnRoVP}djDEnU4Hm}%}aLmqj5WOpWpLKnU! zNhNvPc4_D)V6YqunRn&~1zeLvzSAb_$6;9i7_>SbvXg@p$UsISjGP&tT6r5E;*d;v zX8&=6V~)#yteY6P%o8^GO3=v;{#0gzHo3m<`eljkYa-_j=$MX@1*wJZ=dV^wrg=6b z0;Dc>!9yeduYc|0RAIS9q8sD~d&cyl!a0?P?3en^a#xKljdJGd52VD8E80r8)q4Vx z6@HPLQ6@BVLWpb~&f89mXn(UgO_#^^RK6`57!=M@aHU(T;*b*bcbc`DdN!a z>Zvj!NVDTUN((OD&$P!+&o1PYJ@2T3C=iHC+{fT(Q}cd$yoR?}StOrRIyJ6#3vLX( zC{BURFVl(q&r*Yql1NM?%D3aLZ09HYy2`F6L0>a&%M?ady($^8{`>()FCdXTa*G^~ z$rxSybWwa=x#)@Zq!!6Rd(D-)aOzH(>o6^r6OvqOL~7Ftl!k4tGb=`Wx*$#(Nh_Z; zYGU;SU9HY|D!otEA&BP39XW2hH^s<((48gCH47n>B4V(#$?%=K&g5O#gPs&@ra3Km zR`j!co5>maRf=_i6x-{+70_v*oJ6gEOWhcom!ChJyH zoZFp3W2)B+q$pgjs~U1*cATNl`BC!Q*HCbcJVgqzFattjG&u;AqUD!rR5m*#8S0MQ zIbojTnPaz*CQ5Fc(jtTRJx%B1f`t*0K`iYZN)g0uP%aU`m z2<7_W>?6BZ9n5oFgj&hrbcj?^JSx=u%*IUSGVN~$NO(#yx;lLcz>!M&RF=_)Re>5( zd=stpKC<&g)b3R|C~Y4SG_CCt-Zyb0O-)lc4W?4!XS^(~2CJ=tkHF-wcSm&>+Y>To zZko}>id}rk8Cj^Mnhy0%H)xN)!OmcHt=wFFf*ZlsQu)%3n^^8RB_rpeLzuwvcShm( zze~hOt@`@imIh~hn>#h7I0Upmz88P8`7T(I&JyF<=Zv{`#Vp^O=5JvgL|j&ZmI~XU zqRBfqGL!n^6G(( zbIYT^-dPUZ*NVW&Wk%sUl-V+pm!SojOLLn|oZxJ23l6B4R)ZpUMeW6RNkx2G;1g1c z_8~^f_%oAdKW3aILx9|&WH(*tJ$P*3BOU~=DqQs{#K~d1e2#K(PweAus~WK1|GkZH z*WxU#Mf+$?)<+yZN%j7MGZZ*)jM&u?R1qLQEc|wwhTs%%iXyRyDhr_Tn5klF*!+;t zjJpH6gFcKZ(M>VC(z|)$F}Jqq;^jl6il3PG%Frf+`eeh>55S^LaxMJ?MMNzF}d^EV0~gP_yGMN)28vuFN6l z1$pm=3;J24UAhLo=fL|~Owg4X>ect>C-NzZXD4H zSu~EzXgBaY;3H4pkQ@__#3m0&T=)^o^?(g|7{=d<#FK2}`VBT~8n`-Flp0ZqF4X9g z=v&iP|7H==Cy2JL*y!ZsBg5WjLa+3T%PE35uS4;Ixl?~>sBl2t5lY6SbLdVia$%w7 zhIsR+O|o|_u3u0E=_%P%JN3?eHVzY-CXeszv0c%TfsiGi(+*v@d7;$30ymZGo z3CDZAs;JI?qDm+5Lua2no`+6UIXuMe1I|mJwa7cku*eVVE9-*b6mr7h`UPCg&tlW$ zaS=ySnjO>xHN==kM|Q3p%#OpO4#y(a`^1oQ_QSWwtZjTw-JHGs>E2a1$JEMo9zG{p zgs|9w{{1SW!6c32E80_&J(c0n0m6?va;-l;L9RYCZ>!`icdNmLV!iF*_vJB81Q3X# z4*`E@B!wUt6-E%U^g7U{BvXO@Sjk-`qLXD#f;f$F--fkpd`{If}VXs)hV1!I@ixUeTq>^4s`3+X;jh zKq))J9CB`t;EU6Q*I6Y<*;P?)QglJGGj zf^gicpFu$*o7+2gKsW5f?d z!2^@4cfsSO{;fVxTBQ1d%^ZevtlJEw$?cO#ox>PgDi~4|dl3F6T#9w8HD@HTiR*~I z#Gtme&$E7$`T6ZpE*7>MdysMJm%nPcJZ@DxcFq>8nF)iQj8w-yBg7LZ=fsf>mP8vvi+iFft*sHhmx*l@eti+uYQJ= zonj3zQo?66$W`kt2mhwj2TMXiY{X9|=2s9%#`Zb_HQ}vQpMo4-0hD93{!;%I_rGr6 z>@Rx$ChE@3hDCJ_c$Uy^grDXv=;gBAV_-LJdK6ri`Tuj7yPT_9r4$ChWKIP@z=hDz KhgUvA{q=v>(zN*i literal 0 HcmV?d00001 diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/resources/coner-icon/coner-icon_64.png b/toolkit/samples/dmvapp/dmvapp-gui/src/main/resources/coner-icon/coner-icon_64.png new file mode 100644 index 0000000000000000000000000000000000000000..47678953596bad122992941e8858742a87f9d0d0 GIT binary patch literal 3820 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 literal 0 HcmV?d00001 diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/resources/coner-logo/coner-logo_1024.png b/toolkit/samples/dmvapp/dmvapp-gui/src/main/resources/coner-logo/coner-logo_1024.png new file mode 100644 index 0000000000000000000000000000000000000000..0069588e6063b9af68b47b1baf009a4cd6963bec GIT binary patch literal 45019 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 E0obiFQ2+n{ literal 0 HcmV?d00001 diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/resources/coner-logo/coner-logo_128.png b/toolkit/samples/dmvapp/dmvapp-gui/src/main/resources/coner-logo/coner-logo_128.png new file mode 100644 index 0000000000000000000000000000000000000000..0168b5f1a62b8234320ae31a5c7879847527b6d3 GIT binary patch literal 4423 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 N002ovPDHLkV1k^ltPKDF literal 0 HcmV?d00001 diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/resources/coner-logo/coner-logo_256.png b/toolkit/samples/dmvapp/dmvapp-gui/src/main/resources/coner-logo/coner-logo_256.png new file mode 100644 index 0000000000000000000000000000000000000000..f0457f26c4cd5c489f16ebd8aaf70b146dc175d1 GIT binary patch literal 9631 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

T$igYGlm%MLq4Buc#0!dOlYld4qtLTwdK6j zt}fJDaV%dMji;i5g(!*jnUhaj{ShvsfVJle-3NB-1CXVjs+<0ZwRS4?D`#|O@)X6= ztSjViB~oHZFlOmO{xI4)MgX)rNpGDUQB#;{VY1}Dv#P;jRUn;#oF)nz)9HeTrjIOl zl*Fp6*unK?&=UZ5o@?uDCs%hpQBg^GmS2nudT5aa+yuT0|AMSf*CTb&?KQbB&SMR# z_{#oVRDTVPy|E?vc59WgT^sfw*ck0Z@@Y0U!>d=X@ZJ|uzd$4uWmTX^;0Wv#r1e*S z?`1fApyweE{rc6d=FEGt7G?EnfN1p5B3v8K*Ys|`#m8`b*t&cL``-In+1l^U6N&$j zLr!t!*m*n{KqFh%lC8pJoQk!=M}lN>SpausQfEK_O!?iA(g!E=pyoguz3V5F#IuE< z-a02D`m{E=J-~&@p;G+r4~%h>tv`Qf?2msD7!XT9FZJ;xJB7UUFCQZQzMDdoO;ZL_ zQdtI_2c0!jS1O@MlNG-WixL+$G1L1}Z+a|7(1SfFsk>N!q^#63CVA$#!3l1nJ34UC zgx!9SBwg(NQ;Gv#z5Q3xPBO^&P8%$p`EULwO}9wzhQHDI!6y{thWugws%6A!i=(jG9L?L{QBnLB}cWrw(vavky}>{w=R;h zb)zg|79@5Z@B$tayXZymLwBz)4D(VCD%<)SU7r<-ZyjS?AvMx&9*eDF@C2!3?aJ%F zAw>7Lv`%VGkS+`SV0rVuzrPsfy;uD`GjALIpK^j(V`^Oxu)8%`dA5Ss*7`MclvXr}Q1``OT*JwUx_O&o!>hDToS# z#Nf~aQ5Kq5!in%4{%Od*&l|s{+iGCe3^2GmV-_7XicnH)HA@#8jBhTCBU!y|tacFt z=8hORNXVIa$9d+>@JKm{Rk~oh7-z{Ss@vY$C4<)p`Z1@uwU}W-6clBtNxG{8#+jkW tPPQkKrk7-9Y*h=Sq5Qvf#q>;|^k@T58cceHe3%NLs;H&#RnGe3{{U@YR6GCx literal 0 HcmV?d00001 diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/resources/coner-logo/coner-logo_96.png b/toolkit/samples/dmvapp/dmvapp-gui/src/main/resources/coner-logo/coner-logo_96.png new file mode 100644 index 0000000000000000000000000000000000000000..6ac5015528aa8f146516af4468b5d4eb18f7859c GIT binary patch literal 3142 zcmV-M47u}(P)%6f_t5v zy)e6TIWu$4dHct}vdAv%va_>G9zXxg%sKD-&i8kI@Adb-2R`R>`XXOr-UN^O&UBx8 zG~iUX1LKEVQ>IaeTR>lwyOnhdO0*yT^F-IAxQ#Z`pHr$!Yf-|YGGfUcfIZwA|CpI^ zw_opi@oJBCOR*MOF|D8@yrfdLFRtiVJH=Bs#x3>$MZ+yJ6Nup!&DJr$R|eQ;i!EZP&a%s2aht`0{Wm)DB|yn-J0n6@BthSecaWf z@(wRHxm_F>HG{WLL2;~w0`2sDm###*;$BS= z?vKLek%Z*H@GAZzWB#1$j)z)WWKW)2`d2czc)ScRsg&U*mGa=cybs@>W<;o zdnt_ME~xCLdGpJPOG?hU_|Ow8+1Bak{_V+e86H)Tugfvn7MKY}tOLru+JBBIDbQi2Kazh8E0*ip2)m)78>KmWG z!QZ*+p?l?|Nt2}4>y_2j)pF&^l`<3xb$3Vazx_M;>|HZsAJ5H|kCZz@z|3K>WDsas z{IA^64&}Q}P27~DNWV`P`BQUM?^QW!;WH-_2ad(;Sq`Wg>(ifKHobWAon<*W2ipI@ z&yz{2s;a1~t7Fcb>nScS?k;flP4jr~^)EV7?;OUb;{bBAXirASnghn?C@(x-;ksv9 zt}2`ggiXnjs7+f^+EqDfSsYPwXPMXi_|!tbS5x?}+Ael9#i%fCs#MA5pFGJo{`EPQ zFJI1Mk3ELV6JEc3bo`I`5~ zRgV0MTs{9x+S|6(v$xgg&bzfC#xplqeCy$*?D^nB+S=M!w{9H(CqLPrn4k$yC`AJ3 z$d)~sB5MxNgrcAM{>zZ;dhOP-Ql*bjU}dg;jsr|7*>t>}q7oN#=ibNz4?FuVf)YW}mN}^4Ttw8~$09#vA;ReHgaR_7&IazZ+$gp4ipwmp~0wPJfUmg&^zh76% zJ>|K4=c)n#Y+Huw8$!oyDW{xC_rIZ3qX};fjq;%-YYqroY~2z{wE#GUB%JJDD+qWr zUbxXuWv)&lVIFCy54B3$o_gl~wzgF4REp;TIW)?LmTZP1y6O`g>og@_EmaFP91VB% zH=`|OS8HqdtzfWij6`;yjEGv2^`9ndn-cajLnC?U$!aX9A#S~~p&=Rhf=|&me;RQb z)&(l9#7ZVo2b-EZcGlOm5Q`Z%1Fo~T;hzp0O-)hz0l*q^@k2y5H|3WCf$<*ojtx`Y zGY>^=b9<}V`h$t?6RN7jHBGgpg<{)MNtvd{w(Tk)ueXA1;D<+z(5_SVKQ24w z`{wRozJf?TJEzn$So6>zz{;nd zdMdnp`SLfXO`GujqY=e(U%=t+O-oJG;ulR8 zHt+$Rok|sKLUn1ZA| zZrlVQs;cUrTbA`R(gCsx;OD($k)Im&U;nDbdgr}UvE{2Lx+?DSCB=-qo0exGvw$#+bSq1ICExmK&O|#@|8cWUa{(5ykZ2;Tr$Z}gd!}T&*!bHt8<+$ zzj=W9i-F^rmo+lESQnH}kNC^QIC$`&513q9TAC!iL9R3KhuHz#KEON!=12S5jjohs zTs-AjEP4J>_@=l?zOLfddY`Sl`e}p@+l*w&lHCUe8VpM{r3}Ia9B@scQx}5jfe4&C z8HQj zr_=ud37^%}W!efCemzy5h?wN`7!adL8zB&xun#1Sag)NxS(8GBg;W%~hpc3K(p*N8 zjeqlgaO1QB*Q6EG3w>VwY@X(rnJ$cUtyBCi^%u4jRfCl$gsiDP(XiC-_ZO31LC*nv zq-(oQx)t0CyaQB{?(5r0KlI7KA)p*Mc7ORYd;TF< + page.nameField + .assertExists() + .assertTextEquals(strings.driversLicenseNameField) + page.name + .assertExists() + .assertTextEquals("") + .assertIsEnabled() + page.nameFeedback + .assertValidationFeedbackSupportingTextIsEmpty() + + page.ageField + .assertExists() + .assertTextEquals(strings.driversLicenseAgeField) + page.age + .assertExists() + .assertTextEquals("") + page.ageFeedback + .assertValidationFeedbackSupportingTextIsEmpty() + + page.licenseTypeField + .assertExists() + .assertTextEquals(strings.driversLicenseLicenseTypeField) + page.licenseType + .assertExists() + .assertTextEquals("") + page.licenseTypeDropdownMenu + .assertDoesNotExist() + page.licenseTypeDropdownMenuItems + .assertCountEquals(0) + page.licenseTypeDropdownMenuItemTexts + .assertCountEquals(0) + page.licenseTypeDropdownMenuBox + .assertExists() + .performClick() + page.licenseTypeDropdownMenu + .assertExists() + page.licenseTypeDropdownMenuItems + .assertCountEquals(3) + page.licenseTypeDropdownMenuItemTexts + .assertCountEquals(3) + .apply { + get(0).assertTextContains(strings[LicenseType.GraduatedLearnerPermit]) + get(1).assertTextContains(strings[LicenseType.LearnerPermit]) + get(2).assertTextContains(strings[FullLicense]) + } + page.licenseTypeDropdownMenuBox + .performKeyInput { pressKey(Key.Escape) } + page.licenseTypeDropdownMenu + .assertDoesNotExist() + page.licenseTypeFeedback + .assertValidationFeedbackSupportingTextIsEmpty() + + page.resetButton + .assertExists() + .assertIsNotEnabled() + page.resetButtonIcon + .assertExists() + .assertContentDescriptionEquals(strings.driversLicenseApplicationFormReset) + + page.applyButton + .assertExists() + .assertIsEnabled() + page.applyButtonText + .assertExists() + .assertTextEquals(strings.driversLicenseApplicationFormApply) + + page.applyButtonProgress + .assertDoesNotExist() + } + + @Test + fun acceptsValidInput() = runDriversLicenseFormUiTest { page -> + page.name.performTextInput("name") + page.nameFeedback.assertValidationFeedbackSupportingTextIsEmpty() + + page.age.performTextInput("18") + page.ageFeedback.assertValidationFeedbackSupportingTextIsEmpty() + + val fullLicenseText = strings[FullLicense] + page.licenseType + .assertExists() + .assertTextEquals("") + page.licenseTypeDropdownMenuBox.performClick() + page.licenseTypeDropdownMenuItemTexts.apply { + assertCountEquals(3) + filterToOne(hasText(fullLicenseText)) + .performClick() + } + page.licenseType.assertTextEquals(fullLicenseText) + page.licenseTypeFeedback.assertValidationFeedbackSupportingTextIsEmpty() + + page.resetButton + .assertExists() + .assertIsEnabled() + + page.applyButton + .assertExists() + .assertIsEnabled() + } + + @Test + fun rejectsInvalidInput() = runDriversLicenseFormUiTest { page -> + page.applyButton + .performClick() + + page.nameFeedback + .assertValidationFeedbackSupportingTextIsExactly(strings[NameIsRequired]) + page.ageFeedback + .assertValidationFeedbackSupportingTextIsExactly(strings[AgeIsRequired]) + page.licenseTypeFeedback + .assertValidationFeedbackSupportingTextIsExactly(strings[LicenseTypeIsRequired]) + + page.applyButton + .assertIsNotEnabled() + } + + @Test + fun nameRecoversFromInvalidInput() = runDriversLicenseFormUiTest { page -> + val nameText = "name" + page.applyButton + .performClick() + + page.name + .performTextInput(nameText) + page.name + .assertTextEquals(nameText) + + page.nameFeedback + .assertValidationFeedbackSupportingTextIsEmpty() + } + + @Test + fun ageRecoversFromInvalidInput() = runDriversLicenseFormUiTest { page -> + val ageText = "18" + page.applyButton + .performClick() + + page.age + .performTextInput(ageText) + page.age + .assertTextEquals(ageText) + + page.ageFeedback + .assertValidationFeedbackSupportingTextIsEmpty() + } + + @Test + fun licenseTypeRecoversFromInvalidInput() = runDriversLicenseFormUiTest { page -> + val licenseType = FullLicense + val licenseTypeText = strings[licenseType] + page.applyButton + .performClick() + + page.licenseTypeDropdownMenuBox + .performClick() + page.licenseTypeDropdownMenuItemTexts + .filterToOne(hasText(licenseTypeText)) + .performClick() + + page.licenseTypeFeedback + .assertValidationFeedbackSupportingTextIsEmpty() + } + + private fun runDriversLicenseFormUiTest( + block: ComposeUiTest.(DriversLicenseApplicationFormPage) -> Unit + ) = runComposeUiTest { + setContent { + withDI(di) { + DriversLicenseApplicationFormScreen( + screen = DmvAppScreen.DriversLicenseApplication(Random.nextInt()), + openNavigationDrawer = {} + ) + } + } + + block(this, DriversLicenseApplicationFormPage()) + } +} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/test/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/page/DriversLicenseApplicationFormPage.kt b/toolkit/samples/dmvapp/dmvapp-gui/src/test/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/page/DriversLicenseApplicationFormPage.kt new file mode 100644 index 000000000..777a3e18d --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-gui/src/test/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/page/DriversLicenseApplicationFormPage.kt @@ -0,0 +1,30 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.gui.page + +import androidx.compose.ui.test.ComposeUiTest +import androidx.compose.ui.test.onAllNodesWithTag +import androidx.compose.ui.test.onNodeWithTag + +class DriversLicenseApplicationFormPage( + private val test: ComposeUiTest +) { + val nameField get() = test.onNodeWithTag("nameField", useUnmergedTree = true) + val name get() = test.onNodeWithTag("name", useUnmergedTree = true) + val nameFeedback get() = test.onAllNodesWithTag("nameValidationFeedback", useUnmergedTree = true) + val ageField get() = test.onNodeWithTag("ageField", useUnmergedTree = true) + val age get() = test.onNodeWithTag("age", useUnmergedTree = true) + val ageFeedback get() = test.onAllNodesWithTag("ageValidationFeedback", useUnmergedTree = true) + val licenseTypeDropdownMenuBox get() = test.onNodeWithTag("licenseTypeDropdownMenuBox", useUnmergedTree = true) + val licenseTypeField = test.onNodeWithTag("licenseTypeField", useUnmergedTree = true) + val licenseType get() = test.onNodeWithTag("licenseType", useUnmergedTree = true) + val licenseTypeDropdownMenu get() = test.onNodeWithTag("licenseTypeDropdownMenu", useUnmergedTree = true) + val licenseTypeDropdownMenuItems get() = test.onAllNodesWithTag("licenseTypeDropdownMenuItem", useUnmergedTree = true) + val licenseTypeDropdownMenuItemTexts get() = test.onAllNodesWithTag("licenseTypeDropdownMenuItemText", useUnmergedTree = true) + val licenseTypeFeedback get() = test.onAllNodesWithTag("licenseTypeValidationFeedback", useUnmergedTree = true) + val resetButton get() = test.onNodeWithTag("resetButton", useUnmergedTree = true) + val resetButtonIcon get() = test.onNodeWithTag("resetButtonIcon", useUnmergedTree = true) + val applyButton get() = test.onNodeWithTag("applyButton", useUnmergedTree = true) + val applyButtonText get() = test.onNodeWithTag("applyButtonText", useUnmergedTree = true) + val applyButtonProgress get() = test.onNodeWithTag("applyButtonProgress", useUnmergedTree = true) +} + +fun ComposeUiTest.DriversLicenseApplicationFormPage() = DriversLicenseApplicationFormPage(this) \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/test/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/testutil/ValidationFeedbackTestUtils.kt b/toolkit/samples/dmvapp/dmvapp-gui/src/test/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/testutil/ValidationFeedbackTestUtils.kt new file mode 100644 index 000000000..4a14e7e81 --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-gui/src/test/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/testutil/ValidationFeedbackTestUtils.kt @@ -0,0 +1,15 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.gui.testutil + +import androidx.compose.ui.test.* + +fun SemanticsNodeInteractionCollection.assertValidationFeedbackSupportingTextIsEmpty() = + assertCountEquals(1) + .assertAll(hasText("")) + +fun SemanticsNodeInteractionCollection.assertValidationFeedbackSupportingTextIsExactly(vararg text: String) = + assertCountEquals(text.size) + .apply { + text.forEachIndexed { index, text -> + get(index).assertTextEquals(text) + } + } \ No newline at end of file diff --git a/toolkit/presentation/presentation-test/pom.xml b/toolkit/samples/fooapp/fooapp-common/pom.xml similarity index 68% rename from toolkit/presentation/presentation-test/pom.xml rename to toolkit/samples/fooapp/fooapp-common/pom.xml index b02d36080..bb67bea3d 100644 --- a/toolkit/presentation/presentation-test/pom.xml +++ b/toolkit/samples/fooapp/fooapp-common/pom.xml @@ -5,32 +5,27 @@ 4.0.0 tech.coner.trailer - parent + toolkit-sample-fooapp-parent 0.1.0-SNAPSHOT - ../../../pom.xml + ../fooapp-parent/pom.xml - toolkit-presentation-test + toolkit-sample-fooapp-common tech.coner.trailer - toolkit-presentation + toolkit-presentation-testsupport 0.1.0-SNAPSHOT - compile + test tech.coner.trailer - toolkit-presentation-testsupport + assertk-arrowkt 0.1.0-SNAPSHOT test - - - app.cash.turbine - turbine-jvm - \ No newline at end of file diff --git a/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/data/repository/FooRepositoryImpl.kt b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/data/repository/FooRepositoryImpl.kt new file mode 100644 index 000000000..d2c3d06b4 --- /dev/null +++ b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/data/repository/FooRepositoryImpl.kt @@ -0,0 +1,22 @@ +package tech.coner.trailer.toolkit.sample.fooapp.data.repository + +import tech.coner.trailer.toolkit.sample.fooapp.domain.entity.FOO_ID_BAR +import tech.coner.trailer.toolkit.sample.fooapp.domain.entity.FOO_ID_BAT +import tech.coner.trailer.toolkit.sample.fooapp.domain.entity.FOO_ID_BAZ +import tech.coner.trailer.toolkit.sample.fooapp.domain.entity.FOO_ID_FOO +import tech.coner.trailer.toolkit.sample.fooapp.domain.entity.Foo + +class FooRepositoryImpl : MutableMapRepository() { + + override val keyFn: (Foo) -> Foo.Id = { it.id } + + override val mutableMap = arrayOf( + FOO_ID_FOO to "foo", + FOO_ID_BAR to "bar", + FOO_ID_BAZ to "baz", + FOO_ID_BAT to "bat", + ) + .associate { (idValue, name) -> Foo.Id(idValue).let { it to Foo(it, name) } } + .toMutableMap() + +} \ No newline at end of file diff --git a/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/data/repository/MutableMapRepository.kt b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/data/repository/MutableMapRepository.kt new file mode 100644 index 000000000..60d3579ec --- /dev/null +++ b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/data/repository/MutableMapRepository.kt @@ -0,0 +1,54 @@ +package tech.coner.trailer.toolkit.sample.fooapp.data.repository + +import arrow.core.Either +import arrow.core.raise.either +import arrow.core.raise.ensure +import arrow.core.raise.ensureNotNull +import tech.coner.trailer.toolkit.sample.fooapp.domain.exception.AlreadyExistsException +import tech.coner.trailer.toolkit.sample.fooapp.domain.exception.NotFoundException +import tech.coner.trailer.toolkit.sample.fooapp.domain.repository.SimpleRepository +import tech.coner.trailer.toolkit.sample.fooapp.domain.repository.SimpleRepository.* + +abstract class MutableMapRepository : SimpleRepository { + + protected abstract val keyFn: (VALUE) -> KEY + protected abstract val mutableMap: MutableMap + + override fun create(value: VALUE): Result> = runCatching { + either { + val key = keyFn(value) + ensure(!mutableMap.containsKey(key)) { CreateFailure.AlreadyExists } + value.also { mutableMap[key] = it } + } + } + + override fun read(key: KEY): Result> = runCatching { + either { + ensureNotNull(mutableMap[key]) { + ReadFailure.NotFound + } + } + } + + override fun update(value: VALUE): Result> = runCatching { + either { + val key = keyFn(value) + ensure(mutableMap.containsKey(key)) { + UpdateFailure.NotFound + } + value.also { mutableMap[key] = it } + } + } + + override fun delete(key: KEY): Result> = runCatching { + either { + ensureNotNull(mutableMap.remove(key)) { + DeleteFailure.NotFound + } + } + } + + override fun exists(key: KEY): Result = runCatching { + mutableMap.containsKey(key) + } +} \ No newline at end of file diff --git a/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/data/service/FooServiceImpl.kt b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/data/service/FooServiceImpl.kt new file mode 100644 index 000000000..adaf75140 --- /dev/null +++ b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/data/service/FooServiceImpl.kt @@ -0,0 +1,66 @@ +package tech.coner.trailer.toolkit.sample.fooapp.data.service + +import arrow.core.Either +import arrow.core.raise.either +import arrow.core.raise.ensure +import tech.coner.trailer.toolkit.sample.fooapp.domain.entity.Foo +import tech.coner.trailer.toolkit.sample.fooapp.domain.repository.FooRepository +import tech.coner.trailer.toolkit.sample.fooapp.domain.repository.SimpleRepository +import tech.coner.trailer.toolkit.sample.fooapp.domain.service.FooService +import tech.coner.trailer.toolkit.sample.fooapp.domain.service.FooService.CreateFailure +import tech.coner.trailer.toolkit.sample.fooapp.domain.validation.FooValidator +import tech.coner.trailer.toolkit.validation.invoke + +class FooServiceImpl( + private val repository: FooRepository, + private val validator: FooValidator, +) : FooService { + + override suspend fun create(create: Foo): Result> = runCatching { + either { + validator(create) + .also { ensure(it.isValid) { CreateFailure.Invalid(it) } } + + repository.create(create).getOrThrow() + .mapLeft { + when (it) { + SimpleRepository.CreateFailure.AlreadyExists -> CreateFailure.AlreadyExists + } + } + .bind() + } + } + + override suspend fun findByKey(key: Foo.Id): Result> = runCatching { + repository.read(key).getOrThrow() + .mapLeft { + when (it) { + SimpleRepository.ReadFailure.NotFound -> FooService.FindFailure.NotFound + } + } + } + + override suspend fun update(update: Foo): Result> = runCatching { + either { + validator(update) + .also { ensure(it.isValid) { FooService.UpdateFailure.Invalid(it) } } + + repository.update(update).getOrThrow() + .mapLeft { + when (it) { + SimpleRepository.UpdateFailure.NotFound -> FooService.UpdateFailure.NotFound + } + } + .bind() + } + } + + override suspend fun deleteByKey(key: Foo.Id): Result> = runCatching { + repository.delete(key).getOrThrow() + .mapLeft { + when (it) { + SimpleRepository.DeleteFailure.NotFound -> FooService.DeleteFailure.NotFound + } + } + } +} diff --git a/toolkit/presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/domain/entity/Foo.kt b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/domain/entity/Foo.kt similarity index 71% rename from toolkit/presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/domain/entity/Foo.kt rename to toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/domain/entity/Foo.kt index 059f3a838..77e34fe70 100644 --- a/toolkit/presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/domain/entity/Foo.kt +++ b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/domain/entity/Foo.kt @@ -1,4 +1,4 @@ -package tech.coner.trailer.toolkit.presentation.testsupport.fooapp.domain.entity +package tech.coner.trailer.toolkit.sample.fooapp.domain.entity data class Foo(val id: Id, val name: String) { @JvmInline diff --git a/toolkit/presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/domain/exception/AlreadyExistsException.kt b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/domain/exception/AlreadyExistsException.kt similarity index 56% rename from toolkit/presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/domain/exception/AlreadyExistsException.kt rename to toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/domain/exception/AlreadyExistsException.kt index 4f4d09b42..af1668eec 100644 --- a/toolkit/presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/domain/exception/AlreadyExistsException.kt +++ b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/domain/exception/AlreadyExistsException.kt @@ -1,3 +1,3 @@ -package tech.coner.trailer.toolkit.presentation.testsupport.fooapp.domain.exception +package tech.coner.trailer.toolkit.sample.fooapp.domain.exception class AlreadyExistsException(message: String? = null, cause: Throwable? = null) : Exception(message, cause) diff --git a/toolkit/presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/domain/exception/NotFoundException.kt b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/domain/exception/NotFoundException.kt similarity index 56% rename from toolkit/presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/domain/exception/NotFoundException.kt rename to toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/domain/exception/NotFoundException.kt index 62d029c7a..ca30216ea 100644 --- a/toolkit/presentation/presentation-test/src/main/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/domain/exception/NotFoundException.kt +++ b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/domain/exception/NotFoundException.kt @@ -1,4 +1,4 @@ -package tech.coner.trailer.toolkit.presentation.testsupport.fooapp.domain.exception +package tech.coner.trailer.toolkit.sample.fooapp.domain.exception class NotFoundException(message: String? = null, cause: Throwable? = null) : Exception(message, cause) { } \ No newline at end of file diff --git a/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/domain/repository/FooRepository.kt b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/domain/repository/FooRepository.kt new file mode 100644 index 000000000..070ce9f7c --- /dev/null +++ b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/domain/repository/FooRepository.kt @@ -0,0 +1,5 @@ +package tech.coner.trailer.toolkit.sample.fooapp.domain.repository + +import tech.coner.trailer.toolkit.sample.fooapp.domain.entity.Foo + +typealias FooRepository = SimpleRepository diff --git a/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/domain/repository/SimpleRepository.kt b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/domain/repository/SimpleRepository.kt new file mode 100644 index 000000000..14fac2f08 --- /dev/null +++ b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/domain/repository/SimpleRepository.kt @@ -0,0 +1,32 @@ +package tech.coner.trailer.toolkit.sample.fooapp.domain.repository + +import arrow.core.Either + +interface SimpleRepository { + + fun create(value: VALUE): Result> + + sealed interface CreateFailure { + data object AlreadyExists : CreateFailure + } + + fun read(key: KEY): Result> + + sealed interface ReadFailure { + data object NotFound : ReadFailure + } + + fun update(value: VALUE): Result> + + sealed interface UpdateFailure { + data object NotFound : UpdateFailure + } + + fun delete(key: KEY): Result> + + sealed interface DeleteFailure { + data object NotFound : DeleteFailure + } + + fun exists(key: KEY): Result +} \ No newline at end of file diff --git a/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/domain/service/FooService.kt b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/domain/service/FooService.kt new file mode 100644 index 000000000..bfc647e2d --- /dev/null +++ b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/domain/service/FooService.kt @@ -0,0 +1,36 @@ +package tech.coner.trailer.toolkit.sample.fooapp.domain.service + +import arrow.core.Either +import tech.coner.trailer.toolkit.sample.fooapp.domain.entity.Foo +import tech.coner.trailer.toolkit.sample.fooapp.domain.validation.FooFeedback +import tech.coner.trailer.toolkit.validation.ValidationOutcome + +interface FooService { + + suspend fun create(create: Foo): Result> + + sealed interface CreateFailure { + data class Invalid(val validationOutcome: ValidationOutcome) : CreateFailure + data object AlreadyExists : CreateFailure + } + + suspend fun findByKey(key: Foo.Id): Result> + + sealed interface FindFailure { + data object NotFound : FindFailure + } + + suspend fun update(update: Foo): Result> + + sealed interface UpdateFailure { + data class Invalid(val validationOutcome: ValidationOutcome) : UpdateFailure + data object NotFound : UpdateFailure + } + + suspend fun deleteByKey(key: Foo.Id): Result> + + sealed interface DeleteFailure { + data object NotFound : DeleteFailure + } + +} \ No newline at end of file diff --git a/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/domain/validation/FooFeedback.kt b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/domain/validation/FooFeedback.kt new file mode 100644 index 000000000..b515b1bb5 --- /dev/null +++ b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/domain/validation/FooFeedback.kt @@ -0,0 +1,24 @@ +package tech.coner.trailer.toolkit.sample.fooapp.domain.validation + +import tech.coner.trailer.toolkit.sample.fooapp.domain.entity.Foo +import tech.coner.trailer.toolkit.validation.Feedback +import tech.coner.trailer.toolkit.validation.Severity +import kotlin.reflect.KProperty1 + +sealed class FooFeedback : Feedback { + + override val severity = Severity.Error + + data object IdMustBeInRange : FooFeedback() { + override val property = Foo::id + } + data object NameMustBeLowercaseLettersOnly : FooFeedback() { + override val property = Foo::name + } + data object NameMustBeThreeCharacters : FooFeedback() { + override val property = Foo::name + } + data object NameOtherThanFooMustFollowPatternOfConsonantVowelConsonant : FooFeedback() { + override val property = Foo::name + } +} \ No newline at end of file diff --git a/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/domain/validation/FooValidator.kt b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/domain/validation/FooValidator.kt new file mode 100644 index 000000000..4f18f418d --- /dev/null +++ b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/domain/validation/FooValidator.kt @@ -0,0 +1,28 @@ +package tech.coner.trailer.toolkit.sample.fooapp.domain.validation + +import tech.coner.trailer.toolkit.sample.fooapp.domain.entity.Foo +import tech.coner.trailer.toolkit.sample.fooapp.domain.validation.FooFeedback.IdMustBeInRange +import tech.coner.trailer.toolkit.sample.fooapp.domain.validation.FooFeedback.NameMustBeLowercaseLettersOnly +import tech.coner.trailer.toolkit.sample.fooapp.domain.validation.FooFeedback.NameMustBeThreeCharacters +import tech.coner.trailer.toolkit.sample.fooapp.domain.validation.FooFeedback.NameOtherThanFooMustFollowPatternOfConsonantVowelConsonant +import tech.coner.trailer.toolkit.validation.Validator + +typealias FooValidator = Validator + +fun FooValidator() = Validator { + Foo::id { id -> IdMustBeInRange.takeUnless { id.value in 0..4 } } + Foo::name { name -> NameMustBeLowercaseLettersOnly.takeUnless { name.all { it.isLowerCase() } } } + Foo::name { name -> NameMustBeThreeCharacters.takeUnless { name.length == 3 } } + + val vowels = "aeiouy" + val consonants = "bcdfghjklmnpqrstvwxz" + val namesOtherThanFooPattern = Regex("[$consonants][$vowels][$consonants]") + Foo::name { name -> + NameOtherThanFooMustFollowPatternOfConsonantVowelConsonant.takeUnless { + when (name) { + "foo" -> true + else -> namesOtherThanFooPattern.matches(name) + } + } + } +} \ No newline at end of file diff --git a/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/presentation/adapter/FooEntityModelAdapter.kt b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/presentation/adapter/FooEntityModelAdapter.kt new file mode 100644 index 000000000..984f77b24 --- /dev/null +++ b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/presentation/adapter/FooEntityModelAdapter.kt @@ -0,0 +1,23 @@ +package tech.coner.trailer.toolkit.sample.fooapp.presentation.adapter + +import tech.coner.trailer.toolkit.presentation.adapter.EntityModelAdapter +import tech.coner.trailer.toolkit.sample.fooapp.domain.entity.Foo +import tech.coner.trailer.toolkit.sample.fooapp.presentation.model.FooModel +import tech.coner.trailer.toolkit.sample.fooapp.util.capitalizeFirstChar + +class FooEntityModelAdapter : EntityModelAdapter() { + override val entityToModelAdapter: (Foo) -> FooModel = { + FooModel( + id = it.id, + name = entityToModelNamePropertyAdapter(it.name) + ) + } + override val modelToEntityAdapter: (FooModel) -> Foo = { + Foo( + id = it.id, + name = it.name.lowercase() + ) + } + + val entityToModelNamePropertyAdapter: (String) -> String = { it.capitalizeFirstChar() } +} \ No newline at end of file diff --git a/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/presentation/model/FooItemModel.kt b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/presentation/model/FooItemModel.kt new file mode 100644 index 000000000..ab52616ea --- /dev/null +++ b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/presentation/model/FooItemModel.kt @@ -0,0 +1,26 @@ +package tech.coner.trailer.toolkit.sample.fooapp.presentation.model + +import tech.coner.trailer.toolkit.presentation.model.BaseItemModel +import tech.coner.trailer.toolkit.sample.fooapp.domain.entity.Foo +import tech.coner.trailer.toolkit.sample.fooapp.domain.validation.FooFeedback +import tech.coner.trailer.toolkit.sample.fooapp.domain.validation.FooValidator +import tech.coner.trailer.toolkit.sample.fooapp.presentation.adapter.FooEntityModelAdapter +import tech.coner.trailer.toolkit.sample.fooapp.presentation.validation.FooModelFeedback +import tech.coner.trailer.toolkit.validation.Validator + +class FooItemModel( + override val initialItem: FooModel, + private val adapter: FooEntityModelAdapter = FooEntityModelAdapter() +) : BaseItemModel() { + + override val validator: Validator = Validator { + input( + otherTypeValidator = FooValidator(), + mapContextFn = {}, + mapInputFn = { adapter.modelToEntityAdapter(it) }, + mapFeedbackObjectFn = { FooModelFeedback(it) } + ) + } + override val validatorContext = Unit +} + diff --git a/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/presentation/model/FooModel.kt b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/presentation/model/FooModel.kt new file mode 100644 index 000000000..76d8daadc --- /dev/null +++ b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/presentation/model/FooModel.kt @@ -0,0 +1,9 @@ +package tech.coner.trailer.toolkit.sample.fooapp.presentation.model + +import tech.coner.trailer.toolkit.presentation.model.Model +import tech.coner.trailer.toolkit.sample.fooapp.domain.entity.Foo + +data class FooModel( + val id: Foo.Id, + val name: String +) : Model diff --git a/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/presentation/presenter/FooDetailPresenter.kt b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/presentation/presenter/FooDetailPresenter.kt new file mode 100644 index 000000000..875504176 --- /dev/null +++ b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/presentation/presenter/FooDetailPresenter.kt @@ -0,0 +1,87 @@ +package tech.coner.trailer.toolkit.sample.fooapp.presentation.presenter + +import arrow.core.Either +import arrow.core.raise.either +import kotlinx.coroutines.* +import kotlinx.coroutines.flow.StateFlow +import tech.coner.trailer.toolkit.presentation.model.Loadable +import tech.coner.trailer.toolkit.presentation.model.whenLoadedSuccess +import tech.coner.trailer.toolkit.presentation.presenter.ItemModelPresenter +import tech.coner.trailer.toolkit.presentation.presenter.LoadablePresenter +import tech.coner.trailer.toolkit.presentation.presenter.PresenterCoroutineScope +import tech.coner.trailer.toolkit.presentation.presenter.StatefulPresenter +import tech.coner.trailer.toolkit.presentation.state.StateContainer +import tech.coner.trailer.toolkit.presentation.state.mutableLoadedProperty +import tech.coner.trailer.toolkit.sample.fooapp.domain.entity.Foo +import tech.coner.trailer.toolkit.sample.fooapp.domain.service.FooService +import tech.coner.trailer.toolkit.sample.fooapp.presentation.adapter.FooEntityModelAdapter +import tech.coner.trailer.toolkit.sample.fooapp.presentation.model.FooItemModel +import tech.coner.trailer.toolkit.sample.fooapp.presentation.model.FooModel +import tech.coner.trailer.toolkit.sample.fooapp.presentation.state.FooDetailState +import kotlin.time.Duration.Companion.seconds + +class FooDetailPresenter( + initialState: FooDetailState = FooDetailState(loadable = Loadable.Empty()), + private val argument: Foo.Id, + private val adapter: FooEntityModelAdapter, + private val service: FooService, + coroutineScope: PresenterCoroutineScope +) : LoadablePresenter, + StatefulPresenter, + ItemModelPresenter, + CoroutineScope by coroutineScope { + + private val stateContainer = StateContainer(initialState) + override val state: FooDetailState get() = stateContainer.state + override val stateFlow: StateFlow get() = stateContainer.stateFlow + + override suspend fun load(): Deferred>> = coroutineScope { + async { + runCatching { + stateContainer.update { it.copy(loadable = Loadable.Loading()) } + either { + service.findByKey(argument).getOrThrow() + .map { foo -> + // faking partially loaded with delay + delay(1.seconds) + val partial = FooItemModel( + adapter.entityToModelAdapter( + foo.copy(name = "${foo.name[0]}") + ) + ) + stateContainer.update { it.copy(loadable = Loadable.Loading(partial)) } + delay(1.seconds) + foo + } + .map { foo -> + FooItemModel(adapter.entityToModelAdapter(foo)) + .also { fooItemModel -> stateContainer.update { it.copy(loadable = Loadable.Loaded(Either.Right(fooItemModel))) } } + } + .onLeft { failure -> stateContainer.update { it.copy(loadable = Loadable.Loaded(Either.Left(failure))) } } + .bind() + } + } + .onFailure { throwable -> + stateContainer.update { it.copy(loadable = Loadable.FailedExceptionally(throwable)) } + } + } + } + + override suspend fun commit() { + state.loadable.whenLoadedSuccess { it.commit() } + } + + override suspend fun validate() { + state.loadable.whenLoadedSuccess { it.validate() } + } + + override suspend fun reset() { + state.loadable.whenLoadedSuccess { it.reset() } + } + + val name = stateContainer.mutableLoadedProperty( + getFn = { name }, + updateFn = { copy(name = adapter.entityToModelNamePropertyAdapter(it)) }, + property = FooModel::name + ) +} diff --git a/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/presentation/state/FooDetailState.kt b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/presentation/state/FooDetailState.kt new file mode 100644 index 000000000..18133cddb --- /dev/null +++ b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/presentation/state/FooDetailState.kt @@ -0,0 +1,14 @@ +package tech.coner.trailer.toolkit.sample.fooapp.presentation.state + +import tech.coner.trailer.toolkit.presentation.model.Loadable +import tech.coner.trailer.toolkit.presentation.state.LoadableState +import tech.coner.trailer.toolkit.sample.fooapp.domain.service.FooService +import tech.coner.trailer.toolkit.sample.fooapp.domain.validation.FooFeedback +import tech.coner.trailer.toolkit.sample.fooapp.presentation.model.FooItemModel +import tech.coner.trailer.toolkit.sample.fooapp.presentation.model.FooModel +import tech.coner.trailer.toolkit.sample.fooapp.presentation.validation.FooModelFeedback + +data class FooDetailState( + override val loadable: Loadable = Loadable.Empty() +) : LoadableState { +} diff --git a/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/presentation/validation/FooModelFeedback.kt b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/presentation/validation/FooModelFeedback.kt new file mode 100644 index 000000000..3ed36404a --- /dev/null +++ b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/presentation/validation/FooModelFeedback.kt @@ -0,0 +1,18 @@ +package tech.coner.trailer.toolkit.sample.fooapp.presentation.validation + +import tech.coner.trailer.toolkit.sample.fooapp.domain.entity.Foo +import tech.coner.trailer.toolkit.sample.fooapp.domain.validation.FooFeedback +import tech.coner.trailer.toolkit.sample.fooapp.presentation.model.FooModel +import tech.coner.trailer.toolkit.validation.Feedback +import tech.coner.trailer.toolkit.validation.FeedbackDelegate +import tech.coner.trailer.toolkit.validation.adapter.propertyAdapterOf + +data class FooModelFeedback(val source: FooFeedback) + : Feedback by FeedbackDelegate( + feedback = source, + propertyAdapter = propertyAdapterOf( + Foo::id to FooModel::id, + Foo::name to FooModel::name, + null to null, + ) +) diff --git a/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/util/StringExtensions.kt b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/util/StringExtensions.kt new file mode 100644 index 000000000..06e3d4d4a --- /dev/null +++ b/toolkit/samples/fooapp/fooapp-common/src/main/kotlin/tech/coner/trailer/toolkit/sample/fooapp/util/StringExtensions.kt @@ -0,0 +1,7 @@ +package tech.coner.trailer.toolkit.sample.fooapp.util + +fun String.capitalizeFirstChar() = when (length) { + 0 -> this + 1 -> uppercase() + else -> "${this[0].uppercase()}${substring(1)}" +} \ No newline at end of file diff --git a/toolkit/presentation/presentation-test/src/test/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/domain/entity/FooAssertk.kt b/toolkit/samples/fooapp/fooapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/fooapp/domain/entity/FooAssertk.kt similarity index 62% rename from toolkit/presentation/presentation-test/src/test/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/domain/entity/FooAssertk.kt rename to toolkit/samples/fooapp/fooapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/fooapp/domain/entity/FooAssertk.kt index f28f0e76f..d146a7ecf 100644 --- a/toolkit/presentation/presentation-test/src/test/kotlin/tech/coner/trailer/toolkit/presentation/testsupport/fooapp/domain/entity/FooAssertk.kt +++ b/toolkit/samples/fooapp/fooapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/fooapp/domain/entity/FooAssertk.kt @@ -1,4 +1,4 @@ -package tech.coner.trailer.toolkit.presentation.testsupport.fooapp.domain.entity +package tech.coner.trailer.toolkit.sample.fooapp.domain.entity import assertk.Assert import assertk.assertions.prop diff --git a/toolkit/samples/fooapp/fooapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/fooapp/presentation/model/FooModelAssertk.kt b/toolkit/samples/fooapp/fooapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/fooapp/presentation/model/FooModelAssertk.kt new file mode 100644 index 000000000..e2573cb71 --- /dev/null +++ b/toolkit/samples/fooapp/fooapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/fooapp/presentation/model/FooModelAssertk.kt @@ -0,0 +1,6 @@ +package tech.coner.trailer.toolkit.sample.fooapp.presentation.model + +import assertk.Assert +import assertk.assertions.prop + +fun Assert.name() = prop(FooModel::name) \ No newline at end of file diff --git a/toolkit/samples/fooapp/fooapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/fooapp/presentation/presenter/FooDetailPresenterTest.kt b/toolkit/samples/fooapp/fooapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/fooapp/presentation/presenter/FooDetailPresenterTest.kt new file mode 100644 index 000000000..aca76b8ef --- /dev/null +++ b/toolkit/samples/fooapp/fooapp-common/src/test/kotlin/tech/coner/trailer/toolkit/sample/fooapp/presentation/presenter/FooDetailPresenterTest.kt @@ -0,0 +1,217 @@ +package tech.coner.trailer.toolkit.sample.fooapp.presentation.presenter + +import app.cash.turbine.test +import arrow.core.Either +import arrow.core.right +import assertk.Assert +import assertk.all +import assertk.assertThat +import assertk.assertions.* +import kotlinx.coroutines.CoroutineName +import kotlinx.coroutines.Job +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runTest +import org.junit.jupiter.api.Test +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.ValueSource +import tech.coner.trailer.assertk.arrowkt.isLeft +import tech.coner.trailer.assertk.arrowkt.isRight +import tech.coner.trailer.toolkit.Error +import tech.coner.trailer.toolkit.presentation.model.* +import tech.coner.trailer.toolkit.presentation.model.isDirty +import tech.coner.trailer.toolkit.presentation.model.isValid +import tech.coner.trailer.toolkit.presentation.model.item +import tech.coner.trailer.toolkit.presentation.model.pendingItem +import tech.coner.trailer.toolkit.presentation.model.pendingItemValidation +import tech.coner.trailer.toolkit.presentation.presenter.PresenterCoroutineScope +import tech.coner.trailer.toolkit.presentation.state.loadable +import tech.coner.trailer.toolkit.presentation.state.state +import tech.coner.trailer.toolkit.presentation.state.value +import tech.coner.trailer.toolkit.sample.fooapp.data.repository.FooRepositoryImpl +import tech.coner.trailer.toolkit.sample.fooapp.data.service.FooServiceImpl +import tech.coner.trailer.toolkit.sample.fooapp.domain.entity.FOO_ID_FOO +import tech.coner.trailer.toolkit.sample.fooapp.domain.entity.Foo +import tech.coner.trailer.toolkit.sample.fooapp.domain.repository.FooRepository +import tech.coner.trailer.toolkit.sample.fooapp.domain.service.FooService +import tech.coner.trailer.toolkit.sample.fooapp.domain.validation.FooValidator +import tech.coner.trailer.toolkit.sample.fooapp.presentation.adapter.FooEntityModelAdapter +import tech.coner.trailer.toolkit.sample.fooapp.presentation.model.FooItemModel +import tech.coner.trailer.toolkit.sample.fooapp.presentation.model.name +import tech.coner.trailer.toolkit.sample.fooapp.presentation.state.FooDetailState +import tech.coner.trailer.toolkit.validation.testsupport.isValid + +class FooDetailPresenterTest { + + private val repository: FooRepository = FooRepositoryImpl() + + @Test + fun itsModelFlowShouldBeAdaptedFromInitialState() = runTest { + val id = Foo.Id(FOO_ID_FOO) + val presenter = createPresenterInitial(id) + + presenter.stateFlow.test { + assertThat(expectMostRecentItem()) + .loadable() + .isEmpty() + } + } + + @Test + fun itsModelFlowShouldEmitWhenLoadingAndLoaded() = runTest { + val id = Foo.Id(FOO_ID_FOO) + val presenter = createPresenterInitial(id) + + presenter.stateFlow.test { + skipItems(1) + + presenter.load() + + assertThat(awaitItem()) + .loadable() + .isLoading() + .partial() + .isNull() + assertThat(awaitItem()) + .loadable() + .isLoading() + .partial() + .isNotNull() + .item() + .name() + .length() + .isEqualTo(1) + assertThat(awaitItem()) + .loadable() + .isLoaded() + .either() + .isRight() + .item() + .name() + .isEqualTo("Foo") + } + } + + @Test + fun itsModelFlowShouldEmitWhenLoadingAndLoadFailedNotFound() = runTest { + val id = Foo.Id(Int.MAX_VALUE) + val presenter = createPresenterInitial(id) + + presenter.stateFlow.test { + skipItems(1) + + presenter.load() + + assertThat(awaitItem()) + .loadable() + .isLoading() + assertThat(awaitItem()) + .loadable() + .isLoaded() + .either() + .isLeft() + .isEqualTo(FooService.FindFailure.NotFound) + } + } + + @Test + fun whenItsModelNameChangedValidItsItemModelShouldBeValid() = runTest { + val foo = repository.read(Foo.Id(FOO_ID_FOO)).getOrThrow().getOrNull()!! + val presenter = createPresenterLoaded(foo) + + presenter.name.value = "bax" + presenter.validate() + + assertThat(presenter).all { + name().value().isEqualTo("Bax") + state() + .loadable() + .isLoaded() + .either() + .isRight() + .all { + isValid().isTrue() + isDirty().isTrue() + } + } + } + + @Test + fun whenItsModelNameChangedInvalidItsItemModelShouldBeInvalid() = runTest { + val foo = repository.read(Foo.Id(FOO_ID_FOO)).getOrThrow().getOrNull()!! + val presenter = createPresenterLoaded(foo) + + presenter.name.value = "boo" + presenter.validate() + + assertThat(presenter).all { + name().value().isEqualTo("Boo") + state() + .loadable() + .isLoaded() + .either() + .isRight() + .all { + isValid().isFalse() + isDirty().isTrue() + } + } + } + + @ParameterizedTest + @ValueSource(strings = ["Bar", "Baz", "Bat", "Cat", "Dat", "Far", "Ber", "Fir", "Nor", "Dur", "Xyr"]) + fun whenItsModelNameChangedValidItsItemModelShouldValidateValid(newName: String) = runTest { + val foo = repository.read(Foo.Id(FOO_ID_FOO)).getOrThrow().getOrNull()!! + val presenter = createPresenterLoaded(foo) + + presenter.name.value = newName + presenter.validate() + + assertThat(presenter).all { + state() + .loadable() + .isLoaded() + .either() + .isRight() + .all { + pendingItem().name().isEqualTo(newName) + isValid().isTrue() + pendingItemValidation().isValid() + isDirty().isTrue() + } + } + } +} + +private fun TestScope.createPresenterInitial(id: Foo.Id): FooDetailPresenter { + return createPresenter( + argument = id, + ) +} + +private fun TestScope.createPresenterLoaded(foo: Foo): FooDetailPresenter { + val adapter = FooEntityModelAdapter() + return createPresenter( + initialState = FooDetailState(loadable = Loadable.Loaded(Either.Right(FooItemModel(adapter.entityToModelAdapter(foo))))), + argument = foo.id, + adapter = adapter, + ) +} + +private fun TestScope.createPresenter( + initialState: FooDetailState = FooDetailState(), + argument: Foo.Id, + adapter: FooEntityModelAdapter = FooEntityModelAdapter() +): FooDetailPresenter { + return FooDetailPresenter( + initialState = initialState, + argument = argument, + adapter = adapter, + service = FooServiceImpl( + repository = FooRepositoryImpl(), + validator = FooValidator(), + ), + coroutineScope = PresenterCoroutineScope(coroutineContext + Job() + CoroutineName("FooDetailPresenter")) + ) +} + +fun Assert.name() = prop(FooDetailPresenter::name) diff --git a/toolkit/util/pom.xml b/toolkit/samples/fooapp/fooapp-parent/pom.xml similarity index 60% rename from toolkit/util/pom.xml rename to toolkit/samples/fooapp/fooapp-parent/pom.xml index 20e973e32..6e0b63bac 100644 --- a/toolkit/util/pom.xml +++ b/toolkit/samples/fooapp/fooapp-parent/pom.xml @@ -5,12 +5,16 @@ 4.0.0 tech.coner.trailer - parent + toolkit-sample-common 0.1.0-SNAPSHOT - ../../pom.xml + ../../samples-common/pom.xml - toolkit-util + toolkit-sample-fooapp-parent + pom + + ../fooapp-common + \ No newline at end of file diff --git a/toolkit/samples/passwordapp/src/main/kotlin/tech/coner/trailer/toolkit/sample/passwordapp/domain/entity/Password.kt b/toolkit/samples/passwordapp/src/main/kotlin/tech/coner/trailer/toolkit/sample/passwordapp/domain/entity/Password.kt new file mode 100644 index 000000000..5ac595892 --- /dev/null +++ b/toolkit/samples/passwordapp/src/main/kotlin/tech/coner/trailer/toolkit/sample/passwordapp/domain/entity/Password.kt @@ -0,0 +1,4 @@ +package tech.coner.trailer.toolkit.sample.passwordapp.domain.entity + +@JvmInline +value class Password(val value: String) diff --git a/toolkit/samples/passwordapp/src/main/kotlin/tech/coner/trailer/toolkit/sample/passwordapp/domain/state/ChangePasswordFormatState.kt b/toolkit/samples/passwordapp/src/main/kotlin/tech/coner/trailer/toolkit/sample/passwordapp/domain/state/ChangePasswordFormatState.kt index bf57b198b..7e1c6842f 100644 --- a/toolkit/samples/passwordapp/src/main/kotlin/tech/coner/trailer/toolkit/sample/passwordapp/domain/state/ChangePasswordFormatState.kt +++ b/toolkit/samples/passwordapp/src/main/kotlin/tech/coner/trailer/toolkit/sample/passwordapp/domain/state/ChangePasswordFormatState.kt @@ -1,12 +1,13 @@ package tech.coner.trailer.toolkit.sample.passwordapp.domain.state +import tech.coner.trailer.toolkit.sample.passwordapp.domain.entity.Password import tech.coner.trailer.toolkit.sample.passwordapp.domain.entity.PasswordPolicy data class ChangePasswordFormState( val passwordPolicy: PasswordPolicy, - val currentPassword: String, - val newPassword: String, - val newPasswordRepeated: String + val currentPassword: Password, + val newPassword: Password, + val newPasswordRepeated: Password ) diff --git a/toolkit/samples/passwordapp/src/main/kotlin/tech/coner/trailer/toolkit/sample/passwordapp/domain/validation/ChangePasswordFormFeedback.kt b/toolkit/samples/passwordapp/src/main/kotlin/tech/coner/trailer/toolkit/sample/passwordapp/domain/validation/ChangePasswordFormFeedback.kt index 237586529..32333bb95 100644 --- a/toolkit/samples/passwordapp/src/main/kotlin/tech/coner/trailer/toolkit/sample/passwordapp/domain/validation/ChangePasswordFormFeedback.kt +++ b/toolkit/samples/passwordapp/src/main/kotlin/tech/coner/trailer/toolkit/sample/passwordapp/domain/validation/ChangePasswordFormFeedback.kt @@ -1,19 +1,24 @@ package tech.coner.trailer.toolkit.sample.passwordapp.domain.validation +import tech.coner.trailer.toolkit.sample.passwordapp.domain.state.ChangePasswordFormState import tech.coner.trailer.toolkit.validation.Feedback import tech.coner.trailer.toolkit.validation.Severity +import kotlin.reflect.KProperty1 -sealed class ChangePasswordFormFeedback : Feedback { - data object MustNotBeEmpty : ChangePasswordFormFeedback() { +sealed class ChangePasswordFormFeedback : Feedback { + data class MustNotBeEmpty(override val property: KProperty1) : ChangePasswordFormFeedback() { override val severity = Severity.Error } data object NewPasswordSameAsCurrentPassword : ChangePasswordFormFeedback() { + override val property = ChangePasswordFormState::newPassword override val severity = Severity.Error } data class NewPasswordFeedback(val feedback: PasswordFeedback) : ChangePasswordFormFeedback() { + override val property = ChangePasswordFormState::newPassword override val severity: Severity get() = feedback.severity } data object RepeatPasswordMismatch : ChangePasswordFormFeedback() { + override val property = ChangePasswordFormState::newPasswordRepeated override val severity = Severity.Error } } \ No newline at end of file diff --git a/toolkit/samples/passwordapp/src/main/kotlin/tech/coner/trailer/toolkit/sample/passwordapp/domain/validation/ChangePasswordFormValidator.kt b/toolkit/samples/passwordapp/src/main/kotlin/tech/coner/trailer/toolkit/sample/passwordapp/domain/validation/ChangePasswordFormValidator.kt index cc578e4d4..57e739bc6 100644 --- a/toolkit/samples/passwordapp/src/main/kotlin/tech/coner/trailer/toolkit/sample/passwordapp/domain/validation/ChangePasswordFormValidator.kt +++ b/toolkit/samples/passwordapp/src/main/kotlin/tech/coner/trailer/toolkit/sample/passwordapp/domain/validation/ChangePasswordFormValidator.kt @@ -16,11 +16,9 @@ typealias ChangePasswordFormValidator = Validator - MustNotBeEmpty.takeIf { currentPassword.isEmpty() } - } - ChangePasswordFormState::newPassword { newPassword: String -> - NewPasswordSameAsCurrentPassword.takeIf { input.currentPassword.isNotEmpty() && newPassword == input.currentPassword } + ChangePasswordFormState::currentPassword { if (it.value.isEmpty()) MustNotBeEmpty(property) else null } + ChangePasswordFormState::newPassword { newPassword -> + NewPasswordSameAsCurrentPassword.takeIf { input.currentPassword.value.isNotEmpty() && newPassword == input.currentPassword } } ChangePasswordFormState::newPassword.invoke(passwordValidator, { it.passwordPolicy }, ::NewPasswordFeedback) ChangePasswordFormState::newPasswordRepeated { newPasswordRepeated -> diff --git a/toolkit/samples/passwordapp/src/main/kotlin/tech/coner/trailer/toolkit/sample/passwordapp/domain/validation/PasswordFeedback.kt b/toolkit/samples/passwordapp/src/main/kotlin/tech/coner/trailer/toolkit/sample/passwordapp/domain/validation/PasswordFeedback.kt index 6bfe1c9d7..6423dd5d7 100644 --- a/toolkit/samples/passwordapp/src/main/kotlin/tech/coner/trailer/toolkit/sample/passwordapp/domain/validation/PasswordFeedback.kt +++ b/toolkit/samples/passwordapp/src/main/kotlin/tech/coner/trailer/toolkit/sample/passwordapp/domain/validation/PasswordFeedback.kt @@ -1,9 +1,11 @@ package tech.coner.trailer.toolkit.sample.passwordapp.domain.validation +import tech.coner.trailer.toolkit.sample.passwordapp.domain.entity.Password import tech.coner.trailer.toolkit.validation.Feedback import tech.coner.trailer.toolkit.validation.Severity -sealed class PasswordFeedback : Feedback { +sealed class PasswordFeedback : Feedback { + override val property = null data class InsufficientLength(override val severity: Severity) : PasswordFeedback() data class InsufficientLetterLowercase(override val severity: Severity) : PasswordFeedback() data class InsufficientLetterUppercase(override val severity: Severity) : PasswordFeedback() diff --git a/toolkit/samples/passwordapp/src/main/kotlin/tech/coner/trailer/toolkit/sample/passwordapp/domain/validation/PasswordValidator.kt b/toolkit/samples/passwordapp/src/main/kotlin/tech/coner/trailer/toolkit/sample/passwordapp/domain/validation/PasswordValidator.kt index d4cc750a1..998e2e5bf 100644 --- a/toolkit/samples/passwordapp/src/main/kotlin/tech/coner/trailer/toolkit/sample/passwordapp/domain/validation/PasswordValidator.kt +++ b/toolkit/samples/passwordapp/src/main/kotlin/tech/coner/trailer/toolkit/sample/passwordapp/domain/validation/PasswordValidator.kt @@ -1,5 +1,6 @@ package tech.coner.trailer.toolkit.sample.passwordapp.domain.validation +import tech.coner.trailer.toolkit.sample.passwordapp.domain.entity.Password import tech.coner.trailer.toolkit.sample.passwordapp.domain.entity.PasswordPolicy import tech.coner.trailer.toolkit.sample.passwordapp.domain.validation.PasswordFeedback.InsufficientLength import tech.coner.trailer.toolkit.sample.passwordapp.domain.validation.PasswordFeedback.InsufficientLetterLowercase @@ -11,15 +12,15 @@ import tech.coner.trailer.toolkit.validation.Severity.Error import tech.coner.trailer.toolkit.validation.Severity.Warning import tech.coner.trailer.toolkit.validation.Validator -typealias PasswordValidator = Validator +typealias PasswordValidator = Validator fun PasswordValidator(): PasswordValidator = Validator { input( - { context.lengthThreshold(it.length, ::InsufficientLength) }, - { context.letterLowercaseThreshold(it.count { char -> char.isLowerCase() }, ::InsufficientLetterLowercase ) }, - { context.letterUppercaseThreshold(it.count { char -> char.isUpperCase() }, ::InsufficientLetterUppercase ) }, - { context.numericThreshold(it.count { char -> char.isDigit() }, ::InsufficientNumeric ) }, - { context.specialThreshold(it.count { char -> !char.isLetterOrDigit() }, ::InsufficientSpecial ) } + { context.lengthThreshold(it.value.length, ::InsufficientLength) }, + { context.letterLowercaseThreshold(it.value.count { char -> char.isLowerCase() }, ::InsufficientLetterLowercase ) }, + { context.letterUppercaseThreshold(it.value.count { char -> char.isUpperCase() }, ::InsufficientLetterUppercase ) }, + { context.numericThreshold(it.value.count { char -> char.isDigit() }, ::InsufficientNumeric ) }, + { context.specialThreshold(it.value.count { char -> !char.isLetterOrDigit() }, ::InsufficientSpecial ) } ) } diff --git a/toolkit/samples/passwordapp/src/test/kotlin/validation/ChangePasswordFormValidatorTest.kt b/toolkit/samples/passwordapp/src/test/kotlin/validation/ChangePasswordFormValidatorTest.kt index 5359dfe12..35a1865e0 100644 --- a/toolkit/samples/passwordapp/src/test/kotlin/validation/ChangePasswordFormValidatorTest.kt +++ b/toolkit/samples/passwordapp/src/test/kotlin/validation/ChangePasswordFormValidatorTest.kt @@ -9,6 +9,7 @@ import io.mockk.every import io.mockk.mockk import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.EnumSource +import tech.coner.trailer.toolkit.sample.passwordapp.domain.entity.Password import tech.coner.trailer.toolkit.sample.passwordapp.domain.entity.PasswordPolicy.Factory.anyOneChar import tech.coner.trailer.toolkit.sample.passwordapp.domain.entity.PasswordPolicy.Factory.irritating import tech.coner.trailer.toolkit.sample.passwordapp.domain.state.ChangePasswordFormState @@ -27,9 +28,10 @@ import tech.coner.trailer.toolkit.sample.passwordapp.domain.validation.PasswordF import tech.coner.trailer.toolkit.sample.passwordapp.domain.validation.PasswordValidator import tech.coner.trailer.toolkit.validation.Severity.Error import tech.coner.trailer.toolkit.validation.Severity.Warning -import tech.coner.trailer.toolkit.validation.ValidationResult +import tech.coner.trailer.toolkit.validation.ValidationOutcome import tech.coner.trailer.toolkit.validation.invoke import tech.coner.trailer.toolkit.validation.testsupport.feedback +import tech.coner.trailer.toolkit.validation.testsupport.feedbackByProperty import tech.coner.trailer.toolkit.validation.testsupport.isInvalid import tech.coner.trailer.toolkit.validation.testsupport.isValid @@ -54,28 +56,28 @@ class ChangePasswordFormValidatorTest { mockNewPasswordFeedback = listOf(InsufficientLength(Error)), input = ChangePasswordFormState( passwordPolicy = anyOneChar(), - currentPassword = "", - newPassword = "", - newPasswordRepeated = "" + currentPassword = Password(""), + newPassword = Password(""), + newPasswordRepeated = Password("") ), - expectedCurrentPasswordFeedback = listOf(MustNotBeEmpty), + expectedCurrentPasswordFeedback = listOf(MustNotBeEmpty(ChangePasswordFormState::currentPassword)), expectedIsValid = false ), MINIMUM_ANY_ONE_CHAR_VALID( input = ChangePasswordFormState( passwordPolicy = anyOneChar(), - currentPassword = "a", - newPassword = "b", - newPasswordRepeated = "b" + currentPassword = Password("a"), + newPassword = Password("b"), + newPasswordRepeated = Password("b") ), expectedIsValid = true ), SAME_ANY_ONE_CHAR_INVALID( input = ChangePasswordFormState( passwordPolicy = anyOneChar(), - currentPassword = "a", - newPassword = "a", - newPasswordRepeated = "a" + currentPassword = Password("a"), + newPassword = Password("a"), + newPasswordRepeated = Password("a") ), expectedLocalNewPasswordFeedback = listOf(NewPasswordSameAsCurrentPassword), expectedIsValid = false @@ -83,9 +85,9 @@ class ChangePasswordFormValidatorTest { REPEAT_MISMATCH_ANY_ONE_CHAR_INVALID( input = ChangePasswordFormState( passwordPolicy = anyOneChar(), - currentPassword = "a", - newPassword = "b", - newPasswordRepeated = "c" + currentPassword = Password("a"), + newPassword = Password("b"), + newPasswordRepeated = Password("c") ), expectedNewPasswordRepeatedFeedback = listOf(RepeatPasswordMismatch), expectedIsValid = false @@ -100,9 +102,9 @@ class ChangePasswordFormValidatorTest { ), input = ChangePasswordFormState( passwordPolicy = irritating(), - currentPassword = "a", - newPassword = "aA1!", - newPasswordRepeated = "aA1!" + currentPassword = Password("a"), + newPassword = Password("aA1!"), + newPasswordRepeated = Password("aA1!") ), expectedIsValid = false ), @@ -114,9 +116,9 @@ class ChangePasswordFormValidatorTest { ), input = ChangePasswordFormState( passwordPolicy = irritating(), - currentPassword = "a", - newPassword = "Tr0ub4dor&3", - newPasswordRepeated = "Tr0ub4dor&3" + currentPassword = Password("a"), + newPassword = Password("Tr0ub4dor&3"), + newPasswordRepeated = Password("Tr0ub4dor&3") ), expectedIsValid = true ), @@ -127,9 +129,9 @@ class ChangePasswordFormValidatorTest { ), input = ChangePasswordFormState( passwordPolicy = irritating(), - currentPassword = "a", - newPassword = "battery horse staple correct", - newPasswordRepeated = "battery horse staple correct" + currentPassword = Password("a"), + newPassword = Password("battery horse staple correct"), + newPasswordRepeated = Password("battery horse staple correct") ), expectedIsValid = false ); @@ -156,16 +158,16 @@ class ChangePasswordFormValidatorTest { every { passwordValidator(scenario.input.passwordPolicy, scenario.input.newPassword) } returns( - ValidationResult( + ValidationOutcome( scenario.mockNewPasswordFeedback - ?.let { mapOf(null to it) } - ?: emptyMap()) + ?: emptyList() + ) ) val actual = changePasswordFormValidator(scenario.input) assertThat(actual).all { - feedback().all { + feedbackByProperty().all { when (scenario.expectedCurrentPasswordFeedback) { is List -> key(ChangePasswordFormState::currentPassword).isEqualTo(scenario.expectedCurrentPasswordFeedback) else -> doesNotContainKey(ChangePasswordFormState::currentPassword) diff --git a/toolkit/samples/passwordapp/src/test/kotlin/validation/PasswordValidatorTest.kt b/toolkit/samples/passwordapp/src/test/kotlin/validation/PasswordValidatorTest.kt index cd43d8aa6..09181ffc3 100644 --- a/toolkit/samples/passwordapp/src/test/kotlin/validation/PasswordValidatorTest.kt +++ b/toolkit/samples/passwordapp/src/test/kotlin/validation/PasswordValidatorTest.kt @@ -7,6 +7,7 @@ import assertk.assertions.isEqualTo import assertk.assertions.key import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.EnumSource +import tech.coner.trailer.toolkit.sample.passwordapp.domain.entity.Password import tech.coner.trailer.toolkit.sample.passwordapp.domain.entity.PasswordPolicy import tech.coner.trailer.toolkit.sample.passwordapp.domain.entity.PasswordPolicy.Factory.anyOneChar import tech.coner.trailer.toolkit.sample.passwordapp.domain.entity.PasswordPolicy.Factory.irritating @@ -20,6 +21,7 @@ import tech.coner.trailer.toolkit.sample.passwordapp.domain.validation.PasswordV import tech.coner.trailer.toolkit.validation.Severity.Error import tech.coner.trailer.toolkit.validation.Severity.Warning import tech.coner.trailer.toolkit.validation.testsupport.feedback +import tech.coner.trailer.toolkit.validation.testsupport.feedbackByProperty import tech.coner.trailer.toolkit.validation.testsupport.isInvalid import tech.coner.trailer.toolkit.validation.testsupport.isValid @@ -29,24 +31,24 @@ class PasswordValidatorTest { enum class PasswordScenario( val policy: PasswordPolicy, - val password: String, + val password: Password, val expectedFeedback: List? = null, val expectedIsValid: Boolean ) { EMPTY_ANY_ONE_CHAR_INVALID( policy = anyOneChar(), - password = "", + password = Password(""), expectedFeedback = listOf(InsufficientLength(Error)), expectedIsValid = false ), MINIMUM_ANY_ONE_CHAR_VALID( policy = anyOneChar(), - password = "b", + password = Password("b"), expectedIsValid = true ), IRRITATING_INVALID( policy = irritating(), - password = "aA1!", + password = Password("aA1!"), expectedFeedback = listOf( InsufficientLength(Error), InsufficientLetterLowercase(Warning), @@ -58,7 +60,7 @@ class PasswordValidatorTest { ), IRRITATING_VALID_WITH_WARNINGS( policy = irritating(), - password = "Tr0ub4dor&3", + password = Password("Tr0ub4dor&3"), expectedFeedback = listOf( InsufficientLength(Warning), InsufficientLetterUppercase(Warning), @@ -68,7 +70,7 @@ class PasswordValidatorTest { ), IRRITATING_HARD_TO_REMEMBER_EASY_GUESS_FOR_COMPUTER( policy = irritating(), - password = "battery horse staple correct", + password = Password("battery horse staple correct"), expectedFeedback = listOf( InsufficientLetterUppercase(Error), InsufficientNumeric(Error) @@ -83,7 +85,7 @@ class PasswordValidatorTest { val actual = validator(scenario.policy, scenario.password) assertThat(actual).all { - feedback().all { + feedbackByProperty().all { if (scenario.expectedFeedback?.isNotEmpty() == true) { key(null).isEqualTo(scenario.expectedFeedback) } else { diff --git a/toolkit/samples/samples-common/pom.xml b/toolkit/samples/samples-common/pom.xml index 4a245b088..6afec156c 100644 --- a/toolkit/samples/samples-common/pom.xml +++ b/toolkit/samples/samples-common/pom.xml @@ -5,14 +5,15 @@ 4.0.0 tech.coner.trailer - parent + buildsrc-kotlin-parent 0.1.0-SNAPSHOT - ../../../pom.xml + ../../../buildsrc/buildsrc-kotlin-parent/pom.xml toolkit-sample-common pom + ../fooapp/fooapp-parent ../passwordapp ../dmvapp/dmvapp-parent diff --git a/toolkit/toolkit/pom.xml b/toolkit/toolkit/pom.xml new file mode 100644 index 000000000..7ae8c8b2a --- /dev/null +++ b/toolkit/toolkit/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + + tech.coner.trailer + buildsrc-kotlin-parent + 0.1.0-SNAPSHOT + ../../buildsrc/buildsrc-kotlin-parent/pom.xml + + + toolkit + + + + tech.coner.trailer + toolkit-validation + 0.1.0-SNAPSHOT + + + + \ No newline at end of file diff --git a/toolkit/toolkit/src/main/kotlin/tech/coner/trailer/toolkit/Error.kt b/toolkit/toolkit/src/main/kotlin/tech/coner/trailer/toolkit/Error.kt new file mode 100644 index 000000000..8202ab92f --- /dev/null +++ b/toolkit/toolkit/src/main/kotlin/tech/coner/trailer/toolkit/Error.kt @@ -0,0 +1,29 @@ +package tech.coner.trailer.toolkit + +sealed interface Error { + data object NotFound : Error + data object AlreadyExists : Error + data object ConcurrentEntry : Error + data object InvalidState : Error + + /** + * Indicates unhandled invalid input. + * + * Toolkit users should take care to handle MutationOutcome.InvalidInputFailure and make its ValidationResult's + * feedback available to the user in context. + */ + data object InvalidInput : Error + data object Timeout : Error + + // expand as necessary + + data class Exceptional(val throwable: Throwable) : Error + + fun toException() = ErrorException( + error = this, + cause = when (this) { + is Exceptional -> throwable + else -> null + } + ) +} \ No newline at end of file diff --git a/toolkit/toolkit/src/main/kotlin/tech/coner/trailer/toolkit/ErrorException.kt b/toolkit/toolkit/src/main/kotlin/tech/coner/trailer/toolkit/ErrorException.kt new file mode 100644 index 000000000..2deb263d1 --- /dev/null +++ b/toolkit/toolkit/src/main/kotlin/tech/coner/trailer/toolkit/ErrorException.kt @@ -0,0 +1,4 @@ +package tech.coner.trailer.toolkit + +class ErrorException(val error: Error, cause: Throwable? = null) : Exception(cause) { +} \ No newline at end of file diff --git a/toolkit/util/src/main/kotlin/tech/coner/trailer/toolkit/util/StringExtensions.kt b/toolkit/toolkit/src/main/kotlin/tech/coner/trailer/toolkit/StringExtensions.kt similarity index 56% rename from toolkit/util/src/main/kotlin/tech/coner/trailer/toolkit/util/StringExtensions.kt rename to toolkit/toolkit/src/main/kotlin/tech/coner/trailer/toolkit/StringExtensions.kt index 801ac90b6..ed7ad453a 100644 --- a/toolkit/util/src/main/kotlin/tech/coner/trailer/toolkit/util/StringExtensions.kt +++ b/toolkit/toolkit/src/main/kotlin/tech/coner/trailer/toolkit/StringExtensions.kt @@ -1,3 +1,3 @@ -package tech.coner.trailer.toolkit.util +package tech.coner.trailer.toolkit fun String.dashify() = lowercase().replace(' ', '-') \ No newline at end of file diff --git a/toolkit/validation/validation-testsupport/pom.xml b/toolkit/validation/validation-testsupport/pom.xml index ca7f649ef..e37d06a36 100644 --- a/toolkit/validation/validation-testsupport/pom.xml +++ b/toolkit/validation/validation-testsupport/pom.xml @@ -5,9 +5,9 @@ 4.0.0 tech.coner.trailer - parent + buildsrc-kotlin-parent 0.1.0-SNAPSHOT - ../../../pom.xml + ../../../buildsrc/buildsrc-kotlin-parent/pom.xml toolkit-validation-testsupport diff --git a/toolkit/validation/validation-testsupport/src/main/kotlin/tech/coner/trailer/toolkit/validation/testsupport/ValidationResultAssertk.kt b/toolkit/validation/validation-testsupport/src/main/kotlin/tech/coner/trailer/toolkit/validation/testsupport/ValidationResultAssertk.kt index cc8507b08..b11a0aade 100644 --- a/toolkit/validation/validation-testsupport/src/main/kotlin/tech/coner/trailer/toolkit/validation/testsupport/ValidationResultAssertk.kt +++ b/toolkit/validation/validation-testsupport/src/main/kotlin/tech/coner/trailer/toolkit/validation/testsupport/ValidationResultAssertk.kt @@ -3,10 +3,12 @@ package tech.coner.trailer.toolkit.validation.testsupport import assertk.Assert import assertk.assertions.prop import tech.coner.trailer.toolkit.validation.Feedback -import tech.coner.trailer.toolkit.validation.ValidationResult +import tech.coner.trailer.toolkit.validation.ValidationOutcome -fun Assert>.feedback() = prop(ValidationResult::feedback) +fun > Assert>.feedback() = prop(ValidationOutcome::feedback) -fun Assert>.isValid() = prop(ValidationResult<*, *>::isValid) -fun Assert>.isInvalid() = prop(ValidationResult<*, *>::isInvalid) +fun > Assert>.feedbackByProperty() = prop(ValidationOutcome::feedbackByProperty) + +fun Assert>.isValid() = prop(ValidationOutcome<*, *>::isValid) +fun Assert>.isInvalid() = prop(ValidationOutcome<*, *>::isInvalid) diff --git a/toolkit/validation/validation/pom.xml b/toolkit/validation/validation/pom.xml index 8b36089e7..3b262f8df 100644 --- a/toolkit/validation/validation/pom.xml +++ b/toolkit/validation/validation/pom.xml @@ -5,9 +5,9 @@ 4.0.0 tech.coner.trailer - parent + buildsrc-kotlin-parent 0.1.0-SNAPSHOT - ../../../pom.xml + ../../../buildsrc/buildsrc-kotlin-parent/pom.xml toolkit-validation diff --git a/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/Feedback.kt b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/Feedback.kt index e4fed7db1..da1ff254e 100644 --- a/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/Feedback.kt +++ b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/Feedback.kt @@ -1,6 +1,8 @@ package tech.coner.trailer.toolkit.validation -interface Feedback { +import kotlin.reflect.KProperty1 + +interface Feedback { + val property: KProperty1? val severity: Severity } - diff --git a/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/FeedbackDelegate.kt b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/FeedbackDelegate.kt new file mode 100644 index 000000000..0c40abd01 --- /dev/null +++ b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/FeedbackDelegate.kt @@ -0,0 +1,14 @@ +package tech.coner.trailer.toolkit.validation + +import tech.coner.trailer.toolkit.validation.adapter.PropertyAdapter +import kotlin.reflect.KProperty1 + +class FeedbackDelegate( + val feedback: Feedback, + val propertyAdapter: PropertyAdapter +) : Feedback { + override val property: KProperty1? + get() = propertyAdapter(feedback.property) + override val severity: Severity + get() = feedback.severity +} diff --git a/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/ValidationOutcome.kt b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/ValidationOutcome.kt new file mode 100644 index 000000000..1687d18b4 --- /dev/null +++ b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/ValidationOutcome.kt @@ -0,0 +1,49 @@ +package tech.coner.trailer.toolkit.validation + +import kotlin.reflect.KProperty1 + +data class ValidationOutcome>( + val feedback: List +) { + + val feedbackByProperty: Map?, List> by lazy { + feedback.groupBy { it.property } + } + + val isValid: Boolean by lazy { + feedback.isEmpty() + || feedback.isValid + } + + val isInvalid: Boolean by lazy { + feedback.isNotEmpty() + && feedback.isInvalid + } + + /** + * When this result is valid, invoke `validFn` or no-op + * + * @param validFn the function to invoke if this result is valid + * @return this, fluent interface + */ + fun whenValid(validFn: () -> Unit): ValidationOutcome { + if (isValid) validFn() + return this + } + + /** + * When this result is valid, invoke `validFn` and return its result or no-op and return null + * + * @param validFn the function to invoke if this result is valid + * @return the result of validFn, + */ + fun letValid(validFn: () -> R): R? { + return if (isValid) validFn() else null + } +} + +val List>.isValid: Boolean + get() = all { feedback -> feedback.severity.valid } + +val List>.isInvalid: Boolean + get() = any { feedback -> !feedback.severity.valid } \ No newline at end of file diff --git a/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/ValidationResult.kt b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/ValidationResult.kt deleted file mode 100644 index d99e25e0d..000000000 --- a/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/ValidationResult.kt +++ /dev/null @@ -1,30 +0,0 @@ -package tech.coner.trailer.toolkit.validation - -import kotlin.reflect.KProperty1 - -data class ValidationResult( - val feedback: Map?, List> -) { - val isValid: Boolean by lazy { - feedback.isEmpty() - || feedback.values.all { it.all { feedback -> feedback.severity.valid } } - } - - val isInvalid: Boolean by lazy { - feedback.isNotEmpty() - && feedback.values.any { it.any { feedback -> !feedback.severity.valid } } - } - - /** - * When this result is valid, invoke `validFn` and return its result, or `null` otherwise - * - * @param validFn the function to invoke if this result is valid - * @return the result of `validFn` if this result is valid, or `null` otherwise - */ - fun whenValid(validFn: () -> R?): R? { - return when { - isValid -> validFn() - else -> null - } - } -} \ No newline at end of file diff --git a/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/Validator.kt b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/Validator.kt index 0847cc2fe..30a1f2a75 100644 --- a/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/Validator.kt +++ b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/Validator.kt @@ -1,30 +1,31 @@ package tech.coner.trailer.toolkit.validation +import tech.coner.trailer.toolkit.validation.context.PropertyValidationRuleContext import kotlin.reflect.KProperty1 import tech.coner.trailer.toolkit.validation.context.ValidationRuleContext import tech.coner.trailer.toolkit.validation.impl.ValidatorImpl -fun Validator( +fun > Validator( function: Validator.Builder.() -> Unit ): Validator { return ValidatorImpl(function) } -interface Validator { - operator fun invoke(context: CONTEXT, input: INPUT): ValidationResult +interface Validator> { + operator fun invoke(context: CONTEXT, input: INPUT): ValidationOutcome - interface Builder { + interface Builder> { operator fun KProperty1.invoke( - ruleFn: ValidationRuleContext.(PROPERTY) -> FEEDBACK? + ruleFn: PropertyValidationRuleContext.(PROPERTY) -> FEEDBACK? ) operator fun KProperty1.invoke( vararg ruleFns: ValidationRuleContext.(PROPERTY) -> FEEDBACK? ) - operator fun KProperty1.invoke( + operator fun > KProperty1.invoke( validator: Validator, mapContextFn: CONTEXT.(INPUT) -> DELEGATE_CONTEXT, mapFeedbackFn: (DELEGATE_FEEDBACK) -> FEEDBACK @@ -38,11 +39,14 @@ interface Validator { vararg ruleFns: ValidationRuleContext.(INPUT) -> FEEDBACK? ) - fun input( - validator: Validator, + fun input( + validator: Validator + ) + + fun > input( + otherTypeValidator: Validator, mapContextFn: CONTEXT.(INPUT) -> DELEGATE_CONTEXT, mapInputFn: CONTEXT.(INPUT) -> DELEGATE_INPUT, - mapFeedbackKeys: Map?, KProperty1?>, mapFeedbackObjectFn: (DELEGATE_FEEDBACK) -> FEEDBACK ) @@ -53,22 +57,20 @@ interface Validator { /** * Convenience for invoking Unit-context validators, omitting the redundant Unit context parameter */ -operator fun Validator.invoke(input: INPUT): ValidationResult { +operator fun > Validator.invoke(input: INPUT): ValidationOutcome { return invoke(Unit, input) } /** * Convenience for delegating object validation from one Unit-context validator to another */ -fun Validator.Builder.input( +fun , DELEGATE_INPUT, DELEGATE_FEEDBACK : Feedback> Validator.Builder.input( validator: Validator, mapInputFn: Unit.(INPUT) -> DELEGATE_INPUT, - mapFeedbackKeys: Map?, KProperty1?>, mapFeedbackObjectFn: (DELEGATE_FEEDBACK) -> FEEDBACK ) = input( - validator = validator, + otherTypeValidator = validator, mapContextFn = { }, mapInputFn = mapInputFn, - mapFeedbackKeys = mapFeedbackKeys, mapFeedbackObjectFn = mapFeedbackObjectFn ) \ No newline at end of file diff --git a/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/adapter/PropertyAdapter.kt b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/adapter/PropertyAdapter.kt new file mode 100644 index 000000000..551bf933c --- /dev/null +++ b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/adapter/PropertyAdapter.kt @@ -0,0 +1,35 @@ +package tech.coner.trailer.toolkit.validation.adapter + +import kotlin.reflect.KClass +import kotlin.reflect.KProperty1 + +interface PropertyAdapter { + operator fun invoke(property: KProperty1?): KProperty1? +} + +internal class PropertyAdapterImpl ( + private val map: Map?, KProperty1?> +) : PropertyAdapter { + override operator fun invoke(property: KProperty1?): KProperty1? { + return map[property] + } +} + +inline fun propertyAdapterOf( + vararg pairs: Pair?, KProperty1?> +): PropertyAdapter { + return propertyAdapterOf(rClass = R::class, pairs = pairs) +} + +fun propertyAdapterOf( + rClass: KClass<*>, + vararg pairs: Pair?, KProperty1?> +): PropertyAdapter { + check(pairs.size == rClass.properties.size + 1) { + "Count of validated pairs doesn't match" + } + return PropertyAdapterImpl(pairs.toMap()) +} + +private val KClass<*>.properties: List> + get() = members.filterIsInstance>() \ No newline at end of file diff --git a/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/adapter/ValidationOutcomeAdapter.kt b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/adapter/ValidationOutcomeAdapter.kt new file mode 100644 index 000000000..4f25a2461 --- /dev/null +++ b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/adapter/ValidationOutcomeAdapter.kt @@ -0,0 +1,14 @@ +package tech.coner.trailer.toolkit.validation.adapter + +import tech.coner.trailer.toolkit.validation.Feedback +import tech.coner.trailer.toolkit.validation.ValidationOutcome + +fun interface ValidationOutcomeAdapter, NEW_INPUT, NEW_FEEDBACK : Feedback> { + operator fun invoke(validationOutcome: ValidationOutcome): ValidationOutcome +} + +fun , NEW_INPUT, NEW_FEEDBACK : Feedback> ValidationOutcome.map(fn: (FEEDBACK) -> NEW_FEEDBACK): ValidationOutcome { + return ValidationOutcome( + feedback = feedback.map { fn(it) } + ) +} \ No newline at end of file diff --git a/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/context/PropertyValidationRuleContext.kt b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/context/PropertyValidationRuleContext.kt new file mode 100644 index 000000000..0af2e0c18 --- /dev/null +++ b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/context/PropertyValidationRuleContext.kt @@ -0,0 +1,7 @@ +package tech.coner.trailer.toolkit.validation.context + +import kotlin.reflect.KProperty1 + +interface PropertyValidationRuleContext : ValidationRuleContext { + val property: KProperty1 +} \ No newline at end of file diff --git a/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/impl/ValidatorImpl.kt b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/impl/ValidatorImpl.kt index 5a95aebcd..6366bc78e 100644 --- a/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/impl/ValidatorImpl.kt +++ b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/impl/ValidatorImpl.kt @@ -1,13 +1,16 @@ package tech.coner.trailer.toolkit.validation.impl -import tech.coner.trailer.toolkit.validation.* +import kotlin.reflect.KProperty1 +import tech.coner.trailer.toolkit.validation.Feedback +import tech.coner.trailer.toolkit.validation.ValidationOutcome +import tech.coner.trailer.toolkit.validation.Validator +import tech.coner.trailer.toolkit.validation.context.PropertyValidationRuleContext import tech.coner.trailer.toolkit.validation.context.ValidationRuleContext import tech.coner.trailer.toolkit.validation.impl.entry.ValidationEntry import tech.coner.trailer.toolkit.validation.impl.rule.ObjectValidationRuleImpl import tech.coner.trailer.toolkit.validation.impl.rule.PropertyValidationRuleImpl -import kotlin.reflect.KProperty1 -internal class ValidatorImpl( +internal class ValidatorImpl>( builder: Validator.Builder.() -> Unit ) : Validator { @@ -19,46 +22,51 @@ internal class ValidatorImpl( .also { entries = it.entries } } - override fun invoke(context: CONTEXT, input: INPUT): ValidationResult { - val feedback: MutableMap?, MutableList> = mutableMapOf() + override fun invoke(context: CONTEXT, input: INPUT): ValidationOutcome { + val feedback: MutableList = mutableListOf() for (entry in entries) { when (entry) { is ValidationEntry.InputPropertySingleFeedback -> { entry(context, input) - ?.also { feedback.createOrAppend(entry.property, it) } + ?.also { feedback += it } } is ValidationEntry.InputObjectSingleFeedback -> { entry(context, input) - ?.also { feedback.createOrAppend(null, it) } + ?.also { feedback += it } } is ValidationEntry.InputPropertyDelegatesToValidator -> { entry(context, input) - .also { feedback.createOrAppend(it.feedback) } + .also { feedback.addAll(it.feedback) } + } + + is ValidationEntry.InputObjectDelegatesToOtherTypeValidator -> { + entry(context, input) + .also { feedback += it.feedback } } - is ValidationEntry.InputObjectDelegatesToValidator -> { + is ValidationEntry.InputObjectDelegatesToSameTypeValidator -> { entry(context, input) - .also { feedback.createOrAppend(it.feedback) } + .also { feedback += it.feedback } } is ValidationEntry.ReturnEarlyIfAny -> { - if (entry(feedback.toMap())) { + if (entry(feedback)) { break } } } } - return ValidationResult(feedback.toMap()) + return ValidationOutcome(feedback) } - internal class BuilderImpl : Validator.Builder { + internal class BuilderImpl> : Validator.Builder { internal val entries: MutableList> = mutableListOf() override fun KProperty1.invoke( - ruleFn: ValidationRuleContext.(PROPERTY) -> FEEDBACK? + ruleFn: PropertyValidationRuleContext.(PROPERTY) -> FEEDBACK? ) { entries += ValidationEntry.InputPropertySingleFeedback( property = this, @@ -78,7 +86,7 @@ internal class ValidatorImpl( } } - override fun KProperty1.invoke( + override fun > KProperty1.invoke( validator: Validator, mapContextFn: CONTEXT.(INPUT) -> DELEGATE_CONTEXT, mapFeedbackFn: (DELEGATE_FEEDBACK) -> FEEDBACK @@ -106,22 +114,24 @@ internal class ValidatorImpl( } } - override fun input( - validator: Validator, + override fun > input( + otherTypeValidator: Validator, mapContextFn: CONTEXT.(INPUT) -> DELEGATE_CONTEXT, mapInputFn: CONTEXT.(INPUT) -> DELEGATE_INPUT, - mapFeedbackKeys: Map?, KProperty1?>, mapFeedbackObjectFn: (DELEGATE_FEEDBACK) -> FEEDBACK ) { - entries += ValidationEntry.InputObjectDelegatesToValidator( - validator = validator, + entries += ValidationEntry.InputObjectDelegatesToOtherTypeValidator( + validator = otherTypeValidator, mapContextFn = mapContextFn, mapInputFn = mapInputFn, - mapFeedbackKeys = mapFeedbackKeys, mapFeedbackObjectFn = mapFeedbackObjectFn ) } + override fun input(validator: Validator) { + entries += ValidationEntry.InputObjectDelegatesToSameTypeValidator(validator) + } + override fun returnEarlyIfAny(matchFn: (FEEDBACK) -> Boolean) { entries += ValidationEntry.ReturnEarlyIfAny(matchFn) } diff --git a/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/impl/context/PropertyValidationRuleContextImpl.kt b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/impl/context/PropertyValidationRuleContextImpl.kt new file mode 100644 index 000000000..9404c790f --- /dev/null +++ b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/impl/context/PropertyValidationRuleContextImpl.kt @@ -0,0 +1,10 @@ +package tech.coner.trailer.toolkit.validation.impl.context + +import tech.coner.trailer.toolkit.validation.context.PropertyValidationRuleContext +import kotlin.reflect.KProperty1 + +data class PropertyValidationRuleContextImpl( + override val context: CONTEXT, + override val input: INPUT, + override val property: KProperty1 +) : PropertyValidationRuleContext diff --git a/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/impl/entry/ValidationEntry.kt b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/impl/entry/ValidationEntry.kt index 8f6dc9b5b..088d78d85 100644 --- a/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/impl/entry/ValidationEntry.kt +++ b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/impl/entry/ValidationEntry.kt @@ -2,14 +2,14 @@ package tech.coner.trailer.toolkit.validation.impl.entry import kotlin.reflect.KProperty1 import tech.coner.trailer.toolkit.validation.Feedback -import tech.coner.trailer.toolkit.validation.ValidationResult +import tech.coner.trailer.toolkit.validation.ValidationOutcome import tech.coner.trailer.toolkit.validation.Validator import tech.coner.trailer.toolkit.validation.rule.PropertyValidationRule import tech.coner.trailer.toolkit.validation.rule.ValidationRule -internal sealed class ValidationEntry { +internal sealed class ValidationEntry> { - internal class InputPropertySingleFeedback( + internal class InputPropertySingleFeedback>( val property: KProperty1, private val rule: PropertyValidationRule ) @@ -20,7 +20,7 @@ internal sealed class ValidationEntry { } } - internal class InputObjectSingleFeedback( + internal class InputObjectSingleFeedback>( private val rule: ValidationRule ) : ValidationEntry() { @@ -29,7 +29,7 @@ internal sealed class ValidationEntry { } } - internal class InputPropertyDelegatesToValidator( + internal class InputPropertyDelegatesToValidator, FEEDBACK : Feedback>( private val property: KProperty1, private val validator: Validator, private val mapContextFn: CONTEXT.(INPUT) -> DELEGATE_CONTEXT, @@ -37,54 +37,51 @@ internal sealed class ValidationEntry { ) : ValidationEntry() { - operator fun invoke(context: CONTEXT, input: INPUT): ValidationResult { - return ValidationResult( + operator fun invoke(context: CONTEXT, input: INPUT): ValidationOutcome { + return ValidationOutcome( validator( context = mapContextFn(context, input), input = property.get(input) ) .feedback - .flatMap { it.value.map(mapFeedbackFn) } - .let { - if (it.isNotEmpty()) { - mapOf(property to it) - } else { - emptyMap() - } - } + .map { mapFeedbackFn(it) } ) } } - internal class InputObjectDelegatesToValidator( + internal class InputObjectDelegatesToOtherTypeValidator, FEEDBACK : Feedback>( private val validator: Validator, private val mapContextFn: CONTEXT.(INPUT) -> DELEGATE_CONTEXT, private val mapInputFn: CONTEXT.(INPUT) -> DELEGATE_INPUT, - private val mapFeedbackKeys: Map?, KProperty1?>, private val mapFeedbackObjectFn: (DELEGATE_FEEDBACK) -> FEEDBACK ) : ValidationEntry() { - operator fun invoke(context: CONTEXT, input: INPUT): ValidationResult { - return ValidationResult( + operator fun invoke(context: CONTEXT, input: INPUT): ValidationOutcome { + return ValidationOutcome( validator( context = mapContextFn(context, input), input = mapInputFn(context, input) ) .feedback - .map { mapFeedbackKeys[it.key] to it.value.map(mapFeedbackObjectFn) } - .toMap() + .map { mapFeedbackObjectFn(it) } ) } } - internal class ReturnEarlyIfAny( + internal class InputObjectDelegatesToSameTypeValidator>( + private val validator: Validator, + ) : ValidationEntry() { + operator fun invoke(context: CONTEXT, input: INPUT): ValidationOutcome { + return validator(context, input) + } + } + + internal class ReturnEarlyIfAny>( private val matchFn: (FEEDBACK) -> Boolean ) : ValidationEntry() { - operator fun invoke(feedback: Map?, List>): Boolean { + operator fun invoke(feedback: List): Boolean { return feedback - .values - .flatten() .any { matchFn(it) } } } diff --git a/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/impl/rule/ObjectValidationRuleImpl.kt b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/impl/rule/ObjectValidationRuleImpl.kt index 2c1df1b59..652280a8d 100644 --- a/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/impl/rule/ObjectValidationRuleImpl.kt +++ b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/impl/rule/ObjectValidationRuleImpl.kt @@ -5,7 +5,7 @@ import tech.coner.trailer.toolkit.validation.context.ValidationRuleContext import tech.coner.trailer.toolkit.validation.rule.ObjectValidationRule import tech.coner.trailer.toolkit.validation.impl.context.ValidationRuleContextImpl -class ObjectValidationRuleImpl( +class ObjectValidationRuleImpl>( private val ruleFn: ValidationRuleContext.(INPUT) -> FEEDBACK? ) : ObjectValidationRule { diff --git a/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/impl/rule/PropertyValidationRuleImpl.kt b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/impl/rule/PropertyValidationRuleImpl.kt index a1096bb90..4ee98968d 100644 --- a/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/impl/rule/PropertyValidationRuleImpl.kt +++ b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/impl/rule/PropertyValidationRuleImpl.kt @@ -2,17 +2,19 @@ package tech.coner.trailer.toolkit.validation.impl.rule import kotlin.reflect.KProperty1 import tech.coner.trailer.toolkit.validation.Feedback +import tech.coner.trailer.toolkit.validation.context.PropertyValidationRuleContext import tech.coner.trailer.toolkit.validation.context.ValidationRuleContext +import tech.coner.trailer.toolkit.validation.impl.context.PropertyValidationRuleContextImpl import tech.coner.trailer.toolkit.validation.impl.context.ValidationRuleContextImpl import tech.coner.trailer.toolkit.validation.rule.PropertyValidationRule -internal class PropertyValidationRuleImpl( +internal class PropertyValidationRuleImpl>( override val property: KProperty1, - private val validationRule: ValidationRuleContext.(PROPERTY) -> FEEDBACK? + private val validationRule: PropertyValidationRuleContext.(PROPERTY) -> FEEDBACK? ) : PropertyValidationRule { override fun invoke(context: CONTEXT, input: INPUT): FEEDBACK? { - return ValidationRuleContextImpl(context, input) + return PropertyValidationRuleContextImpl(context, input, property) .validationRule(property.get(input)) } } \ No newline at end of file diff --git a/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/presentation/localization/EnglishUsValidationTranslation.kt b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/presentation/localization/EnglishUsValidationTranslation.kt new file mode 100644 index 000000000..59cce5b92 --- /dev/null +++ b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/presentation/localization/EnglishUsValidationTranslation.kt @@ -0,0 +1,9 @@ +package tech.coner.trailer.toolkit.validation.presentation.localization + +class EnglishUsValidationTranslation : ValidationTranslation { + override val severityError get() = "Error" + override val severityWarning get() = "Warning" + override val severitySuccess get() = "Success" + override val severityInfo get() = "Info" + +} \ No newline at end of file diff --git a/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/presentation/localization/ValidationStrings.kt b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/presentation/localization/ValidationStrings.kt new file mode 100644 index 000000000..f635eb1b4 --- /dev/null +++ b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/presentation/localization/ValidationStrings.kt @@ -0,0 +1,7 @@ +package tech.coner.trailer.toolkit.validation.presentation.localization + +import tech.coner.trailer.toolkit.validation.Severity + +interface ValidationStrings { + operator fun get(severity: Severity): String +} \ No newline at end of file diff --git a/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/presentation/localization/ValidationStringsImpl.kt b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/presentation/localization/ValidationStringsImpl.kt new file mode 100644 index 000000000..dc3a38bf4 --- /dev/null +++ b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/presentation/localization/ValidationStringsImpl.kt @@ -0,0 +1,15 @@ +package tech.coner.trailer.toolkit.validation.presentation.localization + +import tech.coner.trailer.toolkit.validation.Severity + +class ValidationStringsImpl(translation: ValidationTranslation) + : ValidationStrings, + ValidationTranslation by translation { + + override fun get(severity: Severity) = when (severity) { + Severity.Error -> severityError + Severity.Warning -> severityWarning + Severity.Success -> severitySuccess + Severity.Info -> severityInfo + } +} \ No newline at end of file diff --git a/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/presentation/localization/ValidationTranslation.kt b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/presentation/localization/ValidationTranslation.kt new file mode 100644 index 000000000..2a93b5865 --- /dev/null +++ b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/presentation/localization/ValidationTranslation.kt @@ -0,0 +1,8 @@ +package tech.coner.trailer.toolkit.validation.presentation.localization + +interface ValidationTranslation { + val severityError: String + val severityWarning: String + val severitySuccess: String + val severityInfo: String +} \ No newline at end of file diff --git a/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/rule/ObjectValidationRule.kt b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/rule/ObjectValidationRule.kt index 4cc3f48f9..71ebcbb36 100644 --- a/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/rule/ObjectValidationRule.kt +++ b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/rule/ObjectValidationRule.kt @@ -2,6 +2,6 @@ package tech.coner.trailer.toolkit.validation.rule import tech.coner.trailer.toolkit.validation.Feedback -internal interface ObjectValidationRule +internal interface ObjectValidationRule> : ValidationRule { } \ No newline at end of file diff --git a/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/rule/PropertyValidationRule.kt b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/rule/PropertyValidationRule.kt index c3fb63f8d..28beaea09 100644 --- a/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/rule/PropertyValidationRule.kt +++ b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/rule/PropertyValidationRule.kt @@ -3,7 +3,7 @@ package tech.coner.trailer.toolkit.validation.rule import kotlin.reflect.KProperty1 import tech.coner.trailer.toolkit.validation.Feedback -internal interface PropertyValidationRule : +internal interface PropertyValidationRule> : ValidationRule { val property: KProperty1 } \ No newline at end of file diff --git a/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/rule/ValidationRule.kt b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/rule/ValidationRule.kt index 5c4ae3ad1..13d658d31 100644 --- a/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/rule/ValidationRule.kt +++ b/toolkit/validation/validation/src/main/kotlin/tech/coner/trailer/toolkit/validation/rule/ValidationRule.kt @@ -2,7 +2,7 @@ package tech.coner.trailer.toolkit.validation.rule import tech.coner.trailer.toolkit.validation.Feedback -fun interface ValidationRule { +fun interface ValidationRule> { operator fun invoke(context: CONTEXT, input: INPUT): FEEDBACK? } \ No newline at end of file diff --git a/webapp-competition/pom.xml b/webapp-competition/pom.xml index 03154f1b9..90878a25d 100644 --- a/webapp-competition/pom.xml +++ b/webapp-competition/pom.xml @@ -3,9 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - parent + buildsrc-kotlin-parent tech.coner.trailer 0.1.0-SNAPSHOT + ../buildsrc/buildsrc-kotlin-parent/pom.xml 4.0.0

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 '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +APP_NAME="Gradle" +APP_BASE_NAME=${0##*/} + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/toolkit/samples/dmvapp/dmvapp-gui/gradlew.bat b/toolkit/samples/dmvapp/dmvapp-gui/gradlew.bat new file mode 100644 index 000000000..ac1b06f93 --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-gui/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/toolkit/samples/dmvapp/dmvapp-gui/pom.xml b/toolkit/samples/dmvapp/dmvapp-gui/pom.xml new file mode 100644 index 000000000..f62c1c160 --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-gui/pom.xml @@ -0,0 +1,137 @@ + + + 4.0.0 + + tech.coner.trailer + parent + 0.1.0-SNAPSHOT + ../../../../pom.xml + + + toolkit-sample-dmvapp-gui + + + ./gradlew + + + + + tech.coner.trailer + toolkit-sample-dmvapp-common + 0.1.0-SNAPSHOT + + + + + + + org.codehaus.mojo + properties-maven-plugin + + + generate-resources + + write-project-properties + + + ${project.build.directory}/project.properties + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-dependencies + generate-resources + + copy-dependencies + + false + + true + true + ${project.build.directory}/dependencies + true + true + + + + + + org.codehaus.mojo + exec-maven-plugin + + + gradle-build + prepare-package + + ${gradle.executable} + + ${gradle.argument.daemon} + build + + + + exec + + + + + + maven-resources-plugin + + + copy-gradle-jars + package + + copy-resources + + + + ${basedir}/target + + + build/libs/ + + ${project.artifactId}-${project.version}.jar + ${project.artifactId}-${project.version}-javadoc.jar + ${project.artifactId}-${project.version}-sources.jar + + + + + + + + + + + + + gradle-default + + true + + + --daemon + + + + gradle-windows + + + windows + + + + + --no-daemon + + + + diff --git a/toolkit/samples/dmvapp/dmvapp-gui/settings.gradle.kts b/toolkit/samples/dmvapp/dmvapp-gui/settings.gradle.kts new file mode 100644 index 000000000..2956757d3 --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-gui/settings.gradle.kts @@ -0,0 +1,16 @@ +pluginManagement { + repositories { + maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") + google() + gradlePluginPortal() + mavenCentral() + } + + plugins { + kotlin("jvm").version(extra["kotlin.version"] as String) + id("org.jetbrains.compose").version(extra["compose.version"] as String) + id("org.jetbrains.kotlin.plugin.compose").version(extra["kotlin.version"] as String) + } +} + +rootProject.name = "toolkit-sample-dmvapp-gui" diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/DmvAppGui.kt b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/DmvAppGui.kt new file mode 100644 index 000000000..75667ba3c --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/DmvAppGui.kt @@ -0,0 +1,31 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.gui + +import androidx.compose.ui.window.application +import org.kodein.di.DI +import org.kodein.di.compose.withDI +import tech.coner.trailer.toolkit.sample.dmvapp.domain.service.impl.domainServiceModule +import tech.coner.trailer.toolkit.sample.dmvapp.domain.validation.domainValidationModule +import tech.coner.trailer.toolkit.sample.dmvapp.gui.presentation.presenter.guiPresentationPresenterModule +import tech.coner.trailer.toolkit.sample.dmvapp.gui.window.DmvAppMainWindow +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.adapter.presentationAdapterModule +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.localization.presentationLocalizationModule +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.presenter.presentationPresenterModule +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.presentationValidationModule + +fun main() = application { + withDI(di) { + DmvAppMainWindow() + } +} + +val di = DI { + importAll( + domainServiceModule, + domainValidationModule, + presentationLocalizationModule, + presentationPresenterModule, + presentationValidationModule, + presentationAdapterModule, + guiPresentationPresenterModule, + ) +} diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/composable/ConerTopLevelNavigationDrawer.kt b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/composable/ConerTopLevelNavigationDrawer.kt new file mode 100644 index 000000000..719c3549d --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/composable/ConerTopLevelNavigationDrawer.kt @@ -0,0 +1,213 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.gui.composable + +import androidx.compose.desktop.ui.tooling.preview.Preview +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.AccountBox +import androidx.compose.material.icons.filled.Favorite +import androidx.compose.material.icons.filled.Settings +import androidx.compose.material3.DrawerState +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.ModalDrawerSheet +import androidx.compose.material3.ModalNavigationDrawer +import androidx.compose.material3.NavigationDrawerItem +import androidx.compose.material3.PermanentNavigationDrawer +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.unit.dp +import org.kodein.di.compose.rememberInstance +import org.kodein.di.compose.withDI +import tech.coner.trailer.toolkit.sample.dmvapp.gui.di +import tech.coner.trailer.toolkit.sample.dmvapp.gui.presentation.presenter.SettingsPresenter +import tech.coner.trailer.toolkit.sample.dmvapp.gui.theme.ConerBrandColors +import tech.coner.trailer.toolkit.sample.dmvapp.gui.theme.ConerTheme +import tech.coner.trailer.toolkit.sample.dmvapp.gui.util.LocalWindowState +import tech.coner.trailer.toolkit.sample.dmvapp.gui.util.strings + +@Composable +fun ConerTopLevelNavigationDrawer( + drawerState: DrawerState, + heroTitle: String, + heroSubtitle: String, + innerDrawerContent: @Composable ColumnScope.() -> Unit, + content: @Composable () -> Unit +) { + val settingsPresenter: SettingsPresenter by rememberInstance() + val materialWindowSizeClass = LocalWindowState.current.materialSizeClass + val drawerContent: @Composable () -> Unit = { + ConerTopLevelNavigationDrawerContent( + heroTitle = heroTitle, + heroSubtitle = heroSubtitle, + innerDrawerContent = innerDrawerContent + ) + } + when (materialWindowSizeClass) { + MaterialWindowSizeClass.Compact, + MaterialWindowSizeClass.Medium -> ModalNavigationDrawer( + drawerContent = drawerContent, + drawerState = drawerState, + content = content + ) + MaterialWindowSizeClass.Expanded, + MaterialWindowSizeClass.Large, + MaterialWindowSizeClass.ExtraLarge -> PermanentNavigationDrawer( + drawerContent = drawerContent, + content = content + ) + } +} + +@Composable +private fun ConerTopLevelNavigationDrawerContent( + heroTitle: String, + heroSubtitle: String, + innerDrawerContent: @Composable ColumnScope.() -> Unit +) { + ModalDrawerSheet { + ConerTopLevelNavigationDrawerHero( + title = heroTitle, + subtitle = heroSubtitle, + ) + Column( + modifier = Modifier + .padding(28.dp) + ) { + innerDrawerContent() + } + } +} + +@Composable +private fun ColumnScope.ConerTopLevelNavigationDrawerHero( + title: String, + subtitle: String +) { + val settingsPresenter: SettingsPresenter by rememberInstance() + val materialWindowSizeClass = LocalWindowState.current.materialSizeClass + Box( + modifier = Modifier + .background(ConerBrandColors.LogoGray) + .height( + when (materialWindowSizeClass) { + MaterialWindowSizeClass.Compact -> 64.dp + MaterialWindowSizeClass.Medium -> 112.dp + MaterialWindowSizeClass.Expanded, + MaterialWindowSizeClass.Large, + MaterialWindowSizeClass.ExtraLarge -> 152.dp + } + ) + .padding(horizontal = 28.dp) + ) { + when (materialWindowSizeClass) { + MaterialWindowSizeClass.Compact -> Column( + verticalArrangement = Arrangement.Center, + modifier = Modifier + .fillMaxSize() + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .fillMaxWidth() + ) { + Image( + painter = painterResource("coner-icon/coner-icon_48.png"), + contentDescription = strings.conerLogoContentDescription, + ) + Spacer(Modifier.weight(1.0f)) + Column( + horizontalAlignment = Alignment.End + ) { + Text( + text = title, + color = ConerBrandColors.LogoWhite, + fontFamily = FontFamily.Monospace, + style = MaterialTheme.typography.titleMedium, + maxLines = 1, + ) + Text( + text = subtitle, + color = ConerBrandColors.LogoWhite, + fontFamily = FontFamily.Monospace, + style = MaterialTheme.typography.titleSmall, + maxLines = 1 + ) + } + } + } + MaterialWindowSizeClass.Medium, + MaterialWindowSizeClass.Expanded, + MaterialWindowSizeClass.Large, + MaterialWindowSizeClass.ExtraLarge -> Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + modifier = Modifier + .fillMaxSize() + ) { + Image( + painter = painterResource("coner-logo/coner-logo_128.png"), + contentDescription = strings.conerLogoContentDescription, + ) + Spacer(Modifier.size(8.dp)) + Text( + text = title, + color = ConerBrandColors.LogoWhite, + fontFamily = FontFamily.Monospace, + style = MaterialTheme.typography.titleMedium, + maxLines = 1, + ) + Text( + text = subtitle, + color = ConerBrandColors.LogoWhite, + fontFamily = FontFamily.Monospace, + style = MaterialTheme.typography.titleSmall, + maxLines = 1 + ) + } + } + } +} + +@Composable +@Preview +private fun ConerTopLevelNavigationDrawerPreview() { + withDI(di) { + ConerTheme { + ConerTopLevelNavigationDrawerContent( + heroTitle = "Hero Title", + heroSubtitle = "Hero Subtitle", + innerDrawerContent = { + listOf( + Icons.Default.AccountBox, + Icons.Default.Settings, + Icons.Default.Favorite, + ) + .forEachIndexed { index, icon -> + NavigationDrawerItem( + label = { Text(icon.name) }, + selected = index == 0, + onClick = {}, + icon = { Icon(icon, contentDescription = icon.name) }, + ) + } + } + ) + } + } +} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/composable/ConerTopLevelTopAppBar.kt b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/composable/ConerTopLevelTopAppBar.kt new file mode 100644 index 000000000..ddb7c7352 --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/composable/ConerTopLevelTopAppBar.kt @@ -0,0 +1,44 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.gui.composable + +import androidx.compose.foundation.layout.RowScope +import androidx.compose.material3.LargeTopAppBar +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.MediumTopAppBar +import androidx.compose.material3.TopAppBar +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.runtime.Composable +import tech.coner.trailer.toolkit.sample.dmvapp.gui.util.LocalWindowState + +@Composable +fun ConerTopLevelTopAppBar( + title: @Composable () -> Unit, + navigationIcon: @Composable () -> Unit = {}, + actions: @Composable (RowScope.() -> Unit) +) { + val materialWindowSizeClass = LocalWindowState.current.materialSizeClass + val colors = TopAppBarDefaults.topAppBarColors( + containerColor = MaterialTheme.colorScheme.primaryContainer, + ) + when(materialWindowSizeClass) { + MaterialWindowSizeClass.Compact -> TopAppBar( + title = title, + navigationIcon = navigationIcon, + colors = colors, + actions = actions + ) + MaterialWindowSizeClass.Medium -> MediumTopAppBar( + title = title, + navigationIcon = navigationIcon, + colors = colors, + actions = actions + ) + MaterialWindowSizeClass.Expanded, + MaterialWindowSizeClass.Large, + MaterialWindowSizeClass.ExtraLarge -> LargeTopAppBar( + title = title, + // navigationIcon omitted -- this size class uses a standard navigation drawer (always open) + colors = colors, + actions = actions + ) + } +} diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/composable/MaterialWindowSizeClass.kt b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/composable/MaterialWindowSizeClass.kt new file mode 100644 index 000000000..e00b68938 --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/composable/MaterialWindowSizeClass.kt @@ -0,0 +1,20 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.gui.composable + +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.WindowState + +enum class MaterialWindowSizeClass( + val widthRange: ClosedRange +) { + + Compact(Int.MIN_VALUE..600), + Medium(600..839), + Expanded(840..1199), + Large(1200..1599), + ExtraLarge(1600..Int.MAX_VALUE); + + internal val widthRangeDp = widthRange.let { it.start.dp..it.endInclusive.dp } +} + +val WindowState.materialSizeClass: MaterialWindowSizeClass + get() = MaterialWindowSizeClass.entries.first { size.width in it.widthRangeDp } \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/composable/ValidationFeedback.kt b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/composable/ValidationFeedback.kt new file mode 100644 index 000000000..d91147f58 --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/composable/ValidationFeedback.kt @@ -0,0 +1,48 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.gui.composable + +import androidx.compose.foundation.layout.Column +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.testTag +import tech.coner.trailer.toolkit.sample.dmvapp.gui.util.strings +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelFeedback + +@Composable +fun ValidationFeedbackSupportingText( + feedback: List, + testTagPrefix: String +): @Composable (() -> Unit) { + return when { + feedback.isNotEmpty() -> { + { + ValidationFeedbackSupportingTextContent( + feedback = feedback + .map { strings[it] }, + testTagPrefix = testTagPrefix + ) + } + } + else -> { + { + ValidationFeedbackSupportingTextContent(listOf(""), testTagPrefix) + } + } + } +} + +@Composable +private fun ValidationFeedbackSupportingTextContent( + feedback: List, + testTagPrefix: String +) { + Column { + feedback.forEach { + Text( + text = it, + modifier = Modifier + .testTag("${testTagPrefix}ValidationFeedback") + ) + } + } +} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/presentation/entity/ThemeModePreference.kt b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/presentation/entity/ThemeModePreference.kt new file mode 100644 index 000000000..4eee11f8c --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/presentation/entity/ThemeModePreference.kt @@ -0,0 +1,7 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.gui.presentation.entity + +enum class ThemeModePreference { + AUTO, + LIGHT, + DARK +} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/presentation/presenter/GuiPresentationPresenterModule.kt b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/presentation/presenter/GuiPresentationPresenterModule.kt new file mode 100644 index 000000000..2620ed70e --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/presentation/presenter/GuiPresentationPresenterModule.kt @@ -0,0 +1,8 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.gui.presentation.presenter + +import org.kodein.di.DI +import org.kodein.di.bindSingleton + +val guiPresentationPresenterModule by DI.Module { + bindSingleton { SettingsPresenter() } +} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/presentation/presenter/SettingsPresenter.kt b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/presentation/presenter/SettingsPresenter.kt new file mode 100644 index 000000000..3a472b030 --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/presentation/presenter/SettingsPresenter.kt @@ -0,0 +1,20 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.gui.presentation.presenter + +import kotlinx.coroutines.flow.StateFlow +import tech.coner.trailer.toolkit.presentation.presenter.StatefulPresenter +import tech.coner.trailer.toolkit.presentation.state.StateContainer +import tech.coner.trailer.toolkit.sample.dmvapp.gui.presentation.state.SettingsState + +class SettingsPresenter( + initialState: SettingsState = SettingsState() +) : StatefulPresenter { + + private val stateContainer = StateContainer(initialState) + override val state: SettingsState get() = stateContainer.state + override val stateFlow: StateFlow get() = stateContainer.stateFlow + + val themeMode = stateContainer.mutableStateProperty( + { themeMode }, + { newValue -> copy(themeMode = newValue) } + ) +} diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/presentation/state/SettingsState.kt b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/presentation/state/SettingsState.kt new file mode 100644 index 000000000..aff1d8b79 --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/presentation/state/SettingsState.kt @@ -0,0 +1,8 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.gui.presentation.state + +import tech.coner.trailer.toolkit.presentation.state.State +import tech.coner.trailer.toolkit.sample.dmvapp.gui.presentation.entity.ThemeModePreference + +data class SettingsState( + val themeMode: ThemeModePreference = ThemeModePreference.AUTO, +) : State diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/screen/DmvAppScreen.kt b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/screen/DmvAppScreen.kt new file mode 100644 index 000000000..ec6d09c46 --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/screen/DmvAppScreen.kt @@ -0,0 +1,8 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.gui.screen + +import kotlin.random.Random + +sealed class DmvAppScreen { + data class DriversLicenseApplication(private val index: Int = Random.nextInt()) : DmvAppScreen() + data object Settings: DmvAppScreen() +} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/screen/driverslicenseapplication/DriversLicenseApplicationForm.kt b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/screen/driverslicenseapplication/DriversLicenseApplicationForm.kt new file mode 100644 index 000000000..e016a4af7 --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/screen/driverslicenseapplication/DriversLicenseApplicationForm.kt @@ -0,0 +1,421 @@ + +package tech.coner.trailer.toolkit.sample.dmvapp.gui.screen.driverslicenseapplication + +import androidx.compose.desktop.ui.tooling.preview.Preview +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.Undo +import androidx.compose.material.icons.filled.Menu +import androidx.compose.material3.Button +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.DropdownMenuItem +import androidx.compose.material3.ExposedDropdownMenuBox +import androidx.compose.material3.ExposedDropdownMenuDefaults +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.OutlinedCard +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.rememberVectorPainter +import androidx.compose.ui.input.key.Key +import androidx.compose.ui.input.key.key +import androidx.compose.ui.input.key.onKeyEvent +import androidx.compose.ui.platform.testTag +import androidx.compose.ui.unit.dp +import kotlinx.coroutines.CoroutineName +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.cancel +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking +import org.kodein.di.compose.rememberInstance +import org.kodein.di.compose.withDI +import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.LicenseType +import tech.coner.trailer.toolkit.sample.dmvapp.gui.composable.ConerTopLevelTopAppBar +import tech.coner.trailer.toolkit.sample.dmvapp.gui.composable.ValidationFeedbackSupportingText +import tech.coner.trailer.toolkit.sample.dmvapp.gui.di +import tech.coner.trailer.toolkit.sample.dmvapp.gui.screen.DmvAppScreen +import tech.coner.trailer.toolkit.sample.dmvapp.gui.theme.ConerTheme +import tech.coner.trailer.toolkit.sample.dmvapp.gui.util.FocusFirstFocusRequester +import tech.coner.trailer.toolkit.sample.dmvapp.gui.util.FocusFirstFocusRequester.Companion.FocusFirstFocusRequester +import tech.coner.trailer.toolkit.sample.dmvapp.gui.util.collectAsState +import tech.coner.trailer.toolkit.sample.dmvapp.gui.util.collectFeedbackAsState +import tech.coner.trailer.toolkit.sample.dmvapp.gui.util.collectValueAsState +import tech.coner.trailer.toolkit.sample.dmvapp.gui.util.focusOnError +import tech.coner.trailer.toolkit.sample.dmvapp.gui.util.strings +import tech.coner.trailer.toolkit.sample.dmvapp.gui.window.DriversLicenseWindow +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.model.DriversLicenseApplicationModel +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.model.DriversLicenseApplicationRejectionModel +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.presenter.DriversLicenseApplicationPresenter +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.validation.DriversLicenseApplicationModelFeedback +import tech.coner.trailer.toolkit.validation.Severity +import tech.coner.trailer.toolkit.validation.isInvalid + +@Composable +fun DriversLicenseApplicationFormScreen( + screen: DmvAppScreen.DriversLicenseApplication, + openNavigationDrawer: () -> Unit +) { + val presenter: DriversLicenseApplicationPresenter by rememberInstance() + + val coroutineScope = rememberCoroutineScope { Dispatchers.Main.immediate + CoroutineName("DriversLicenseApplicationFormScreen") } + + val focusFirstError = remember { + FocusFirstFocusRequester( + properties = listOf( + DriversLicenseApplicationModel::name, + DriversLicenseApplicationModel::age, + DriversLicenseApplicationModel::licenseType + ) + ) + } + + val name = remember { mutableStateOf("") } + val age = remember { mutableStateOf("") } + + val performReset: () -> Unit = { + coroutineScope.launch { + name.value = "" + age.value = "" + presenter.reset() + } + } + + val outcome = presenter.stateFlow + .map { it.outcome } + .collectAsState(null).value + outcome + ?.onLeft { rejection -> + when (rejection) { + is DriversLicenseApplicationRejectionModel.Sassed -> { + DriversLicenseApplicationRejectionDialog( + onDismissRequest = { + coroutineScope.launch { + presenter.clearOutcome() + } + }, + rejection = rejection + ) + } + is DriversLicenseApplicationRejectionModel.Invalid -> { + // no-op, presented inline + } + } + } + ?.onRight { driversLicense -> + DriversLicenseWindow( + driversLicense = driversLicense, + onCloseRequest = performReset + ) + } + DisposableEffect(screen) { + with(coroutineScope) { + presenter.validationOutcomeFlow + .onEach { validationResult -> + validationResult.feedbackByProperty.entries + .firstOrNull { (_, feedbacks) -> + feedbacks.any { + it.severity == Severity.Error + } + } + ?.key + ?.also { property -> focusFirstError.requestFocus(property) } + } + .launchIn(this@with) + } + onDispose { + runBlocking { presenter.reset() } + coroutineScope.cancel() + } + } + + DriversLicenseApplicationFormContent( + openNavigationDrawer = openNavigationDrawer, + fieldsEditable = presenter.fieldsEditable.collectAsState().value, + name = name, + onNameChange = { presenter.name.value = it }, + nameFeedback = presenter.name.collectFeedbackAsState().value, + age = age, + onAgeChange = { presenter.age.value = it.toIntOrNull() }, + ageFeedback = presenter.age.collectFeedbackAsState().value, + licenseType = presenter.licenseType.collectValueAsState().value, + onLicenseTypeChange = { presenter.licenseType.value = it }, + licenseTypeFeedback = presenter.licenseType.collectFeedbackAsState().value, + performReset = performReset, + resetButtonEnabled = presenter.canResetFlow.collectAsState(false).value, + applyButtonEnabled = presenter.canApplyFlow.collectAsState(true).value, + onApplyButtonClicked = { coroutineScope.launch { presenter.submitApplication() } }, + processingApplication = presenter.processingApplication.collectAsState().value, + focusFirstFocusRequester = focusFirstError + ) +} + +@Composable +fun DriversLicenseApplicationFormContent( + openNavigationDrawer: () -> Unit, + fieldsEditable: Boolean, + name: MutableState, + onNameChange: (String) -> Unit, + nameFeedback: List, + age: MutableState, + onAgeChange: (String) -> Unit, + ageFeedback: List, + licenseType: LicenseType?, + onLicenseTypeChange: (LicenseType) -> Unit, + licenseTypeFeedback: List, + performReset: () -> Unit, + resetButtonEnabled: Boolean, + applyButtonEnabled: Boolean, + onApplyButtonClicked: () -> Unit, + processingApplication: Boolean, + focusFirstFocusRequester: FocusFirstFocusRequester +) { + Column { + ConerTopLevelTopAppBar( + title = { Text(strings.driversLicenseApplicationHeading) }, + navigationIcon = { + IconButton( + onClick = openNavigationDrawer + ) { + Icon(Icons.Default.Menu, contentDescription = strings.menuContentDescription) + } + }, + actions = { + IconButton( + onClick = performReset, + enabled = resetButtonEnabled, + modifier = Modifier + .testTag("resetButton") + ) { + Icon( + painter = rememberVectorPainter(Icons.AutoMirrored.Filled.Undo), + contentDescription = strings.driversLicenseApplicationFormReset, + modifier = Modifier + .testTag("resetButtonIcon"), + ) + } + } + ) + Box( + contentAlignment = Alignment.Center, + modifier = Modifier + .fillMaxSize() + ) { + OutlinedCard( + modifier = Modifier + .width(432.dp) + ) { + Column( + modifier = Modifier + .padding(16.dp) + ) { + Row { + OutlinedTextField( + value = name.value, + label = { + Text( + text = strings.driversLicenseNameField, + modifier = Modifier + .testTag("nameField") + ) + }, + singleLine = true, + onValueChange = { + name.value = it + onNameChange(it) + }, + isError = nameFeedback.isInvalid, + supportingText = ValidationFeedbackSupportingText(nameFeedback, "name"), + readOnly = !fieldsEditable, + modifier = Modifier + .fillMaxWidth() + .focusOnError(focusFirstFocusRequester, DriversLicenseApplicationModel::name) + .testTag("name") + ) + } + Row { + OutlinedTextField( + value = age.value, + label = { + Text( + text = strings.driversLicenseAgeField, + modifier = Modifier + .testTag("ageField") + ) + }, + singleLine = true, + onValueChange = { + if (it.isEmpty() || it.all { char -> char.isDigit() }) { + age.value = it + onAgeChange(it) + } + }, + isError = ageFeedback.isInvalid, + supportingText = ValidationFeedbackSupportingText(ageFeedback, "age"), + readOnly = !fieldsEditable, + modifier = Modifier + .fillMaxWidth() + .focusOnError(focusFirstFocusRequester, DriversLicenseApplicationModel::age) + .testTag("age") + ) + } + Row { + var expanded by remember { mutableStateOf(false) } + val guardedMutateExpanded: (Boolean) -> Unit = { + if (fieldsEditable || !it) expanded = it + } + ExposedDropdownMenuBox( + expanded = expanded, + onExpandedChange = guardedMutateExpanded, + modifier = Modifier + .testTag("licenseTypeDropdownMenuBox") + ) { + OutlinedTextField( + value = licenseType.let { strings.getNullable(it) }, + label = { + Text( + text = strings.driversLicenseLicenseTypeField, + modifier = Modifier + .testTag("licenseTypeField") + ) + }, + readOnly = true, + onValueChange = { }, + isError = licenseTypeFeedback.isInvalid, + supportingText = ValidationFeedbackSupportingText(licenseTypeFeedback, "licenseType"), + trailingIcon = { + ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) + }, + modifier = Modifier + .fillMaxWidth() + .menuAnchor() + .onKeyEvent { + when { + it.key == Key.DirectionDown -> { guardedMutateExpanded(true); true } + else -> false + } + } + .focusOnError(focusFirstFocusRequester, DriversLicenseApplicationModel::licenseType) + .testTag("licenseType") + ) + ExposedDropdownMenu( + expanded = expanded, + onDismissRequest = { guardedMutateExpanded(false) }, + modifier = Modifier + .testTag("licenseTypeDropdownMenu") + ) { + strings.licenseTypeLabels.forEach { pair -> + DropdownMenuItem( + text = { + Text( + text = pair.second, + modifier = Modifier + .testTag("licenseTypeDropdownMenuItemText") + ) + }, + onClick = { + guardedMutateExpanded(false) + onLicenseTypeChange(pair.first) + }, + modifier = Modifier + .testTag("licenseTypeDropdownMenuItem") + ) + } + } + } + } + Box( + modifier = Modifier + .fillMaxWidth() + ) { + Button( + onClick = onApplyButtonClicked, + enabled = applyButtonEnabled, + modifier = Modifier + .align(Alignment.CenterEnd) + .testTag("applyButton") + ) { + Row { + if (processingApplication) { + CircularProgressIndicator( + modifier = Modifier + .size(16.dp) + .align(Alignment.CenterVertically) + .testTag("applyButtonProgress") + ) + Spacer( + modifier = Modifier + .width(8.dp) + ) + } + Text( + text = strings.driversLicenseApplicationFormApply, + modifier = Modifier + .testTag("applyButtonText") + ) + } + } + } + } + } + } + } +} + +@Composable +@Preview +private fun DriversLicenseApplicationFormPreview() { + withDI(di) { + ConerTheme { + Scaffold { + DriversLicenseApplicationFormContent( + openNavigationDrawer= {}, + fieldsEditable = true, + name = mutableStateOf(""), + onNameChange = {}, + nameFeedback = emptyList(), + age = mutableStateOf(""), + onAgeChange = {}, + ageFeedback = emptyList(), + licenseType = null, + onLicenseTypeChange = {}, + licenseTypeFeedback = emptyList(), + performReset = {}, + resetButtonEnabled = false, + applyButtonEnabled = true, + onApplyButtonClicked = {}, + processingApplication = false, + FocusFirstFocusRequester( + listOf( + DriversLicenseApplicationModel::name, + DriversLicenseApplicationModel::age, + DriversLicenseApplicationModel::licenseType + ) + ) + ) + } + } + } +} diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/screen/driverslicenseapplication/DriversLicenseApplicationRejectionDialog.kt b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/screen/driverslicenseapplication/DriversLicenseApplicationRejectionDialog.kt new file mode 100644 index 000000000..529564665 --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/screen/driverslicenseapplication/DriversLicenseApplicationRejectionDialog.kt @@ -0,0 +1,58 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.gui.screen.driverslicenseapplication + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.material3.AlertDialogDefaults +import androidx.compose.material3.BasicAlertDialog +import androidx.compose.material3.Button +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import tech.coner.trailer.toolkit.sample.dmvapp.gui.util.LocalStrings +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.model.DriversLicenseApplicationRejectionModel + +@Composable +fun DriversLicenseApplicationRejectionDialog( + onDismissRequest: () -> Unit, + rejection: DriversLicenseApplicationRejectionModel.Sassed +) { + val strings = LocalStrings.current + BasicAlertDialog( + onDismissRequest = onDismissRequest + ) { + Surface( + modifier = Modifier.wrapContentSize(), + shape = MaterialTheme.shapes.large, + tonalElevation = AlertDialogDefaults.TonalElevation + ) { + Column( + modifier = Modifier.padding(16.dp) + ) { + Text( + strings.driversLicenseApplicationRejectionTitle, + style = MaterialTheme.typography.titleSmall + ) + Spacer( + Modifier.size(8.dp) + ) + Text(strings[rejection.sass]) + Spacer( + Modifier.size(8.dp) + ) + Button( + modifier = Modifier.align(Alignment.End), + onClick = onDismissRequest + ) { + Text(strings.ok) + } + } + } + } +} diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/screen/driverslicenseapplication/DriversLicenseScreen.kt b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/screen/driverslicenseapplication/DriversLicenseScreen.kt new file mode 100644 index 000000000..abdef4bdb --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/screen/driverslicenseapplication/DriversLicenseScreen.kt @@ -0,0 +1,144 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.gui.screen.driverslicenseapplication + +import androidx.compose.desktop.ui.tooling.preview.Preview +import androidx.compose.foundation.layout.Box +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign +import androidx.constraintlayout.compose.ConstraintLayout +import org.kodein.di.compose.withDI +import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.DriversLicense +import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.LicenseType +import tech.coner.trailer.toolkit.sample.dmvapp.gui.di +import tech.coner.trailer.toolkit.sample.dmvapp.gui.theme.ConerTheme +import tech.coner.trailer.toolkit.sample.dmvapp.gui.util.strings + +@Composable +fun DriversLicenseScreen( + driversLicense: DriversLicense +) { + DriversLicenseContent( + driversLicense = driversLicense + ) +} + +@Composable +private fun DriversLicenseContent( + driversLicense: DriversLicense +) { + ConstraintLayout { + val (dmv, heading, dmvMotto, photoBox, nameField, name, ageField, age, typeField, type) = createRefs() + val fieldEndBarrier = createEndBarrier(nameField, ageField, typeField) + Text( + text = strings.dmvLabel, + modifier = Modifier + .constrainAs(dmv) { + start.linkTo(parent.start) + end.linkTo(fieldEndBarrier) + top.linkTo(parent.top) + } + ) + Text( + text = strings.driversLicenseHeading, + textAlign = TextAlign.End, + modifier = Modifier + .constrainAs(heading) { + start.linkTo(fieldEndBarrier) + end.linkTo(parent.end) + top.linkTo(parent.top) + } + ) + Text( + text = strings.dmvMotto, + modifier = Modifier + .constrainAs(dmvMotto) { + start.linkTo(parent.start) + top.linkTo(dmv.bottom) + }, + ) + Box( + contentAlignment = Alignment.Center, + modifier = Modifier + .constrainAs(photoBox) { + start.linkTo(parent.start) + bottom.linkTo(parent.bottom) + } + ) { + Text( + text = strings.driversLicensePhotoPlaceholder + ) + } + Text( + text = strings.driversLicenseNameField, + modifier = Modifier + .constrainAs(nameField) { + start.linkTo(photoBox.end) + top.linkTo(dmvMotto.bottom) + bottom.linkTo(name.bottom) + } + ) + Text( + text = driversLicense.name, + modifier = Modifier + .constrainAs(name) { + start.linkTo(fieldEndBarrier) + top.linkTo(nameField.top) + } + ) + Text( + text = strings.driversLicenseAgeField, + modifier = Modifier + .constrainAs(ageField) { + start.linkTo(photoBox.end) + top.linkTo(nameField.bottom) + bottom.linkTo(age.bottom) + } + ) + Text( + text = driversLicense.age.toString(), + modifier = Modifier + .constrainAs(age) { + start.linkTo(fieldEndBarrier) + top.linkTo(ageField.top) + } + ) + Text( + text = strings.driversLicenseLicenseTypeField, + modifier = Modifier + .constrainAs(typeField) { + start.linkTo(photoBox.end) + top.linkTo(ageField.bottom) + bottom.linkTo(type.bottom) + } + ) + Text( + text = strings[driversLicense.licenseType], + modifier = Modifier + .constrainAs(type) { + start.linkTo(fieldEndBarrier) + top.linkTo(typeField.top) + } + ) + } +} + +@Composable +@Preview +private fun DriversLicensePreview() { + withDI(di) { + ConerTheme { + Scaffold { + DriversLicenseContent( + driversLicense = DriversLicense( + name = "John Doe", + age = 18, + licenseType = LicenseType.FullLicense + ) + ) + } + } + } +} diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/screen/main/DmvAppMainScreen.kt b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/screen/main/DmvAppMainScreen.kt new file mode 100644 index 000000000..17ac48654 --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/screen/main/DmvAppMainScreen.kt @@ -0,0 +1,61 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.gui.screen.main + +import androidx.compose.desktop.ui.tooling.preview.Preview +import androidx.compose.material3.DrawerValue +import androidx.compose.material3.Scaffold +import androidx.compose.material3.rememberDrawerState +import androidx.compose.runtime.* +import kotlinx.coroutines.launch +import org.kodein.di.compose.rememberDI +import org.kodein.di.compose.rememberInstance +import org.kodein.di.instance +import tech.coner.trailer.toolkit.sample.dmvapp.gui.presentation.entity.ThemeModePreference +import tech.coner.trailer.toolkit.sample.dmvapp.gui.presentation.presenter.SettingsPresenter +import tech.coner.trailer.toolkit.sample.dmvapp.gui.screen.DmvAppScreen +import tech.coner.trailer.toolkit.sample.dmvapp.gui.screen.driverslicenseapplication.DriversLicenseApplicationFormScreen +import tech.coner.trailer.toolkit.sample.dmvapp.gui.screen.settings.SettingsScreen +import tech.coner.trailer.toolkit.sample.dmvapp.gui.theme.ConerTheme +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.localization.Strings + +@Composable +@Preview +fun DmvAppMainScreen() { + val strings: Strings by rememberInstance() + val selectedScreen = remember { + mutableStateOf(DmvAppScreen.DriversLicenseApplication()) + } + val drawerState = rememberDrawerState(DrawerValue.Closed) + val coroutineScope = rememberCoroutineScope() + val settingsPresenter: SettingsPresenter by rememberInstance() + val openNavigationDrawer: () -> Unit = remember { + { + coroutineScope.launch { + drawerState.open() + } + } + } + ConerTheme( + themeModePreference = settingsPresenter.themeMode.flow.collectAsState(ThemeModePreference.AUTO).value + ) { + Scaffold { + DmvAppNavigationDrawerScreen( + drawerState = drawerState, + selectedScreen = selectedScreen + ) { + when (val screen = selectedScreen.value) { + is DmvAppScreen.DriversLicenseApplication -> { + DriversLicenseApplicationFormScreen( + screen = screen, + openNavigationDrawer = openNavigationDrawer + ) + } + DmvAppScreen.Settings -> { + SettingsScreen( + openNavigationDrawer = openNavigationDrawer + ) + } + } + } + } + } +} diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/screen/main/DmvAppNavigationDrawerScreen.kt b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/screen/main/DmvAppNavigationDrawerScreen.kt new file mode 100644 index 000000000..29fc3e2db --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/screen/main/DmvAppNavigationDrawerScreen.kt @@ -0,0 +1,97 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.gui.screen.main + +import androidx.compose.desktop.ui.tooling.preview.Preview +import androidx.compose.foundation.layout.Spacer +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.AccountBox +import androidx.compose.material.icons.filled.Settings +import androidx.compose.material3.DrawerState +import androidx.compose.material3.DrawerValue +import androidx.compose.material3.Icon +import androidx.compose.material3.NavigationDrawerItem +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.rememberDrawerState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Modifier +import kotlinx.coroutines.launch +import org.kodein.di.compose.rememberInstance +import org.kodein.di.compose.withDI +import tech.coner.trailer.toolkit.sample.dmvapp.gui.composable.ConerTopLevelNavigationDrawer +import tech.coner.trailer.toolkit.sample.dmvapp.gui.di +import tech.coner.trailer.toolkit.sample.dmvapp.gui.screen.DmvAppScreen +import tech.coner.trailer.toolkit.sample.dmvapp.gui.theme.ConerTheme +import tech.coner.trailer.toolkit.sample.dmvapp.gui.util.strings +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.localization.Strings + +@Composable +fun DmvAppNavigationDrawerScreen( + drawerState: DrawerState, + selectedScreen: MutableState, + appContent: @Composable () -> Unit +) { + val strings: Strings by rememberInstance() + DmvAppNavigationDrawerContent( + drawerState = drawerState, + selectedScreen = selectedScreen, + appContent = appContent + ) +} + +@Composable +fun DmvAppNavigationDrawerContent( + drawerState: DrawerState, + selectedScreen: MutableState, + appContent: @Composable () -> Unit +) { + val coroutineScope = rememberCoroutineScope() + val closeAndSelect: (DmvAppScreen) -> Unit = remember { + { + coroutineScope.launch { + drawerState.close() + } + selectedScreen.value = it + } + } + ConerTopLevelNavigationDrawer( + drawerState = drawerState, + heroTitle = strings.dmvLabel, + heroSubtitle = strings.dmvMotto, + innerDrawerContent = { + NavigationDrawerItem( + label = { Text(strings.driversLicenseApplicationHeading) }, + icon = { Icon(Icons.Default.AccountBox, strings.driversLicenseApplicationHeading) }, + selected = selectedScreen.value is DmvAppScreen.DriversLicenseApplication, + onClick = { closeAndSelect(DmvAppScreen.DriversLicenseApplication()) } + ) + Spacer(Modifier.weight(1f)) + NavigationDrawerItem( + label = { Text(strings.settings) }, + icon = { Icon(Icons.Default.Settings, strings.settings) }, + selected = selectedScreen.value == DmvAppScreen.Settings, + onClick = { closeAndSelect(DmvAppScreen.Settings) } + ) + }, + content = appContent + ) +} + +@Composable +@Preview +private fun DmvAppNavigationDrawerScreenPreview() { + withDI(di) { + ConerTheme { + Scaffold { + DmvAppNavigationDrawerContent( + drawerState = rememberDrawerState(DrawerValue.Open), + selectedScreen = remember { mutableStateOf(DmvAppScreen.DriversLicenseApplication()) }, + appContent = {} + ) + } + } + } +} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/screen/settings/SettingsScreen.kt b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/screen/settings/SettingsScreen.kt new file mode 100644 index 000000000..5f2471324 --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/screen/settings/SettingsScreen.kt @@ -0,0 +1,178 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.gui.screen.settings + +import androidx.compose.desktop.ui.tooling.preview.Preview +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Menu +import androidx.compose.material3.Card +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.RadioButton +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import org.kodein.di.compose.rememberInstance +import org.kodein.di.compose.withDI +import tech.coner.trailer.toolkit.sample.dmvapp.gui.composable.ConerTopLevelTopAppBar +import tech.coner.trailer.toolkit.sample.dmvapp.gui.di +import tech.coner.trailer.toolkit.sample.dmvapp.gui.presentation.entity.ThemeModePreference +import tech.coner.trailer.toolkit.sample.dmvapp.gui.presentation.presenter.SettingsPresenter +import tech.coner.trailer.toolkit.sample.dmvapp.gui.theme.ConerTheme +import tech.coner.trailer.toolkit.sample.dmvapp.gui.util.collectAsState +import tech.coner.trailer.toolkit.sample.dmvapp.gui.util.strings +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.localization.Strings + +@Composable +fun SettingsScreen(openNavigationDrawer: () -> Unit) { + val strings: Strings by rememberInstance() + val presenter: SettingsPresenter by rememberInstance() + SettingsContent( + openNavigationDrawer, + themeMode = presenter.themeMode.collectAsState().value, + setThemeMode = { presenter.themeMode.value = it } + ) +} + +@Composable +fun SettingsContent( + openNavigationDrawer: () -> Unit, + themeMode: ThemeModePreference, + setThemeMode: (ThemeModePreference) -> Unit +) { + val coroutineScope = rememberCoroutineScope() + Column { + ConerTopLevelTopAppBar( + title = { Text(text = strings.settings) }, + navigationIcon = { + IconButton( + onClick = openNavigationDrawer + ) { + Icon(Icons.Default.Menu, contentDescription = strings.menuContentDescription) + } + }, + actions = {}, + ) + LazyColumn( + contentPadding = PaddingValues(16.dp), + verticalArrangement = Arrangement.spacedBy(16.dp), + modifier = Modifier + .padding(16.dp) + ) { + item { + ThemeCard( + themeMode = themeMode, + setThemeMode = setThemeMode + ) + } + } + } +} + +@Composable +private fun ThemeCard( + themeMode: ThemeModePreference, + setThemeMode: (ThemeModePreference) -> Unit +) { + @Composable + fun ThemeModeRow( + selected: Boolean, + onClick: () -> Unit, + text: String + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.clickable(onClick = onClick), + ) { + RadioButton( + selected = selected, + onClick = null + ) + Spacer(Modifier.size(8.dp)) + Text( + text = text, + style = MaterialTheme.typography.labelLarge + ) + } + } + + SettingsCard( + title = strings.settingsThemeTitle + ) { + Text( + text = strings.settingsThemeModeTitle, + style = MaterialTheme.typography.titleMedium + ) + ThemeModeRow( + selected = themeMode == ThemeModePreference.AUTO, + onClick = { setThemeMode(ThemeModePreference.AUTO) }, + text = strings.settingsThemeModeAuto + ) + ThemeModeRow( + selected = themeMode == ThemeModePreference.LIGHT, + onClick = { setThemeMode(ThemeModePreference.LIGHT) }, + text = strings.settingsThemeModeLight + ) + ThemeModeRow( + selected = themeMode == ThemeModePreference.DARK, + onClick = { setThemeMode(ThemeModePreference.DARK) }, + text = strings.settingsThemeModeDark + ) + } +} + +@Composable +private fun SettingsCard( + title: String, + content: @Composable ColumnScope.() -> Unit +) { + Card( + modifier = Modifier + .fillMaxWidth() + ) { + + Column( + modifier = Modifier + .padding(16.dp), + ) { + Text( + text = title, + style = MaterialTheme.typography.titleLarge + ) + Spacer(Modifier.height(16.dp)) + content() + } + } +} + +@Preview +@Composable +fun SettingsPreview() { + withDI(di) { + val presenter: SettingsPresenter by rememberInstance() + ConerTheme { + Scaffold { + SettingsContent( + openNavigationDrawer = {}, + themeMode = presenter.themeMode.value, + setThemeMode = {} + ) + } + } + } +} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/theme/ConerBrandColors.kt b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/theme/ConerBrandColors.kt new file mode 100644 index 000000000..1a760593b --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/theme/ConerBrandColors.kt @@ -0,0 +1,9 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.gui.theme + +import androidx.compose.ui.graphics.Color + +object ConerBrandColors { + val LogoOrange = Color(0xFFF15A24) + val LogoGray = Color(0xFF808080) + val LogoWhite = Color(0xFFFFFFFF) +} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/theme/ConerTheme.kt b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/theme/ConerTheme.kt new file mode 100644 index 000000000..76e77341b --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/theme/ConerTheme.kt @@ -0,0 +1,27 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.gui.theme + +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import tech.coner.trailer.toolkit.sample.dmvapp.gui.presentation.entity.ThemeModePreference + +@Composable +fun ConerTheme( + themeModePreference: ThemeModePreference = ThemeModePreference.AUTO, + content: @Composable () -> Unit +) { + val colors = ConerThemeColorsGenerated20240628_2 + MaterialTheme( + colorScheme = with(colors) { + when (themeModePreference) { + ThemeModePreference.AUTO -> if (isSystemInDarkTheme()) + darkColorScheme() + else + lightColorScheme() + ThemeModePreference.LIGHT -> lightColorScheme() + ThemeModePreference.DARK -> darkColorScheme() + } + }, + content = content + ) +} diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/theme/ConerThemeColors.kt b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/theme/ConerThemeColors.kt new file mode 100644 index 000000000..738fabcba --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/theme/ConerThemeColors.kt @@ -0,0 +1,306 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.gui.theme + +import androidx.compose.material3.darkColorScheme +import androidx.compose.ui.graphics.Color + +interface ConerThemeColors { + val Primary: Color + val OnPrimary: Color + val PrimaryContainer: Color + val OnPrimaryContainer: Color + val Secondary: Color + val OnSecondary: Color + val SecondaryContainer: Color + val OnSecondaryContainer: Color + val Tertiary: Color + val OnTertiary: Color + val TertiaryContainer: Color + val OnTertiaryContainer: Color + val Error: Color + val OnError: Color + val ErrorContainer: Color + val OnErrorContainer: Color + val Background: Color + val OnBackground: Color + val Surface: Color + val OnSurface: Color + val SurfaceVariant: Color + val OnSurfaceVariant: Color + val Outline: Color + val PrimaryDark: Color + val OnPrimaryDark: Color + val PrimaryContainerDark: Color + val OnPrimaryContainerDark: Color + val SecondaryDark: Color + val OnSecondaryDark: Color + val SecondaryContainerDark: Color + val OnSecondaryContainerDark: Color + val TertiaryDark: Color + val OnTertiaryDark: Color + val TertiaryContainerDark: Color + val OnTertiaryContainerDark: Color + val ErrorDark: Color + val OnErrorDark: Color + val ErrorContainerDark: Color + val OnErrorContainerDark: Color + val BackgroundDark: Color + val OnBackgroundDark: Color + val SurfaceDark: Color + val OnSurfaceDark: Color + val SurfaceVariantDark: Color + val OnSurfaceVariantDark: Color + val OutlineDark: Color + + fun lightColorScheme() = androidx.compose.material3.lightColorScheme( + primary = Primary, + onPrimary = OnPrimary, + primaryContainer = PrimaryContainer, + onPrimaryContainer = OnPrimaryContainer, + secondary = Secondary, + onSecondary = OnSecondary, + secondaryContainer = SecondaryContainer, + onSecondaryContainer = OnSecondaryContainer, + tertiary = Tertiary, + onTertiary = OnTertiary, + tertiaryContainer = TertiaryContainer, + onTertiaryContainer = OnTertiaryContainer, + error = Error, + onError = OnError, + errorContainer = ErrorContainer, + onErrorContainer = OnErrorContainer, + background = Background, + onBackground = OnBackground, + surface = Surface, + onSurface = OnSurface, + surfaceVariant = SurfaceVariant, + onSurfaceVariant = OnSurfaceVariant, + outline = Outline + ) + + fun darkColorScheme() = darkColorScheme( + primary = PrimaryDark, + onPrimary = OnPrimaryDark, + primaryContainer = PrimaryContainerDark, + onPrimaryContainer = OnPrimaryContainerDark, + secondary = SecondaryDark, + onSecondary = OnSecondaryDark, + secondaryContainer = SecondaryContainerDark, + onSecondaryContainer = OnSecondaryContainerDark, + tertiary = TertiaryDark, + onTertiary = OnTertiaryDark, + tertiaryContainer = TertiaryContainerDark, + onTertiaryContainer = OnTertiaryContainerDark, + error = ErrorDark, + onError = OnErrorDark, + errorContainer = ErrorContainerDark, + onErrorContainer = OnErrorContainerDark, + background = BackgroundDark, + onBackground = OnBackgroundDark, + surface = SurfaceDark, + onSurface = OnSurfaceDark, + surfaceVariant = SurfaceVariantDark, + onSurfaceVariant = OnSurfaceVariantDark, + outline = OutlineDark + ) +} + +object ConerThemeColorsGenerated20240628_2 : ConerThemeColors { + override val Primary = Color(0xFF063E65) + override val OnPrimary = Color(0xFFFFFFFF) + override val PrimaryContainer = Color(0xFFA1C9E6) + override val OnPrimaryContainer = Color(0xFF031F33) + override val Secondary = Color(0xFFF15A24) + override val OnSecondary = Color(0xFFFFFFFF) + override val SecondaryContainer = Color(0xFFE6B8A8) + override val OnSecondaryContainer = Color(0xFF331308) + override val Tertiary = Color(0xFF428D00) + override val OnTertiary = Color(0xFFFFFFFF) + override val TertiaryContainer = Color(0xFFBFE69D) + override val OnTertiaryContainer = Color(0xFF183300) + override val Error = Color(0xFFB3261E) + override val OnError = Color(0xFFFFFFFF) + override val ErrorContainer = Color(0xFFE6ACA9) + override val OnErrorContainer = Color(0xFF330B09) + override val Background = Color(0xFFfbfcfc) + override val OnBackground = Color(0xFF313233) + override val Surface = Color(0xFFfbfcfc) + override val OnSurface = Color(0xFF313233) + override val SurfaceVariant = Color(0xFFd8e0e6) + override val OnSurfaceVariant = Color(0xFF535e66) + override val Outline = Color(0xFF7c8d99) + + override val PrimaryDark = Color(0xFF85BDE6) + override val OnPrimaryDark = Color(0xFF052F4C) + override val PrimaryContainerDark = Color(0xFF063E66) + override val OnPrimaryContainerDark = Color(0xFFA1C9E6) + override val SecondaryDark = Color(0xFFE6A58E) + override val OnSecondaryDark = Color(0xFF4C1C0B) + override val SecondaryContainerDark = Color(0xFF66260F) + override val OnSecondaryContainerDark = Color(0xFFE6B8A8) + override val TertiaryDark = Color(0xFFAFE67F) + override val OnTertiaryDark = Color(0xFF244C00) + override val TertiaryContainerDark = Color(0xFF306600) + override val OnTertiaryContainerDark = Color(0xFFBFE69D) + override val ErrorDark = Color(0xFFE69490) + override val OnErrorDark = Color(0xFF4C100D) + override val ErrorContainerDark = Color(0xFF661511) + override val OnErrorContainerDark = Color(0xFFE6ACA9) + override val BackgroundDark = Color(0xFF313233) + override val OnBackgroundDark = Color(0xFFe2e4e6) + override val SurfaceDark = Color(0xFF313233) + override val OnSurfaceDark = Color(0xFFe2e4e6) + override val SurfaceVariantDark = Color(0xFF535e66) + override val OnSurfaceVariantDark = Color(0xFFd2dde6) + override val OutlineDark = Color(0xFF9daab3) +} + +object ConerThemeColorsGenerated20240628_1 : ConerThemeColors { + override val Primary = Color(0xFF063E65) + override val OnPrimary = Color(0xFFFFFFFF) + override val PrimaryContainer = Color(0xFFA1C9E6) + override val OnPrimaryContainer = Color(0xFF031F33) + override val Secondary = Color(0xFF428D00) + override val OnSecondary = Color(0xFFFFFFFF) + override val SecondaryContainer = Color(0xFFBFE69D) + override val OnSecondaryContainer = Color(0xFF183300) + override val Tertiary = Color(0xFFF15A24) + override val OnTertiary = Color(0xFFFFFFFF) + override val TertiaryContainer = Color(0xFFE6B8A8) + override val OnTertiaryContainer = Color(0xFF331308) + override val Error = Color(0xFFB3261E) + override val OnError = Color(0xFFFFFFFF) + override val ErrorContainer = Color(0xFFE6ACA9) + override val OnErrorContainer = Color(0xFF330B09) + override val Background = Color(0xFFfbfcfc) + override val OnBackground = Color(0xFF313233) + override val Surface = Color(0xFFfbfcfc) + override val OnSurface = Color(0xFF313233) + override val SurfaceVariant = Color(0xFFd8e0e6) + override val OnSurfaceVariant = Color(0xFF535e66) + override val Outline = Color(0xFF7c8d99) + + override val PrimaryDark = Color(0xFF85BDE6) + override val OnPrimaryDark = Color(0xFF052F4C) + override val PrimaryContainerDark = Color(0xFF063E66) + override val OnPrimaryContainerDark = Color(0xFFA1C9E6) + override val SecondaryDark = Color(0xFFAFE67F) + override val OnSecondaryDark = Color(0xFF244C00) + override val SecondaryContainerDark = Color(0xFF306600) + override val OnSecondaryContainerDark = Color(0xFFBFE69D) + override val TertiaryDark = Color(0xFFE6A58E) + override val OnTertiaryDark = Color(0xFF4C1C0B) + override val TertiaryContainerDark = Color(0xFF66260F) + override val OnTertiaryContainerDark = Color(0xFFE6B8A8) + override val ErrorDark = Color(0xFFE69490) + override val OnErrorDark = Color(0xFF4C100D) + override val ErrorContainerDark = Color(0xFF661511) + override val OnErrorContainerDark = Color(0xFFE6ACA9) + override val BackgroundDark = Color(0xFF313233) + override val OnBackgroundDark = Color(0xFFe2e4e6) + override val SurfaceDark = Color(0xFF313233) + override val OnSurfaceDark = Color(0xFFe2e4e6) + override val SurfaceVariantDark = Color(0xFF535e66) + override val OnSurfaceVariantDark = Color(0xFFd2dde6) + override val OutlineDark = Color(0xFF9daab3) +} + +object ConerThemeColorsGenerated20240628_0 : ConerThemeColors { + override val Primary = Color(0xFF606060) + override val OnPrimary = Color(0xFFFFFFFF) + override val PrimaryContainer = Color(0xFFE6E6E6) + override val OnPrimaryContainer = Color(0xFF333333) + override val Secondary = Color(0xFF1F679B) + override val OnSecondary = Color(0xFFFFFFFF) + override val SecondaryContainer = Color(0xFFABCDE6) + override val OnSecondaryContainer = Color(0xFF0A2233) + override val Tertiary = Color(0xFF77D720) + override val OnTertiary = Color(0xFFFFFFFF) + override val TertiaryContainer = Color(0xFFC5E6A8) + override val OnTertiaryContainer = Color(0xFF1C3308) + override val Error = Color(0xFFB3261E) + override val OnError = Color(0xFFFFFFFF) + override val ErrorContainer = Color(0xFFE6ACA9) + override val OnErrorContainer = Color(0xFF330B09) + override val Background = Color(0xFFfcfcfc) + override val OnBackground = Color(0xFF333333) + override val Surface = Color(0xFFfcfcfc) + override val OnSurface = Color(0xFF333333) + override val SurfaceVariant = Color(0xFFe6e6e6) + override val OnSurfaceVariant = Color(0xFF666666) + override val Outline = Color(0xFF999999) + + override val PrimaryDark = Color(0xFFE6E6E6) + override val OnPrimaryDark = Color(0xFF4C4C4C) + override val PrimaryContainerDark = Color(0xFF666666) + override val OnPrimaryContainerDark = Color(0xFFE6E6E6) + override val SecondaryDark = Color(0xFF93C3E6) + override val OnSecondaryDark = Color(0xFF0F324C) + override val SecondaryContainerDark = Color(0xFF144366) + override val OnSecondaryContainerDark = Color(0xFFABCDE6) + override val TertiaryDark = Color(0xFFB7E68E) + override val OnTertiaryDark = Color(0xFF2A4C0B) + override val TertiaryContainerDark = Color(0xFF38660F) + override val OnTertiaryContainerDark = Color(0xFFC5E6A8) + override val ErrorDark = Color(0xFFE69490) + override val OnErrorDark = Color(0xFF4C100D) + override val ErrorContainerDark = Color(0xFF661511) + override val OnErrorContainerDark = Color(0xFFE6ACA9) + override val BackgroundDark = Color(0xFF333333) + override val OnBackgroundDark = Color(0xFFe6e6e6) + override val SurfaceDark = Color(0xFF333333) + override val OnSurfaceDark = Color(0xFFe6e6e6) + override val SurfaceVariantDark = Color(0xFF666666) + override val OnSurfaceVariantDark = Color(0xFFe6e6e6) + override val OutlineDark = Color(0xFFb3b3b3) +} + +object ConerThemeColorsGenerated20240627 : ConerThemeColors { + + override val Primary = Color(0xFF1F679B) + override val OnPrimary = Color(0xFFFFFFFF) + override val PrimaryContainer = Color(0xFFABCDE6) + override val OnPrimaryContainer = Color(0xFF0A2233) + override val Secondary = Color(0xFF77D720) + override val OnSecondary = Color(0xFFFFFFFF) + override val SecondaryContainer = Color(0xFFC5E6A8) + override val OnSecondaryContainer = Color(0xFF1C3308) + override val Tertiary = Color(0xFFFF7900) + override val OnTertiary = Color(0xFFFFFFFF) + override val TertiaryContainer = Color(0xFFE6BF9D) + override val OnTertiaryContainer = Color(0xFF331800) + override val Error = Color(0xFFB3261E) + override val OnError = Color(0xFFFFFFFF) + override val ErrorContainer = Color(0xFFE6ACA9) + override val OnErrorContainer = Color(0xFF330B09) + override val Background = Color(0xFFfbfcfc) + override val OnBackground = Color(0xFF313233) + override val Surface = Color(0xFFfbfcfc) + override val OnSurface = Color(0xFF313233) + override val SurfaceVariant = Color(0xFFdae1e6) + override val OnSurfaceVariant = Color(0xFF565f66) + override val Outline = Color(0xFF818f99) + + override val PrimaryDark = Color(0xFF93C3E6) + override val OnPrimaryDark = Color(0xFF0F324C) + override val PrimaryContainerDark = Color(0xFF144366) + override val OnPrimaryContainerDark = Color(0xFFABCDE6) + override val SecondaryDark = Color(0xFFB7E68E) + override val OnSecondaryDark = Color(0xFF2A4C0B) + override val SecondaryContainerDark = Color(0xFF38660F) + override val OnSecondaryContainerDark = Color(0xFFC5E6A8) + override val TertiaryDark = Color(0xFFE6AF7F) + override val OnTertiaryDark = Color(0xFF4C2400) + override val TertiaryContainerDark = Color(0xFF663000) + override val OnTertiaryContainerDark = Color(0xFFE6BF9D) + override val ErrorDark = Color(0xFFE69490) + override val OnErrorDark = Color(0xFF4C100D) + override val ErrorContainerDark = Color(0xFF661511) + override val OnErrorContainerDark = Color(0xFFE6ACA9) + override val BackgroundDark = Color(0xFF313233) + override val OnBackgroundDark = Color(0xFFe3e4e6) + override val SurfaceDark = Color(0xFF313233) + override val OnSurfaceDark = Color(0xFFe3e4e6) + override val SurfaceVariantDark = Color(0xFF565f66) + override val OnSurfaceVariantDark = Color(0xFFd5dfe6) + override val OutlineDark = Color(0xFFa0abb3) +} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/util/ComposeFlowExtensions.kt b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/util/ComposeFlowExtensions.kt new file mode 100644 index 000000000..9df4c135e --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/util/ComposeFlowExtensions.kt @@ -0,0 +1,34 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.gui.util + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import kotlin.coroutines.CoroutineContext +import kotlin.coroutines.EmptyCoroutineContext +import tech.coner.trailer.toolkit.presentation.state.ItemModelState +import tech.coner.trailer.toolkit.presentation.state.MutableItemModelPropertyDelegate +import tech.coner.trailer.toolkit.presentation.state.State +import tech.coner.trailer.toolkit.presentation.state.StateContainer +import tech.coner.trailer.toolkit.validation.Feedback + +@Composable +fun StateContainer.StatePropertyContainer.collectAsState( + context: CoroutineContext = EmptyCoroutineContext +) = flow.collectAsState(immutableValue, context) + +@Composable +fun , ITEM, PROPERTY, FEEDBACK : Feedback> + MutableItemModelPropertyDelegate.collectValueAsState( + context: CoroutineContext = EmptyCoroutineContext +) = valueFlow.collectAsState( + initial = value, + context = context +) + +@Composable +fun , ITEM, PROPERTY, FEEDBACK : Feedback> +MutableItemModelPropertyDelegate.collectFeedbackAsState( + context: CoroutineContext = EmptyCoroutineContext +) = feedbackFlow.collectAsState( + initial = feedback, + context = context +) diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/util/FocusFirstFocusRequester.kt b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/util/FocusFirstFocusRequester.kt new file mode 100644 index 000000000..982b8f991 --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/util/FocusFirstFocusRequester.kt @@ -0,0 +1,47 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.gui.util + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.focus.onFocusEvent +import kotlin.reflect.KProperty1 + +class FocusFirstFocusRequester( + internal val store: LinkedHashMap, Entry> +) { + + fun requestFocus(property: KProperty1) { + if (store.values.any { it.focused }) return + store[property]?.focusRequester?.requestFocus() + } + + class Entry( + val focusRequester: FocusRequester, + ) { + var focused: Boolean = false + } + + companion object { + + fun FocusFirstFocusRequester(properties: List>): FocusFirstFocusRequester { + return FocusFirstFocusRequester( + store = linkedMapOf( + *properties.map { it to Entry(FocusRequester()) }.toTypedArray() + ) + ) + } + } +} + +@Composable +fun Modifier.focusOnError( + focusFirstFocusRequester: FocusFirstFocusRequester, + property: KProperty1 +): Modifier { + val focusRequester: FocusRequester = focusFirstFocusRequester.store[property]?.focusRequester ?: return this + return focusRequester(focusRequester) + .onFocusEvent { + focusFirstFocusRequester.store[property]?.focused = it.isFocused + } +} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/util/LocalStrings.kt b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/util/LocalStrings.kt new file mode 100644 index 000000000..626526548 --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/util/LocalStrings.kt @@ -0,0 +1,13 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.gui.util + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.compositionLocalOf +import org.kodein.di.direct +import org.kodein.di.instance +import tech.coner.trailer.toolkit.sample.dmvapp.gui.di +import tech.coner.trailer.toolkit.sample.dmvapp.presentation.localization.Strings + +val LocalStrings = compositionLocalOf { di.direct.instance() } + +val strings: Strings +@Composable get() = LocalStrings.current \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/util/LocalWindowState.kt b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/util/LocalWindowState.kt new file mode 100644 index 000000000..d41d59d5a --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/util/LocalWindowState.kt @@ -0,0 +1,6 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.gui.util + +import androidx.compose.runtime.compositionLocalOf +import androidx.compose.ui.window.WindowState + +val LocalWindowState = compositionLocalOf { WindowState() } diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/window/DmvAppMainWindow.kt b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/window/DmvAppMainWindow.kt new file mode 100644 index 000000000..4f54f94bd --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/window/DmvAppMainWindow.kt @@ -0,0 +1,31 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.gui.window + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.window.ApplicationScope +import androidx.compose.ui.window.Window +import androidx.compose.ui.window.rememberWindowState +import java.awt.Dimension +import tech.coner.trailer.toolkit.sample.dmvapp.gui.screen.main.DmvAppMainScreen +import tech.coner.trailer.toolkit.sample.dmvapp.gui.util.LocalWindowState +import tech.coner.trailer.toolkit.sample.dmvapp.gui.util.strings + +@Composable +fun ApplicationScope.DmvAppMainWindow() { + val state = rememberWindowState() + CompositionLocalProvider(LocalWindowState provides state) { + Window( + title = strings.dmvLabel, + icon = painterResource("coner-icon/coner-icon_512.png"), + state = state, + onCloseRequest = ::exitApplication, + ) { + LaunchedEffect(null) { + window.minimumSize = Dimension(600, 600) + } + DmvAppMainScreen() + } + } +} \ No newline at end of file diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/window/DriversLicenseWindow.kt b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/window/DriversLicenseWindow.kt new file mode 100644 index 000000000..50c46fbce --- /dev/null +++ b/toolkit/samples/dmvapp/dmvapp-gui/src/main/kotlin/tech/coner/trailer/toolkit/sample/dmvapp/gui/window/DriversLicenseWindow.kt @@ -0,0 +1,26 @@ +package tech.coner.trailer.toolkit.sample.dmvapp.gui.window + +import androidx.compose.runtime.Composable +import androidx.compose.ui.window.Window +import org.kodein.di.compose.rememberInstance +import tech.coner.trailer.toolkit.sample.dmvapp.domain.entity.DriversLicense +import tech.coner.trailer.toolkit.sample.dmvapp.gui.presentation.presenter.SettingsPresenter +import tech.coner.trailer.toolkit.sample.dmvapp.gui.screen.driverslicenseapplication.DriversLicenseScreen +import tech.coner.trailer.toolkit.sample.dmvapp.gui.theme.ConerTheme +import tech.coner.trailer.toolkit.sample.dmvapp.gui.util.collectAsState + + +@Composable +fun DriversLicenseWindow( + driversLicense: DriversLicense, + onCloseRequest: () -> Unit +) { + val settingsPresenter: SettingsPresenter by rememberInstance() + Window( + onCloseRequest = onCloseRequest + ) { + ConerTheme(settingsPresenter.themeMode.collectAsState().value) { + DriversLicenseScreen(driversLicense) + } + } +} diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/resources/coner-icon/coner-icon_1024.png b/toolkit/samples/dmvapp/dmvapp-gui/src/main/resources/coner-icon/coner-icon_1024.png new file mode 100644 index 0000000000000000000000000000000000000000..b2390c982633285d6f302a57c3db484c4f75f647 GIT binary patch literal 90565 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 BAAJA- literal 0 HcmV?d00001 diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/resources/coner-icon/coner-icon_128.png b/toolkit/samples/dmvapp/dmvapp-gui/src/main/resources/coner-icon/coner-icon_128.png new file mode 100644 index 0000000000000000000000000000000000000000..b4305078b775d9a6f7f2c2c429fea166b14f29a0 GIT binary patch literal 8741 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 literal 0 HcmV?d00001 diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/resources/coner-icon/coner-icon_256.png b/toolkit/samples/dmvapp/dmvapp-gui/src/main/resources/coner-icon/coner-icon_256.png new file mode 100644 index 0000000000000000000000000000000000000000..fe4e03a49cbb9278e7fdfb0b6a732fbb6bbfd641 GIT binary patch literal 19308 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 Rh~5AI002ovPDHLkV1lqfeXIZg literal 0 HcmV?d00001 diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/resources/coner-icon/coner-icon_32.png b/toolkit/samples/dmvapp/dmvapp-gui/src/main/resources/coner-icon/coner-icon_32.png new file mode 100644 index 0000000000000000000000000000000000000000..382fe9618276d58f159de18e3ed54229ba660802 GIT binary patch literal 1531 zcmV(9+#*yUV_} zJ2Q8#KiZnM*|uw0&###~_nhy{_kH)yTp+Q~0+^m)&A7l9B=H}-JX2_X%)~j0&B6%) zDe(}wL_}X=K^o&XD}GBchBN(;LO&ec1*q)bU3FFtK=vDFFb#Lb!ah_J!*Kwp&sZHbc*A z89<}e@_(9?Xi-yGb@og2)>vM`GEh`lG@mWo@7;T~BP;8}3qrLE_W(dE2u1nHeAKRG zx5nZn%s_F;s;77CdviJfxOf~>vEH5D?Se7at%ogOe-~D>6 zuf4rJBnX1i+}Y#ytuDiFKDH~%(-sItB6BbGDL(?}8_DIz(HsS<1_fy%zdcoeJypY` zYgs1suaH`O-KQK{VHH0v&ow_|<(y>4rB=VHs!^lS7~WrAP64E;o1RTO@{+S*TIXe* z2v`QjXvbxs*sS^Xz+7#vLV+_brOzu<$*5tsmgiZv?3tfD+dZJxRy2Av^LWbVwEUv` z+bAaO+Eo{>s;UCZvd~*IR2h^E0FklU@fgr%>DVNZWpJoNzW?s>^jRs|QI(VO&vxee zWi<%^?s%oH6lb+^H$b$IKj>Ry>|2lw=h|r9gU;s2LL+0EDJZ z_RbWM^8i3wP?~w7CJ4)LH76pDumByQ+ui5qd=MrKm^Bo%)7j(Z2vJjS`HAd|(r>10peL%{@XB;kFsdjM%`32oD+??l6hi8H zogO%!vgXDB9PF(wdOQQA3JhOeC9%fae;ca?N%u*0a8-3njtGnN~f>LS( zfS-EhzFHsI>x$C5u{iN$fC2FO?_Q;LvrSiaxUsLRvT%AE&-36oh9!g$Nm96QIFc#L zByS|~reBHt&?|k`=vOaJBt8n1(sclG0B8WDu3x`?sa~%?-_p{up+N3mvfC=BopHmt zJDtg#$n`mw;y&k+E9<<xK6%UEe3nma)fsqv8B1xD8N#vEht%f959xFnwpy7Z+3PZ^N$TR?vxN~Lz!l^ zT8IB!oN?-y6KSA3BO_yYJQRn91VBurffSR;#865tacbBBJeaD1SgXK~!NxmEDRl#g zVlWdX0J#8s00J2Nw|fY{h)EjtzZ!4?XatZBVB^re0zk!J#>@b`Lt_REo`_?9XdW4q hQenh(%#+Qd;veW+OKFbwPd)$u002ovPDHLkV1lQ6!^;2w literal 0 HcmV?d00001 diff --git a/toolkit/samples/dmvapp/dmvapp-gui/src/main/resources/coner-icon/coner-icon_3840.png b/toolkit/samples/dmvapp/dmvapp-gui/src/main/resources/coner-icon/coner-icon_3840.png new file mode 100644 index 0000000000000000000000000000000000000000..f4088fa0cb04a7710bfc4c5a2e02bba2b3a6fdc0 GIT binary patch literal 415999 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