From 018853cd9666eb2639ebdf9c2538861b3a16ad7f Mon Sep 17 00:00:00 2001 From: Sebastian Date: Sun, 16 Oct 2016 21:46:35 +0200 Subject: [PATCH] 1) More tests 2) Angular2 integrated --- config/config.js | 4 + .../CQRS/Commands/CommandHandler.cs | 2 +- .../CQRS/EventStore/DefaultNameResolver.cs | 10 +- .../CQRS/EventStore/EventStoreBus.cs | 4 +- .../Apps/MongoAppRepository.cs | 7 +- src/PinkParrot.Store.MongoDb/MongoDbModule.cs | 3 + .../Schemas/MongoSchemaRepository.cs | 2 +- .../Utils/EntityMapper.cs | 2 +- .../Utils/MongoExtensions.cs | 2 +- .../Apps/AppCommandHandler.cs | 21 +- .../Configurations/EventStoreModule.cs | 4 + src/PinkParrot/Configurations/ReadModule.cs | 7 - src/PinkParrot/Configurations/WebpackUsage.cs | 33 ++ .../Modules/Api/Apps/AppController.cs | 33 +- .../Modules/Api/Apps/Models/CreateAppDto.cs | 15 + .../Modules/Api/EntityCreatedDto.cs | 6 +- .../Api/Schemas/Models/CreateFieldDto.cs | 1 - .../Modules/Api/Schemas/SchemasController.cs | 3 +- src/PinkParrot/PinkParrot.xproj | 5 +- .../DeactivateForAppDomainAttribute.cs | 26 ++ src/PinkParrot/Pipeline/WebpackMiddleware.cs | 129 ++++++++ src/PinkParrot/Pipeline/WebpackRunner.cs | 93 ++++++ src/PinkParrot/Properties/launchSettings.json | 2 +- src/PinkParrot/Startup.cs | 26 +- src/PinkParrot/app-config/auto-loader.js | 67 ++++ .../app-config/fix-coverage-loader.js | 47 +++ src/PinkParrot/app-config/helpers.js | 13 + src/PinkParrot/app-config/karma-test-shim.js | 36 +++ src/PinkParrot/app-config/karma.conf.js | 52 +++ .../app-config/karma.coverage.conf.js | 77 +++++ src/PinkParrot/app-config/webpack.common.js | 117 +++++++ src/PinkParrot/app-config/webpack.coverage.js | 23 ++ src/PinkParrot/app-config/webpack.dev.js | 67 ++++ src/PinkParrot/app-config/webpack.prod.js | 106 ++++++ src/PinkParrot/app-config/webpack.test.js | 77 +++++ src/PinkParrot/app-libs/typings/global.d.ts | 2 + src/PinkParrot/app/app.component.html | 3 + src/PinkParrot/app/app.component.js.map | 1 + src/PinkParrot/app/app.component.scss | 8 + src/PinkParrot/app/app.component.spec.js.map | 1 + src/PinkParrot/app/app.component.spec.ts | 15 + src/PinkParrot/app/app.component.ts | 8 + src/PinkParrot/app/app.module.js.map | 1 + src/PinkParrot/app/app.module.ts | 16 + src/PinkParrot/app/core/angular/action.js.map | 1 + .../app/core/angular/action.spec.js.map | 1 + .../app/core/angular/action.spec.ts | 61 ++++ src/PinkParrot/app/core/angular/action.ts | 69 ++++ .../app/core/angular/cloak.directive.js.map | 1 + .../core/angular/cloak.directive.spec.js.map | 1 + .../app/core/angular/cloak.directive.spec.ts | 28 ++ .../app/core/angular/cloak.directive.ts | 19 ++ .../core/angular/color-picker.component.html | 11 + .../angular/color-picker.component.js.map | 1 + .../core/angular/color-picker.component.scss | 56 ++++ .../color-picker.component.spec.js.map | 1 + .../angular/color-picker.component.spec.ts | 124 +++++++ .../core/angular/color-picker.component.ts | 96 ++++++ .../app/core/angular/date-time.pipes.js.map | 1 + .../core/angular/date-time.pipes.spec.js.map | 1 + .../app/core/angular/date-time.pipes.spec.ts | 87 +++++ .../app/core/angular/date-time.pipes.ts | 65 ++++ .../core/angular/drag-model.directive.js.map | 1 + .../app/core/angular/drag-model.directive.ts | 117 +++++++ .../angular/focus-on-change.directive.js.map | 1 + .../focus-on-change.directive.spec.js.map | 1 + .../angular/focus-on-change.directive.spec.ts | 52 +++ .../core/angular/focus-on-change.directive.ts | 28 ++ .../core/angular/image-drop.directive.js.map | 1 + .../app/core/angular/image-drop.directive.ts | 127 ++++++++ .../app/core/angular/money.pipe.js.map | 1 + .../app/core/angular/money.pipe.spec.js.map | 1 + .../app/core/angular/money.pipe.spec.ts | 48 +++ src/PinkParrot/app/core/angular/money.pipe.ts | 37 +++ .../core/angular/shortcut.component.js.map | 1 + .../angular/shortcut.component.spec.js.map | 1 + .../core/angular/shortcut.component.spec.ts | 83 +++++ .../app/core/angular/shortcut.component.ts | 54 ++++ .../app/core/angular/slider.component.html | 3 + .../app/core/angular/slider.component.js.map | 1 + .../app/core/angular/slider.component.scss | 37 +++ .../app/core/angular/slider.component.ts | 145 +++++++++ .../app/core/angular/spinner.component.js.map | 1 + .../app/core/angular/spinner.component.ts | 40 +++ .../core/angular/user-report.component.js.map | 1 + .../app/core/angular/user-report.component.ts | 37 +++ .../app/core/angular/validators.js.map | 1 + .../app/core/angular/validators.spec.js.map | 1 + .../app/core/angular/validators.spec.ts | 50 +++ src/PinkParrot/app/core/angular/validators.ts | 26 ++ src/PinkParrot/app/core/configurations.js.map | 1 + src/PinkParrot/app/core/configurations.ts | 31 ++ src/PinkParrot/app/core/index.js.map | 1 + src/PinkParrot/app/core/index.ts | 29 ++ src/PinkParrot/app/core/plattform.js.map | 1 + src/PinkParrot/app/core/plattform.ts | 14 + .../core/services/clipboard.service.js.map | 1 + .../services/clipboard.service.spec.js.map | 1 + .../core/services/clipboard.service.spec.ts | 51 +++ .../app/core/services/clipboard.service.ts | 34 ++ .../app/core/services/drag.service.js.map | 1 + .../core/services/drag.service.spec.js.map | 1 + .../app/core/services/drag.service.spec.ts | 42 +++ .../app/core/services/drag.service.ts | 28 ++ .../core/services/local-store.service.js.map | 1 + .../services/local-store.service.spec.js.map | 1 + .../core/services/local-store.service.spec.ts | 59 ++++ .../app/core/services/local-store.service.ts | 26 ++ .../app/core/services/shortcut.service.js.map | 1 + .../services/shortcut.service.spec.js.map | 1 + .../core/services/shortcut.service.spec.ts | 45 +++ .../app/core/services/shortcut.service.ts | 26 ++ .../app/core/services/title.service.js.map | 1 + .../core/services/title.service.spec.js.map | 1 + .../app/core/services/title.service.spec.ts | 62 ++++ .../app/core/services/title.service.ts | 34 ++ .../app/core/utils/color-palette.js.map | 1 + .../app/core/utils/color-palette.spec.js.map | 1 + .../app/core/utils/color-palette.spec.ts | 16 + .../app/core/utils/color-palette.ts | 41 +++ src/PinkParrot/app/core/utils/color.js.map | 1 + .../app/core/utils/color.spec.js.map | 1 + src/PinkParrot/app/core/utils/color.spec.ts | 273 ++++++++++++++++ src/PinkParrot/app/core/utils/color.ts | 204 ++++++++++++ .../app/core/utils/date-helper.js.map | 1 + .../app/core/utils/date-helper.spec.js.map | 1 + .../app/core/utils/date-helper.spec.ts | 31 ++ src/PinkParrot/app/core/utils/date-helper.ts | 20 ++ .../app/core/utils/date-time.js.map | 1 + .../app/core/utils/date-time.spec.js.map | 1 + .../app/core/utils/date-time.spec.ts | 169 ++++++++++ src/PinkParrot/app/core/utils/date-time.ts | 227 +++++++++++++ src/PinkParrot/app/core/utils/duration.js.map | 1 + .../app/core/utils/duration.spec.js.map | 1 + .../app/core/utils/duration.spec.ts | 52 +++ src/PinkParrot/app/core/utils/duration.ts | 36 +++ .../app/core/utils/immutable-id-map.js.map | 1 + .../core/utils/immutable-id-map.spec.js.map | 1 + .../app/core/utils/immutable-id-map.spec.ts | 281 ++++++++++++++++ .../app/core/utils/immutable-id-map.ts | 218 +++++++++++++ .../app/core/utils/immutable-list.js.map | 1 + .../app/core/utils/immutable-list.spec.js.map | 1 + .../app/core/utils/immutable-list.spec.ts | 238 ++++++++++++++ .../app/core/utils/immutable-list.ts | 206 ++++++++++++ .../app/core/utils/immutable-object.js.map | 1 + .../core/utils/immutable-object.spec.js.map | 1 + .../app/core/utils/immutable-object.spec.ts | 38 +++ .../app/core/utils/immutable-object.ts | 22 ++ .../app/core/utils/immutable-set.js.map | 1 + .../app/core/utils/immutable-set.spec.js.map | 1 + .../app/core/utils/immutable-set.spec.ts | 158 +++++++++ .../app/core/utils/immutable-set.ts | 92 ++++++ .../app/core/utils/math-helper.js.map | 1 + .../app/core/utils/math-helper.spec.js.map | 1 + .../app/core/utils/math-helper.spec.ts | 74 +++++ src/PinkParrot/app/core/utils/math-helper.ts | 84 +++++ src/PinkParrot/app/core/utils/rect2.js.map | 1 + .../app/core/utils/rect2.spec.js.map | 1 + src/PinkParrot/app/core/utils/rect2.spec.ts | 237 ++++++++++++++ src/PinkParrot/app/core/utils/rect2.ts | 191 +++++++++++ src/PinkParrot/app/core/utils/rotation.js.map | 1 + .../app/core/utils/rotation.spec.js.map | 1 + .../app/core/utils/rotation.spec.ts | 73 +++++ src/PinkParrot/app/core/utils/rotation.ts | 57 ++++ src/PinkParrot/app/core/utils/vec2.js.map | 1 + .../app/core/utils/vec2.spec.js.map | 1 + src/PinkParrot/app/core/utils/vec2.spec.ts | 159 +++++++++ src/PinkParrot/app/core/utils/vec2.ts | 127 ++++++++ src/PinkParrot/app/main.js.map | 1 + src/PinkParrot/app/main.ts | 12 + src/PinkParrot/app/polyfills.js.map | 1 + src/PinkParrot/app/polyfills.ts | 10 + src/PinkParrot/app/theme/_bootstrap.scss | 69 ++++ src/PinkParrot/app/theme/_layout.scss | 10 + src/PinkParrot/app/theme/_mixins.scss | 306 ++++++++++++++++++ src/PinkParrot/app/theme/_vars.scss | 4 + src/PinkParrot/app/theme/theme.scss | 2 + src/PinkParrot/app/theme/vendor.scss | 7 + src/PinkParrot/app/vendor.js.map | 1 + src/PinkParrot/app/vendor.ts | 11 + src/PinkParrot/appsettings.json | 22 +- src/PinkParrot/karma.coverage.conf.js | 1 + src/PinkParrot/package.json | 76 +++++ src/PinkParrot/tsconfig.json | 13 + src/PinkParrot/tslint.json | 92 ++++++ src/PinkParrot/typings.json | 7 + src/PinkParrot/webpack.config.js | 1 + src/PinkParrot/wwwroot/index.html | 12 + .../AutofacDomainObjectFactoryTests.cs | 13 +- .../CQRS/Commands/InMemoryCommandBusTests.cs | 12 +- .../CQRS/EnvelopeExtensionsTests.cs | 13 +- .../PropertiesBagTests.cs | 1 - .../project.json | 1 - .../Apps/AppCommandHandlerTests.cs | 66 ++++ ...nObjectTest.cs => AppDomainObjectTests.cs} | 2 +- ...jectTest.cs => SchemaDomainObjectTests.cs} | 4 +- tests/PinkParrot.Write.Tests/project.json | 4 + tests/Postman-Collection.json | 145 +++++++++ 198 files changed, 7395 insertions(+), 66 deletions(-) create mode 100644 config/config.js create mode 100644 src/PinkParrot/Configurations/WebpackUsage.cs create mode 100644 src/PinkParrot/Modules/Api/Apps/Models/CreateAppDto.cs create mode 100644 src/PinkParrot/Pipeline/DeactivateForAppDomainAttribute.cs create mode 100644 src/PinkParrot/Pipeline/WebpackMiddleware.cs create mode 100644 src/PinkParrot/Pipeline/WebpackRunner.cs create mode 100644 src/PinkParrot/app-config/auto-loader.js create mode 100644 src/PinkParrot/app-config/fix-coverage-loader.js create mode 100644 src/PinkParrot/app-config/helpers.js create mode 100644 src/PinkParrot/app-config/karma-test-shim.js create mode 100644 src/PinkParrot/app-config/karma.conf.js create mode 100644 src/PinkParrot/app-config/karma.coverage.conf.js create mode 100644 src/PinkParrot/app-config/webpack.common.js create mode 100644 src/PinkParrot/app-config/webpack.coverage.js create mode 100644 src/PinkParrot/app-config/webpack.dev.js create mode 100644 src/PinkParrot/app-config/webpack.prod.js create mode 100644 src/PinkParrot/app-config/webpack.test.js create mode 100644 src/PinkParrot/app-libs/typings/global.d.ts create mode 100644 src/PinkParrot/app/app.component.html create mode 100644 src/PinkParrot/app/app.component.js.map create mode 100644 src/PinkParrot/app/app.component.scss create mode 100644 src/PinkParrot/app/app.component.spec.js.map create mode 100644 src/PinkParrot/app/app.component.spec.ts create mode 100644 src/PinkParrot/app/app.component.ts create mode 100644 src/PinkParrot/app/app.module.js.map create mode 100644 src/PinkParrot/app/app.module.ts create mode 100644 src/PinkParrot/app/core/angular/action.js.map create mode 100644 src/PinkParrot/app/core/angular/action.spec.js.map create mode 100644 src/PinkParrot/app/core/angular/action.spec.ts create mode 100644 src/PinkParrot/app/core/angular/action.ts create mode 100644 src/PinkParrot/app/core/angular/cloak.directive.js.map create mode 100644 src/PinkParrot/app/core/angular/cloak.directive.spec.js.map create mode 100644 src/PinkParrot/app/core/angular/cloak.directive.spec.ts create mode 100644 src/PinkParrot/app/core/angular/cloak.directive.ts create mode 100644 src/PinkParrot/app/core/angular/color-picker.component.html create mode 100644 src/PinkParrot/app/core/angular/color-picker.component.js.map create mode 100644 src/PinkParrot/app/core/angular/color-picker.component.scss create mode 100644 src/PinkParrot/app/core/angular/color-picker.component.spec.js.map create mode 100644 src/PinkParrot/app/core/angular/color-picker.component.spec.ts create mode 100644 src/PinkParrot/app/core/angular/color-picker.component.ts create mode 100644 src/PinkParrot/app/core/angular/date-time.pipes.js.map create mode 100644 src/PinkParrot/app/core/angular/date-time.pipes.spec.js.map create mode 100644 src/PinkParrot/app/core/angular/date-time.pipes.spec.ts create mode 100644 src/PinkParrot/app/core/angular/date-time.pipes.ts create mode 100644 src/PinkParrot/app/core/angular/drag-model.directive.js.map create mode 100644 src/PinkParrot/app/core/angular/drag-model.directive.ts create mode 100644 src/PinkParrot/app/core/angular/focus-on-change.directive.js.map create mode 100644 src/PinkParrot/app/core/angular/focus-on-change.directive.spec.js.map create mode 100644 src/PinkParrot/app/core/angular/focus-on-change.directive.spec.ts create mode 100644 src/PinkParrot/app/core/angular/focus-on-change.directive.ts create mode 100644 src/PinkParrot/app/core/angular/image-drop.directive.js.map create mode 100644 src/PinkParrot/app/core/angular/image-drop.directive.ts create mode 100644 src/PinkParrot/app/core/angular/money.pipe.js.map create mode 100644 src/PinkParrot/app/core/angular/money.pipe.spec.js.map create mode 100644 src/PinkParrot/app/core/angular/money.pipe.spec.ts create mode 100644 src/PinkParrot/app/core/angular/money.pipe.ts create mode 100644 src/PinkParrot/app/core/angular/shortcut.component.js.map create mode 100644 src/PinkParrot/app/core/angular/shortcut.component.spec.js.map create mode 100644 src/PinkParrot/app/core/angular/shortcut.component.spec.ts create mode 100644 src/PinkParrot/app/core/angular/shortcut.component.ts create mode 100644 src/PinkParrot/app/core/angular/slider.component.html create mode 100644 src/PinkParrot/app/core/angular/slider.component.js.map create mode 100644 src/PinkParrot/app/core/angular/slider.component.scss create mode 100644 src/PinkParrot/app/core/angular/slider.component.ts create mode 100644 src/PinkParrot/app/core/angular/spinner.component.js.map create mode 100644 src/PinkParrot/app/core/angular/spinner.component.ts create mode 100644 src/PinkParrot/app/core/angular/user-report.component.js.map create mode 100644 src/PinkParrot/app/core/angular/user-report.component.ts create mode 100644 src/PinkParrot/app/core/angular/validators.js.map create mode 100644 src/PinkParrot/app/core/angular/validators.spec.js.map create mode 100644 src/PinkParrot/app/core/angular/validators.spec.ts create mode 100644 src/PinkParrot/app/core/angular/validators.ts create mode 100644 src/PinkParrot/app/core/configurations.js.map create mode 100644 src/PinkParrot/app/core/configurations.ts create mode 100644 src/PinkParrot/app/core/index.js.map create mode 100644 src/PinkParrot/app/core/index.ts create mode 100644 src/PinkParrot/app/core/plattform.js.map create mode 100644 src/PinkParrot/app/core/plattform.ts create mode 100644 src/PinkParrot/app/core/services/clipboard.service.js.map create mode 100644 src/PinkParrot/app/core/services/clipboard.service.spec.js.map create mode 100644 src/PinkParrot/app/core/services/clipboard.service.spec.ts create mode 100644 src/PinkParrot/app/core/services/clipboard.service.ts create mode 100644 src/PinkParrot/app/core/services/drag.service.js.map create mode 100644 src/PinkParrot/app/core/services/drag.service.spec.js.map create mode 100644 src/PinkParrot/app/core/services/drag.service.spec.ts create mode 100644 src/PinkParrot/app/core/services/drag.service.ts create mode 100644 src/PinkParrot/app/core/services/local-store.service.js.map create mode 100644 src/PinkParrot/app/core/services/local-store.service.spec.js.map create mode 100644 src/PinkParrot/app/core/services/local-store.service.spec.ts create mode 100644 src/PinkParrot/app/core/services/local-store.service.ts create mode 100644 src/PinkParrot/app/core/services/shortcut.service.js.map create mode 100644 src/PinkParrot/app/core/services/shortcut.service.spec.js.map create mode 100644 src/PinkParrot/app/core/services/shortcut.service.spec.ts create mode 100644 src/PinkParrot/app/core/services/shortcut.service.ts create mode 100644 src/PinkParrot/app/core/services/title.service.js.map create mode 100644 src/PinkParrot/app/core/services/title.service.spec.js.map create mode 100644 src/PinkParrot/app/core/services/title.service.spec.ts create mode 100644 src/PinkParrot/app/core/services/title.service.ts create mode 100644 src/PinkParrot/app/core/utils/color-palette.js.map create mode 100644 src/PinkParrot/app/core/utils/color-palette.spec.js.map create mode 100644 src/PinkParrot/app/core/utils/color-palette.spec.ts create mode 100644 src/PinkParrot/app/core/utils/color-palette.ts create mode 100644 src/PinkParrot/app/core/utils/color.js.map create mode 100644 src/PinkParrot/app/core/utils/color.spec.js.map create mode 100644 src/PinkParrot/app/core/utils/color.spec.ts create mode 100644 src/PinkParrot/app/core/utils/color.ts create mode 100644 src/PinkParrot/app/core/utils/date-helper.js.map create mode 100644 src/PinkParrot/app/core/utils/date-helper.spec.js.map create mode 100644 src/PinkParrot/app/core/utils/date-helper.spec.ts create mode 100644 src/PinkParrot/app/core/utils/date-helper.ts create mode 100644 src/PinkParrot/app/core/utils/date-time.js.map create mode 100644 src/PinkParrot/app/core/utils/date-time.spec.js.map create mode 100644 src/PinkParrot/app/core/utils/date-time.spec.ts create mode 100644 src/PinkParrot/app/core/utils/date-time.ts create mode 100644 src/PinkParrot/app/core/utils/duration.js.map create mode 100644 src/PinkParrot/app/core/utils/duration.spec.js.map create mode 100644 src/PinkParrot/app/core/utils/duration.spec.ts create mode 100644 src/PinkParrot/app/core/utils/duration.ts create mode 100644 src/PinkParrot/app/core/utils/immutable-id-map.js.map create mode 100644 src/PinkParrot/app/core/utils/immutable-id-map.spec.js.map create mode 100644 src/PinkParrot/app/core/utils/immutable-id-map.spec.ts create mode 100644 src/PinkParrot/app/core/utils/immutable-id-map.ts create mode 100644 src/PinkParrot/app/core/utils/immutable-list.js.map create mode 100644 src/PinkParrot/app/core/utils/immutable-list.spec.js.map create mode 100644 src/PinkParrot/app/core/utils/immutable-list.spec.ts create mode 100644 src/PinkParrot/app/core/utils/immutable-list.ts create mode 100644 src/PinkParrot/app/core/utils/immutable-object.js.map create mode 100644 src/PinkParrot/app/core/utils/immutable-object.spec.js.map create mode 100644 src/PinkParrot/app/core/utils/immutable-object.spec.ts create mode 100644 src/PinkParrot/app/core/utils/immutable-object.ts create mode 100644 src/PinkParrot/app/core/utils/immutable-set.js.map create mode 100644 src/PinkParrot/app/core/utils/immutable-set.spec.js.map create mode 100644 src/PinkParrot/app/core/utils/immutable-set.spec.ts create mode 100644 src/PinkParrot/app/core/utils/immutable-set.ts create mode 100644 src/PinkParrot/app/core/utils/math-helper.js.map create mode 100644 src/PinkParrot/app/core/utils/math-helper.spec.js.map create mode 100644 src/PinkParrot/app/core/utils/math-helper.spec.ts create mode 100644 src/PinkParrot/app/core/utils/math-helper.ts create mode 100644 src/PinkParrot/app/core/utils/rect2.js.map create mode 100644 src/PinkParrot/app/core/utils/rect2.spec.js.map create mode 100644 src/PinkParrot/app/core/utils/rect2.spec.ts create mode 100644 src/PinkParrot/app/core/utils/rect2.ts create mode 100644 src/PinkParrot/app/core/utils/rotation.js.map create mode 100644 src/PinkParrot/app/core/utils/rotation.spec.js.map create mode 100644 src/PinkParrot/app/core/utils/rotation.spec.ts create mode 100644 src/PinkParrot/app/core/utils/rotation.ts create mode 100644 src/PinkParrot/app/core/utils/vec2.js.map create mode 100644 src/PinkParrot/app/core/utils/vec2.spec.js.map create mode 100644 src/PinkParrot/app/core/utils/vec2.spec.ts create mode 100644 src/PinkParrot/app/core/utils/vec2.ts create mode 100644 src/PinkParrot/app/main.js.map create mode 100644 src/PinkParrot/app/main.ts create mode 100644 src/PinkParrot/app/polyfills.js.map create mode 100644 src/PinkParrot/app/polyfills.ts create mode 100644 src/PinkParrot/app/theme/_bootstrap.scss create mode 100644 src/PinkParrot/app/theme/_layout.scss create mode 100644 src/PinkParrot/app/theme/_mixins.scss create mode 100644 src/PinkParrot/app/theme/_vars.scss create mode 100644 src/PinkParrot/app/theme/theme.scss create mode 100644 src/PinkParrot/app/theme/vendor.scss create mode 100644 src/PinkParrot/app/vendor.js.map create mode 100644 src/PinkParrot/app/vendor.ts create mode 100644 src/PinkParrot/karma.coverage.conf.js create mode 100644 src/PinkParrot/package.json create mode 100644 src/PinkParrot/tsconfig.json create mode 100644 src/PinkParrot/tslint.json create mode 100644 src/PinkParrot/typings.json create mode 100644 src/PinkParrot/webpack.config.js create mode 100644 src/PinkParrot/wwwroot/index.html create mode 100644 tests/PinkParrot.Write.Tests/Apps/AppCommandHandlerTests.cs rename tests/PinkParrot.Write.Tests/Apps/{AppDomainObjectTest.cs => AppDomainObjectTests.cs} (97%) rename tests/PinkParrot.Write.Tests/Schemas/{SchemaDomainObjectTest.cs => SchemaDomainObjectTests.cs} (98%) create mode 100644 tests/Postman-Collection.json diff --git a/config/config.js b/config/config.js new file mode 100644 index 000000000..a116f897a --- /dev/null +++ b/config/config.js @@ -0,0 +1,4 @@ +fromCategory('pinkparrot') + .whenAny(function(s,e) { + linkTo('pinkparrot',e); + }); \ No newline at end of file diff --git a/src/PinkParrot.Infrastructure/CQRS/Commands/CommandHandler.cs b/src/PinkParrot.Infrastructure/CQRS/Commands/CommandHandler.cs index 30c0d0a7e..d4acdbf8e 100644 --- a/src/PinkParrot.Infrastructure/CQRS/Commands/CommandHandler.cs +++ b/src/PinkParrot.Infrastructure/CQRS/Commands/CommandHandler.cs @@ -44,7 +44,7 @@ namespace PinkParrot.Infrastructure.CQRS.Commands await creator(domainObject); - await domainObjectRepository.SaveAsync(domainObject, command.AggregateId); + await domainObjectRepository.SaveAsync(domainObject, Guid.NewGuid()); } protected Task CreateAsync(IAggregateCommand command, Action creator) diff --git a/src/PinkParrot.Infrastructure/CQRS/EventStore/DefaultNameResolver.cs b/src/PinkParrot.Infrastructure/CQRS/EventStore/DefaultNameResolver.cs index af0d0abf9..933826718 100644 --- a/src/PinkParrot.Infrastructure/CQRS/EventStore/DefaultNameResolver.cs +++ b/src/PinkParrot.Infrastructure/CQRS/EventStore/DefaultNameResolver.cs @@ -13,6 +13,7 @@ namespace PinkParrot.Infrastructure.CQRS.EventStore { public sealed class DefaultNameResolver : IStreamNameResolver { + private const string Suffix = "DomainObject"; private readonly string prefix; public DefaultNameResolver(string prefix) @@ -24,7 +25,14 @@ namespace PinkParrot.Infrastructure.CQRS.EventStore public string GetStreamName(Type aggregateType, Guid id) { - return string.Format(CultureInfo.InvariantCulture, "{0}-{1}-{2}", prefix, char.ToLower(aggregateType.Name[0]) + aggregateType.Name.Substring(1), id); + var typeName = char.ToLower(aggregateType.Name[0]) + aggregateType.Name.Substring(1); + + if (typeName.EndsWith(Suffix)) + { + typeName = typeName.Substring(0, typeName.Length - Suffix.Length); + } + + return string.Format(CultureInfo.InvariantCulture, "{0}-{1}-{2}", prefix, typeName, id); } } } diff --git a/src/PinkParrot.Infrastructure/CQRS/EventStore/EventStoreBus.cs b/src/PinkParrot.Infrastructure/CQRS/EventStore/EventStoreBus.cs index 811c49e4a..103a86ca2 100644 --- a/src/PinkParrot.Infrastructure/CQRS/EventStore/EventStoreBus.cs +++ b/src/PinkParrot.Infrastructure/CQRS/EventStore/EventStoreBus.cs @@ -66,7 +66,7 @@ namespace PinkParrot.Infrastructure.CQRS.EventStore var position = positions.ReadPosition(); - logger.LogInformation($"Subscribing from: {0}", position); + logger.LogInformation("Subscribing from {0}", position.HasValue ? position.Value.ToString() : "beginning"); var settings = new CatchUpSubscriptionSettings( @@ -97,6 +97,8 @@ namespace PinkParrot.Infrastructure.CQRS.EventStore var @event = formatter.Parse(resolvedEvent); + logger.LogInformation("Received event {0} ({1})", @event.Payload.GetType().Name, @event.Headers.AggregateId()); + if (isLive) { DispatchConsumers(liveConsumers, @event).Wait(); diff --git a/src/PinkParrot.Store.MongoDb/Apps/MongoAppRepository.cs b/src/PinkParrot.Store.MongoDb/Apps/MongoAppRepository.cs index bd18a170c..94158088e 100644 --- a/src/PinkParrot.Store.MongoDb/Apps/MongoAppRepository.cs +++ b/src/PinkParrot.Store.MongoDb/Apps/MongoAppRepository.cs @@ -28,6 +28,11 @@ namespace PinkParrot.Store.MongoDb.Apps { } + protected override Task SetupCollectionAsync(IMongoCollection collection) + { + return collection.Indexes.CreateOneAsync(IndexKeys.Ascending(x => x.Name)); + } + public async Task> QueryAllAsync() { var entities = @@ -46,7 +51,7 @@ namespace PinkParrot.Store.MongoDb.Apps public Task On(AppCreated @event, EnvelopeHeaders headers) { - return Collection.CreateAsync(headers, a => SimpleMapper.Map(a, @event)); + return Collection.CreateAsync(headers, a => SimpleMapper.Map(@event, a)); } public Task On(Envelope @event) diff --git a/src/PinkParrot.Store.MongoDb/MongoDbModule.cs b/src/PinkParrot.Store.MongoDb/MongoDbModule.cs index e50b00757..b61b8c9bd 100644 --- a/src/PinkParrot.Store.MongoDb/MongoDbModule.cs +++ b/src/PinkParrot.Store.MongoDb/MongoDbModule.cs @@ -11,6 +11,7 @@ using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity.MongoDB; using Microsoft.Extensions.Options; using MongoDB.Driver; +using PinkParrot.Infrastructure.CQRS.Events; using PinkParrot.Infrastructure.CQRS.EventStore; using PinkParrot.Read.Apps.Repositories; using PinkParrot.Read.Schemas.Repositories; @@ -59,10 +60,12 @@ namespace PinkParrot.Store.MongoDb builder.RegisterType() .As() + .As() .SingleInstance(); builder.RegisterType() .As() + .As() .SingleInstance(); } } diff --git a/src/PinkParrot.Store.MongoDb/Schemas/MongoSchemaRepository.cs b/src/PinkParrot.Store.MongoDb/Schemas/MongoSchemaRepository.cs index 1fa031ecc..c834d6ca0 100644 --- a/src/PinkParrot.Store.MongoDb/Schemas/MongoSchemaRepository.cs +++ b/src/PinkParrot.Store.MongoDb/Schemas/MongoSchemaRepository.cs @@ -132,7 +132,7 @@ namespace PinkParrot.Store.MongoDb.Schemas public Task On(SchemaCreated @event, EnvelopeHeaders headers) { - return Collection.CreateAsync(headers, s => SimpleMapper.Map(s, @event)); + return Collection.CreateAsync(headers, s => SimpleMapper.Map(@event, s)); } public Task On(Envelope @event) diff --git a/src/PinkParrot.Store.MongoDb/Utils/EntityMapper.cs b/src/PinkParrot.Store.MongoDb/Utils/EntityMapper.cs index 0d8563293..b8d7332d8 100644 --- a/src/PinkParrot.Store.MongoDb/Utils/EntityMapper.cs +++ b/src/PinkParrot.Store.MongoDb/Utils/EntityMapper.cs @@ -63,7 +63,7 @@ namespace PinkParrot.Store.MongoDb.Utils updater(entity); - return collection.InsertOneIfExistsAsync(entity); + return collection.InsertOneIfNotExistsAsync(entity); } public static async Task UpdateAsync(this IMongoCollection collection, EnvelopeHeaders headers, Action updater) where T : class, IEntity diff --git a/src/PinkParrot.Store.MongoDb/Utils/MongoExtensions.cs b/src/PinkParrot.Store.MongoDb/Utils/MongoExtensions.cs index c86764058..8d07d0fd7 100644 --- a/src/PinkParrot.Store.MongoDb/Utils/MongoExtensions.cs +++ b/src/PinkParrot.Store.MongoDb/Utils/MongoExtensions.cs @@ -13,7 +13,7 @@ namespace PinkParrot.Store.MongoDb.Utils { public static class MongoExtensions { - public static async Task InsertOneIfExistsAsync(this IMongoCollection collection, T document) + public static async Task InsertOneIfNotExistsAsync(this IMongoCollection collection, T document) { try { diff --git a/src/PinkParrot.Write/Apps/AppCommandHandler.cs b/src/PinkParrot.Write/Apps/AppCommandHandler.cs index bbeae2761..430044d1b 100644 --- a/src/PinkParrot.Write/Apps/AppCommandHandler.cs +++ b/src/PinkParrot.Write/Apps/AppCommandHandler.cs @@ -7,24 +7,39 @@ // ========================================================================== using System.Threading.Tasks; +using PinkParrot.Infrastructure; using PinkParrot.Infrastructure.CQRS.Commands; using PinkParrot.Infrastructure.Dispatching; +using PinkParrot.Read.Apps.Repositories; using PinkParrot.Write.Apps.Commands; namespace PinkParrot.Write.Apps { public class AppCommandHandler : CommandHandler { + private readonly IAppRepository appRepository; + public AppCommandHandler( IDomainObjectFactory domainObjectFactory, - IDomainObjectRepository domainObjectRepository) + IDomainObjectRepository domainObjectRepository, + IAppRepository appRepository) : base(domainObjectFactory, domainObjectRepository) { + Guard.NotNull(appRepository, nameof(appRepository)); + + this.appRepository = appRepository; } - public Task On(CreateApp command) + public async Task On(CreateApp command) { - return CreateAsync(command, x => x.Create(command)); + if (await appRepository.FindAppByNameAsync(command.Name) != null) + { + var error = new ValidationError($"A app with name '{command.Name}' already exists", "Name"); + + throw new ValidationException("Cannot create a new app", error); + } + + await CreateAsync(command, x => x.Create(command)); } public override Task HandleAsync(CommandContext context) diff --git a/src/PinkParrot/Configurations/EventStoreModule.cs b/src/PinkParrot/Configurations/EventStoreModule.cs index 1dd331540..871008e55 100644 --- a/src/PinkParrot/Configurations/EventStoreModule.cs +++ b/src/PinkParrot/Configurations/EventStoreModule.cs @@ -50,6 +50,10 @@ namespace PinkParrot.Configurations return new DefaultNameResolver(options.Prefix); }).SingleInstance(); + + builder.Register(c => new DefaultNameResolver("pinkparrot")) + .As() + .SingleInstance(); } } } diff --git a/src/PinkParrot/Configurations/ReadModule.cs b/src/PinkParrot/Configurations/ReadModule.cs index 855ad8932..8367128f5 100644 --- a/src/PinkParrot/Configurations/ReadModule.cs +++ b/src/PinkParrot/Configurations/ReadModule.cs @@ -10,10 +10,8 @@ using Autofac; using PinkParrot.Infrastructure.CQRS.Events; using PinkParrot.Read.Apps.Services; using PinkParrot.Read.Apps.Services.Implementations; -using PinkParrot.Read.Schemas.Repositories; using PinkParrot.Read.Schemas.Services; using PinkParrot.Read.Schemas.Services.Implementations; -using PinkParrot.Store.MongoDb.Schemas; namespace PinkParrot.Configurations { @@ -29,11 +27,6 @@ namespace PinkParrot.Configurations .As() .As() .SingleInstance(); - - builder.RegisterType() - .As() - .As() - .SingleInstance(); } } } diff --git a/src/PinkParrot/Configurations/WebpackUsage.cs b/src/PinkParrot/Configurations/WebpackUsage.cs new file mode 100644 index 000000000..eb71dd50b --- /dev/null +++ b/src/PinkParrot/Configurations/WebpackUsage.cs @@ -0,0 +1,33 @@ +// ========================================================================== +// WebpackUsage.cs +// PinkParrot Headless CMS +// ========================================================================== +// Copyright (c) PinkParrot Group +// All rights reserved. +// ========================================================================== + +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using PinkParrot.Pipeline; + +namespace PinkParrot.Configurations +{ + public static class WebpackExtensions + { + public static IServiceCollection AddWebpack(this IServiceCollection services) + { + services.AddSingleton(); + + return services; + } + + public static IApplicationBuilder UseWebpack(this IApplicationBuilder app) + { + app.ApplicationServices.GetService().Execute(); + + app.UseMiddleware(); + + return app; + } + } +} diff --git a/src/PinkParrot/Modules/Api/Apps/AppController.cs b/src/PinkParrot/Modules/Api/Apps/AppController.cs index 8b7ac5801..43b46b1a4 100644 --- a/src/PinkParrot/Modules/Api/Apps/AppController.cs +++ b/src/PinkParrot/Modules/Api/Apps/AppController.cs @@ -1,31 +1,54 @@ -using System; +// ========================================================================== +// AppController.cs +// PinkParrot Headless CMS +// ========================================================================== +// Copyright (c) PinkParrot Group +// All rights reserved. +// ========================================================================== + +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; +using PinkParrot.Infrastructure.CQRS.Commands; using PinkParrot.Infrastructure.Reflection; using PinkParrot.Modules.Api.Apps.Models; -using PinkParrot.Modules.Api.Schemas.Models; +using PinkParrot.Pipeline; using PinkParrot.Read.Apps.Repositories; +using PinkParrot.Write.Apps.Commands; namespace PinkParrot.Modules.Api.Apps { - public class AppController + [DeactivateForAppDomain] + public class AppController : ControllerBase { private readonly IAppRepository appRepository; - public AppController(IAppRepository appRepository) + public AppController(ICommandBus commandBus, IAppRepository appRepository) + : base(commandBus) { this.appRepository = appRepository; } [HttpGet] - [Route("api/schemas/")] + [Route("api/apps/")] public async Task> Query() { var schemas = await appRepository.QueryAllAsync(); return schemas.Select(s => SimpleMapper.Map(s, new ListAppDto())).ToList(); } + + [HttpPost] + [Route("api/apps/")] + public async Task Create([FromBody] CreateAppDto model) + { + var command = SimpleMapper.Map(model, new CreateApp { AggregateId = Guid.NewGuid() }); + + await CommandBus.PublishAsync(command); + + return CreatedAtAction("Query", new EntityCreatedDto { Id = command.AggregateId }); + } } } diff --git a/src/PinkParrot/Modules/Api/Apps/Models/CreateAppDto.cs b/src/PinkParrot/Modules/Api/Apps/Models/CreateAppDto.cs new file mode 100644 index 000000000..20ab6b35e --- /dev/null +++ b/src/PinkParrot/Modules/Api/Apps/Models/CreateAppDto.cs @@ -0,0 +1,15 @@ +// ========================================================================== +// CreateAppDto.cs +// PinkParrot Headless CMS +// ========================================================================== +// Copyright (c) PinkParrot Group +// All rights reserved. +// ========================================================================== + +namespace PinkParrot.Modules.Api.Apps.Models +{ + public sealed class CreateAppDto + { + public string Name { get; set; } + } +} diff --git a/src/PinkParrot/Modules/Api/EntityCreatedDto.cs b/src/PinkParrot/Modules/Api/EntityCreatedDto.cs index 98f714bff..362ce3c72 100644 --- a/src/PinkParrot/Modules/Api/EntityCreatedDto.cs +++ b/src/PinkParrot/Modules/Api/EntityCreatedDto.cs @@ -6,14 +6,10 @@ // All rights reserved. // ========================================================================== -using System; -using System.ComponentModel.DataAnnotations; - namespace PinkParrot.Modules.Api { public class EntityCreatedDto { - [Required] - public Guid Id { get; set; } + public object Id { get; set; } } } diff --git a/src/PinkParrot/Modules/Api/Schemas/Models/CreateFieldDto.cs b/src/PinkParrot/Modules/Api/Schemas/Models/CreateFieldDto.cs index ef9edd138..eec331354 100644 --- a/src/PinkParrot/Modules/Api/Schemas/Models/CreateFieldDto.cs +++ b/src/PinkParrot/Modules/Api/Schemas/Models/CreateFieldDto.cs @@ -6,7 +6,6 @@ // All rights reserved. // ========================================================================== -using System.ComponentModel.DataAnnotations; using Newtonsoft.Json; using Newtonsoft.Json.Linq; diff --git a/src/PinkParrot/Modules/Api/Schemas/SchemasController.cs b/src/PinkParrot/Modules/Api/Schemas/SchemasController.cs index d182c7570..f2b6d2159 100644 --- a/src/PinkParrot/Modules/Api/Schemas/SchemasController.cs +++ b/src/PinkParrot/Modules/Api/Schemas/SchemasController.cs @@ -11,7 +11,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; -using PinkParrot.Core.Schemas; using PinkParrot.Infrastructure.CQRS.Commands; using PinkParrot.Infrastructure.Reflection; using PinkParrot.Modules.Api.Schemas.Models; @@ -64,7 +63,7 @@ namespace PinkParrot.Modules.Api.Schemas await CommandBus.PublishAsync(command); - return CreatedAtAction("Query", new EntityCreatedDto { Id = command.AggregateId }); + return CreatedAtAction("Get", new { name = model.Name }, new EntityCreatedDto { Id = command.Name }); } [HttpPut] diff --git a/src/PinkParrot/PinkParrot.xproj b/src/PinkParrot/PinkParrot.xproj index f525b6954..8c6f5ccaf 100644 --- a/src/PinkParrot/PinkParrot.xproj +++ b/src/PinkParrot/PinkParrot.xproj @@ -4,7 +4,6 @@ 14.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - 61f6bbce-a080-4400-b194-70e2f5d2096e @@ -13,10 +12,12 @@ .\bin\ v4.5.2 - 2.0 + + True + diff --git a/src/PinkParrot/Pipeline/DeactivateForAppDomainAttribute.cs b/src/PinkParrot/Pipeline/DeactivateForAppDomainAttribute.cs new file mode 100644 index 000000000..af468a7a8 --- /dev/null +++ b/src/PinkParrot/Pipeline/DeactivateForAppDomainAttribute.cs @@ -0,0 +1,26 @@ +// ========================================================================== +// DeactivateForAppDomainAttribute.cs +// PinkParrot Headless CMS +// ========================================================================== +// Copyright (c) PinkParrot Group +// All rights reserved. +// ========================================================================== + +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; + +namespace PinkParrot.Pipeline +{ + public sealed class DeactivateForAppDomainAttribute : ActionFilterAttribute + { + public override void OnActionExecuting(ActionExecutingContext context) + { + var app = context.HttpContext.Features.Get(); + + if (app != null) + { + context.Result = new NotFoundResult(); + } + } + } +} diff --git a/src/PinkParrot/Pipeline/WebpackMiddleware.cs b/src/PinkParrot/Pipeline/WebpackMiddleware.cs new file mode 100644 index 000000000..fd444d854 --- /dev/null +++ b/src/PinkParrot/Pipeline/WebpackMiddleware.cs @@ -0,0 +1,129 @@ +// ========================================================================== +// WebpackMiddleware.cs +// PinkParrot Headless CMS +// ========================================================================== +// Copyright (c) PinkParrot Group +// All rights reserved. +// ========================================================================== + +using System.IO; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; + +// ReSharper disable LoopCanBeConvertedToQuery + +namespace PinkParrot.Pipeline +{ + public sealed class WebpackMiddleware + { + private const string Host = "localhost"; + private const string Port = "3000"; + private static readonly string[] Scripts = { "polyfills.js", "vendor.js", "app.js" }; + private static readonly string[] Styles = { "vendor.css" }; + private readonly RequestDelegate next; + private readonly ILogger logger; + + public WebpackMiddleware(RequestDelegate next, ILoggerFactory loggerFactory) + { + logger = loggerFactory.CreateLogger(); + + this.next = next; + } + + public async Task Invoke(HttpContext context) + { + var buffer = new MemoryStream(); + var body = context.Response.Body; + + context.Response.Body = buffer; + + await next(context); + + buffer.Seek(0, SeekOrigin.Begin); + + if (context.Response.StatusCode == 200 && IsHtml(context)) + { + using (var reader = new StreamReader(buffer)) + { + var response = await reader.ReadToEndAsync(); + + response = InjectStyles(response); + response = InjectScripts(response); + + using (var memoryStream = new MemoryStream()) + { + using (var writer = new StreamWriter(memoryStream)) + { + writer.Write(response); + writer.Flush(); + + memoryStream.Seek(0, SeekOrigin.Begin); + + context.Response.Headers["Content-Length"] = memoryStream.Length.ToString(); + + await memoryStream.CopyToAsync(body); + } + } + } + } + else + { + await buffer.CopyToAsync(body); + } + + context.Response.Body = body; + } + + private string InjectStyles(string response) + { + if (!response.Contains("")) + { + return response; + } + + logger.LogInformation("A full html page is returned so the necessary styles for webpack will be injected"); + + var stylesTag = string.Empty; + + foreach (var file in Styles) + { + stylesTag += $""; + } + + response = response.Replace("", $"{stylesTag}"); + + logger.LogInformation($"Inject style {stylesTag} as a last element in the head "); + + return response; + } + + private string InjectScripts(string response) + { + if (!response.Contains("")) + { + return response; + } + + logger.LogInformation("A full html page is returned so the necessary script for webpack will be injected"); + + var scriptsTag = string.Empty; + + foreach (var file in Scripts) + { + scriptsTag += $""; + } + + response = response.Replace("", $"{scriptsTag}"); + + logger.LogInformation($"Inject script {scriptsTag} as a last element in the body "); + + return response; + } + + private static bool IsHtml(HttpContext context) + { + return context.Response.ContentType?.ToLower().Contains("text/html") == true; + } + } +} diff --git a/src/PinkParrot/Pipeline/WebpackRunner.cs b/src/PinkParrot/Pipeline/WebpackRunner.cs new file mode 100644 index 000000000..9213adcc1 --- /dev/null +++ b/src/PinkParrot/Pipeline/WebpackRunner.cs @@ -0,0 +1,93 @@ +// ========================================================================== +// WebpackRunner.cs +// PinkParrot Headless CMS +// ========================================================================== +// Copyright (c) PinkParrot Group +// All rights reserved. +// ========================================================================== + +using System; +using System.Diagnostics; +using System.IO; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Logging; + +// ReSharper disable ConvertToConstant.Local + +namespace PinkParrot.Pipeline +{ + public sealed class WebpackRunner + { + private const string WebpackDevServer = "webpack-dev-server"; + + private readonly ILoggerFactory loggerFactory; + private readonly IApplicationLifetime lifetime; + private Process process; + + public WebpackRunner(ILoggerFactory loggerFactory, IApplicationLifetime lifetime) + { + this.loggerFactory = loggerFactory; + + this.lifetime = lifetime; + } + + public void Execute() + { + if (process != null) + { + return; + } + + var logger = loggerFactory.CreateLogger(WebpackDevServer); + + EnsuereNodeModluesInstalled(logger); + + logger.LogInformation($"{WebpackDevServer} Execution started"); + + var app = GetNodeExecutable(WebpackDevServer); + var args = "--inline --hot --port 3000"; + + process = Process.Start(new ProcessStartInfo + { + FileName = app, Arguments = args, UseShellExecute = false + }); + + lifetime.ApplicationStopping.Register(OnShutdown); + + logger.LogInformation($"{WebpackDevServer} started successfully"); + } + + private void OnShutdown() + { + process?.Kill(); + process = null; + } + + private static void EnsuereNodeModluesInstalled(ILogger logger) + { + logger.LogInformation("Verifying required tools are installed"); + + if (!File.Exists(GetNodeExecutable(WebpackDevServer))) + { + logger.LogError("webpack-dev-server is not installed. Please install it by executing npm i webpack-dev-server"); + } + + logger.LogInformation("All node modules are properly installed"); + } + + private static string GetNodeExecutable(string module) + { + var executablePath = Path.Combine(Directory.GetCurrentDirectory(), "node_modules", ".bin", module); + + var osEnVariable = Environment.GetEnvironmentVariable("OS"); + + if (!string.IsNullOrEmpty(osEnVariable) && + string.Equals(osEnVariable, "Windows_NT", StringComparison.OrdinalIgnoreCase)) + { + executablePath += ".cmd"; + } + + return executablePath; + } + } +} diff --git a/src/PinkParrot/Properties/launchSettings.json b/src/PinkParrot/Properties/launchSettings.json index a19c657ab..418339fa8 100644 --- a/src/PinkParrot/Properties/launchSettings.json +++ b/src/PinkParrot/Properties/launchSettings.json @@ -3,7 +3,7 @@ "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { - "applicationUrl": "http://localhost:65351/", + "applicationUrl": "http://localhost:5000/", "sslPort": 0 } }, diff --git a/src/PinkParrot/Startup.cs b/src/PinkParrot/Startup.cs index fa767f3ae..48e80edd7 100644 --- a/src/PinkParrot/Startup.cs +++ b/src/PinkParrot/Startup.cs @@ -7,6 +7,7 @@ // ========================================================================== using System; +using System.Collections.Generic; using Autofac; using Autofac.Extensions.DependencyInjection; using Microsoft.AspNetCore.Builder; @@ -39,20 +40,24 @@ namespace PinkParrot public IServiceProvider ConfigureServices(IServiceCollection services) { - services.AddMvc().AddAppSerializers(); - services.AddRouting(); - services.AddMemoryCache(); - services.AddOptions(); services.AddEventFormatter(); services.AddIdentity().AddDefaultTokenProviders(); + services.AddLogging(); + services.AddMemoryCache(); + services.AddMvc().AddAppSerializers(); + services.AddOptions(); + services.AddRouting(); + services.AddWebpack(); - services.Configure( - Configuration.GetSection("MongoDb")); + services.Configure( + Configuration.GetSection("stores:mongoDb")); services.Configure( - Configuration.GetSection("EventStore")); + Configuration.GetSection("stores:eventStore")); var builder = new ContainerBuilder(); builder.RegisterModule(); + builder.RegisterModule(); + builder.RegisterModule(); builder.RegisterModule(); builder.RegisterModule(); builder.Populate(services); @@ -63,10 +68,17 @@ namespace PinkParrot public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { loggerFactory.AddConsole(); + loggerFactory.AddDebug(); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); + app.UseWebpack(); + app.UseDefaultFiles(); + } + else + { + app.UseDefaultFiles(new DefaultFilesOptions { DefaultFileNames = new List { "build/index.html" } }); } app.UseApps(); diff --git a/src/PinkParrot/app-config/auto-loader.js b/src/PinkParrot/app-config/auto-loader.js new file mode 100644 index 000000000..0e00c23b2 --- /dev/null +++ b/src/PinkParrot/app-config/auto-loader.js @@ -0,0 +1,67 @@ +'use strict'; + + var path = require('path'), + fs = require('fs'), +loaderUtils = require('loader-utils'), + SourceMap = require('source-map'); + +function capitalize(str) { + return str.charAt(0).toUpperCase() + str.slice(1); +}; + +function applyPlaceholders(str, dirname, filename) { + if (!str.length) { + return str; + } + + return str + .split('[file]').join(filename) + .split('[File]').join(capitalize(filename)); +}; + +function loadBaggage(source, sourcemap) { + var query = loaderUtils.parseQuery(this.query); + + var srcFilepath = this.resourcePath; + var srcFilename = path.basename(srcFilepath, path.extname(srcFilepath)); + var srcDirpath = path.dirname(srcFilepath); + var srcDirname = srcDirpath.split(path.sep).pop(); + + this.cacheable(); + + if (Object.keys(query).length) { + var inject = '\n/* injects from baggage-loader */\n'; + + Object.keys(query).forEach(function (baggageFile) { + var baggageVar = query[baggageFile]; + + if (typeof baggageVar === 'string' || baggageVar === true) { + baggageFile = applyPlaceholders(baggageFile, srcDirname, srcFilename); + + try { + var stats = fs.statSync(path.resolve(srcDirpath, baggageFile)); + + if (stats.isFile()) { + if (baggageVar.length) { + inject += 'const ' + baggageVar + ' = '; + } + + if (baggageVar === 'styles') { + inject += '[require(\'./' + baggageFile + '\')];\n'; + } else { + inject += 'require(\'./' + baggageFile + '\');\n'; + } + } + } catch (e) { } + } + }); + + inject += '\n'; + + return inject + source; + } + + return source; +}; + +module.exports = loadBaggage; \ No newline at end of file diff --git a/src/PinkParrot/app-config/fix-coverage-loader.js b/src/PinkParrot/app-config/fix-coverage-loader.js new file mode 100644 index 000000000..d5e5f2ff9 --- /dev/null +++ b/src/PinkParrot/app-config/fix-coverage-loader.js @@ -0,0 +1,47 @@ +function fixCoverage(contents) { + this.cacheable(); + + var ignores = [ + { name: 'arguments', line: 'var _a' }, + { name: 'decorate', line: 'var __decorate =', }, + { name: 'metadata', line: 'var __metadata =', }, + { name: 'extends', line: 'var __extends =', }, + { name: 'export', line: 'function __export' } + ]; + + var updates = 0; + var rows = contents.split('\n'); + + for (var rowIndex = 0; rowIndex < rows.length; rowIndex++) { + var row = rows[rowIndex].trim(); + + for (var ignoreIndex = 0; ignoreIndex < ignores.length; ignoreIndex++) { + var ignore = ignores[ignoreIndex]; + + if (row.indexOf(ignore.line) >= 0) { + rows.splice(rowIndex, 0, '/* istanbul ignore next: TypeScript ' + ignore.name + ' */'); + rowIndex++; + updates++; + break; + } + } + + if (row.indexOf('hasOwnProperty') >= 0) { + rows.splice(rowIndex, 0, '/* istanbul ignore else */'); + rowIndex++; + updates++; + } + + if (updates === ignores.length) { + break; + } + } + + if (updates > 0) { + return rows.join('\n'); + } else { + return contents; + } +} + +module.exports = fixCoverage; \ No newline at end of file diff --git a/src/PinkParrot/app-config/helpers.js b/src/PinkParrot/app-config/helpers.js new file mode 100644 index 000000000..18af40621 --- /dev/null +++ b/src/PinkParrot/app-config/helpers.js @@ -0,0 +1,13 @@ +// ReSharper disable InconsistentNaming +// ReSharper disable PossiblyUnassignedProperty +// ReSharper disable InconsistentNaming + +var path = require('path'); + +var appRoot = path.resolve(__dirname, '..'); + +exports.root = function () { + var newArgs = Array.prototype.slice.call(arguments, 0); + + return path.join.apply(path, [appRoot].concat(newArgs)); +}; \ No newline at end of file diff --git a/src/PinkParrot/app-config/karma-test-shim.js b/src/PinkParrot/app-config/karma-test-shim.js new file mode 100644 index 000000000..13e285d15 --- /dev/null +++ b/src/PinkParrot/app-config/karma-test-shim.js @@ -0,0 +1,36 @@ +Error.stackTraceLimit = Infinity; + +require('core-js/es6'); +require('core-js/es7/reflect'); + +require('zone.js/dist/zone'); +require('zone.js/dist/long-stack-trace-zone'); +require('zone.js/dist/proxy'); +require('zone.js/dist/sync-test'); +require('zone.js/dist/jasmine-patch'); +require('zone.js/dist/async-test'); +require('zone.js/dist/fake-async-test'); + +require('rxjs/Rx'); + +var testing = require('@angular/core/testing'); +var browser = require('@angular/platform-browser-dynamic/testing'); + +testing.TestBed.initTestEnvironment( + browser.BrowserDynamicTestingModule, + browser.platformBrowserDynamicTesting() +); + +var testContext = require.context('../app', true, /\.spec\.ts/); + +/* + * get all the files, for each file, call the context function + * that will require the file and load it up here. Context will + * loop and require those spec files here + */ +function requireAll(requireContext) { + return requireContext.keys().map(requireContext); +} + +// requires and returns all modules that match +var modules = requireAll(testContext); \ No newline at end of file diff --git a/src/PinkParrot/app-config/karma.conf.js b/src/PinkParrot/app-config/karma.conf.js new file mode 100644 index 000000000..e13359e66 --- /dev/null +++ b/src/PinkParrot/app-config/karma.conf.js @@ -0,0 +1,52 @@ +var webpackConfig = require('./webpack.test'); + +module.exports = function (config) { + var _config = { + /** + * Base path that will be used to resolve all patterns (e.g. files, exclude) + */ + basePath: '', + + frameworks: ['jasmine'], + + /** + * Load additional test shim to setup angular2 for testing + */ + files: [ + { pattern: './app-config/karma-test-shim.js', watched: false } + ], + + preprocessors: { + './app-config/karma-test-shim.js': ['webpack', 'sourcemap'], + }, + + /** + * Load the files with webpack and use test configuration for it. + */ + webpack: webpackConfig, + + webpackMiddleware: { + stats: 'errors-only' + }, + + webpackServer: { + noInfo: true + }, + + + /* + * Use a mocha style console reporter, html reporter and the code coverage reporter + */ + reporters: ['mocha'], + + + /** + * Run with chrome to enable debugging + * + * available browser launchers: https://npmjs.org/browse/keyword/karma-launcher + */ + browsers: ['Chrome'] + }; + + config.set(_config); +}; \ No newline at end of file diff --git a/src/PinkParrot/app-config/karma.coverage.conf.js b/src/PinkParrot/app-config/karma.coverage.conf.js new file mode 100644 index 000000000..e7e2c7802 --- /dev/null +++ b/src/PinkParrot/app-config/karma.coverage.conf.js @@ -0,0 +1,77 @@ +var webpackConfig = require('./webpack.coverage'); + +module.exports = function (config) { + var _config = { + /** + * Base path that will be used to resolve all patterns (e.g. files, exclude) + */ + basePath: '', + + frameworks: ['jasmine'], + + /** + * Load additional test shim to setup angular2 for testing + */ + files: [ + { pattern: './app-config/karma-test-shim.js', watched: false } + ], + + preprocessors: { + './config/karma-test-shim.js': ['webpack', 'sourcemap'], + }, + + /** + * Load the files with webpack and use test configuration for it. + */ + webpack: webpackConfig, + + webpackMiddleware: { + stats: 'errors-only' + }, + + webpackServer: { + noInfo: true + }, + + /* + * Use a mocha style console reporter, html reporter and the code coverage reporter + */ + reporters: ['mocha', 'html', 'coverage'], + + // HtmlReporter configuration + htmlReporter: { + useCompactStyle: true, + /** + * Use the same folder like the html report for coverage reports + */ + outputFile: '_test-output/tests.html', + + /** + * Group the output by test suite (describe), equivalent to mocha reporter + */ + groupSuites: true + }, + + coverageReporter: { + type: 'html', + /** + * Use the same folder like the html report for coverage reports + */ + dir: '_test-output/coverage' + }, + + /** + * Disable continuous Integration mode, run only one time + */ + singleRun: true, + + /** + * Run with chrome because phantom js does not provide all types, e.g. DragEvent + * + * available browser launchers: https://npmjs.org/browse/keyword/karma-launcher + */ + browsers: ['PhantomJS'] + }; + + config.set(_config); +}; \ No newline at end of file diff --git a/src/PinkParrot/app-config/webpack.common.js b/src/PinkParrot/app-config/webpack.common.js new file mode 100644 index 000000000..61cea21b1 --- /dev/null +++ b/src/PinkParrot/app-config/webpack.common.js @@ -0,0 +1,117 @@ +// ReSharper disable InconsistentNaming +// ReSharper disable PossiblyUnassignedProperty + + var webpack = require('webpack'), + path = require('path'), + HtmlWebpackPlugin = require('html-webpack-plugin'), + ExtractTextPlugin = require('extract-text-webpack-plugin'), + helpers = require('./helpers'); + +module.exports = { + /** + * The entry point for the bundle + * Our Angular.js app + * + * See: http://webpack.github.io/docs/configuration.html#entry + */ + entry: { + 'polyfills': './app/polyfills.ts', + 'vendor': './app/vendor.ts', + 'app': './app/main.ts' + }, + + /** + * Options affecting the resolving of modules. + * + * See: http://webpack.github.io/docs/configuration.html#resolve + */ + resolve: { + /** + * An array of extensions that should be used to resolve modules. + * + * See: http://webpack.github.io/docs/configuration.html#resolve-extensions + */ + extensions: ['', '.js', '.ts', '.css', '.scss'], + root: [ + helpers.root('app'), + helpers.root('app-libs') + ] + }, + + /* + * Options affecting the normal modules. + * + * See: http://webpack.github.io/docs/configuration.html#module + */ + module: { + preLoaders: [{ + test: /\.ts/, + loader: helpers.root('app-config', 'auto-loader') + '?[file].html=template&[file].scss=styles', + }], + + /** + * An array of automatically applied loaders. + * + * IMPORTANT: The loaders here are resolved relative to the resource which they are applied to. + * This means they are not resolved relative to the configuration file. + * + * See: http://webpack.github.io/docs/configuration.html#module-loaders + */ + loaders: [ + { + test: /\.ts$/, + loader: 'awesome-typescript-loader' + }, { + test: /\.html$/, + loader: 'html' + }, { + test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)(\?.*$|$)/, + loader: 'file?name=assets/[name].[hash].[ext]' + }, { + test: /\.css$/, + loader: ExtractTextPlugin.extract('style', 'css?sourceMap') + }, { + test: /\.scss$/, + exclude: helpers.root('app', 'theme'), + loaders: ['raw', 'sass'] + } + ] + }, + + plugins: [ + /** + * Plugin: CommonsChunkPlugin + * Description: Shares common code between the pages. + * It identifies common modules and put them into a commons chunk. + * + * See: https://webpack.github.io/docs/list-of-plugins.html#commonschunkplugin + */ + new webpack.optimize.CommonsChunkPlugin({ + name: ['app', 'vendor', 'polyfills'] + }), + + /** + * Plugin: HtmlWebpackPlugin + * Description: Simplifies creation of HTML files to serve your webpack bundles. + * This is especially useful for webpack bundles that include a hash in the filename + * which changes every compilation. + * + * See: https://github.com/ampedandwired/html-webpack-plugin + */ + new HtmlWebpackPlugin({ + template: 'wwwroot/index.html' + }), + + new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /en/), + + /** + * Shim additional libraries + * + * See: https://webpack.github.io/docs/shimming-modules.html + */ + new webpack.ProvidePlugin({ + // Mouse trap handles shortcut management + 'Mousetrap': 'mousetrap/mousetrap' + }) + ] +}; \ No newline at end of file diff --git a/src/PinkParrot/app-config/webpack.coverage.js b/src/PinkParrot/app-config/webpack.coverage.js new file mode 100644 index 000000000..5e4ca1056 --- /dev/null +++ b/src/PinkParrot/app-config/webpack.coverage.js @@ -0,0 +1,23 @@ + +var webpackMerge = require('webpack-merge'), + path = require('path'), + helpers = require('./helpers'), + testConfig = require('./webpack.test.js'); + +module.exports = webpackMerge(testConfig, { + module: { + postLoaders: [ + { + test: /\.(js|ts)$/, + include: helpers.root('app'), + exclude: [/\.(e2e|spec)\.ts$/], + loader: 'istanbul-instrumenter-loader' + }, { + test: /\.(js|ts)$/, + include: helpers.root('app'), + exclude: [/\.(e2e|spec)\.ts$/], + loader: helpers.root('app-config', 'fix-coverage-loader') + } + ] + } +}); \ No newline at end of file diff --git a/src/PinkParrot/app-config/webpack.dev.js b/src/PinkParrot/app-config/webpack.dev.js new file mode 100644 index 000000000..a856cd797 --- /dev/null +++ b/src/PinkParrot/app-config/webpack.dev.js @@ -0,0 +1,67 @@ +// ReSharper disable InconsistentNaming +// ReSharper disable PossiblyUnassignedProperty + + var webpackMerge = require('webpack-merge'), + ExtractTextPlugin = require('extract-text-webpack-plugin'), + commonConfig = require('./webpack.common.js'), + helpers = require('./helpers'); + +module.exports = webpackMerge(commonConfig, { + /** + * Developer tool to enhance debugging + * + * See: http://webpack.github.io/docs/configuration.html#devtool + * See: https://github.com/webpack/docs/wiki/build-performance#sourcemaps + */ + devtool: 'cheap-module-eval-source-map', + + output: { + filename: '[name].js', + // Set the public path, because we are running the website from another port (5000) + publicPath: 'http://localhost:3000/' + }, + + /* + * Options affecting the normal modules. + * + * See: http://webpack.github.io/docs/configuration.html#module + */ + module: { + /** + * An array of automatically applied loaders. + * + * IMPORTANT: The loaders here are resolved relative to the resource which they are applied to. + * This means they are not resolved relative to the configuration file. + * + * See: http://webpack.github.io/docs/configuration.html#module-loaders + */ + loaders: [ + { + test: /\.scss$/, + include: helpers.root('app', 'theme'), + loaders: ['style', 'css', 'sass?sourceMap'] + } + ] + }, + + plugins: [ + new ExtractTextPlugin('[name].css') + ], + + tslint: { + /** + * Run tslint in production build, but do not fail if there is a warning. + * + * See: https://github.com/wbuchwalter/tslint-loader + */ + failOnHint: false, + /** + * Share the configuration file with the IDE + */ + configuration: require('./../tslint.json') + }, + + devServer: { + historyApiFallback: true, stats: 'minimal' + } +}); \ No newline at end of file diff --git a/src/PinkParrot/app-config/webpack.prod.js b/src/PinkParrot/app-config/webpack.prod.js new file mode 100644 index 000000000..88cb7a539 --- /dev/null +++ b/src/PinkParrot/app-config/webpack.prod.js @@ -0,0 +1,106 @@ + var webpack = require('webpack'), + webpackMerge = require('webpack-merge'), +ExtractTextPlugin = require('extract-text-webpack-plugin'), + commonConfig = require('./webpack.common.js'), + helpers = require('./helpers'); + +const ENV = process.env.NODE_ENV = process.env.ENV = 'production'; + +module.exports = webpackMerge(commonConfig, { + devtool: 'source-map', + + output: { + /** + * The output directory as absolute path (required). + * + * See: http://webpack.github.io/docs/configuration.html#output-path + */ + path: helpers.root('wwwroot/build/'), + + publicPath: '/build/', + + /** + * Specifies the name of each output file on disk. + * IMPORTANT: You must not specify an absolute path here! + * + * See: http://webpack.github.io/docs/configuration.html#output-filename + */ + filename: '[name].[hash].js', + + /** + * The filename of non-entry chunks as relative path + * inside the output.path directory. + * + * See: http://webpack.github.io/docs/configuration.html#output-chunkfilename + */ + chunkFilename: '[id].[hash].chunk.js' + }, + + /* + * Options affecting the normal modules. + * + * See: http://webpack.github.io/docs/configuration.html#module + */ + module: { + preLoaders: [{ + test: /\.ts$/, + loader: "tslint" + }], + + /** + * An array of automatically applied loaders. + * + * IMPORTANT: The loaders here are resolved relative to the resource which they are applied to. + * This means they are not resolved relative to the configuration file. + * + * See: http://webpack.github.io/docs/configuration.html#module-loaders + */ + loaders: [ + { + test: /\.scss$/, + include: helpers.root('app', 'theme'), + loader: ExtractTextPlugin.extract('style', 'css!sass?sourceMap') + } + ] + }, + + tslint: { + /** + * Run tslint in production build and fail if there is one warning. + * + * See: https://github.com/wbuchwalter/tslint-loader + */ + failOnHint: true, + /** + * Share the configuration file with the IDE + */ + configuration: require('./../tslint.json') + }, + + /** + * Html loader advanced options + * + * See: https://github.com/webpack/html-loader#advanced-options + */ + htmlLoader: { + minimize: false + }, + + plugins: [ + new webpack.NoErrorsPlugin(), + new webpack.optimize.DedupePlugin(), + new webpack.optimize.UglifyJsPlugin({ mangle: { screw_ie8: true, keep_fnames: true } }), + new webpack.DefinePlugin({ 'process.env': { 'ENV': JSON.stringify(ENV) } }), + new ExtractTextPlugin('[name].[hash].css'), + + function () { + this.plugin("done", function (stats) { + if (stats.compilation.errors && stats.compilation.errors.length && process.argv.indexOf('--watch') == -1) { + console.log(stats.compilation.errors); + + throw new Error('webpack build failed.'); + } + }); + } + ] +}); \ No newline at end of file diff --git a/src/PinkParrot/app-config/webpack.test.js b/src/PinkParrot/app-config/webpack.test.js new file mode 100644 index 000000000..97c35bdbe --- /dev/null +++ b/src/PinkParrot/app-config/webpack.test.js @@ -0,0 +1,77 @@ +var webpack = require('webpack'), + helpers = require('./helpers'); + +module.exports = { + /** + * Source map for Karma from the help of karma-sourcemap-loader & karma-webpack + * + * Do not change, leave as is or it wont work. + * See: https://github.com/webpack/karma-webpack#source-maps + */ + devtool: 'inline-source-map', + + resolve: { + /** + * An array of extensions that should be used to resolve modules. + * + * See: http://webpack.github.io/docs/configuration.html#resolve-extensions + */ + extensions: ['', '.ts', '.js'], + root: [ + helpers.root('app'), + helpers.root('app-libs') + ] + }, + + /* + * Options affecting the normal modules. + * + * See: http://webpack.github.io/docs/configuration.html#module + */ + module: { + preLoaders: [{ + test: /\.ts/, + loader: helpers.root('app-config', 'auto-loader') + '?[file].html=template&[file].scss=styles', + }], + + /** + * An array of automatically applied loaders. + * + * IMPORTANT: The loaders here are resolved relative to the resource which they are applied to. + * This means they are not resolved relative to the configuration file. + * + * See: http://webpack.github.io/docs/configuration.html#module-loaders + */ + loaders: [ + { + test: /\.ts$/, + loader: 'awesome-typescript-loader' + }, { + test: /\.html$/, + loader: 'html' + }, { + test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)(\?.*$|$)/, + loader: 'null' + }, { + test: /\.css$/, + loader: 'null' + }, { + test: /\.scss$/, + exclude: helpers.root('app', 'theme'), + loaders: ['raw', 'sass'] + } + ] + }, + + plugins: [ + /** + * Shim additional libraries + * + * See: https://webpack.github.io/docs/shimming-modules.html + */ + new webpack.ProvidePlugin({ + // Mouse trap handles shortcut management + 'Mousetrap': 'mousetrap/mousetrap' + }) + ] +} \ No newline at end of file diff --git a/src/PinkParrot/app-libs/typings/global.d.ts b/src/PinkParrot/app-libs/typings/global.d.ts new file mode 100644 index 000000000..aaa3d95b4 --- /dev/null +++ b/src/PinkParrot/app-libs/typings/global.d.ts @@ -0,0 +1,2 @@ +declare var styles: string[]; +declare var template: string; \ No newline at end of file diff --git a/src/PinkParrot/app/app.component.html b/src/PinkParrot/app/app.component.html new file mode 100644 index 000000000..aa8f55823 --- /dev/null +++ b/src/PinkParrot/app/app.component.html @@ -0,0 +1,3 @@ +
+

Hello from Angular 2 App with Webpack!

+
\ No newline at end of file diff --git a/src/PinkParrot/app/app.component.js.map b/src/PinkParrot/app/app.component.js.map new file mode 100644 index 000000000..4d1ffa83a --- /dev/null +++ b/src/PinkParrot/app/app.component.js.map @@ -0,0 +1 @@ +{"version":3,"file":"app.component.js","sourceRoot":"","sources":["app.component.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,IAAY,GAAG,WAAM,eAAe,CAAC,CAAA;AAOrC;IAAA;IAA4B,CAAC;IAL7B;QAAC,GAAG,CAAC,SAAS,CAAC;YACX,QAAQ,EAAE,QAAQ;YAClB,UAAA,QAAQ;YACR,QAAA,MAAM;SACT,CAAC;;oBAAA;IAC0B,mBAAC;AAAD,CAAC,AAA7B,IAA6B;AAAhB,oBAAY,eAAI,CAAA"} \ No newline at end of file diff --git a/src/PinkParrot/app/app.component.scss b/src/PinkParrot/app/app.component.scss new file mode 100644 index 000000000..040e5e425 --- /dev/null +++ b/src/PinkParrot/app/app.component.scss @@ -0,0 +1,8 @@ +main { + padding: 1em; + font-family: Arial, Helvetica, sans-serif; + font-size: 1.1rem; + text-align: center; + margin-top: 50px; + display: block; +} \ No newline at end of file diff --git a/src/PinkParrot/app/app.component.spec.js.map b/src/PinkParrot/app/app.component.spec.js.map new file mode 100644 index 000000000..c19e3e9b6 --- /dev/null +++ b/src/PinkParrot/app/app.component.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"app.component.spec.js","sourceRoot":"","sources":["app.component.spec.ts"],"names":[],"mappings":";AAAA,wBAAwB,uBAAuB,CAAC,CAAA;AAEhD,8BAA6B,iBAAiB,CAAC,CAAA;AAE/C,QAAQ,CAAC,KAAK,EAAE;IACZ,UAAU,CAAC;QACP,iBAAO,CAAC,sBAAsB,CAAC,EAAE,YAAY,EAAE,CAAC,4BAAY,CAAC,EAAE,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,aAAa,EAAE;QACd,IAAM,OAAO,GAAG,iBAAO,CAAC,eAAe,CAAC,4BAAY,CAAC,CAAC;QAEtD,MAAM,CAAC,OAAO,CAAC,iBAAiB,YAAY,4BAAY,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,4BAA4B,CAAC,CAAC;IACvG,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/src/PinkParrot/app/app.component.spec.ts b/src/PinkParrot/app/app.component.spec.ts new file mode 100644 index 000000000..2cf23d457 --- /dev/null +++ b/src/PinkParrot/app/app.component.spec.ts @@ -0,0 +1,15 @@ +import { TestBed } from '@angular/core/testing'; + +import { AppComponent } from './app.component'; + +describe('App', () => { + beforeEach(() => { + TestBed.configureTestingModule({ declarations: [AppComponent] }); + }); + + it('should work', () => { + const fixture = TestBed.createComponent(AppComponent); + + expect(fixture.componentInstance instanceof AppComponent).toBe(true, 'should create AppComponent'); + }); +}); \ No newline at end of file diff --git a/src/PinkParrot/app/app.component.ts b/src/PinkParrot/app/app.component.ts new file mode 100644 index 000000000..6da7a2663 --- /dev/null +++ b/src/PinkParrot/app/app.component.ts @@ -0,0 +1,8 @@ +import * as Ng2 from '@angular/core'; + +@Ng2.Component({ + selector: 'my-app', + template, + styles +}) +export class AppComponent { } \ No newline at end of file diff --git a/src/PinkParrot/app/app.module.js.map b/src/PinkParrot/app/app.module.js.map new file mode 100644 index 000000000..5ded4bff9 --- /dev/null +++ b/src/PinkParrot/app/app.module.js.map @@ -0,0 +1 @@ +{"version":3,"file":"app.module.js","sourceRoot":"","sources":["app.module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,IAAY,GAAG,WAAM,eAAe,CAAC,CAAA;AAErC,iCAA8B,2BAA2B,CAAC,CAAA;AAE1D,8BAA6B,iBAAiB,CAAC,CAAA;AAW/C;IAAA;IAAyB,CAAC;IAT1B;QAAC,GAAG,CAAC,QAAQ,CAAC;YACV,OAAO,EAAE;gBACL,gCAAa;aAChB;YACD,YAAY,EAAE;gBACV,4BAAY;aACf;YACD,SAAS,EAAE,CAAC,4BAAY,CAAC;SAC5B,CAAC;;iBAAA;IACuB,gBAAC;AAAD,CAAC,AAA1B,IAA0B;AAAb,iBAAS,YAAI,CAAA"} \ No newline at end of file diff --git a/src/PinkParrot/app/app.module.ts b/src/PinkParrot/app/app.module.ts new file mode 100644 index 000000000..7d881ad3b --- /dev/null +++ b/src/PinkParrot/app/app.module.ts @@ -0,0 +1,16 @@ +import * as Ng2 from '@angular/core'; + +import { BrowserModule } from '@angular/platform-browser'; + +import { AppComponent } from './app.component'; + +@Ng2.NgModule({ + imports: [ + BrowserModule + ], + declarations: [ + AppComponent + ], + bootstrap: [AppComponent] +}) +export class AppModule { } \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/action.js.map b/src/PinkParrot/app/core/angular/action.js.map new file mode 100644 index 000000000..c589163d1 --- /dev/null +++ b/src/PinkParrot/app/core/angular/action.js.map @@ -0,0 +1 @@ +{"version":3,"file":"action.js","sourceRoot":"","sources":["action.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAEH,IAAM,UAAU,GAAG,cAAQ,CAAC,CAAC;AAE7B;IACI,MAAM,CAAC,UAAU,MAAW,EAAE,GAAW;QACrC,IAAI,UAAe,CAAC;QACpB,IAAI,QAAa,CAAC;QAClB,IAAI,aAAkB,CAAC;QACvB,IAAI,YAAiB,CAAC;QAEtB;YACI,IAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;YAE7B,EAAE,CAAC,CAAC,KAAK,IAAI,UAAU,IAAI,UAAU,CAAC,SAAS,IAAI,OAAO,UAAU,CAAC,SAAS,KAAK,UAAU,CAAC,CAAC,CAAC;gBAC5F,YAAY,GAAG,UAAU,CAAC,SAAS,CAAC,UAAC,CAAM,IAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;oBAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAE/E,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACrC,CAAC;QACL,CAAC;QAAA,CAAC;QAEF;YACI,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;gBACf,YAAY,CAAC,WAAW,EAAE,CAAC;gBAE3B,aAAa,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;YAC9D,CAAC;QACL,CAAC;QAAA,CAAC;QAEF,EAAE,CAAC,CAAC,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACrB,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,GAAG,EAAE;gBAC/B,GAAG,EAAE;oBACD,MAAM,CAAC,UAAU,CAAC;gBACtB,CAAC;gBACD,GAAG,EAAE,UAAU,CAAC;oBACZ,QAAQ,GAAG,IAAI,CAAC;oBAEhB,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC,CAAC;wBAC7B,QAAQ,CAAC,gBAAgB,GAAG,EAAE,CAAC;wBAE/B,IAAI,SAAO,GAAG,QAAQ,CAAC,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,UAAU,CAAC;wBAEtF,QAAQ,CAAC,WAAW,GAAG;4BACnB,GAAG,CAAC,CAAU,UAAa,EAAb,+BAAa,EAAb,2BAAa,EAAb,IAAa,CAAC;gCAAvB,IAAI,CAAC,sBAAA;gCACN,CAAC,CAAC,WAAW,EAAE,CAAC;6BACnB;4BAED,QAAQ,CAAC,gBAAgB,GAAG,IAAI,CAAC;4BAEjC,SAAO,EAAE,CAAC;wBACd,CAAC,CAAC;oBACN,CAAC;oBAED,aAAa,GAAG,QAAQ,CAAC,gBAAgB,CAAC;oBAE1C,UAAU,GAAG,CAAC,CAAC;oBAEf,WAAW,EAAE,CAAC;oBACd,SAAS,EAAE,CAAC;gBAChB,CAAC;aACJ,CAAC,CAAC;QACP,CAAC;IACL,CAAC,CAAC;AACN,CAAC;AA3De,cAAM,SA2DrB,CAAA"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/action.spec.js.map b/src/PinkParrot/app/core/angular/action.spec.js.map new file mode 100644 index 000000000..667b50cbe --- /dev/null +++ b/src/PinkParrot/app/core/angular/action.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"action.spec.js","sourceRoot":"","sources":["action.spec.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;;;;;;;;;;AAEH,qBAAwB,MAAM,CAAC,CAAA;AAE/B,iBAAuB,OAAO,CAAC,CAAA;AAE/B;IACI,sBAAoB,QAAc,EAAE,GAAG;QAA3B,wBAAsB,GAAtB,gBAAsB;QAAd,aAAQ,GAAR,QAAQ,CAAM;QAE3B,oBAAe,GAAG,KAAK,CAAC;QAGxB,WAAM,GAAG,IAAI,cAAO,EAAU,CAAC,GAAG,CAAC,UAAA,CAAC,IAAM,MAAM,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAG7E,WAAM,GAAG,IAAI,cAAO,EAAU,CAAC,GAAG,CAAC,UAAA,CAAC,IAAM,MAAM,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IARzC,CAAC;IAUrC,2BAAI,GAAX;QACI,IAAI,CAAC,MAAM,GAAG,IAAI,cAAO,EAAU,CAAC,GAAG,CAAC,UAAA,CAAC,IAAM,MAAM,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACtF,CAAC;IAEM,kCAAW,GAAlB;QACI,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;IAChC,CAAC;IAZD;QAAC,SAAM,EAAE;;gDAAA;IAGT;QAAC,SAAM,EAAE;;gDAAA;IAUb,mBAAC;AAAD,CAAC,AAlBD,IAkBC;AAED,QAAQ,CAAC,QAAQ,EAAE;IACf,EAAE,CAAC,+EAA+E,EAAE;QAChF,IAAI,aAAa,GAAG,CAAC,CAAC;QAEtB,IAAM,KAAK,GAAG;YACV,IAAI,EAAE,UAAC,CAAM;gBACT,aAAa,EAAE,CAAC;gBAEhB,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACvC,CAAC;SACJ,CAAC;QAEF,IAAM,IAAI,GAAG,IAAI,YAAY,CAAC,KAAK,CAAC,CAAC;QAErC,IAAI,CAAC,IAAI,EAAE,CAAC;QAEN,IAAI,CAAC,MAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1B,IAAI,CAAC,MAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAEhC,MAAM,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAE9B,IAAI,CAAC,WAAW,EAAE,CAAC;QAEb,IAAI,CAAC,MAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1B,IAAI,CAAC,MAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAEhC,MAAM,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,UAAU,EAAE,CAAC;IAC9C,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/action.spec.ts b/src/PinkParrot/app/core/angular/action.spec.ts new file mode 100644 index 000000000..695f59cb2 --- /dev/null +++ b/src/PinkParrot/app/core/angular/action.spec.ts @@ -0,0 +1,61 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { Subject } from 'rxjs'; + +import { Action } from './../'; + +class MockupObject { + constructor(private readonly store: any) { } + + public isDestroyCalled = false; + + @Action() + public event1 = new Subject().map(x => { return { type: 'MOCK_ACTION' }; }); + + @Action() + public event2 = new Subject().map(x => { return { type: 'MOCK_ACTION' }; }); + + public init() { + this.event2 = new Subject().map(x => { return { type: 'MOCK_ACTION' }; }); + } + + public ngOnDestroy() { + this.isDestroyCalled = true; + } +} + +describe('Action', () => { + it('should test complete flow to subscribe and unsubscribe and to trigger actions', () => { + let dispatchCount = 0; + + const state = { + next: (e: any) => { + dispatchCount++; + + expect(e.type).toBe('MOCK_ACTION'); + } + }; + + const mock = new MockupObject(state); + + mock.init(); + + (mock.event1).next('TEST'); + (mock.event2).next('TEST'); + + expect(dispatchCount).toBe(2); + + mock.ngOnDestroy(); + + (mock.event1).next('TEST'); + (mock.event2).next('TEST'); + + expect(dispatchCount).toBe(2); + expect(mock.isDestroyCalled).toBeTruthy(); + }); +}); \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/action.ts b/src/PinkParrot/app/core/angular/action.ts new file mode 100644 index 000000000..2ee2646c3 --- /dev/null +++ b/src/PinkParrot/app/core/angular/action.ts @@ -0,0 +1,69 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +const EMPTY_FUNC = () => { }; + +export function Action() { + return function (target: any, key: string) { + let observable: any; + let instance: any; + let subscriptions: any; + let subscription: any; + + function subscribe() { + const store = instance.store; + + if (store && observable && observable.subscribe && typeof observable.subscribe === 'function') { + subscription = observable.subscribe((a: any) => { if (a) { store.next(a); } }); + + subscriptions.push(subscription); + } + }; + + function unsubscribe() { + if (subscription) { + subscription.unsubscribe(); + + subscriptions.splice(subscriptions.indexOf(subscribe), 1); + } + }; + + if (delete target[key]) { + Object.defineProperty(target, key, { + get: function () { + return observable; + }, + set: function (v) { + instance = this; + + if (!instance.___subscriptions) { + instance.___subscriptions = []; + + let destroy = instance.ngOnDestroy ? instance.ngOnDestroy.bind(instance) : EMPTY_FUNC; + + instance.ngOnDestroy = () => { + for (let s of subscriptions) { + s.unsubscribe(); + } + + instance.___subscriptions = null; + + destroy(); + }; + } + + subscriptions = instance.___subscriptions; + + observable = v; + + unsubscribe(); + subscribe(); + } + }); + } + }; +} \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/cloak.directive.js.map b/src/PinkParrot/app/core/angular/cloak.directive.js.map new file mode 100644 index 000000000..652f81e0b --- /dev/null +++ b/src/PinkParrot/app/core/angular/cloak.directive.js.map @@ -0,0 +1 @@ +{"version":3,"file":"cloak.directive.js","sourceRoot":"","sources":["cloak.directive.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;;;;;;;;;;AAEH,IAAY,GAAG,WAAM,eAAe,CAAC,CAAA;AAKrC;IACI,wBAAoB,QAAgB,EAAE,GAAG,EAAC,UAAU;QAAxC,wBAAwB,GAAxB,kBAAwB;QAAhB,aAAQ,GAAR,QAAQ,CAAQ;IAAoB,CAAC;IAElD,iCAAQ,GAAf;QACI,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC5D,CAAC;IARL;QAAC,GAAG,CAAC,SAAS,CAAC;YACX,QAAQ,EAAE,WAAW;SACxB,CAAC;;sBAAA;IAOF,qBAAC;AAAD,CAAC,AAND,IAMC;AANY,sBAAc,iBAM1B,CAAA"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/cloak.directive.spec.js.map b/src/PinkParrot/app/core/angular/cloak.directive.spec.js.map new file mode 100644 index 000000000..b42558414 --- /dev/null +++ b/src/PinkParrot/app/core/angular/cloak.directive.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"cloak.directive.spec.js","sourceRoot":"","sources":["cloak.directive.spec.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAEH,gCAA+B,mBAAmB,CAAC,CAAA;AAEnD,QAAQ,CAAC,gBAAgB,EAAE;IACvB,EAAE,CAAC,8CAA8C,EAAE;QAC/C,IAAI,MAAM,GAAG,KAAK,CAAC;QAEnB,IAAM,OAAO,GAAG;YACZ,aAAa,EAAE;gBACX,SAAS,EAAE;oBACP,MAAM,EAAE;wBACJ,MAAM,GAAG,IAAI,CAAC;oBAClB,CAAC;iBACJ;aACJ;SACJ,CAAC;QAED,IAAI,gCAAc,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC;QAExC,MAAM,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,CAAC;IAChC,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/cloak.directive.spec.ts b/src/PinkParrot/app/core/angular/cloak.directive.spec.ts new file mode 100644 index 000000000..50e07313a --- /dev/null +++ b/src/PinkParrot/app/core/angular/cloak.directive.spec.ts @@ -0,0 +1,28 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { CloakDirective } from './cloak.directive'; + +describe('CloakDirective', () => { + it('should remove class from element on ngOnInit', () => { + let called = false; + + const element = { + nativeElement: { + classList: { + remove: () => { + called = true; + } + } + } + }; + + new CloakDirective(element).ngOnInit(); + + expect(called).toBeTruthy(); + }); +}); diff --git a/src/PinkParrot/app/core/angular/cloak.directive.ts b/src/PinkParrot/app/core/angular/cloak.directive.ts new file mode 100644 index 000000000..f183adfa3 --- /dev/null +++ b/src/PinkParrot/app/core/angular/cloak.directive.ts @@ -0,0 +1,19 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import * as Ng2 from '@angular/core'; + +@Ng2.Directive({ + selector: '.gp-cloak' +}) +export class CloakDirective implements Ng2.OnInit { + constructor(private readonly element: Ng2.ElementRef) { } + + public ngOnInit() { + this.element.nativeElement.classList.remove('gp-cloak'); + } +} \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/color-picker.component.html b/src/PinkParrot/app/core/angular/color-picker.component.html new file mode 100644 index 000000000..b49292d73 --- /dev/null +++ b/src/PinkParrot/app/core/angular/color-picker.component.html @@ -0,0 +1,11 @@ +
+ + + +
\ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/color-picker.component.js.map b/src/PinkParrot/app/core/angular/color-picker.component.js.map new file mode 100644 index 000000000..741a92562 --- /dev/null +++ b/src/PinkParrot/app/core/angular/color-picker.component.js.map @@ -0,0 +1 @@ +{"version":3,"file":"color-picker.component.js","sourceRoot":"","sources":["color-picker.component.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/color-picker.component.scss b/src/PinkParrot/app/core/angular/color-picker.component.scss new file mode 100644 index 000000000..e2e6a5fdc --- /dev/null +++ b/src/PinkParrot/app/core/angular/color-picker.component.scss @@ -0,0 +1,56 @@ +@import '../../theme/_mixins.scss'; + +$color-size: 24px; +$button-size: 1.81rem; + +.color-palette { + & { + @include clearfix(); + width: 8 * ($color-size + 6); + padding: 6px; + } + + &-box { + margin: 2px; + border: 2px solid transparent; + width: $color-size; + height: $color-size; + float: left; + } + + &-box:hover { + border-color: #1460A8; + } + + &-box.selected { + border-color: #1875CC; + } + + &-box.selected:hover { + border-color: #1875CC; + } + + &-box.disabled { + border-color: transparent; + } + + &-color { + border: 1px solid white; + width: $color-size - 4; + height: $color-size - 4; + display: block; + } +} + +.dropdown-menu { + background: #eee; +} + +.btn-group > .btn:first-child { + @include border-radius(0.25em); +} + +.btn { + width: $button-size; + height: $button-size; +} \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/color-picker.component.spec.js.map b/src/PinkParrot/app/core/angular/color-picker.component.spec.js.map new file mode 100644 index 000000000..3f8e5e3cb --- /dev/null +++ b/src/PinkParrot/app/core/angular/color-picker.component.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"color-picker.component.spec.js","sourceRoot":"","sources":["color-picker.component.spec.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/color-picker.component.spec.ts b/src/PinkParrot/app/core/angular/color-picker.component.spec.ts new file mode 100644 index 000000000..181cb105f --- /dev/null +++ b/src/PinkParrot/app/core/angular/color-picker.component.spec.ts @@ -0,0 +1,124 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { Color } from './../'; + +import { ColorPickerComponent } from './color-picker.component'; + +describe('ColorPickerComponent', () => { + it('should instantiate', () => { + const colorPicker = new ColorPickerComponent({ nativeElement: {} }); + + expect(colorPicker).toBeDefined(); + }); + + it('should close color picker when clicking outside of the modal', () => { + const element = { + nativeElement: { + contains: () => { + return false; + } + } + }; + + const colorPicker = new ColorPickerComponent(element); + colorPicker.open(); + colorPicker.onClick({}); + + expect(colorPicker.isOpen).toBeFalsy(); + }); + + it('should not close color picker when clicking inside the modal', () => { + const element = { + nativeElement: { + contains: () => { + return true; + } + } + }; + + const colorPicker = new ColorPickerComponent(element); + colorPicker.open(); + colorPicker.onClick({}); + + expect(colorPicker.isOpen).toBeTruthy(); + }); + + it('should close modal and emit event when setting color', () => { + const colorPicker = new ColorPickerComponent({ nativeElement: {} }); + const selectedColor = Color.RED; + + let lastColor: Color | null = null; + + colorPicker.colorChange.subscribe((c: Color) => { + lastColor = c; + }); + + colorPicker.open(); + colorPicker.selectColor(selectedColor); + + expect(lastColor).toBe(selectedColor); + expect(colorPicker.isOpen).toBeFalsy(); + }); + + it('should not emit event when selecting same color', () => { + const colorPicker = new ColorPickerComponent({ nativeElement: {} }); + const selectedColor = Color.RED; + + colorPicker.selectColor(selectedColor); + + let lastColor: Color | null = null; + + colorPicker.colorChange.subscribe((c: Color) => { + lastColor = c; + }); + + colorPicker.selectColor(selectedColor); + + expect(lastColor).toBeNull(); + }); + + it('should update selected color when component changes', () => { + const colorPicker = new ColorPickerComponent({ nativeElement: {} }); + const selectedColor = Color.RED; + + colorPicker.color = selectedColor; + + colorPicker.ngOnChanges({}); + + expect(colorPicker.selectedColor).toBe(selectedColor); + }); + + it('should update selected color with palette default if setting invalid color', () => { + const colorPicker = new ColorPickerComponent({ nativeElement: {} }); + + colorPicker.color = 'invalid'; + + colorPicker.ngOnChanges({}); + + expect(colorPicker.selectedColor).toBe(colorPicker.palette.defaultColor); + }); + + it('should update selected color with black if setting invalid color and palette is null', () => { + const colorPicker = new ColorPickerComponent({ nativeElement: {} }); + + colorPicker.palette = undefined!; + colorPicker.color = 'invalid'; + + colorPicker.ngOnChanges({}); + + expect(colorPicker.selectedColor).toBe(Color.BLACK); + }); + + it('should update isOpen prperty when toggleOpen is invoked', () => { + const colorPicker = new ColorPickerComponent({ nativeElement: {} }); + + colorPicker.toggleOpen(); + + expect(colorPicker.isOpen).toBeTruthy(); + }); +}); \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/color-picker.component.ts b/src/PinkParrot/app/core/angular/color-picker.component.ts new file mode 100644 index 000000000..146a3ef8c --- /dev/null +++ b/src/PinkParrot/app/core/angular/color-picker.component.ts @@ -0,0 +1,96 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import * as Ng2 from '@angular/core'; + +import { Color } from './../utils/color'; +import { ColorPalette } from './../utils/color-palette'; + +@Ng2.Component({ + selector: 'gp-color-picker', + styles, + template +}) +export class ColorPickerComponent implements Ng2.OnChanges { + private selectedColorValue = new Color(0, 0, 0); + + @Ng2.Output() + public colorChange = new Ng2.EventEmitter(); + + @Ng2.Input() + public color: string | number | Color; + + @Ng2.Input() + public palette = ColorPalette.colors(); + + @Ng2.Input() + public isOpen = false; + + public get selectedColor(): Color { + return this.selectedColorValue; + } + + constructor(private readonly element: Ng2.ElementRef) { + this.updateColor(); + } + + @Ng2.HostListener('document:click', ['$event.target']) + public onClick(targetElement: any) { + const clickedInside = this.element.nativeElement.contains(targetElement); + + if (!clickedInside) { + this.close(); + } + } + + public ngOnChanges(changes: Ng2.SimpleChanges) { + this.updateColor(); + } + + public toggleOpen() { + this.isOpen = !this.isOpen; + } + + public close() { + this.isOpen = false; + } + + public open() { + this.isOpen = true; + } + + public selectColor(color: Color) { + this.updateParent(color); + this.updateColor(color); + this.close(); + } + + private updateParent(color: Color) { + if (this.selectedColorValue.ne(color)) { + this.colorChange.emit(color); + } + } + + private updateColor(color?: Color) { + let hasColor = false; + try { + this.selectedColorValue = Color.fromValue(color || this.color); + + hasColor = true; + } catch (e) { + hasColor = false; + } + + if (!hasColor || !this.selectedColorValue) { + if (this.palette) { + this.selectedColorValue = this.palette.defaultColor; + } else { + this.selectedColorValue = Color.BLACK; + } + } + } +} \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/date-time.pipes.js.map b/src/PinkParrot/app/core/angular/date-time.pipes.js.map new file mode 100644 index 000000000..6bd5cc5da --- /dev/null +++ b/src/PinkParrot/app/core/angular/date-time.pipes.js.map @@ -0,0 +1 @@ +{"version":3,"file":"date-time.pipes.js","sourceRoot":"","sources":["date-time.pipes.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;;;;;;;;;;AAEH,IAAY,GAAG,WAAM,eAAe,CAAC,CAAA;AAQrC;IAAA;IAIA,CAAC;IAHU,iCAAS,GAAhB,UAAiB,KAAe,EAAE,IAAc;QAC5C,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;IAC1C,CAAC;IANL;QAAC,GAAG,CAAC,IAAI,CAAC;YACN,IAAI,EAAE,WAAW;SACpB,CAAC;;qBAAA;IAKF,oBAAC;AAAD,CAAC,AAJD,IAIC;AAJY,qBAAa,gBAIzB,CAAA;AAKD;IAAA;IAIA,CAAC;IAHU,6BAAS,GAAhB,UAAiB,KAAe,EAAE,IAAc;QAC5C,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,CAAC;IANL;QAAC,GAAG,CAAC,IAAI,CAAC;YACN,IAAI,EAAE,OAAO;SAChB,CAAC;;iBAAA;IAKF,gBAAC;AAAD,CAAC,AAJD,IAIC;AAJY,iBAAS,YAIrB,CAAA;AAKD;IAAA;IAIA,CAAC;IAHU,iCAAS,GAAhB,UAAiB,KAAe,EAAE,IAAc;QAC5C,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;IANL;QAAC,GAAG,CAAC,IAAI,CAAC;YACN,IAAI,EAAE,WAAW;SACpB,CAAC;;qBAAA;IAKF,oBAAC;AAAD,CAAC,AAJD,IAIC;AAJY,qBAAa,gBAIzB,CAAA;AAKD;IAAA;IAIA,CAAC;IAHU,2BAAS,GAAhB,UAAiB,KAAe,EAAE,IAAc;QAC5C,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;IANL;QAAC,GAAG,CAAC,IAAI,CAAC;YACN,IAAI,EAAE,KAAK;SACd,CAAC;;eAAA;IAKF,cAAC;AAAD,CAAC,AAJD,IAIC;AAJY,eAAO,UAInB,CAAA;AAKD;IAAA;IAIA,CAAC;IAHU,iCAAS,GAAhB,UAAiB,KAAe,EAAE,IAAc;QAC5C,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IACzC,CAAC;IANL;QAAC,GAAG,CAAC,IAAI,CAAC;YACN,IAAI,EAAE,WAAW;SACpB,CAAC;;qBAAA;IAKF,oBAAC;AAAD,CAAC,AAJD,IAIC;AAJY,qBAAa,gBAIzB,CAAA;AAKD;IAAA;IAIA,CAAC;IAHU,gCAAS,GAAhB,UAAiB,KAAe,EAAE,IAAc;QAC5C,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;IAC5B,CAAC;IANL;QAAC,GAAG,CAAC,IAAI,CAAC;YACN,IAAI,EAAE,UAAU;SACnB,CAAC;;oBAAA;IAKF,mBAAC;AAAD,CAAC,AAJD,IAIC;AAJY,oBAAY,eAIxB,CAAA"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/date-time.pipes.spec.js.map b/src/PinkParrot/app/core/angular/date-time.pipes.spec.js.map new file mode 100644 index 000000000..e2cb4fa05 --- /dev/null +++ b/src/PinkParrot/app/core/angular/date-time.pipes.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"date-time.pipes.spec.js","sourceRoot":"","sources":["date-time.pipes.spec.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/date-time.pipes.spec.ts b/src/PinkParrot/app/core/angular/date-time.pipes.spec.ts new file mode 100644 index 000000000..6e1ec86f1 --- /dev/null +++ b/src/PinkParrot/app/core/angular/date-time.pipes.spec.ts @@ -0,0 +1,87 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { DateTime, Duration } from './../'; + +import { + DayOfWeekPipe, + DayPipe, + DurationPipe, + MonthPipe, + ShortDatePipe, + ShortTimePipe, +} from './date-time.pipes'; + +const dateTime = DateTime.parse('2013-10-03T12:13:14.125', DateTime.iso8601()); + +describe('DurationPipe', () => { + it('should format to standard duration string', () => { + const duration = Duration.create(dateTime, dateTime.addMinutes(10).addDays(13)); + + const pipe = new DurationPipe(); + + const actual = pipe.transform(duration, []); + const expected = '312:10h'; + + expect(actual).toBe(expected); + }); +}); + +describe('DayPipe', () => { + it('should format to day numbers', () => { + const pipe = new DayPipe(); + + const actual = pipe.transform(dateTime, []); + const expected = '03'; + + expect(actual).toBe(expected); + }); +}); + +describe('MonthPipe', () => { + it('should format to long month name', () => { + const pipe = new MonthPipe(); + + const actual = pipe.transform(dateTime, []); + const expected = 'October'; + + expect(actual).toBe(expected); + }); +}); + +describe('DayOfWeekPipe', () => { + it('should format to short week of day string', () => { + const pipe = new DayOfWeekPipe(); + + const actual = pipe.transform(dateTime, []); + const expected = 'Th'; + + expect(actual).toBe(expected); + }); +}); + +describe('ShortDatePipe', () => { + it('should format to two digit day number and short month name', () => { + const pipe = new ShortDatePipe(); + + const actual = pipe.transform(dateTime, []); + const expected = '03.Oct'; + + expect(actual).toBe(expected); + }); +}); + +describe('ShortTimePipe', () => { + it('should format to short time string', () => { + const pipe = new ShortTimePipe(); + + const actual = pipe.transform(dateTime, []); + const expected = '12:13'; + + expect(actual).toBe(expected); + }); +}); diff --git a/src/PinkParrot/app/core/angular/date-time.pipes.ts b/src/PinkParrot/app/core/angular/date-time.pipes.ts new file mode 100644 index 000000000..393320d91 --- /dev/null +++ b/src/PinkParrot/app/core/angular/date-time.pipes.ts @@ -0,0 +1,65 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import * as Ng2 from '@angular/core'; + +import { DateTime } from './../utils/date-time'; +import { Duration } from './../utils/duration'; + +@Ng2.Pipe({ + name: 'shortDate' +}) +export class ShortDatePipe { + public transform(value: DateTime, args: string[]): any { + return value.toStringFormat('DD.MMM'); + } +} + +@Ng2.Pipe({ + name: 'month' +}) +export class MonthPipe { + public transform(value: DateTime, args: string[]): any { + return value.toStringFormat('MMMM'); + } +} + +@Ng2.Pipe({ + name: 'dayOfWeek' +}) +export class DayOfWeekPipe { + public transform(value: DateTime, args: string[]): any { + return value.toStringFormat('dd'); + } +} + +@Ng2.Pipe({ + name: 'day' +}) +export class DayPipe { + public transform(value: DateTime, args: string[]): any { + return value.toStringFormat('DD'); + } +} + +@Ng2.Pipe({ + name: 'shortTime' +}) +export class ShortTimePipe { + public transform(value: DateTime, args: string[]): any { + return value.toStringFormat('HH:mm'); + } +} + +@Ng2.Pipe({ + name: 'duration' +}) +export class DurationPipe { + public transform(value: Duration, args: string[]): any { + return value.toString(); + } +} \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/drag-model.directive.js.map b/src/PinkParrot/app/core/angular/drag-model.directive.js.map new file mode 100644 index 000000000..69fba26ca --- /dev/null +++ b/src/PinkParrot/app/core/angular/drag-model.directive.js.map @@ -0,0 +1 @@ +{"version":3,"file":"drag-model.directive.js","sourceRoot":"","sources":["drag-model.directive.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/drag-model.directive.ts b/src/PinkParrot/app/core/angular/drag-model.directive.ts new file mode 100644 index 000000000..16a459ea2 --- /dev/null +++ b/src/PinkParrot/app/core/angular/drag-model.directive.ts @@ -0,0 +1,117 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import * as Ng2 from '@angular/core'; + +import { DragService, Vec2 } from './../'; + +@Ng2.Directive({ + selector: '[gpDragModel]' +}) +export class DragModelDirective { + private startOffset: Vec2; + private startPosition: Vec2; + private mouseMoveSubscription: Function | null; + private mouseUpSubscription: Function | null; + private clonedElement: HTMLElement | null; + + @Ng2.Input('gpDragModel') + public model: any; + + constructor( + private readonly element: Ng2.ElementRef, + private readonly renderer: Ng2.Renderer, + private readonly dragService: DragService + ) { + } + + @Ng2.HostListener('mousedown', ['$event']) + public onMouseDown(event: MouseEvent) { + this.startOffset = new Vec2(event.offsetX, event.offsetY); + this.startPosition = new Vec2(event.clientX, event.clientY); + + this.mouseMoveSubscription = + this.renderer.listenGlobal('window', 'mousemove', (e: MouseEvent) => { + this.onMouseMove(e); + }); + + this.mouseUpSubscription = + this.renderer.listenGlobal('window', 'mouseup', (e: MouseEvent) => { + this.onMouseUp(e); + }); + + this.stopEvent(event); + } + + private onMouseMove(event: MouseEvent) { + const position = new Vec2(event.clientX, event.clientY); + + if (!this.clonedElement && position.sub(this.startPosition).lengtSquared > 100) { + this.clonedElement = this.element.nativeElement.cloneNode(true); + + this.clonedElement!.style.position = 'fixed'; + this.clonedElement!.style.zIndex = '10000'; + + document.body.appendChild(this.clonedElement!); + } + + if (this.clonedElement) { + const elementPosition = position.sub(this.startOffset); + + this.clonedElement.style.left = elementPosition.x + 'px'; + this.clonedElement.style.top = elementPosition.y + 'px'; + } + + this.stopEvent(event); + } + + private onMouseUp(event: MouseEvent) { + if (this.clonedElement) { + this.clonedElement.remove(); + } + + let dropCandidate: Element | null = document.elementFromPoint(event.clientX, event.clientY); + + while (dropCandidate && (dropCandidate.classList && !dropCandidate.classList.contains('gp-drop'))) { + dropCandidate = dropCandidate.parentNode as Element; + } + + if (dropCandidate && dropCandidate.id) { + const position = this.getRelativeCoordinates(event, dropCandidate).sub(this.startOffset).round(); + + this.dragService.emitDrop({ position, model: this.model, dropTarget: dropCandidate.id }); + } + + if (this.mouseMoveSubscription) { + this.mouseMoveSubscription(); + this.mouseMoveSubscription = null; + } + + if (this.mouseUpSubscription) { + this.mouseUpSubscription(); + this.mouseUpSubscription = null; + } + + this.clonedElement = null; + + this.stopEvent(event); + } + + private stopEvent(event: Event) { + event.preventDefault(); + event.stopPropagation(); + } + + private getRelativeCoordinates(e: any, container: any): Vec2 { + const rect = container.getBoundingClientRect(); + + const x = !!e.touches ? e.touches[0].pageX : e.pageX; + const y = !!e.touches ? e.touches[0].pageY : e.pageY; + + return new Vec2(x - rect.left, y - rect.top); + } +} \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/focus-on-change.directive.js.map b/src/PinkParrot/app/core/angular/focus-on-change.directive.js.map new file mode 100644 index 000000000..ade008581 --- /dev/null +++ b/src/PinkParrot/app/core/angular/focus-on-change.directive.js.map @@ -0,0 +1 @@ +{"version":3,"file":"focus-on-change.directive.js","sourceRoot":"","sources":["focus-on-change.directive.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;;;;;;;;;;AAEH,IAAY,GAAG,WAAM,eAAe,CAAC,CAAA;AAKrC;IAII,gCACY,QAAmB,EAAE,GAAG,EAAC,UAAU,EACnC,QAAiB,EAAE,GAAG,EAAC,QAAQ;QADvC,wBAA2B,GAA3B,qBAA2B;QAC3B,wBAAyB,GAAzB,mBAAyB;QADjB,aAAQ,GAAR,QAAQ,CAAW;QACnB,aAAQ,GAAR,QAAQ,CAAS;IAE7B,CAAC;IAEM,4CAAW,GAAlB,UAAmB,OAA4C;QAA/D,iBAIC;QAHG,UAAU,CAAC;YACP,KAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC,KAAI,CAAC,UAAU,CAAC,aAAa,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;QAClF,CAAC,EAAE,GAAG,CAAC,CAAC;IACZ,CAAC;IAbD;QAAC,GAAG,CAAC,KAAK,EAAE;;mEAAA;IAJhB;QAAC,GAAG,CAAC,SAAS,CAAC;YACX,QAAQ,EAAE,mBAAmB;SAChC,CAAC;;8BAAA;IAgBF,6BAAC;AAAD,CAAC,AAfD,IAeC;AAfY,8BAAsB,yBAelC,CAAA"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/focus-on-change.directive.spec.js.map b/src/PinkParrot/app/core/angular/focus-on-change.directive.spec.js.map new file mode 100644 index 000000000..09bf9b753 --- /dev/null +++ b/src/PinkParrot/app/core/angular/focus-on-change.directive.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"focus-on-change.directive.spec.js","sourceRoot":"","sources":["focus-on-change.directive.spec.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAIH,0CAAuC,6BAA6B,CAAC,CAAA;AAErE,QAAQ,CAAC,wBAAwB,EAAE;IAC/B,IAAI,eAAe,GAAG,CAAC,CAAC;IAExB,UAAU,CAAC;QACP,eAAe,GAAG,OAAO,CAAC,wBAAwB,CAAC;QAEnD,OAAO,CAAC,wBAAwB,GAAG,GAAG,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,UAAC,IAAS;QAC5D,IAAI,YAAiB,CAAC;QACtB,IAAI,aAAkB,CAAC;QAEvB,IAAM,QAAQ,GAAG;YACb,mBAAmB,EAAE,UAAC,OAAY,EAAE,MAAW,EAAE,IAAS;gBACtD,aAAa,GAAG,OAAO,CAAC;gBACxB,YAAY,GAAG,MAAM,CAAC;YAC1B,CAAC;SACJ,CAAC;QAEF,IAAM,OAAO,GAAmB;YAC5B,aAAa,EAAE,EAAE;SACpB,CAAC;QAEF,IAAI,kDAAsB,CAAC,OAAO,EAAE,QAAwB,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QAE9E,MAAM,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;QACvC,MAAM,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;QAExC,UAAU,CAAC;YACP,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACnC,MAAM,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;YAElD,IAAI,EAAE,CAAC;QACX,CAAC,EAAE,GAAG,CAAC,CAAC;IACZ,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC;QACN,OAAO,CAAC,wBAAwB,GAAG,eAAe,CAAC;IACvD,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/focus-on-change.directive.spec.ts b/src/PinkParrot/app/core/angular/focus-on-change.directive.spec.ts new file mode 100644 index 000000000..ed4b8f4b9 --- /dev/null +++ b/src/PinkParrot/app/core/angular/focus-on-change.directive.spec.ts @@ -0,0 +1,52 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import * as Ng2 from '@angular/core'; + +import { FocusOnChangeDirective } from './focus-on-change.directive'; + +describe('FocusOnChangeDirective', () => { + let originalTimeout = 0; + + beforeEach(() => { + originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL; + + jasmine.DEFAULT_TIMEOUT_INTERVAL = 800; + }); + + it('should call focus on element when value changes', (done: any) => { + let calledMethod: any; + let calledElement: any; + + const renderer = { + invokeElementMethod: (element: any, method: any, args: any) => { + calledElement = element; + calledMethod = method; + } + }; + + const element: Ng2.ElementRef = { + nativeElement: {} + }; + + new FocusOnChangeDirective(element, renderer as Ng2.Renderer).ngOnChanges({}); + + expect(calledMethod).not.toBeDefined(); + expect(calledElement).not.toBeDefined(); + + setTimeout(() => { + expect(calledMethod).toBe('focus'); + expect(calledElement).toBe(element.nativeElement); + + done(); + }, 400); + }); + + afterEach(() => { + jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout; + }); +}); diff --git a/src/PinkParrot/app/core/angular/focus-on-change.directive.ts b/src/PinkParrot/app/core/angular/focus-on-change.directive.ts new file mode 100644 index 000000000..607cbba5d --- /dev/null +++ b/src/PinkParrot/app/core/angular/focus-on-change.directive.ts @@ -0,0 +1,28 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import * as Ng2 from '@angular/core'; + +@Ng2.Directive({ + selector: '[gpFocusOnChange]' +}) +export class FocusOnChangeDirective implements Ng2.OnChanges { + @Ng2.Input() + public gpFocusOnChange: any; + + constructor( + private readonly elementRef: Ng2.ElementRef, + private readonly renderer: Ng2.Renderer + ) { + } + + public ngOnChanges(changes: { [key: string]: Ng2.SimpleChange }) { + setTimeout(() => { + this.renderer.invokeElementMethod(this.elementRef.nativeElement, 'focus', []); + }, 100); + } +} \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/image-drop.directive.js.map b/src/PinkParrot/app/core/angular/image-drop.directive.js.map new file mode 100644 index 000000000..76a3a5e17 --- /dev/null +++ b/src/PinkParrot/app/core/angular/image-drop.directive.js.map @@ -0,0 +1 @@ +{"version":3,"file":"image-drop.directive.js","sourceRoot":"","sources":["image-drop.directive.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/image-drop.directive.ts b/src/PinkParrot/app/core/angular/image-drop.directive.ts new file mode 100644 index 000000000..440e07459 --- /dev/null +++ b/src/PinkParrot/app/core/angular/image-drop.directive.ts @@ -0,0 +1,127 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import * as Ng2 from '@angular/core'; + +import { DragService, Vec2 } from './../'; + +@Ng2.Directive({ + selector: '.gp-image-drop' +}) +export class ImageDropDirective { + constructor( + private readonly element: Ng2.ElementRef, + private readonly renderer: Ng2.Renderer, + private readonly dragService: DragService + ) { + } + + @Ng2.HostListener('dragenter', ['$event']) + public onDragEnter(event: DragDropEvent) { + this.tryStopEvent(event); + } + + @Ng2.HostListener('dragover', ['$event']) + public onDragOver(event: DragDropEvent) { + this.tryStopEvent(event); + } + + @Ng2.HostListener('drop', ['$event']) + public onDrop(event: DragDropEvent) { + const image = this.findImage(event); + + if (!image) { + return; + } + + const position = this.getRelativeCoordinates(event, this.element.nativeElement).round(); + + const reader = new FileReader(); + + reader.onload = (loadedFile: any) => { + const imageSource: string = loadedFile.target.result; + const imageElement = document.createElement('img'); + + imageElement.onload = () => { + this.dragService.emitDrop({ + position, dropTarget: this.element.nativeElement.id, model: { + sizeX: imageElement.width, + sizeY: imageElement.height, + source: imageSource + } + }); + }; + imageElement.src = imageSource; + }; + reader.readAsDataURL(image); + + this.stopEvent(event); + } + + private stopEvent(event: Event) { + event.preventDefault(); + event.stopPropagation(); + } + + private tryStopEvent(event: DragDropEvent) { + const hasFiles = this.hasFiles(event.dataTransfer.types); + + if (!hasFiles) { + return; + } + + this.stopEvent(event); + } + + private hasFiles(types: any): boolean { + if (!types) { + return false; + } + + if (isFunction(types.indexOf)) { + return types.indexOf('Files') !== -1; + } else if (isFunction(types.contains)) { + return types.contains('Files'); + } else { + return false; + } + } + + private findImage(event: DragDropEvent): File | null { + let image: File | null = null; + + for (let i = 0; i < event.dataTransfer.files.length; i++) { + const file = event.dataTransfer.files[i]; + + if (file.type.match('image.*')) { + image = file; + break; + } + } + + return image; + } + + private getRelativeCoordinates(e: any, container: any): Vec2 { + const rect = container.getBoundingClientRect(); + + let pos = { x: 0, y: 0 }; + + pos.x = !!e.touches ? e.touches[0].pageX : e.pageX; + pos.y = !!e.touches ? e.touches[0].pageY : e.pageY; + + return new Vec2(pos.x - rect.left, pos.y - rect.top); + } +} + +function isFunction(obj: any): boolean { + return !!(obj && obj.constructor && obj.call && obj.apply); +}; + +interface DragDropEvent extends MouseEvent { + readonly dataTransfer: DataTransfer; +} \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/money.pipe.js.map b/src/PinkParrot/app/core/angular/money.pipe.js.map new file mode 100644 index 000000000..1c4d52a53 --- /dev/null +++ b/src/PinkParrot/app/core/angular/money.pipe.js.map @@ -0,0 +1 @@ +{"version":3,"file":"money.pipe.js","sourceRoot":"","sources":["money.pipe.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;;;;;;;;;;AAEH,IAAY,GAAG,WAAM,eAAe,CAAC,CAAA;AAOrC;IACI,mBACY,QAAiB,EAAE,cAAc,EACjC,QAAkB,EAAE,sBAAsB;QADlD,wBAAyB,GAAzB,mBAAyB;QACzB,wBAA0B,GAA1B,oBAA0B;QADlB,aAAQ,GAAR,QAAQ,CAAS;QACjB,aAAQ,GAAR,QAAQ,CAAU;IAE9B,CAAC;IAEM,6BAAS,GAAhB,UAAiB,KAAa,EAAE,IAAc;QAC1C,IAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;QAE1C,IAAI,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,GAAG,wBAAwB,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,SAAS,CAAC;QAEjJ,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;YAC1B,MAAM,GAAG,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;QACjD,CAAC;QAAC,IAAI,CAAC,CAAC;YACJ,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC;QACjD,CAAC;QAED,MAAM,CAAC,MAAM,CAAC;IAClB,CAAC;IAtBL;QAAC,GAAG,CAAC,IAAI,CAAC;YACN,IAAI,EAAE,OAAO;SAChB,CAAC;;iBAAA;IAqBF,gBAAC;AAAD,CAAC,AApBD,IAoBC;AApBY,iBAAS,YAoBrB,CAAA"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/money.pipe.spec.js.map b/src/PinkParrot/app/core/angular/money.pipe.spec.js.map new file mode 100644 index 000000000..baa2d9c5c --- /dev/null +++ b/src/PinkParrot/app/core/angular/money.pipe.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"money.pipe.spec.js","sourceRoot":"","sources":["money.pipe.spec.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAEH,iBAAuD,OAAO,CAAC,CAAA;AAE/D,2BAA0B,cAAc,CAAC,CAAA;AAEzC,QAAQ,CAAC,WAAW,EAAE;IAClB,EAAE,CAAC,qDAAqD,EAAE;QACtD,IAAM,IAAI,GAAG,IAAI,sBAAS,CAAC,IAAI,iBAAc,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,IAAI,yBAAsB,CAAC,GAAG,CAAC,CAAC,CAAC;QAE5F,IAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC1C,IAAM,QAAQ,GAAG,uCAAuC,CAAC;QAEzD,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qEAAqE,EAAE;QACtE,IAAM,IAAI,GAAG,IAAI,sBAAS,CAAC,IAAI,iBAAc,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,IAAI,yBAAsB,CAAC,GAAG,CAAC,CAAC,CAAC;QAE5F,IAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACzC,IAAM,QAAQ,GAAG,uCAAuC,CAAC;QAEzD,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sDAAsD,EAAE;QACvD,IAAM,IAAI,GAAG,IAAI,sBAAS,CAAC,IAAI,iBAAc,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,EAAE,IAAI,yBAAsB,CAAC,GAAG,CAAC,CAAC,CAAC;QAEnG,IAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC1C,IAAM,QAAQ,GAAG,uCAAuC,CAAC;QAEzD,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sEAAsE,EAAE;QACvE,IAAM,IAAI,GAAG,IAAI,sBAAS,CAAC,IAAI,iBAAc,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,EAAE,IAAI,yBAAsB,CAAC,GAAG,CAAC,CAAC,CAAC;QAEnG,IAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACzC,IAAM,QAAQ,GAAG,uCAAuC,CAAC;QAEzD,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/money.pipe.spec.ts b/src/PinkParrot/app/core/angular/money.pipe.spec.ts new file mode 100644 index 000000000..c080ee2cd --- /dev/null +++ b/src/PinkParrot/app/core/angular/money.pipe.spec.ts @@ -0,0 +1,48 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { CurrencyConfig, DecimalSeparatorConfig } from './../'; + +import { MoneyPipe } from './money.pipe'; + +describe('MoneyPipe', () => { + it('should format money values with symbol after number', () => { + const pipe = new MoneyPipe(new CurrencyConfig('EUR', '€'), new DecimalSeparatorConfig(',')); + + const actual = pipe.transform(123.49, []); + const expected = '123,49 €'; + + expect(actual).toBe(expected); + }); + + it('should format money values with symbol after number and one decimal', () => { + const pipe = new MoneyPipe(new CurrencyConfig('EUR', '€'), new DecimalSeparatorConfig(',')); + + const actual = pipe.transform(123.4, []); + const expected = '123,40 €'; + + expect(actual).toBe(expected); + }); + + it('should format money values with symbol before number', () => { + const pipe = new MoneyPipe(new CurrencyConfig('EUR', '€', false), new DecimalSeparatorConfig(',')); + + const actual = pipe.transform(123.49, []); + const expected = '€ 123,49'; + + expect(actual).toBe(expected); + }); + + it('should format money values with symbol before number and one decimal', () => { + const pipe = new MoneyPipe(new CurrencyConfig('EUR', '€', false), new DecimalSeparatorConfig(',')); + + const actual = pipe.transform(123.4, []); + const expected = '€ 123,40'; + + expect(actual).toBe(expected); + }); +}); diff --git a/src/PinkParrot/app/core/angular/money.pipe.ts b/src/PinkParrot/app/core/angular/money.pipe.ts new file mode 100644 index 000000000..6528768f8 --- /dev/null +++ b/src/PinkParrot/app/core/angular/money.pipe.ts @@ -0,0 +1,37 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import * as Ng2 from '@angular/core'; + +import { CurrencyConfig, DecimalSeparatorConfig } from './../configurations'; + +@Ng2.Pipe({ + name: 'money' +}) +export class MoneyPipe { + constructor( + private readonly currency: CurrencyConfig, + private readonly separator: DecimalSeparatorConfig + ) { + } + + public transform(value: number, args: string[]): any { + const money = value.toFixed(2).toString(); + + let result = money.substr(0, money.length - 3) + this.separator.value + '' + money.substr(money.length - 2, 2) + ''; + + if (this.currency.showAfter) { + result = result + ' ' + this.currency.symbol; + } else { + result = this.currency.symbol + ' ' + result; + } + + return result; + } +} + + diff --git a/src/PinkParrot/app/core/angular/shortcut.component.js.map b/src/PinkParrot/app/core/angular/shortcut.component.js.map new file mode 100644 index 000000000..717371a82 --- /dev/null +++ b/src/PinkParrot/app/core/angular/shortcut.component.js.map @@ -0,0 +1 @@ +{"version":3,"file":"shortcut.component.js","sourceRoot":"","sources":["shortcut.component.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;;;;;;;;;;AAEH,IAAY,GAAG,WAAM,eAAe,CAAC,CAAA;AAQrC;IAYI,2BACY,QAAwB,EAAE,eAAe,EACzC,QAAa,EAAE,GAAG,EAAC,MAAM;QADjC,wBAAgC,GAAhC,0BAAgC;QAChC,wBAAqB,GAArB,eAAqB;QADb,aAAQ,GAAR,QAAQ,CAAgB;QACxB,aAAQ,GAAR,QAAQ,CAAK;QANlB,YAAO,GAAG,IAAI,GAAG,CAAC,YAAY,EAAE,CAAC;IAQxC,CAAC;IAEM,oCAAQ,GAAf;QAAA,iBAcC;QAbG,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC;QAE1B,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;YAChB,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAA,CAAC;gBACpC,EAAE,CAAC,CAAC,CAAC,KAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;oBACjB,KAAI,CAAC,IAAI,CAAC,GAAG,CAAC;wBACV,KAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;oBACzB,CAAC,CAAC,CAAC;gBACP,CAAC;gBAED,MAAM,CAAC,KAAK,CAAC;YACjB,CAAC,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IACM,uCAAW,GAAlB;QACI,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;YAChB,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC5C,CAAC;IACL,CAAC;IApCD;QAAC,GAAG,CAAC,KAAK,EAAE;;mDAAA;IAGZ;QAAC,GAAG,CAAC,KAAK,EAAE;;uDAAA;IAGZ;QAAC,GAAG,CAAC,MAAM,EAAE;;sDAAA;IAXjB;QAAC,GAAG,CAAC,SAAS,CAAC;YACX,QAAQ,EAAE,aAAa;YACvB,QAAQ,EAAE,EAAE;SACf,CAAC;;yBAAA;IAuCF,wBAAC;AAAD,CAAC,AAtCD,IAsCC;AAtCY,yBAAiB,oBAsC7B,CAAA"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/shortcut.component.spec.js.map b/src/PinkParrot/app/core/angular/shortcut.component.spec.js.map new file mode 100644 index 000000000..2bfada609 --- /dev/null +++ b/src/PinkParrot/app/core/angular/shortcut.component.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"shortcut.component.spec.js","sourceRoot":"","sources":["shortcut.component.spec.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/shortcut.component.spec.ts b/src/PinkParrot/app/core/angular/shortcut.component.spec.ts new file mode 100644 index 000000000..48e30926e --- /dev/null +++ b/src/PinkParrot/app/core/angular/shortcut.component.spec.ts @@ -0,0 +1,83 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import * as Ng2 from '@angular/core'; + +import { ShortcutService } from './../'; +import { ShortcutComponent } from './shortcut.component'; + +describe('ShortcutComponent', () => { + let shortcutService: ShortcutService; + + beforeEach(() => { + shortcutService = new ShortcutService(); + }); + + it('should instantiate', () => { + const shortcutComponent = new ShortcutComponent(shortcutService, new Ng2.NgZone({})); + + expect(shortcutComponent).toBeDefined(); + }); + + it('should init without keys', () => { + const shortcutComponent = new ShortcutComponent(shortcutService, new Ng2.NgZone({})); + + shortcutComponent.keys = null!; + shortcutComponent.ngOnInit(); + }); + + it('should destroy without keys', () => { + const shortcutComponent = new ShortcutComponent(shortcutService, new Ng2.NgZone({})); + + shortcutComponent.keys = null!; + shortcutComponent.ngOnDestroy(); + }); + + it('should raise event when triggered', () => { + const shortcutComponent = new ShortcutComponent(shortcutService, new Ng2.NgZone({})); + + let isTriggered = false; + + shortcutComponent.keys = 'ctrl+a'; + shortcutComponent.ngOnInit(); + shortcutComponent.trigger.subscribe(() => { isTriggered = true; }); + + shortcutService.trigger('ctrl+a'); + + expect(isTriggered).toBeTruthy(); + }); + + it('should not raise event when triggered but disabled', () => { + const shortcutComponent = new ShortcutComponent(shortcutService, new Ng2.NgZone({})); + + let isTriggered = false; + + shortcutComponent.keys = 'ctrl+a'; + shortcutComponent.ngOnInit(); + shortcutComponent.trigger.subscribe(() => { isTriggered = true; }); + shortcutComponent.disabled = true; + + shortcutService.trigger('ctrl+a'); + + expect(isTriggered).toBeFalsy(); + }); + + it('should not raise event when triggered but destroyed', () => { + const shortcutComponent = new ShortcutComponent(shortcutService, new Ng2.NgZone({})); + + let isTriggered = false; + + shortcutComponent.keys = 'ctrl+a'; + shortcutComponent.ngOnInit(); + shortcutComponent.trigger.subscribe(() => { isTriggered = true; }); + shortcutComponent.ngOnDestroy(); + + shortcutService.trigger('ctrl+a'); + + expect(isTriggered).toBeFalsy(); + }); +}); diff --git a/src/PinkParrot/app/core/angular/shortcut.component.ts b/src/PinkParrot/app/core/angular/shortcut.component.ts new file mode 100644 index 000000000..5cfb935e5 --- /dev/null +++ b/src/PinkParrot/app/core/angular/shortcut.component.ts @@ -0,0 +1,54 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import * as Ng2 from '@angular/core'; + +import { ShortcutService } from './../services/shortcut.service'; + +@Ng2.Component({ + selector: 'gp-shortcut', + template: '' +}) +export class ShortcutComponent implements Ng2.OnInit, Ng2.OnDestroy { + @Ng2.Input() + public keys: string; + + @Ng2.Input() + public disabled: boolean; + + @Ng2.Output() + public trigger = new Ng2.EventEmitter(); + + private lastKeys: string; + + constructor( + private readonly shortcutService: ShortcutService, + private readonly zone: Ng2.NgZone + ) { + } + + public ngOnInit() { + this.lastKeys = this.keys; + + if (this.lastKeys) { + this.shortcutService.on(this.lastKeys, e => { + if (!this.disabled) { + this.zone.run(() => { + this.trigger.next(e); + }); + } + + return false; + }); + } + } + public ngOnDestroy() { + if (this.lastKeys) { + this.shortcutService.off(this.lastKeys); + } + } +} \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/slider.component.html b/src/PinkParrot/app/core/angular/slider.component.html new file mode 100644 index 000000000..dd705a7a8 --- /dev/null +++ b/src/PinkParrot/app/core/angular/slider.component.html @@ -0,0 +1,3 @@ +
+
+
\ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/slider.component.js.map b/src/PinkParrot/app/core/angular/slider.component.js.map new file mode 100644 index 000000000..d30184da8 --- /dev/null +++ b/src/PinkParrot/app/core/angular/slider.component.js.map @@ -0,0 +1 @@ +{"version":3,"file":"slider.component.js","sourceRoot":"","sources":["slider.component.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/slider.component.scss b/src/PinkParrot/app/core/angular/slider.component.scss new file mode 100644 index 000000000..be3c6bb17 --- /dev/null +++ b/src/PinkParrot/app/core/angular/slider.component.scss @@ -0,0 +1,37 @@ +@import '../../theme/_mixins.scss'; + +$bar-height: 12px; + +$thumb-size: 20px; +$thumb-margin: ($thumb-size - $bar-height) * 0.5; + +$color-border: #ccc; +$color-focus: #66afe9; + +.slider { + &-bar { + @include border-radius($bar-height * 0.5); + position: relative; + border: 1px solid $color-border; + margin-bottom: 20px; + margin-top: 5px; + margin-right: $thumb-size * 0.5; + background: white; + height: $bar-height; + } + + &-thumb { + @include border-radius($thumb-size * 0.5); + position: absolute; + width: $thumb-size; + height: $thumb-size; + border: 1px solid $color-border; + background: white; + margin-top: -$thumb-margin; + margin-left: -$thumb-size * 0.5; + } + + &-thumb.focused { + border-color: $color-focus; + } +} \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/slider.component.ts b/src/PinkParrot/app/core/angular/slider.component.ts new file mode 100644 index 000000000..62988c6ed --- /dev/null +++ b/src/PinkParrot/app/core/angular/slider.component.ts @@ -0,0 +1,145 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import * as Ng2 from '@angular/core'; + +@Ng2.Component({ + selector: 'gp-slider', + styles, + template +}) +export class SliderComponent implements Ng2.OnChanges { + private mouseMoveSubscription: Function | null; + private mouseUpSubscription: Function | null; + private centerStartOffset = 0; + private startValue: number; + + @Ng2.ViewChild('bar') + public bar: Ng2.ElementRef; + + @Ng2.ViewChild('thumb') + public thumb: Ng2.ElementRef; + + @Ng2.Input() + public min: number = 0; + + @Ng2.Input() + public max: number = 100; + + @Ng2.Input() + public value: number; + + @Ng2.Output() + public valueChange = new Ng2.EventEmitter(); + + constructor(private readonly renderer: Ng2.Renderer) { } + + public ngOnChanges(changes: Ng2.SimpleChanges) { + const relativeValue = (this.value - this.min) / (this.max - this.min); + + this.setThumbPosition(relativeValue); + } + + public onBarMouseClick(event: MouseEvent) { + const relativeValue = this.getRelativeX(event); + + this.setThumbPosition(relativeValue); + + const newValue = Math.round(relativeValue * (this.max - this.min) + this.min); + + if (newValue !== this.value) { + this.valueChange.emit(newValue); + } + + this.stopEvent(event); + } + + public onThumbMouseDown(event: MouseEvent) { + this.centerStartOffset = event.offsetX - this.thumb.nativeElement.clientWidth * 0.5; + + this.startValue = this.value; + + this.mouseMoveSubscription = + this.renderer.listenGlobal('window', 'mousemove', (e: MouseEvent) => { + this.onMouseMove(e); + }); + + this.mouseUpSubscription = + this.renderer.listenGlobal('window', 'mouseup', (e: MouseEvent) => { + this.onMouseUp(e); + }); + + this.renderer.setElementClass(this.thumb.nativeElement, 'focused', true); + + this.stopEvent(event); + } + + private onMouseMove(event: MouseEvent) { + const relativeValue = this.getRelativeX(event); + + this.setThumbPosition(relativeValue); + + this.stopEvent(event); + } + + private onMouseUp(event: MouseEvent) { + const relativeValue = this.getRelativeX(event); + + const newValue = Math.round(relativeValue * (this.max - this.min) + this.min); + + if (newValue !== this.startValue) { + this.valueChange.emit(newValue); + } + + this.releaseMouseHandlers(); + this.renderer.setElementClass(this.thumb.nativeElement, 'focused', false); + + this.centerStartOffset = 0; + + this.stopEvent(event); + } + + private getRelativeX(event: MouseEvent): number { + const parentOffsetX = this.getParentX(event, this.bar.nativeElement) - this.centerStartOffset; + const parentWidth = this.bar.nativeElement.clientWidth; + + const relativeValue = Math.min(1, Math.max(0, (parentOffsetX - this.centerStartOffset) / parentWidth)); + + return relativeValue; + } + + private getParentX(e: any, container: any): number { + const rect = container.getBoundingClientRect(); + + const x = !!e.touches ? e.touches[0].pageX : e.pageX; + + return x - rect.left; + } + + private setThumbPosition(relativeValue: number) { + relativeValue = Math.min(1, Math.max(0, relativeValue)); + + this.renderer.setElementStyle(this.thumb.nativeElement, 'left', relativeValue * 100 + '%'); + } + + private stopEvent(event: Event) { + event.preventDefault(); + event.stopPropagation(); + } + + private releaseMouseHandlers() { + if (this.mouseMoveSubscription) { + this.mouseMoveSubscription(); + this.mouseMoveSubscription = null; + } + + if (this.mouseUpSubscription) { + this.mouseUpSubscription(); + this.mouseUpSubscription = null; + } + } +} \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/spinner.component.js.map b/src/PinkParrot/app/core/angular/spinner.component.js.map new file mode 100644 index 000000000..041f0584e --- /dev/null +++ b/src/PinkParrot/app/core/angular/spinner.component.js.map @@ -0,0 +1 @@ +{"version":3,"file":"spinner.component.js","sourceRoot":"","sources":["spinner.component.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;;;;;;;;;;AAEH,IAAY,GAAG,WAAM,eAAe,CAAC,CAAA;AAQrC;IACI,0BAAY,OAAuB;QAC/B,IAAM,aAAa,GAAG;YAClB,KAAK,EAAE,EAAE;YACT,MAAM,EAAE,CAAC;YACT,KAAK,EAAE,CAAC;YACR,MAAM,EAAE,CAAC;YACT,OAAO,EAAE,CAAC;YACV,MAAM,EAAE,CAAC;YACT,SAAS,EAAE,CAAC;YACZ,KAAK,EAAE,MAAM;YACb,KAAK,EAAE,GAAG;YACV,KAAK,EAAE,EAAE;YACT,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,KAAK;YACd,SAAS,EAAE,SAAS;YACpB,MAAM,EAAE,CAAC;YACT,QAAQ,EAAE,UAAU;SACvB,CAAC;QAEF,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;QAEtD,IAAI,OAAO,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;IAC3D,CAAC;IA3BL;QAAC,GAAG,CAAC,SAAS,CAAC;YACX,QAAQ,EAAE,YAAY;YACtB,QAAQ,EAAE,EAAE;SACf,CAAC;6CAE2B,UAAU;wBAFrC;IAyBF,uBAAC;AAAD,CAAC,AAxBD,IAwBC;AAxBY,wBAAgB,mBAwB5B,CAAA"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/spinner.component.ts b/src/PinkParrot/app/core/angular/spinner.component.ts new file mode 100644 index 000000000..a32df741a --- /dev/null +++ b/src/PinkParrot/app/core/angular/spinner.component.ts @@ -0,0 +1,40 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import * as Ng2 from '@angular/core'; + +declare var Spinner: any; + +@Ng2.Component({ + selector: 'gp-spinner', + template: '' +}) +export class SpinnerComponent { + constructor(element: Ng2.ElementRef) { + const mediumOptions = { + lines: 12, + length: 5, + width: 2, + radius: 6, + corners: 1, + rotate: 0, + direction: 1, + color: '#000', + speed: 1.5, + trail: 40, + shadow: false, + hwaccel: false, + className: 'spinner', + zIndex: 0, + position: 'relative' + }; + + element.nativeElement.classList.add('spinner-medium'); + + new Spinner(mediumOptions).spin(element.nativeElement); + } +} \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/user-report.component.js.map b/src/PinkParrot/app/core/angular/user-report.component.js.map new file mode 100644 index 000000000..66f959aab --- /dev/null +++ b/src/PinkParrot/app/core/angular/user-report.component.js.map @@ -0,0 +1 @@ +{"version":3,"file":"user-report.component.js","sourceRoot":"","sources":["user-report.component.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;;;;;;;;;;AAEH,IAAY,GAAG,WAAM,eAAe,CAAC,CAAA;AAErC,+BAAiC,qBAAqB,CAAC,CAAA;AAMvD;IACI,6BAAY,MAAwB,EACxB,QAAiB,EAAE,GAAG,EAAC,QAAQ;QAAvC,wBAAyB,GAAzB,mBAAyB;QAAjB,aAAQ,GAAR,QAAQ,CAAS;QAEzB,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACtC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IACrD,CAAC;IAEM,sCAAQ,GAAf;QACI,UAAU,CAAC;YACP,IAAM,GAAG,GAAG,0CAA0C,CAAC;YAEvD,IAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;YAChD,MAAM,CAAC,GAAG,GAAG,GAAG,CAAC;YACjB,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC;YAEpB,IAAM,IAAI,GAAG,QAAQ,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;YAExD,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC/C,CAAC,EAAE,IAAI,CAAC,CAAC;IACb,CAAC;IAxBL;QAAC,GAAG,CAAC,SAAS,CAAC;YACX,QAAQ,EAAE,gBAAgB;YAC1B,QAAQ,EAAE,EAAE;SACf,CAAC;;2BAAA;IAsBF,0BAAC;AAAD,CAAC,AArBD,IAqBC;AArBY,2BAAmB,sBAqB/B,CAAA"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/user-report.component.ts b/src/PinkParrot/app/core/angular/user-report.component.ts new file mode 100644 index 000000000..f96502663 --- /dev/null +++ b/src/PinkParrot/app/core/angular/user-report.component.ts @@ -0,0 +1,37 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import * as Ng2 from '@angular/core'; + +import { UserReportConfig } from './../configurations'; + +@Ng2.Component({ + selector: 'gp-user-report', + template: '' +}) +export class UserReportComponent implements Ng2.OnInit { + constructor(config: UserReportConfig, + private readonly renderer: Ng2.Renderer + ) { + window['_urq'] = window['_urq'] || []; + window['_urq'].push(['initSite', config.siteId]); + } + + public ngOnInit() { + setTimeout(() => { + const url = 'https://cdn.userreport.com/userreport.js'; + + const script = document.createElement('script'); + script.src = url; + script.async = true; + + const node = document.getElementsByTagName('script')[0]; + + node.parentNode.insertBefore(script, node); + }, 4000); + } +} \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/validators.js.map b/src/PinkParrot/app/core/angular/validators.js.map new file mode 100644 index 000000000..67a5d802b --- /dev/null +++ b/src/PinkParrot/app/core/angular/validators.js.map @@ -0,0 +1 @@ +{"version":3,"file":"validators.js","sourceRoot":"","sources":["validators.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAIH;IAAA;IAgBA,CAAC;IAfiB,kBAAO,GAArB,UAAsB,QAAgB,EAAE,QAAgB;QACpD,MAAM,CAAC,UAAC,OAAiC;YACrC,IAAI,CAAC,GAAW,OAAO,CAAC,KAAK,CAAC;YAE9B,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC;gBACxB,MAAM,CAAC,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC;YACpC,CAAC;YAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC;gBACtB,MAAM,CAAC,EAAE,UAAU,EAAE,EAAE,eAAe,EAAE,QAAQ,EAAE,aAAa,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3E,CAAC;YAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC;gBACtB,MAAM,CAAC,EAAE,UAAU,EAAE,EAAE,eAAe,EAAE,QAAQ,EAAE,aAAa,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3E,CAAC;YAED,MAAM,CAAC,EAAE,CAAC;QACd,CAAC,CAAC;IACN,CAAC;IACL,iBAAC;AAAD,CAAC,AAhBD,IAgBC;AAhBY,kBAAU,aAgBtB,CAAA"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/validators.spec.js.map b/src/PinkParrot/app/core/angular/validators.spec.js.map new file mode 100644 index 000000000..b1d9b5c12 --- /dev/null +++ b/src/PinkParrot/app/core/angular/validators.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"validators.spec.js","sourceRoot":"","sources":["validators.spec.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAEH,IAAY,QAAQ,WAAM,gBAAgB,CAAC,CAAA;AAE3C,iBAA2B,OAAO,CAAC,CAAA;AAEnC,QAAQ,CAAC,YAAY,EAAE;IACnB,IAAI,eAAoB,CAAC;IAEzB,UAAU,CAAC;QACP,eAAe,GAAG,aAAU,CAAC,OAAO,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE;QACxC,IAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAE/C,IAAM,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QAErC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,SAAS,EAAE,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE;QACnD,IAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QAE1C,IAAM,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QAErC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE;QACtD,IAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAE5C,IAAM,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QAErC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE;QAChD,IAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QAE3C,IAAM,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QAErC,MAAM,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;IAChC,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/angular/validators.spec.ts b/src/PinkParrot/app/core/angular/validators.spec.ts new file mode 100644 index 000000000..d6ab3e318 --- /dev/null +++ b/src/PinkParrot/app/core/angular/validators.spec.ts @@ -0,0 +1,50 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import * as Ng2Forms from '@angular/forms'; + +import { Validators } from './../'; + +describe('Validators', () => { + let validateBetween: any; + + beforeEach(() => { + validateBetween = Validators.between(10, 200); + }); + + it('should return error when not a number', () => { + const input = new Ng2Forms.FormControl('text'); + + const error = validateBetween(input); + + expect(error.validNumber).toBeFalsy(); + }); + + it('should return error if less than minimum setting', () => { + const input = new Ng2Forms.FormControl(5); + + const error = validateBetween(input); + + expect(error.minValue).toBeDefined(); + }); + + it('should return error if greater than maximum setting', () => { + const input = new Ng2Forms.FormControl(300); + + const error = validateBetween(input); + + expect(error.maxValue).toBeDefined(); + }); + + it('should return empty value when value is valid', () => { + const input = new Ng2Forms.FormControl(50); + + const error = validateBetween(input); + + expect(error).toBeDefined(); + }); +}); diff --git a/src/PinkParrot/app/core/angular/validators.ts b/src/PinkParrot/app/core/angular/validators.ts new file mode 100644 index 000000000..fc3f6d67b --- /dev/null +++ b/src/PinkParrot/app/core/angular/validators.ts @@ -0,0 +1,26 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import * as Ng2Forms from '@angular/forms'; + +export class Validators { + public static between(minValue: number, maxValue: number) { + return (control: Ng2Forms.AbstractControl): { [key: string]: any } => { + let n: number = control.value; + + if (typeof n !== 'number') { + return { 'validNumber': false }; + } else if (n < minValue) { + return { 'minValue': { 'requiredValue': minValue, 'actualValue': n } }; + } else if (n > maxValue) { + return { 'maxValue': { 'requiredValue': maxValue, 'actualValue': n } }; + } + + return {}; + }; + } +} \ No newline at end of file diff --git a/src/PinkParrot/app/core/configurations.js.map b/src/PinkParrot/app/core/configurations.js.map new file mode 100644 index 000000000..56ceaa38a --- /dev/null +++ b/src/PinkParrot/app/core/configurations.js.map @@ -0,0 +1 @@ +{"version":3,"file":"configurations.js","sourceRoot":"","sources":["configurations.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAEH;IACI,sBAAmB,QAAc,EAAE,MAAM;QAA7B,wBAAqB,GAArB,gBAAqB;QAAd,aAAQ,GAAR,QAAQ,CAAM;IAAY,CAAC;IAClD,mBAAC;AAAD,CAAC,AAFD,IAEC;AAFY,oBAAY,eAExB,CAAA;AAED;IACI,gCAAmB,QAAc,EAAE,MAAM;QAA7B,wBAAqB,GAArB,gBAAqB;QAAd,aAAQ,GAAR,QAAQ,CAAM;IAAY,CAAC;IAClD,6BAAC;AAAD,CAAC,AAFD,IAEC;AAFY,8BAAsB,yBAElC,CAAA;AAED;IACI,8BAAmB,QAAyB,EAAE,OAAO;QAAzC,wBAAgC,GAAhC,2BAAgC;QAAzB,aAAQ,GAAR,QAAQ,CAAiB;IAAa,CAAC;IAC9D,2BAAC;AAAD,CAAC,AAFD,IAEC;AAFY,4BAAoB,uBAEhC,CAAA;AAED;IACI,0BAAmB,QAAe,EAAE,MAAM;QAA9B,wBAAsB,GAAtB,iBAAsB;QAAf,aAAQ,GAAR,QAAQ,CAAO;IAAY,CAAC;IACnD,uBAAC;AAAD,CAAC,AAFD,IAEC;AAFY,wBAAgB,mBAE5B,CAAA;AAED;IACI,wBACW,QAAa,EAAE,MAAM,EACrB,QAAe,EAAE,MAAM,EACvB,QAAyB;QAFhC,wBAAoB,GAApB,eAAoB;QACpB,wBAAsB,GAAtB,iBAAsB;QACtB,wBAAgC,GAAhC,WAAgB,SAAS,GAAG,IAAI;QAFzB,aAAQ,GAAR,QAAQ,CAAK;QACb,aAAQ,GAAR,QAAQ,CAAO;QACf,aAAQ,GAAR,QAAQ,CAAiB;IAEpC,CAAC;IACL,qBAAC;AAAD,CAAC,AAPD,IAOC;AAPY,sBAAc,iBAO1B,CAAA"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/configurations.ts b/src/PinkParrot/app/core/configurations.ts new file mode 100644 index 000000000..35067263f --- /dev/null +++ b/src/PinkParrot/app/core/configurations.ts @@ -0,0 +1,31 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +export class ApiUrlConfig { + constructor(public readonly value: string) { } +} + +export class DecimalSeparatorConfig { + constructor(public readonly value: string) { } +} + +export class ProductionModeConfig { + constructor(public readonly isProductionMode: boolean) { } +} + +export class UserReportConfig { + constructor(public readonly siteId: string) { } +} + +export class CurrencyConfig { + constructor( + public readonly code: string, + public readonly symbol: string, + public readonly showAfter = true + ) { + } +} \ No newline at end of file diff --git a/src/PinkParrot/app/core/index.js.map b/src/PinkParrot/app/core/index.js.map new file mode 100644 index 000000000..112ed2a92 --- /dev/null +++ b/src/PinkParrot/app/core/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;;;;AAEH,iBAAc,kBAAkB,CAAC,EAAA;AACjC,iBAAc,sBAAsB,CAAC,EAAA;AACrC,iBAAc,kBAAkB,CAAC,EAAA;AACjC,iBAAc,aAAa,CAAC,EAAA;AAC5B,iBAAc,8BAA8B,CAAC,EAAA;AAC7C,iBAAc,yBAAyB,CAAC,EAAA;AACxC,iBAAc,gCAAgC,CAAC,EAAA;AAC/C,iBAAc,6BAA6B,CAAC,EAAA;AAC5C,iBAAc,0BAA0B,CAAC,EAAA;AACzC,iBAAc,eAAe,CAAC,EAAA;AAC9B,iBAAc,uBAAuB,CAAC,EAAA;AACtC,iBAAc,qBAAqB,CAAC,EAAA;AACpC,iBAAc,mBAAmB,CAAC,EAAA;AAClC,iBAAc,kBAAkB,CAAC,EAAA;AACjC,iBAAc,0BAA0B,CAAC,EAAA;AACzC,iBAAc,wBAAwB,CAAC,EAAA;AACvC,iBAAc,0BAA0B,CAAC,EAAA;AACzC,iBAAc,uBAAuB,CAAC,EAAA;AACtC,iBAAc,qBAAqB,CAAC,EAAA;AACpC,iBAAc,kBAAkB,CAAC,EAAA;AACjC,iBAAc,cAAc,CAAC,EAAA;AAC7B,iBAAc,eAAe,CAAC,EAAA"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/index.ts b/src/PinkParrot/app/core/index.ts new file mode 100644 index 000000000..eeb444dd8 --- /dev/null +++ b/src/PinkParrot/app/core/index.ts @@ -0,0 +1,29 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +export * from './angular/action'; +export * from './angular/validators'; +export * from './configurations'; +export * from './plattform'; +export * from './services/clipboard.service'; +export * from './services/drag.service'; +export * from './services/local-store.service'; +export * from './services/shortcut.service'; +export * from './services/title.service'; +export * from './utils/color'; +export * from './utils/color-palette'; +export * from './utils/date-helper'; +export * from './utils/date-time'; +export * from './utils/duration'; +export * from './utils/immutable-id-map'; +export * from './utils/immutable-list'; +export * from './utils/immutable-object'; +export * from './utils/immutable-set'; +export * from './utils/math-helper'; +export * from './utils/rotation'; +export * from './utils/vec2'; +export * from './utils/rect2'; \ No newline at end of file diff --git a/src/PinkParrot/app/core/plattform.js.map b/src/PinkParrot/app/core/plattform.js.map new file mode 100644 index 000000000..48d4b9937 --- /dev/null +++ b/src/PinkParrot/app/core/plattform.js.map @@ -0,0 +1 @@ +{"version":3,"file":"plattform.js","sourceRoot":"","sources":["plattform.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAIH;IAAA;IAIA,CAAC;IAAD,eAAC;AAAD,CAAC,AAJD,IAIC;AAJqB,gBAAQ,WAI7B,CAAA"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/plattform.ts b/src/PinkParrot/app/core/plattform.ts new file mode 100644 index 000000000..a0adf046e --- /dev/null +++ b/src/PinkParrot/app/core/plattform.ts @@ -0,0 +1,14 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { Observable } from 'rxjs/Observable'; + +export abstract class AppStore { + public abstract select(pathOrMapFn: any, ...paths: string[]): Observable; + + public abstract next(action: any): void; +} \ No newline at end of file diff --git a/src/PinkParrot/app/core/services/clipboard.service.js.map b/src/PinkParrot/app/core/services/clipboard.service.js.map new file mode 100644 index 000000000..8586d43ad --- /dev/null +++ b/src/PinkParrot/app/core/services/clipboard.service.js.map @@ -0,0 +1 @@ +{"version":3,"file":"clipboard.service.js","sourceRoot":"","sources":["clipboard.service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAEH,qBAA4C,MAAM,CAAC,CAAA;AAEtC,+BAAuB,GAAG;IACnC,MAAM,CAAC,IAAI,gBAAgB,EAAE,CAAC;AAClC,CAAC,CAAC;AAEF;IAAA;QACY,iBAAY,GAAG,IAAI,sBAAe,CAAS,EAAE,CAAC,CAAC;IAmB3D,CAAC;IAjBG,sBAAW,kCAAI;aAAf;YACI,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC;QAC7B,CAAC;;;OAAA;IAEM,qCAAU,GAAjB;QACI,IAAI,MAAM,GAAG,EAAE,CAAC;QAEhB,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,UAAA,CAAC;YACzB,MAAM,GAAG,CAAC,CAAC;QACf,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QAEjB,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC;IACxB,CAAC;IAEM,kCAAO,GAAd,UAAe,IAAS;QACpB,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IACL,uBAAC;AAAD,CAAC,AApBD,IAoBC;AApBY,wBAAgB,mBAoB5B,CAAA"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/services/clipboard.service.spec.js.map b/src/PinkParrot/app/core/services/clipboard.service.spec.js.map new file mode 100644 index 000000000..9f34bed18 --- /dev/null +++ b/src/PinkParrot/app/core/services/clipboard.service.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"clipboard.service.spec.js","sourceRoot":"","sources":["clipboard.service.spec.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAEH,iBAA0D,OAAO,CAAC,CAAA;AAElE,QAAQ,CAAC,iBAAiB,EAAE;IAExB,EAAE,CAAC,iCAAiC,EAAE;QAClC,IAAM,gBAAgB,GAAG,0BAAuB,EAAE,CAAC;QAEnD,MAAM,CAAC,gBAAgB,CAAC,CAAC,WAAW,EAAE,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oBAAoB,EAAE;QACrB,IAAM,gBAAgB,GAAG,IAAI,mBAAgB,EAAE,CAAC;QAEhD,MAAM,CAAC,gBAAgB,CAAC,CAAC,WAAW,EAAE,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE;QACnD,IAAM,gBAAgB,GAAG,IAAI,mBAAgB,EAAE,CAAC;QAEhD,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE;QAClC,IAAM,gBAAgB,GAAG,IAAI,mBAAgB,EAAE,CAAC;QAEhD,gBAAgB,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAEtC,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE;QACzC,IAAM,gBAAgB,GAAG,IAAI,mBAAgB,EAAE,CAAC;QAEhD,IAAI,IAAI,GAAG,EAAE,CAAC;QAEd,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,UAAA,CAAC;YAC7B,IAAI,GAAG,CAAC,CAAC;QACb,CAAC,CAAC,CAAC;QAEH,gBAAgB,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAEtC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/services/clipboard.service.spec.ts b/src/PinkParrot/app/core/services/clipboard.service.spec.ts new file mode 100644 index 000000000..d705b2799 --- /dev/null +++ b/src/PinkParrot/app/core/services/clipboard.service.spec.ts @@ -0,0 +1,51 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { ClipboardService, ClipboardServiceFactory } from './../'; + +describe('ShortcutService', () => { + + it('should instantiate from factory', () => { + const clipboardService = ClipboardServiceFactory(); + + expect(clipboardService).toBeDefined(); + }); + + it('should instantiate', () => { + const clipboardService = new ClipboardService(); + + expect(clipboardService).toBeDefined(); + }); + + it('should return empty string if clipboard is empty', () => { + const clipboardService = new ClipboardService(); + + expect(clipboardService.selectText()).toBe(''); + }); + + it('should get value from clipboard', () => { + const clipboardService = new ClipboardService(); + + clipboardService.setText('MyContent'); + + expect(clipboardService.selectText()).toBe('MyContent'); + }); + + it('should raise subject when setting text', () => { + const clipboardService = new ClipboardService(); + + let text = ''; + + clipboardService.text.subscribe(t => { + text = t; + }); + + clipboardService.setText('MyContent'); + + expect(text).toBe('MyContent'); + }); +}); diff --git a/src/PinkParrot/app/core/services/clipboard.service.ts b/src/PinkParrot/app/core/services/clipboard.service.ts new file mode 100644 index 000000000..94b6fabe9 --- /dev/null +++ b/src/PinkParrot/app/core/services/clipboard.service.ts @@ -0,0 +1,34 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { BehaviorSubject, Observable } from 'rxjs'; + +export const ClipboardServiceFactory = () => { + return new ClipboardService(); +}; + +export class ClipboardService { + private textInstance = new BehaviorSubject(''); + + public get text(): Observable { + return this.textInstance; + } + + public selectText(): string { + let result = ''; + + this.textInstance.subscribe(t => { + result = t; + }).unsubscribe(); + + return result || ''; + } + + public setText(text: any) { + this.textInstance.next(text); + } +} \ No newline at end of file diff --git a/src/PinkParrot/app/core/services/drag.service.js.map b/src/PinkParrot/app/core/services/drag.service.js.map new file mode 100644 index 000000000..772840f5f --- /dev/null +++ b/src/PinkParrot/app/core/services/drag.service.js.map @@ -0,0 +1 @@ +{"version":3,"file":"drag.service.js","sourceRoot":"","sources":["drag.service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAEH,qBAAoC,MAAM,CAAC,CAAA;AAM9B,0BAAkB,GAAG;IAC9B,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;AAC7B,CAAC,CAAC;AAEF;IAAA;QACY,aAAQ,GAAC,SAAS,GAAG,IAAI,cAAO,EAAa,CAAC;IAS1D,CAAC;IAPG,sBAAW,6BAAI;aAAf;YACI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;QAC1B,CAAC;;;OAAA;IAEM,8BAAQ,GAAf,UAAgB,KAAgB;QAC5B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IACL,kBAAC;AAAD,CAAC,AAVD,IAUC;AAVY,mBAAW,cAUvB,CAAA"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/services/drag.service.spec.js.map b/src/PinkParrot/app/core/services/drag.service.spec.js.map new file mode 100644 index 000000000..2d331c434 --- /dev/null +++ b/src/PinkParrot/app/core/services/drag.service.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"drag.service.spec.js","sourceRoot":"","sources":["drag.service.spec.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAEH,iBAIO,OAAO,CAAC,CAAA;AAEf,QAAQ,CAAC,aAAa,EAAE;IACpB,EAAE,CAAC,iCAAiC,EAAE;QAClC,IAAM,WAAW,GAAG,qBAAkB,EAAE,CAAC;QAEzC,MAAM,CAAC,WAAW,CAAC,CAAC,WAAW,EAAE,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oBAAoB,EAAE;QACrB,IAAM,WAAW,GAAG,IAAI,cAAW,EAAE,CAAC;QAEtC,MAAM,CAAC,WAAW,CAAC,CAAC,WAAW,EAAE,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE;QAC1C,IAAI,YAAY,GAAc,IAAI,GAAG,IAAI,CAAC;QAE1C,IAAM,WAAW,GAAG,IAAI,cAAW,EAAE,CAAC;QAEtC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,UAAA,CAAC;YACxB,YAAY,GAAG,CAAC,CAAC;QACrB,CAAC,CAAC,CAAC;QAEH,IAAM,KAAK,GAAc,EAAE,QAAQ,EAAE,IAAI,EAAA,CAAA;QAAA,CAAC,EAAE,KAAK,CAAA;QAAE,IAAI,CAAA;QAAA,CAAC,EAAE,UAAU,CAAA;QAAE,IAAI,CAAA;QAAA,CAAE,AAAD,CAAA;IAAC,CAAC,CAAA,CAAC;IAE9E,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE5B,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACrC,CAAC,CAAC,CAAC;AACL,CAAC"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/services/drag.service.spec.ts b/src/PinkParrot/app/core/services/drag.service.spec.ts new file mode 100644 index 000000000..a3d9cf2ed --- /dev/null +++ b/src/PinkParrot/app/core/services/drag.service.spec.ts @@ -0,0 +1,42 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { + DragService, + DragServiceFactory, + DropEvent +} from './../'; + +describe('DragService', () => { + it('should instantiate from factory', () => { + const dragService = DragServiceFactory(); + + expect(dragService).toBeDefined(); + }); + + it('should instantiate', () => { + const dragService = new DragService(); + + expect(dragService).toBeDefined(); + }); + + it('should raise event handler when dropped', () => { + let emittedEvent: DropEvent | null = null; + + const dragService = new DragService(); + + dragService.drop.subscribe(e => { + emittedEvent = e; + }); + + const event: DropEvent = { position: null!, model: null!, dropTarget: null! }; + + dragService.emitDrop(event); + + expect(emittedEvent).toBe(event); + }); +}); \ No newline at end of file diff --git a/src/PinkParrot/app/core/services/drag.service.ts b/src/PinkParrot/app/core/services/drag.service.ts new file mode 100644 index 000000000..0e2e3d1d4 --- /dev/null +++ b/src/PinkParrot/app/core/services/drag.service.ts @@ -0,0 +1,28 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { Subject, Observable } from 'rxjs'; + +import { Vec2 } from './../utils/vec2'; + +export interface DropEvent { position: Vec2; model: any; dropTarget: string; } + +export const DragServiceFactory = () => { + return new DragService(); +}; + +export class DragService { + private readonly dropEvent = new Subject(); + + public get drop(): Observable { + return this.dropEvent; + } + + public emitDrop(event: DropEvent) { + this.dropEvent.next(event); + } +} \ No newline at end of file diff --git a/src/PinkParrot/app/core/services/local-store.service.js.map b/src/PinkParrot/app/core/services/local-store.service.js.map new file mode 100644 index 000000000..b0dbf7151 --- /dev/null +++ b/src/PinkParrot/app/core/services/local-store.service.js.map @@ -0,0 +1 @@ +{"version":3,"file":"local-store.service.js","sourceRoot":"","sources":["local-store.service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAEU,gCAAwB,GAAG;IACpC,MAAM,CAAC,IAAI,iBAAiB,EAAE,CAAC;AACnC,CAAC,CAAC;AAEF;IAAA;QACY,UAAK,GAAQ,YAAY,CAAC;IAatC,CAAC;IAXU,0CAAc,GAArB,UAAsB,KAAU;QAC5B,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACvB,CAAC;IAEM,+BAAG,GAAV,UAAW,GAAW;QAClB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACnC,CAAC;IAEM,+BAAG,GAAV,UAAW,GAAW,EAAE,KAAU;QAC9B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACnC,CAAC;IACL,wBAAC;AAAD,CAAC,AAdD,IAcC;AAdY,yBAAiB,oBAc7B,CAAA"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/services/local-store.service.spec.js.map b/src/PinkParrot/app/core/services/local-store.service.spec.js.map new file mode 100644 index 000000000..428a9350c --- /dev/null +++ b/src/PinkParrot/app/core/services/local-store.service.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"local-store.service.spec.js","sourceRoot":"","sources":["local-store.service.spec.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAEH,iBAA4D,OAAO,CAAC,CAAA;AAEpE,QAAQ,CAAC,YAAY,EAAE;IACnB,EAAE,CAAC,iCAAiC,EAAE;QAClC,IAAM,iBAAiB,GAAG,2BAAwB,EAAE,CAAC;QAErD,MAAM,CAAC,iBAAiB,CAAC,CAAC,WAAW,EAAE,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oBAAoB,EAAE;QACrB,IAAM,iBAAiB,GAAG,IAAI,oBAAiB,EAAE,CAAC;QAElD,MAAM,CAAC,iBAAiB,CAAC,CAAC,WAAW,EAAE,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE;QAC3C,IAAM,iBAAiB,GAAG,IAAI,oBAAiB,EAAE,CAAC;QAElD,IAAI,SAAS,GAAG,EAAE,EAAE,SAAS,GAAG,EAAE,CAAC;QAEnC,iBAAiB,CAAC,cAAc,CAAC;YAC7B,OAAO,EAAE,UAAC,CAAS,EAAE,CAAS;gBAC1B,SAAS,GAAG,CAAC,CAAC;gBACd,SAAS,GAAG,CAAC,CAAC;YAClB,CAAC;SACJ,CAAC,CAAC;QAEH,iBAAiB,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAExC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAChC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE;QAC3C,IAAM,iBAAiB,GAAG,IAAI,oBAAiB,EAAE,CAAC;QAElD,IAAI,SAAS,GAAG,EAAE,CAAC;QAEnB,iBAAiB,CAAC,cAAc,CAAC;YAC7B,OAAO,EAAE,UAAC,GAAW;gBACjB,SAAS,GAAG,GAAG,CAAC;gBAEhB,MAAM,CAAC,OAAO,CAAC;YACnB,CAAC;SACJ,CAAC,CAAC;QAEH,IAAI,WAAW,GAAG,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAEjD,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAChC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/services/local-store.service.spec.ts b/src/PinkParrot/app/core/services/local-store.service.spec.ts new file mode 100644 index 000000000..0c49c57a8 --- /dev/null +++ b/src/PinkParrot/app/core/services/local-store.service.spec.ts @@ -0,0 +1,59 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { LocalStoreService, LocalStoreServiceFactory } from './../'; + +describe('LocalStore', () => { + it('should instantiate from factory', () => { + const localStoreService = LocalStoreServiceFactory(); + + expect(localStoreService).toBeDefined(); + }); + + it('should instantiate', () => { + const localStoreService = new LocalStoreService(); + + expect(localStoreService).toBeDefined(); + }); + + it('should call local store for set function', () => { + const localStoreService = new LocalStoreService(); + + let passedKey = '', passedVal = ''; + + localStoreService.configureStore({ + setItem: (k: string, v: string) => { + passedKey = k; + passedVal = v; + } + }); + + localStoreService.set('mykey', 'myval'); + + expect(passedKey).toBe('mykey'); + expect(passedVal).toBe('myval'); + }); + + it('should call local store for get function', () => { + const localStoreService = new LocalStoreService(); + + let passedKey = ''; + + localStoreService.configureStore({ + getItem: (key: string): string => { + passedKey = key; + + return 'myval'; + } + }); + + let returnedVal = localStoreService.get('mykey'); + + expect(passedKey).toBe('mykey'); + expect(returnedVal).toBe('myval'); + }); +}); diff --git a/src/PinkParrot/app/core/services/local-store.service.ts b/src/PinkParrot/app/core/services/local-store.service.ts new file mode 100644 index 000000000..a007b90ab --- /dev/null +++ b/src/PinkParrot/app/core/services/local-store.service.ts @@ -0,0 +1,26 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +export const LocalStoreServiceFactory = () => { + return new LocalStoreService(); +}; + +export class LocalStoreService { + private store: any = localStorage; + + public configureStore(store: any) { + this.store = store; + } + + public get(key: string): any { + return this.store.getItem(key); + } + + public set(key: string, value: any) { + this.store.setItem(key, value); + } +} \ No newline at end of file diff --git a/src/PinkParrot/app/core/services/shortcut.service.js.map b/src/PinkParrot/app/core/services/shortcut.service.js.map new file mode 100644 index 000000000..e55167fc9 --- /dev/null +++ b/src/PinkParrot/app/core/services/shortcut.service.js.map @@ -0,0 +1 @@ +{"version":3,"file":"shortcut.service.js","sourceRoot":"","sources":["shortcut.service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAEU,8BAAsB,GAAG;IAClC,MAAM,CAAC,IAAI,eAAe,EAAE,CAAC;AACjC,CAAC,CAAC;AAEF;IAAA;IAcA,CAAC;IAbU,4BAAE,GAAT,UAAU,IAAY,EAAE,QAAmD;QACvE,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,UAAC,KAAK,EAAE,KAAK;YACrC,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;IACP,CAAC;IAEM,6BAAG,GAAV,UAAW,IAAY;QACnB,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IAEM,iCAAO,GAAd,UAAe,IAAY;QACvB,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IACL,sBAAC;AAAD,CAAC,AAdD,IAcC;AAdY,uBAAe,kBAc3B,CAAA"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/services/shortcut.service.spec.js.map b/src/PinkParrot/app/core/services/shortcut.service.spec.js.map new file mode 100644 index 000000000..3ad72f41c --- /dev/null +++ b/src/PinkParrot/app/core/services/shortcut.service.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"shortcut.service.spec.js","sourceRoot":"","sources":["shortcut.service.spec.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAEH,iBAAwD,OAAO,CAAC,CAAA;AAEhE,QAAQ,CAAC,iBAAiB,EAAE;IACxB,EAAE,CAAC,iCAAiC,EAAE;QAClC,IAAM,eAAe,GAAG,yBAAsB,EAAE,CAAC;QAEjD,MAAM,CAAC,eAAe,CAAC,CAAC,WAAW,EAAE,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oBAAoB,EAAE;QACrB,IAAM,eAAe,GAAG,IAAI,kBAAe,EAAE,CAAC;QAE9C,MAAM,CAAC,eAAe,CAAC,CAAC,WAAW,EAAE,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mCAAmC,EAAE;QACpC,IAAM,eAAe,GAAG,IAAI,kBAAe,EAAE,CAAC;QAE9C,IAAI,WAAW,GAAG,KAAK,CAAC;QAExB,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,UAAA,CAAC,IAAM,WAAW,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3D,eAAe,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAElC,MAAM,CAAC,WAAW,CAAC,CAAC,UAAU,EAAE,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE;QACzD,IAAM,eAAe,GAAG,IAAI,kBAAe,EAAE,CAAC;QAE9C,IAAI,WAAW,GAAG,KAAK,CAAC;QAExB,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,UAAA,CAAC,IAAM,WAAW,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3D,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC9B,eAAe,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAElC,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,EAAE,CAAC;IACpC,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/services/shortcut.service.spec.ts b/src/PinkParrot/app/core/services/shortcut.service.spec.ts new file mode 100644 index 000000000..04cd457d9 --- /dev/null +++ b/src/PinkParrot/app/core/services/shortcut.service.spec.ts @@ -0,0 +1,45 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { ShortcutService, ShortcutServiceFactory } from './../'; + +describe('ShortcutService', () => { + it('should instantiate from factory', () => { + const shortcutService = ShortcutServiceFactory(); + + expect(shortcutService).toBeDefined(); + }); + + it('should instantiate', () => { + const shortcutService = new ShortcutService(); + + expect(shortcutService).toBeDefined(); + }); + + it('should raise event when triggered', () => { + const shortcutService = new ShortcutService(); + + let isTriggered = false; + + shortcutService.on('ctrl+a', e => { isTriggered = true; }); + shortcutService.trigger('ctrl+a'); + + expect(isTriggered).toBeTruthy(); + }); + + it('should not raise event when triggered but unsubscribed', () => { + const shortcutService = new ShortcutService(); + + let isTriggered = false; + + shortcutService.on('ctrl+a', e => { isTriggered = true; }); + shortcutService.off('ctrl+a'); + shortcutService.trigger('ctrl+a'); + + expect(isTriggered).toBeFalsy(); + }); +}); diff --git a/src/PinkParrot/app/core/services/shortcut.service.ts b/src/PinkParrot/app/core/services/shortcut.service.ts new file mode 100644 index 000000000..728a92681 --- /dev/null +++ b/src/PinkParrot/app/core/services/shortcut.service.ts @@ -0,0 +1,26 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +export const ShortcutServiceFactory = () => { + return new ShortcutService(); +}; + +export class ShortcutService { + public on(keys: string, callback: (e: KeyboardEvent, combo: string) => void) { + return Mousetrap.bind(keys, (event, combo) => { + return callback(event, combo); + }); + } + + public off(keys: string) { + Mousetrap.unbind(keys); + } + + public trigger(keys: string) { + Mousetrap.trigger(keys); + } +} \ No newline at end of file diff --git a/src/PinkParrot/app/core/services/title.service.js.map b/src/PinkParrot/app/core/services/title.service.js.map new file mode 100644 index 000000000..b503f7939 --- /dev/null +++ b/src/PinkParrot/app/core/services/title.service.js.map @@ -0,0 +1 @@ +{"version":3,"file":"title.service.js","sourceRoot":"","sources":["title.service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAEH;IAAA;IAC+D,CAAC;IAAD,mBAAC;AAAD,CAAC,AADhE,IACgE;AADnD,oBAAY,eACuC,CAAA;AAAE,CAAC,CAAC,CAAC;AAGxD,2BAAmB,GAAG,UAAC,MAAoB;IACpD,MAAM,CAAC,IAAI,YAAY,CAAC,MAAM,CAAC,CAAC;AACpC,CAAC,CAAC;AAEF;IACI,sBAAoB,QAAe,EAAE,YAAY;QAArC,wBAAuB,GAAvB,iBAAuB;QAAf,aAAQ,GAAR,QAAQ,CAAO;IAAkB,CAAC;IAE/C,+BAAQ,GAAf,UAAgB,GAAW,EAAE,UAAqC;QAC9D,IAAI,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QAEzC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;YACT,MAAM,CAAC;QACX,CAAC;QAED,GAAG,CAAC,CAAC,IAAI,SAAS,IAAI,UAAU,CAAC,CAAC,CAAC;YAC/B,EAAE,CAAC,CAAC,UAAU,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;gBACvC,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,MAAI,SAAS,MAAG,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;YACnE,CAAC;QACL,CAAC;QAED,QAAQ,CAAC,KAAK,GAAG,KAAK,CAAC;IAC3B,CAAC;IACL,mBAAC;AAAD,CAAC,AAlBD,IAkBC;AAlBY,oBAAY,eAkBxB,CAAA"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/services/title.service.spec.js.map b/src/PinkParrot/app/core/services/title.service.spec.js.map new file mode 100644 index 000000000..61530c10e --- /dev/null +++ b/src/PinkParrot/app/core/services/title.service.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"title.service.spec.js","sourceRoot":"","sources":["title.service.spec.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAEH,iBAIO,OAAO,CAAC,CAAA;AAEf,QAAQ,CAAC,cAAc,EAAE;IACrB,UAAU,CAAC;QACP,QAAQ,CAAC,KAAK,GAAG,EAAE,CAAC;IACxB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE;QAClC,IAAM,YAAY,GAAG,sBAAmB,CAAC,IAAI,eAAY,CAAC,EAAE,CAAC,CAAC,CAAC;QAE/D,MAAM,CAAC,YAAY,CAAC,CAAC,WAAW,EAAE,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oBAAoB,EAAE;QACrB,IAAM,YAAY,GAAG,IAAI,eAAY,CAAC,IAAI,eAAY,CAAC,EAAE,CAAC,CAAC,CAAC;QAE5D,MAAM,CAAC,YAAY,CAAC,CAAC,WAAW,EAAE,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gEAAgE,EAAE;QACjE,IAAM,YAAY,GAAG,IAAI,eAAY,CAAC,IAAI,eAAY,CAAC,EAAE,CAAC,CAAC,CAAC;QAE5D,YAAY,CAAC,QAAQ,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QAErC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oEAAoE,EAAE;QACrE,IAAM,MAAM,GAA8B;YACtC,KAAK,EAAE,aAAa;SACvB,CAAC;QAEF,IAAM,YAAY,GAAG,IAAI,eAAY,CAAC,IAAI,eAAY,CAAC,MAAM,CAAC,CAAC,CAAC;QAEhE,YAAY,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAEnC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qFAAqF,EAAE;QACtF,IAAM,MAAM,GAA8B;YACtC,KAAK,EAAE,qBAAqB;SAC/B,CAAC;QAEF,IAAM,YAAY,GAAG,IAAI,eAAY,CAAC,IAAI,eAAY,CAAC,MAAM,CAAC,CAAC,CAAC;QAEhE,YAAY,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QAEpD,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/services/title.service.spec.ts b/src/PinkParrot/app/core/services/title.service.spec.ts new file mode 100644 index 000000000..95c25cd0e --- /dev/null +++ b/src/PinkParrot/app/core/services/title.service.spec.ts @@ -0,0 +1,62 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { + TitlesConfig, + TitleService, + TitleServiceFactory +} from './../'; + +describe('TitleService', () => { + beforeEach(() => { + document.title = ''; + }); + + it('should instantiate from factory', () => { + const titleService = TitleServiceFactory(new TitlesConfig({})); + + expect(titleService).toBeDefined(); + }); + + it('should instantiate', () => { + const titleService = new TitleService(new TitlesConfig({})); + + expect(titleService).toBeDefined(); + }); + + it('should do nothing when title key is not found in configuration', () => { + const titleService = new TitleService(new TitlesConfig({})); + + titleService.setTitle('invalid', {}); + + expect(document.title).toBe(''); + }); + + it('should set document title when title key is found in configuration', () => { + const titles: { [key: string]: string } = { + found: 'found-title' + }; + + const titleService = new TitleService(new TitlesConfig(titles)); + + titleService.setTitle('found', {}); + + expect(document.title).toBe('found-title'); + }); + + it('should set document title to formatted string when title key found in configuration', () => { + const titles: { [key: string]: string } = { + found: 'my {value} in title' + }; + + const titleService = new TitleService(new TitlesConfig(titles)); + + titleService.setTitle('found', { value: 'secret' }); + + expect(document.title).toBe('my secret in title'); + }); +}); diff --git a/src/PinkParrot/app/core/services/title.service.ts b/src/PinkParrot/app/core/services/title.service.ts new file mode 100644 index 000000000..ec2921376 --- /dev/null +++ b/src/PinkParrot/app/core/services/title.service.ts @@ -0,0 +1,34 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +export class TitlesConfig { + constructor(public readonly value: { [key: string]: string }) { } +} + +export const TitleServiceFactory = (titles: TitlesConfig) => { + return new TitleService(titles); +}; + +export class TitleService { + constructor(private readonly titles: TitlesConfig) { } + + public setTitle(key: string, parameters: { [key: string]: string }) { + let title = this.titles.value[key] || ''; + + if (!title) { + return; + } + + for (let parameter in parameters) { + if (parameters.hasOwnProperty(parameter)) { + title = title.replace(`{${parameter}}`, parameters[parameter]); + } + } + + document.title = title; + } +} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/color-palette.js.map b/src/PinkParrot/app/core/utils/color-palette.js.map new file mode 100644 index 000000000..f91ad7f8a --- /dev/null +++ b/src/PinkParrot/app/core/utils/color-palette.js.map @@ -0,0 +1 @@ +{"version":3,"file":"color-palette.js","sourceRoot":"","sources":["color-palette.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAEH,sBAAsB,SAAS,CAAC,CAAA;AAEhC,IAAM,OAAO,GAAG;IACV,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC;IACzF,OAAO,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC;IACtF,IAAI,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC;IACxF,MAAM,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC;IACzF,OAAO,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC;IACvF,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC;CAC5F,CAAC;AAEF;IACI,sBACW,QAAe,EAAE,KAAO,EACxB,QAAqB,EAAE,KAAK;QADnC,wBAAsB,GAAtB,iBAAsB;QAAE,qBAAO,GAAP,UAAO;QAC/B,wBAA4B,GAA5B,uBAA4B;QADrB,aAAQ,GAAR,QAAQ,CAAO;QACf,aAAQ,GAAR,QAAQ,CAAa;IAEhC,CAAC;IAEa,mBAAM,GAApB;QACI,IAAM,MAAM,GAAY,EAAE,CAAC;QAE3B,GAAG,CAAC,CAAC,IAAI,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC;YACtB,EAAE,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;gBAC9B,IAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;gBAE5B,GAAG,CAAC,CAAc,UAAM,EAAN,iBAAM,EAAN,oBAAM,EAAN,IAAM,CAAC;oBAApB,IAAI,KAAK,eAAA;oBACV,MAAM,CAAC,IAAI,CAAC,aAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;iBACxC;YACL,CAAC;QACL,CAAC;QAED,MAAM,CAAC,IAAI,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/C,CAAC;IACL,mBAAC;AAAD,CAAC,AAtBD,IAsBC;AAtBY,oBAAY,eAsBxB,CAAA"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/color-palette.spec.js.map b/src/PinkParrot/app/core/utils/color-palette.spec.js.map new file mode 100644 index 000000000..62dd351eb --- /dev/null +++ b/src/PinkParrot/app/core/utils/color-palette.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"color-palette.spec.js","sourceRoot":"","sources":["color-palette.spec.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAEH,iBAA6B,OAAO,CAAC,CAAA;AAErC,QAAQ,CAAC,cAAc,EAAE;IACrB,EAAE,CAAC,wBAAwB,EAAE;QACzB,IAAM,OAAO,GAAG,eAAY,CAAC,MAAM,EAAE,CAAC;QAEtC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/color-palette.spec.ts b/src/PinkParrot/app/core/utils/color-palette.spec.ts new file mode 100644 index 000000000..1126c3aed --- /dev/null +++ b/src/PinkParrot/app/core/utils/color-palette.spec.ts @@ -0,0 +1,16 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { ColorPalette } from './../'; + +describe('ColorPalatte', () => { + it('should generate colors', () => { + const palette = ColorPalette.colors(); + + expect(palette.colors.length).toBeGreaterThan(20); + }); +}); diff --git a/src/PinkParrot/app/core/utils/color-palette.ts b/src/PinkParrot/app/core/utils/color-palette.ts new file mode 100644 index 000000000..59f04440e --- /dev/null +++ b/src/PinkParrot/app/core/utils/color-palette.ts @@ -0,0 +1,41 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { Color } from './color'; + +const BREWERS = { + greys: [0xffffff, 0xF0F0F0, 0xbdbdbd, 0x969696, 0x737373, 0x525252, 0x252525, 0x000000], + oranges: [0xfee6ce, 0xfdd0a2, 0xfdae6b, 0xfd8d3c, 0xf16913, 0xd94801, 0xa63603, 0x7f2704], + reds: [0xfee0d2, 0xfcbba1, 0xfc9272, 0xfb6a4a, 0xef3b2c, 0xcb181d, 0xa50f15, 0x67000d], + greens: [0xe5f5e0, 0xc7e9c0, 0xa1d99b, 0x74c476, 0x41ab5d, 0x238b45, 0x006d2c, 0x00441b], + purples: [0xefedf5, 0xdadaeb, 0xbcbddc, 0x9e9ac8, 0x807dba, 0x6a51a3, 0x54278f, 0x3f007d], + blues: [0xdeebf7, 0xc6dbef, 0x9ecae1, 0x6baed6, 0x4292c6, 0x2171b5, 0x08519c, 0x08306b] +}; + +export class ColorPalette { + constructor( + public readonly colors: Color[], + public readonly defaultColor: Color + ) { + } + + public static colors(): ColorPalette { + const colors: Color[] = []; + + for (let key in BREWERS) { + if (BREWERS.hasOwnProperty(key)) { + const brewer = BREWERS[key]; + + for (let color of brewer) { + colors.push(Color.fromNumber(color)); + } + } + } + + return new ColorPalette(colors, colors[7]); + } +} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/color.js.map b/src/PinkParrot/app/core/utils/color.js.map new file mode 100644 index 000000000..861e7f79d --- /dev/null +++ b/src/PinkParrot/app/core/utils/color.js.map @@ -0,0 +1 @@ +{"version":3,"file":"color.js","sourceRoot":"","sources":["color.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/color.spec.js.map b/src/PinkParrot/app/core/utils/color.spec.js.map new file mode 100644 index 000000000..fea96e746 --- /dev/null +++ b/src/PinkParrot/app/core/utils/color.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"color.spec.js","sourceRoot":"","sources":["color.spec.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/color.spec.ts b/src/PinkParrot/app/core/utils/color.spec.ts new file mode 100644 index 000000000..52d7d22bc --- /dev/null +++ b/src/PinkParrot/app/core/utils/color.spec.ts @@ -0,0 +1,273 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { Color } from './../'; + +describe('Color', () => { + it('should instantiate', () => { + const color = new Color(0.3, 0.6, 0.9); + + expect(color.r).toBe(0.3); + expect(color.g).toBe(0.6); + expect(color.b).toBe(0.9); + }); + + it('should adjust values when instantiating', () => { + const color = new Color(-1, 0.5, 2); + + expect(color.r).toBe(0); + expect(color.g).toBe(0.5); + expect(color.b).toBe(1); + }); + + it('should convert to color', () => { + const color = Color.fromHex(23, 46, 59); + + expect(color.toNumber()).toBe(0x234659); + }); + + it('should convert to string', () => { + const color = Color.fromHex(23, 46, 59); + + expect(color.toString()).toBe('#234659'); + }); + + it('should convert to string with leading zeros', () => { + const color = Color.fromHex(3, 6, 9); + + expect(color.toString()).toBe('#030609'); + }); + + it('should be created from long string', () => { + const color = Color.fromValue('#336699'); + + expect(color.r).toBe(0.2); + expect(color.g).toBe(0.4); + expect(color.b).toBe(0.6); + }); + + it('should be created from short string', () => { + const color = Color.fromValue('#369'); + + expect(color.r).toBe(0.2); + expect(color.g).toBe(0.4); + expect(color.b).toBe(0.6); + }); + + it('should be created from rgb string', () => { + const color = Color.fromValue('rgb(51, 102, 153)'); + + expect(color.r).toBe(0.2); + expect(color.g).toBe(0.4); + expect(color.b).toBe(0.6); + }); + + it('should be created from rgb number', () => { + const color = Color.fromValue(0x336699); + + expect(color.r).toBe(0.2); + expect(color.g).toBe(0.4); + expect(color.b).toBe(0.6); + }); + + it('should be created from rgb values', () => { + const color = Color.fromHex(33, 66, 99); + + expect(color.r).toBe(0.2); + expect(color.g).toBe(0.4); + expect(color.b).toBe(0.6); + }); + + it('should convert from hsl with black', () => { + const color = Color.fromHsl(0, 0, 0); + + expect(color.r).toBe(0); + expect(color.g).toBe(0); + expect(color.b).toBe(0); + }); + + it('should convert from hsl with dark black', () => { + const color = Color.fromHsl(0, 1, 0.1); + + expect(color.r).toBe(0.2); + expect(color.g).toBe(0); + expect(color.b).toBe(0); + }); + + it('should convert from hsl with red', () => { + const color = Color.fromHsl(0, 1, 0.5); + + expect(color.r).toBeCloseTo(1, 1); + expect(color.g).toBe(0); + expect(color.b).toBe(0); + }); + + it('should convert from hsl with yellow', () => { + const color = Color.fromHsl(60, 1, 0.5); + + expect(color.r).toBeCloseTo(1, 1); + expect(color.g).toBeCloseTo(1, 1); + expect(color.b).toBe(0); + }); + + it('should convert from hsl with blue', () => { + const color = Color.fromHsl(120, 1, 0.5); + + expect(color.r).toBe(0); + expect(color.g).toBe(1); + expect(color.b).toBe(0); + }); + + it('should convert from hsl with turkis', () => { + const color = Color.fromHsl(180, 1, 0.5); + + expect(color.r).toBe(0); + expect(color.g).toBeCloseTo(1, 1); + expect(color.b).toBeCloseTo(1, 1); + }); + + it('should convert from hsv with red', () => { + const color = Color.fromHsv(240, 1, 1); + + expect(color.r).toBe(0); + expect(color.g).toBe(0); + expect(color.b).toBe(1); + }); + + it('should convert from hsv with pink', () => { + const color = Color.fromHsv(300, 1, 1); + + expect(color.r).toBe(1); + expect(color.g).toBe(0); + expect(color.b).toBe(1); + }); + + it('should convert from hsl with another red', () => { + const color = Color.fromHsl(360, 1, 0.5); + + expect(color.r).toBeCloseTo(1, 1); + expect(color.g).toBe(0); + expect(color.b).toBe(0); + }); + + it('should convert from hsv with red', () => { + const color = Color.fromHsv(0, 1, 1); + + expect(color.r).toBe(1); + expect(color.g).toBe(0); + expect(color.b).toBe(0); + }); + + it('should convert from hsv with yellow', () => { + const color = Color.fromHsv(60, 1, 1); + + expect(color.r).toBe(1); + expect(color.g).toBe(1); + expect(color.b).toBe(0); + }); + + it('should convert from hsv with blue', () => { + const color = Color.fromHsv(120, 1, 1); + + expect(color.r).toBe(0); + expect(color.g).toBe(1); + expect(color.b).toBe(0); + }); + + it('should convert from hsv with turkis', () => { + const color = Color.fromHsv(180, 1, 1); + + expect(color.r).toBe(0); + expect(color.g).toBe(1); + expect(color.b).toBe(1); + }); + + it('should convert from hsv with red', () => { + const color = Color.fromHsv(240, 1, 1); + + expect(color.r).toBe(0); + expect(color.g).toBe(0); + expect(color.b).toBe(1); + }); + + it('should convert from hsv with pink', () => { + const color = Color.fromHsv(300, 1, 1); + + expect(color.r).toBe(1); + expect(color.g).toBe(0); + expect(color.b).toBe(1); + }); + + it('should be valid black', () => { + const color = Color.BLACK; + + expect(color.r).toBe(0); + expect(color.g).toBe(0); + expect(color.b).toBe(0); + }); + + it('should be valid white', () => { + const color = Color.WHITE; + + expect(color.r).toBe(1); + expect(color.g).toBe(1); + expect(color.b).toBe(1); + }); + + it('should be valid red', () => { + const color = Color.RED; + + expect(color.r).toBe(1); + expect(color.g).toBe(0); + expect(color.b).toBe(0); + }); + + it('should be valid green', () => { + const color = Color.GREEN; + + expect(color.r).toBe(0); + expect(color.g).toBe(1); + expect(color.b).toBe(0); + }); + + it('should be valid blue', () => { + const color = Color.BLUE; + + expect(color.r).toBe(0); + expect(color.g).toBe(0); + expect(color.b).toBe(1); + }); + + it('should calculate correct luminance', () => { + expect(new Color(1, 1, 1).luminance).toBe(1); + expect(new Color(0, 0, 0).luminance).toBe(0); + expect(new Color(1, 0, 0).luminance).toBe(1 / 3); + expect(new Color(0, 1, 0).luminance).toBe(1 / 2); + expect(new Color(0, 0, 1).luminance).toBe(1 / 6); + }); + + it('should make valid equal comparisons', () => { + expect(new Color(0.1, 0.1, 0.1).eq(new Color(0.1, 0.1, 0.1))).toBeTruthy(); + expect(new Color(0.1, 0.1, 0.4).eq(new Color(0.1, 0.1, 0.1))).toBeFalsy(); + }); + + it('should make valid not equal comparisons', () => { + expect(new Color(0.1, 0.1, 0.1).ne(new Color(0.1, 0.1, 0.4))).toBeTruthy(); + expect(new Color(0.1, 0.1, 0.1).ne(new Color(0.1, 0.1, 0.1))).toBeFalsy(); + }); + + it('should return color when creating from color', () => { + const color = Color.fromHsv(300, 1, 1); + const created = Color.fromValue(color); + + expect(created).toBe(color); + }); + + it('should throw error for invalid string', () => { + expect(() => Color.fromValue('INVALID')).toThrowError('Color is not in a valid format.'); + }); +}); diff --git a/src/PinkParrot/app/core/utils/color.ts b/src/PinkParrot/app/core/utils/color.ts new file mode 100644 index 000000000..0d1dcf688 --- /dev/null +++ b/src/PinkParrot/app/core/utils/color.ts @@ -0,0 +1,204 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +interface IColorDefinition { + regex: RegExp; + + process(bots: RegExpExecArray): Color; +} + +const ColorDefinitions: IColorDefinition[] = [ + { + regex: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/, + process: function (bits) { + return new Color( + parseInt(bits[1], 10) / 255, + parseInt(bits[2], 10) / 255, + parseInt(bits[3], 10) / 255); + } + }, + { + regex: /^(\w{2})(\w{2})(\w{2})$/, + process: function (bits) { + return new Color( + parseInt(bits[1], 16) / 255, + parseInt(bits[2], 16) / 255, + parseInt(bits[3], 16) / 255); + } + }, + { + regex: /^(\w{1})(\w{1})(\w{1})$/, + process: function (bits) { + return new Color( + parseInt(bits[1] + bits[1], 16) / 255, + parseInt(bits[2] + bits[2], 16) / 255, + parseInt(bits[3] + bits[3], 16) / 255); + } + } +]; + +export class Color { + public static readonly BLACK = new Color(0, 0, 0); + public static readonly WHITE = new Color(1, 1, 1); + public static readonly GREEN = new Color(0, 1, 0); + public static readonly BLUE = new Color(0, 0, 1); + public static readonly RED = new Color(1, 0, 0); + + public readonly r: number; + public readonly g: number; + public readonly b: number; + + public get luminance() { + return (this.r + this.r + this.b + this.g + this.g + this.g) / 6; + } + + constructor(r: number, g: number, b: number) { + this.r = Math.min(1, Math.max(0, r)); + this.g = Math.min(1, Math.max(0, g)); + this.b = Math.min(1, Math.max(0, b)); + + Object.freeze(this); + } + + public eq(v: Color): boolean { + return this.r === v.r && this.g === v.g && this.b === v.b; + } + + public ne(v: Color): boolean { + return this.r !== v.r || this.g !== v.g || this.b !== v.b; + } + + public toNumber(): number { + return ((this.r * 255) << 16) + ((this.g * 255) << 8) + (this.b * 255); + } + + public toString(): string { + let r = Math.round(this.r * 255).toString(16); + let g = Math.round(this.g * 255).toString(16); + let b = Math.round(this.b * 255).toString(16); + + if (r.length === 1) { + r = '0' + r; + } + if (g.length === 1) { + g = '0' + g; + } + if (b.length === 1) { + b = '0' + b; + } + + return '#' + r + g + b; + } + + public static fromHex(r: number, g: number, b: number): Color { + return new Color( + parseInt('' + r, 16) / 255, + parseInt('' + g, 16) / 255, + parseInt('' + b, 16) / 255); + } + + public static fromNumber(rgb: number): Color { + return new Color( + ((rgb >> 16) & 0xff) / 255, + ((rgb >> 8) & 0xff) / 255, + ((rgb >> 0) & 0xff) / 255); + } + + public static fromValue(value: number | string | Color): Color { + if (typeof value === 'string') { + return Color.fromString(value); + } else if (typeof value === 'number') { + return Color.fromNumber(value); + } else { + return value; + } + } + + public static fromString(value: string) { + if (value.charAt(0) === '#') { + value = value.substr(1, 6); + } + + value = value.replace(/ /g, '').toLowerCase(); + + for (let colorDefinition of ColorDefinitions) { + const bits = colorDefinition.regex.exec(value); + + if (bits) { + return colorDefinition.process(bits); + } + } + + throw new Error('Color is not in a valid format.'); + } + + public static fromHsv(h: number, s: number, v: number): Color { + const hi = Math.floor(h / 60) % 6; + + const f = (h / 60) - Math.floor(h / 60); + + v = v * 255; + + const p = (v * (1 - s)); + const q = (v * (1 - (f * s))); + const t = (v * (1 - ((1 - f) * s))); + + switch (hi) { + case 0: + return new Color(v, t, p); + case 1: + return new Color(q, v, p); + case 2: + return new Color(p, v, t); + case 3: + return new Color(p, q, v); + case 4: + return new Color(t, p, v); + default: + return new Color(v, p, q); + } + } + + public static fromHsl(h: number, s: number, l: number): Color { + let r = 0, g = 0, b = 0; + + h = h / 360; + + if (s === 0) { + r = g = b = l; + } else { + const hue2rgb = (p: number, q: number, t: number) => { + if (t < 0) { + t += 1; + } + + if (t > 1) { + t -= 1; + } + if (t < 1 / 6) { + return p + (q - p) * 6 * t; + } + if (t < 1 / 2) { + return q; + } + if (t < 2 / 3) { + return p + (q - p) * (2 / 3 - t) * 6; + } + return p; + }; + + const q = l < 0.5 ? l * (1 + s) : l + s - l * s; + const p = 2 * l - q; + + r = hue2rgb(p, q, h + 1 / 3); + g = hue2rgb(p, q, h); + b = hue2rgb(p, q, h - 1 / 3); + } + + return new Color(r, g, b); + } +} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/date-helper.js.map b/src/PinkParrot/app/core/utils/date-helper.js.map new file mode 100644 index 000000000..d4fc02ae8 --- /dev/null +++ b/src/PinkParrot/app/core/utils/date-helper.js.map @@ -0,0 +1 @@ +{"version":3,"file":"date-helper.js","sourceRoot":"","sources":["date-helper.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAEH,IAAY,MAAM,WAAM,QAAQ,CAAC,CAAA;AAEjC,IAAc,UAAU,CAUvB;AAVD,WAAc,UAAU,EAAC,CAAC;IACtB,IAAI,cAAmB,CAAC;IAExB,mBAA0B,KAAU;QAChC,cAAc,GAAG,KAAK,CAAC;IAC3B,CAAC;IAFe,oBAAS,YAExB,CAAA;IAED,gBAAuB,IAAY;QAC/B,CAAC,cAAc,IAAI,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC5C,CAAC;IAFe,iBAAM,SAErB,CAAA;AACL,CAAC,EAVa,UAAU,GAAV,kBAAU,KAAV,kBAAU,QAUvB"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/date-helper.spec.js.map b/src/PinkParrot/app/core/utils/date-helper.spec.js.map new file mode 100644 index 000000000..71ccd2b7d --- /dev/null +++ b/src/PinkParrot/app/core/utils/date-helper.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"date-helper.spec.js","sourceRoot":"","sources":["date-helper.spec.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAEH,IAAY,MAAM,WAAM,QAAQ,CAAC,CAAA;AAEjC,iBAA2B,OAAO,CAAC,CAAA;AAEnC,QAAQ,CAAC,YAAY,EAAE;IACnB,EAAE,CAAC,4CAA4C,EAAE;QAC7C,IAAI,MAAM,GAAW,IAAI,GAAG,IAAI,CAAC;QAEjC,aAAU,CAAC,SAAS,CAAC;YACjB,MAAM,EAAE,UAAC,CAAS,IAAO,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;SACzC,CAAC,CAAC;QAEH,aAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAExB,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE;QAC7C,aAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC3B,aAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAExB,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/date-helper.spec.ts b/src/PinkParrot/app/core/utils/date-helper.spec.ts new file mode 100644 index 000000000..833ba7375 --- /dev/null +++ b/src/PinkParrot/app/core/utils/date-helper.spec.ts @@ -0,0 +1,31 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import * as moment from 'moment'; + +import { DateHelper } from './../'; + +describe('DateHelper', () => { + it('should call config method of moment object', () => { + let called: string | null = null; + + DateHelper.setMoment({ + locale: (l: string) => { called = l; } + }); + + DateHelper.locale('en'); + + expect(called).toBe('en'); + }); + + it('should use global moment if not configured', () => { + DateHelper.setMoment(null); + DateHelper.locale('en'); + + expect(moment.locale()).toBe('en'); + }); +}); diff --git a/src/PinkParrot/app/core/utils/date-helper.ts b/src/PinkParrot/app/core/utils/date-helper.ts new file mode 100644 index 000000000..26ab46c7d --- /dev/null +++ b/src/PinkParrot/app/core/utils/date-helper.ts @@ -0,0 +1,20 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import * as moment from 'moment'; + +export module DateHelper { + let momentInstance: any; + + export function setMoment(value: any) { + momentInstance = value; + } + + export function locale(code: string) { + (momentInstance || moment).locale(code); + } +} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/date-time.js.map b/src/PinkParrot/app/core/utils/date-time.js.map new file mode 100644 index 000000000..526e7980d --- /dev/null +++ b/src/PinkParrot/app/core/utils/date-time.js.map @@ -0,0 +1 @@ +{"version":3,"file":"date-time.js","sourceRoot":"","sources":["date-time.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/date-time.spec.js.map b/src/PinkParrot/app/core/utils/date-time.spec.js.map new file mode 100644 index 000000000..8393e5d56 --- /dev/null +++ b/src/PinkParrot/app/core/utils/date-time.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"date-time.spec.js","sourceRoot":"","sources":["date-time.spec.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/date-time.spec.ts b/src/PinkParrot/app/core/utils/date-time.spec.ts new file mode 100644 index 000000000..410478975 --- /dev/null +++ b/src/PinkParrot/app/core/utils/date-time.spec.ts @@ -0,0 +1,169 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { DateTime } from './../'; + +describe('DateTime', () => { + const today = DateTime.today(); + const today2 = DateTime.today(); + const now = DateTime.now(); + + it('should parse from iso string', () => { + const value = DateTime.parse('2013-10-16T12:13:14.125', DateTime.iso8601()); + + expect(value.year).toBe(2013); + expect(value.month).toBe(10); + expect(value.day).toBe(16); + expect(value.hours).toBe(12); + expect(value.minutes).toBe(13); + expect(value.seconds).toBe(14); + expect(value.milliseconds).toBe(125); + expect(value.weekDay).toBe(3); + + expect(value.raw).not.toBeNull(); + }); + + it('should throw when date string to parse is null', () => { + expect(() => DateTime.parseUTC('#', DateTime.iso8601())).toThrow(); + }); + + it('should throw when date string to parse is invalid', () => { + expect(() => DateTime.parse('#', 'yyyy-MM-dd')).toThrow(); + }); + + it('should parse Microsoft date format', () => { + const actual = DateTime.parseMSDate('/Date(1224043200000)/'); + const expected = DateTime.parse('2008-10-15T04:00:00', DateTime.iso8601()); + + expect(actual).toEqual(expected); + }); + + it('should parse Microsoft date format with positive offset', () => { + const actual = DateTime.parseMSDate('/Date(1224043200000+2)/'); + const expected = DateTime.parse('2008-10-15T06:00:00', DateTime.iso8601()); + + expect(actual).toEqual(expected); + }); + + it('should parse Microsoft date format with negative offset', () => { + const actual = DateTime.parseMSDate('/Date(1224043200000-2)/'); + const expected = DateTime.parse('2008-10-15T02:00:00', DateTime.iso8601()); + + expect(actual).toEqual(expected); + }); + + it('should create today and now instance correctly', () => { + const actual = DateTime.today(); + const expected = DateTime.now().date; + + expect(actual).toEqual(expected); + }); + + it('should create tomorrow instance correctly', () => { + const actual = DateTime.tomorrow(); + const expected = DateTime.today().addDays(1); + + expect(actual).toEqual(expected); + }); + + it('should create yesterday instance correctly', () => { + const actual = DateTime.yesterday(); + const expected = DateTime.today().addDays(-1); + + expect(actual).toEqual(expected); + }); + + it('should print to formatted string', () => { + const value = DateTime.parseUTC('2013-10-16T12:13:14T', DateTime.iso8601()); + const actual = value.toStringFormat('hh:mm'); + const expected = '12:13'; + + expect(actual).toEqual(expected); + }); + + it('should print to iso string', () => { + const value = DateTime.parseUTC('2013-10-16T12:13:14', DateTime.iso8601()); + const actual = value.toString().substr(0, 19); + const expected = '2013-10-16T12:13:14'; + + expect(actual).toEqual(expected); + }); + + it('should print to valid utc string', () => { + const value = DateTime.parseUTC('2013-10-16T12:13:14', DateTime.iso8601()); + + expect(value.toUTCString()).toBeDefined(); + }); + + it('should print from format with underscore', () => { + const actual = DateTime.parse('2013-10-16T00:00:00', DateTime.iso8601()); + const expected = DateTime.parse('10_2013_16', 'MM_YYYY_DD'); + + expect(actual).toEqual(expected); + }); + + it('should calculate valid first of week', () => { + const actual = DateTime.parseUTC('2013-10-16T12:13:14.125', DateTime.iso8601()).date.firstOfWeek(); + const expected = DateTime.parseUTC('2013-10-14T00:00:00', DateTime.iso8601()); + + expect(actual).toEqual(expected); + }); + + it('should calculate valid first of month', () => { + const actual = DateTime.parseUTC('2013-10-16T12:13:14.125', DateTime.iso8601()).date.firstOfMonth(); + const expected = DateTime.parseUTC('2013-10-01', DateTime.iso8601()); + + expect(actual).toEqual(expected); + }); + + it('should add various offsets to date time', () => { + const actual = + DateTime.parseUTC('2013-05-01T12:12:12.100', DateTime.iso8601()) + .addYears(1) + .addMonths(2) + .addDays(13) + .addHours(3) + .addMinutes(10) + .addSeconds(15) + .addMilliseconds(125); + const expected = DateTime.parseUTC('2014-07-16T15:22:27.225', DateTime.iso8601()); + + expect(actual).toEqual(expected); + }); + + it('should make valid equal comparisons', () => { + expect(today.eq(today2)).toBeTruthy(); + expect(today.eq(now)).toBeFalsy(); + }); + + it('should make valid not equal comparisons', () => { + expect(today.ne(today2)).toBeFalsy(); + expect(today.ne(now)).toBeTruthy(); + }); + + it('should make valid less comparisons', () => { + expect(today.lt(now)).toBeTruthy(); + expect(now.lt(today)).toBeFalsy(); + }); + + it('should make valid less equals comparisons', () => { + expect(today.le(now)).toBeTruthy(); + expect(today.le(today)).toBeTruthy(); + expect(now.le(today)).toBeFalsy(); + }); + + it('should make valid greater comparisons', () => { + expect(now.gt(today)).toBeTruthy(); + expect(today.gt(now)).toBeFalsy(); + }); + + it('should make valid greater equals comparisons', () => { + expect(now.ge(today)).toBeTruthy(); + expect(now.ge(now)).toBeTruthy(); + expect(today.ge(now)).toBeFalsy(); + }); +}); diff --git a/src/PinkParrot/app/core/utils/date-time.ts b/src/PinkParrot/app/core/utils/date-time.ts new file mode 100644 index 000000000..747455e90 --- /dev/null +++ b/src/PinkParrot/app/core/utils/date-time.ts @@ -0,0 +1,227 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import * as moment from 'moment'; + +export class DateTime { + public get raw(): Date { + return this.value; + } + + public get weekDay(): number { + return this.value.getDay(); + } + + public get year(): number { + return this.value.getFullYear(); + } + + public get timestamp(): number { + return this.value.getTime(); + } + + public get month(): number { + return this.value.getMonth() + 1; + } + + public get day(): number { + return this.value.getDate(); + } + + public get hours(): number { + return this.value.getHours(); + } + + public get minutes(): number { + return this.value.getMinutes(); + } + + public get seconds(): number { + return this.value.getSeconds(); + } + + public get milliseconds(): number { + return this.value.getMilliseconds(); + } + + public get date(): DateTime { + const clone = this.cloneDate(); + + clone.setHours(0, 0, 0, 0); + + return new DateTime(clone); + } + + constructor(private readonly value: Date) { + Object.freeze(this); + } + + public static iso8601(): any { + return moment.ISO_8601; + } + + public static now(): DateTime { + return new DateTime(new Date()); + } + + public static today(): DateTime { + return DateTime.now().date; + } + + public static tomorrow(): DateTime { + return DateTime.now().addDays(1).date; + } + + public static yesterday(): DateTime { + return DateTime.now().addDays(-1).date; + } + + public static parseMSDate(value: string): DateTime { + let off = parseInt(value.substr(19, 3), 10); + + if (isNaN(off)) { + off = 0; + } + + const date = new Date(parseInt(value.substr(6), 10)); + const time = (date.getTime()); + const offs = (date.getTimezoneOffset() + off * 60) * 60000; + + date.setTime(time + offs); + + return new DateTime(date); + } + + public static parse(value: string, format: string): DateTime { + const parsedMoment = moment(value, format); + + if (parsedMoment.isValid()) { + return new DateTime(parsedMoment.toDate()); + } else { + throw `${value} is not a valid date time string`; + + } + } + + public static parseUTC(value: string, format: string): DateTime { + const parsedMoment = moment.utc(value, format); + + if (parsedMoment.isValid()) { + return new DateTime(new Date(parsedMoment.valueOf() - parsedMoment.local().utcOffset() * 60 * 1000)); + } else { + throw `${value} is not a valid date time string`; + } + } + + private cloneDate(): Date { + return new Date(this.value.getTime()); + } + + public eq(v: DateTime): boolean { + return v && (this === v || this.timestamp === v.timestamp); + } + + public ne(v: DateTime): boolean { + return !v || this.timestamp !== v.timestamp; + } + + public lt(v: DateTime): boolean { + return v && this.timestamp < v.timestamp; + } + + public le(v: DateTime): boolean { + return v && this.timestamp <= v.timestamp; + } + + public gt(v: DateTime): boolean { + return v && this.timestamp > v.timestamp; + } + + public ge(v: DateTime): boolean { + return v && this.timestamp >= v.timestamp; + } + + public firstOfWeek(): DateTime { + const weekStart = new Date(this.value.valueOf() - (this.weekDay - 1) * 86400000); + + return new DateTime(weekStart); + } + + public firstOfMonth(): DateTime { + const monthStart = new Date(this.year, this.month - 1, 1); + + return new DateTime(monthStart); + } + + public addYears(value: number): DateTime { + const clone = this.cloneDate(); + + clone.setFullYear(clone.getFullYear() + value, clone.getMonth(), clone.getDay()); + + return new DateTime(clone); + } + + public addMonths(value: number): DateTime { + const clone = this.cloneDate(); + + clone.setMonth(clone.getMonth() + value, clone.getDate()); + + return new DateTime(clone); + } + + public addDays(value: number): DateTime { + const clone = this.cloneDate(); + + clone.setDate(clone.getDate() + value); + + return new DateTime(clone); + } + + public addHours(value: number): DateTime { + const clone = this.cloneDate(); + + clone.setTime(clone.getTime() + (value * 60 * 60 * 1000)); + + return new DateTime(clone); + } + + public addMinutes(value: number): DateTime { + const clone = this.cloneDate(); + + clone.setTime(clone.getTime() + (value * 60 * 1000)); + + return new DateTime(clone); + } + + public addSeconds(value: number): DateTime { + const clone = this.cloneDate(); + + clone.setTime(clone.getTime() + (value * 1000)); + + return new DateTime(clone); + } + + public addMilliseconds(value: number): DateTime { + const clone = this.cloneDate(); + + clone.setTime(clone.getTime() + value); + + return new DateTime(clone); + } + + public toUTCString(): string { + return this.value.toUTCString(); + } + + public toString(): string { + return moment(this.value).format(); + } + + public toStringFormat(format: string): string { + return moment(this.value).format(format); + } +} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/duration.js.map b/src/PinkParrot/app/core/utils/duration.js.map new file mode 100644 index 000000000..a30e0369e --- /dev/null +++ b/src/PinkParrot/app/core/utils/duration.js.map @@ -0,0 +1 @@ +{"version":3,"file":"duration.js","sourceRoot":"","sources":["duration.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAEH,IAAY,MAAM,WAAM,QAAQ,CAAC,CAAA;AAIjC;IAKI,kBAAoB,QAAc,EAAE,MAAM;QAA9B,wBAAsB,GAAtB,gBAAsB;QAAd,aAAQ,GAAR,QAAQ,CAAM;QAC9B,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAND,sBAAW,+BAAS;aAApB;YACI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;QACtB,CAAC;;;OAAA;IAMa,eAAM,GAApB,UAAqB,KAAe,EAAE,MAAgB;QAClD,MAAM,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC;IAC5D,CAAC;IAEM,2BAAQ,GAAf;QACI,IAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAE7C,IAAI,aAAa,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC;QAElD,EAAE,CAAC,CAAC,aAAa,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;YAC7B,aAAa,GAAG,MAAI,aAAe,CAAC;QACxC,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,GAAG,GAAG,GAAG,aAAa,GAAG,GAAG,CAAC;IACtE,CAAC;IACL,eAAC;AAAD,CAAC,AAxBD,IAwBC;AAxBY,gBAAQ,WAwBpB,CAAA"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/duration.spec.js.map b/src/PinkParrot/app/core/utils/duration.spec.js.map new file mode 100644 index 000000000..0f46b98b4 --- /dev/null +++ b/src/PinkParrot/app/core/utils/duration.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"duration.spec.js","sourceRoot":"","sources":["duration.spec.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAEH,iBAAmC,OAAO,CAAC,CAAA;AAE3C,QAAQ,CAAC,UAAU,EAAE;IACjB,EAAE,CAAC,sDAAsD,EAAE;QACvD,IAAM,QAAQ,GAAG,IAAI,WAAQ,CAAC,EAAE,CAAC,CAAC;QAElC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE;QACxD,IAAM,CAAC,GAAG,WAAQ,CAAC,KAAK,EAAE,CAAC;QAC3B,IAAM,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QAE5B,IAAM,QAAQ,GAAG,WAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAEvC,IAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC;QAClC,IAAM,QAAQ,GAAG,MAAM,CAAC;QAExB,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE;QACnC,IAAM,CAAC,GAAG,WAAQ,CAAC,KAAK,EAAE,CAAC;QAC3B,IAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QAEtD,IAAM,QAAQ,GAAG,WAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAEvC,IAAM,MAAM,GAAG,QAAQ,CAAC,QAAQ,EAAE,CAAC;QACnC,IAAM,QAAQ,GAAG,OAAO,CAAC;QAEzB,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE;QACzD,IAAM,CAAC,GAAG,WAAQ,CAAC,KAAK,EAAE,CAAC;QAC3B,IAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QAErD,IAAM,QAAQ,GAAG,WAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAEvC,IAAM,MAAM,GAAG,QAAQ,CAAC,QAAQ,EAAE,CAAC;QACnC,IAAM,QAAQ,GAAG,OAAO,CAAC;QAEzB,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/duration.spec.ts b/src/PinkParrot/app/core/utils/duration.spec.ts new file mode 100644 index 000000000..57d38fc7f --- /dev/null +++ b/src/PinkParrot/app/core/utils/duration.spec.ts @@ -0,0 +1,52 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { DateTime, Duration } from './../'; + +describe('Duration', () => { + it('should instantiate and provide timestamp as property', () => { + const duration = new Duration(10); + + expect(duration.timestamp).toBe(10); + }); + + it('should calculate timestamp from first and second time', () => { + const s = DateTime.today(); + const d = s.addSeconds(100); + + const duration = Duration.create(s, d); + + const actual = duration.timestamp; + const expected = 100000; + + expect(actual).toBe(expected); + }); + + it('should print to string correctly', () => { + const s = DateTime.today(); + const d = s.addHours(1).addMinutes(30).addSeconds(60); + + const duration = Duration.create(s, d); + + const actual = duration.toString(); + const expected = '1:31h'; + + expect(actual).toBe(expected); + }); + + it('should print to string correctly for one digit minutes', () => { + const s = DateTime.today(); + const d = s.addHours(1).addMinutes(1).addSeconds(60); + + const duration = Duration.create(s, d); + + const actual = duration.toString(); + const expected = '1:02h'; + + expect(actual).toBe(expected); + }); +}); diff --git a/src/PinkParrot/app/core/utils/duration.ts b/src/PinkParrot/app/core/utils/duration.ts new file mode 100644 index 000000000..ea7b2c8be --- /dev/null +++ b/src/PinkParrot/app/core/utils/duration.ts @@ -0,0 +1,36 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import * as moment from 'moment'; + +import { DateTime } from './date-time'; + +export class Duration { + public get timestamp(): number { + return this.value; + } + + constructor(private readonly value: number) { + Object.freeze(this); + } + + public static create(first: DateTime, second: DateTime): Duration { + return new Duration(second.timestamp - first.timestamp); + } + + public toString(): string { + const duration = moment.duration(this.value); + + let minutesString = duration.minutes().toString(); + + if (minutesString.length === 1) { + minutesString = `0${minutesString}`; + } + + return Math.floor(duration.asHours()) + ':' + minutesString + 'h'; + } +} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/immutable-id-map.js.map b/src/PinkParrot/app/core/utils/immutable-id-map.js.map new file mode 100644 index 000000000..af8d89b5f --- /dev/null +++ b/src/PinkParrot/app/core/utils/immutable-id-map.js.map @@ -0,0 +1 @@ +{"version":3,"file":"immutable-id-map.js","sourceRoot":"","sources":["immutable-id-map.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/immutable-id-map.spec.js.map b/src/PinkParrot/app/core/utils/immutable-id-map.spec.js.map new file mode 100644 index 000000000..821600388 --- /dev/null +++ b/src/PinkParrot/app/core/utils/immutable-id-map.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"immutable-id-map.spec.js","sourceRoot":"","sources":["immutable-id-map.spec.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/immutable-id-map.spec.ts b/src/PinkParrot/app/core/utils/immutable-id-map.spec.ts new file mode 100644 index 000000000..68f4e8842 --- /dev/null +++ b/src/PinkParrot/app/core/utils/immutable-id-map.spec.ts @@ -0,0 +1,281 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { ImmutableIdMap } from './../'; + +class MockupData { + public readonly id: string; + + constructor(public readonly value: string | null, id?: string) { + this.id = id || value!; + } +} + +describe('ImmutableIdMap', () => { + const v1 = new MockupData('value1'); + const v2 = new MockupData('value2'); + const v3 = new MockupData('value3'); + const v4 = new MockupData('value4'); + const v5 = new MockupData('value5'); + const v6 = new MockupData('value6'); + + it('should instantiate without arguments', () => { + const list = new ImmutableIdMap(); + + expect(list).toBeDefined(); + }); + + it('should instantiate from array of items', () => { + const list_1 = new ImmutableIdMap([v1, v2, v3]); + + expect(list_1.size).toBe(3); + expect(list_1.get('value1')).toBe(v1); + expect(list_1.get('value2')).toBe(v2); + expect(list_1.get('value3')).toBe(v3); + + expect(list_1.first).toBe(v1); + expect(list_1.last).toBe(v3); + }); + + it('should add values to list', () => { + const list_1 = new ImmutableIdMap(); + const list_2 = list_1.add(v1); + const list_3 = list_2.add(v2); + const list_4 = list_3.add(v3); + + expect(list_4.size).toBe(3); + expect(list_4.get('value1')).toBe(v1); + expect(list_4.get('value2')).toBe(v2); + expect(list_4.get('value3')).toBe(v3); + }); + + it('should convert to array', () => { + const list_1 = new ImmutableIdMap(); + const list_2 = list_1.add(v1); + const list_3 = list_2.add(v2); + const list_4 = list_3.add(v3); + + const items = list_4.toArray(); + + expect(items.length).toBe(3); + expect(items[0]).toBe(v1); + expect(items[1]).toBe(v2); + expect(items[2]).toBe(v3); + }); + + it('should return original list when value to add has no id', () => { + const list_1 = new ImmutableIdMap(); + const list_2 = list_1.add(new MockupData(null)); + + expect(list_2).toBe(list_1); + }); + + it('should return original list when value to add is null', () => { + const list_1 = new ImmutableIdMap(); + const list_2 = list_1.add(null!); + + expect(list_2).toBe(list_1); + }); + + it('should return original list when item to add has already been added', () => { + const list_1 = new ImmutableIdMap(); + const list_2 = list_1.add(v1); + const list_3 = list_2.add(v1); + + expect(list_3).toBe(list_2); + }); + + it('should update item', () => { + const newValue = new MockupData(v1.value, v1.id); + + const list_1 = new ImmutableIdMap(); + const list_2 = list_1.add(v1); + const list_3 = list_2.update(v1.id, t => newValue); + + expect(list_3.size).toBe(1); + expect(list_3.get('value1')).toBe(newValue); + }); + + it('should return undefined for invalid id', () => { + const list_1 = new ImmutableIdMap(); + + expect(list_1.get(null!)).toBeUndefined(); + }); + + it('should return original list when id to update is null', () => { + const newValue = new MockupData(v1.value, v1.id); + + const list_1 = new ImmutableIdMap(); + const list_2 = list_1.add(v1); + const list_3 = list_2.update(null!, t => newValue); + + expect(list_3).toBe(list_2); + }); + + it('should return original list when id to update does not exists', () => { + const newValue = new MockupData(v1.value, v1.id); + + const list_1 = new ImmutableIdMap(); + const list_2 = list_1.add(v1); + const list_3 = list_2.update('unknown', t => newValue); + + expect(list_3).toBe(list_2); + }); + + it('should return original list when updater is null', () => { + const list_1 = new ImmutableIdMap(); + const list_2 = list_1.add(v1); + const list_3 = list_2.update(v1.id, null!); + + expect(list_3).toBe(list_2); + }); + + it('should return original list when updater returns same item', () => { + const list_1 = new ImmutableIdMap(); + const list_2 = list_1.add(v1); + const list_3 = list_2.update(v1.id, t => t); + + expect(list_3).toBe(list_2); + }); + + it('should return original list when updater returns item with another id', () => { + const list_1 = new ImmutableIdMap(); + const list_2 = list_1.add(v1); + const list_3 = list_2.update(v1.id, t => v2); + + expect(list_3).toBe(list_2); + }); + + it('should remove values from list', () => { + const list_1 = new ImmutableIdMap(); + const list_2 = list_1.add(v1); + const list_3 = list_2.add(v2); + const list_4 = list_3.remove('value1'); + + expect(list_4.size).toBe(1); + expect(list_4.get('value2')).toBe(v2); + expect(list_4.contains(v1.id)).toBeFalsy(); + }); + + it('should return original list when id to remove is null', () => { + const list_1 = new ImmutableIdMap(); + const list_2 = list_1.add(v1); + const list_3 = list_2.remove(v1.id, null!); + + expect(list_3).toBe(list_2); + }); + + it('should return original list when id to remove does not exists', () => { + const list_1 = new ImmutableIdMap(); + const list_2 = list_1.add(v1); + const list_3 = list_2.remove(v1.id, 'unknown'); + + expect(list_3).toBe(list_2); + }); + + it('should bring to front', () => { + const list_1 = new ImmutableIdMap().add(v1, v2, v3, v4, v5, v6); + const list_2 = list_1.bringToFront([v3.id, v5.id]); + + expect(list_2.map(t => t.id)).toEqual([v1, v2, v4, v6, v3, v5].map(t => t.id)); + }); + + it('should bring forwards', () => { + const list_1 = new ImmutableIdMap().add(v1, v2, v3, v4, v5, v6); + const list_2 = list_1.bringForwards([v3.id, v4.id]); + + expect(list_2.map(t => t.id)).toEqual([v1, v2, v5, v3, v4, v6].map(t => t.id)); + }); + + it('should send to back', () => { + const list_1 = new ImmutableIdMap().add(v1, v2, v3, v4, v5, v6); + const list_2 = list_1.sendToBack([v3.id, v5.id]); + + expect(list_2.map(t => t.id)).toEqual([v3, v5, v1, v2, v4, v6].map(t => t.id)); + }); + + it('should send backwards', () => { + const list_1 = new ImmutableIdMap().add(v1, v2, v3, v4, v5, v6); + const list_2 = list_1.sendBackwards([v3.id, v5.id]); + + expect(list_2.map(t => t.id)).toEqual([v1, v3, v5, v2, v4, v6].map(t => t.id)); + }); + + it('should move item', () => { + const list_1 = new ImmutableIdMap().add(v1, v2, v3, v4, v5, v6); + const list_2 = list_1.moveTo([v4.id], 1); + + expect(list_2.map(t => t.id)).toEqual([v1, v4, v2, v3, v5, v6].map(t => t.id)); + }); + + it('should ignore items that are not found', () => { + const list_1 = new ImmutableIdMap().add(v1, v2, v3, v4, v5, v6); + const list_2 = list_1.bringToFront([v3.id, 'not found']); + + expect(list_2.map(t => t.id)).toEqual([v1, v2, v4, v5, v6, v3].map(t => t.id)); + }); + + it('should return original list no id found', () => { + const list_1 = new ImmutableIdMap().add(v1, v2, v3, v4, v5, v6); + const list_2 = list_1.sendBackwards(['not found', 'other not found']); + + expect(list_2).toBe(list_1); + }); + + it('should return original list when ids is null', () => { + const list_1 = new ImmutableIdMap().add(v1, v2, v3, v4, v5, v6); + const list_2 = list_1.sendBackwards(null!); + + expect(list_2).toBe(list_1); + }); + + it('should return correct result for map', () => { + const list_1 = new ImmutableIdMap().add(v1, v2, v3, v4, v5, v6); + + const result = list_1.map(t => t.id); + + expect(result).toEqual(['value1', 'value2', 'value3', 'value4', 'value5', 'value6']); + }); + + it('should return correct result for forEach', () => { + const list_1 = new ImmutableIdMap().add(v1, v2, v3, v4, v5, v6); + + const result: string[] = []; + + list_1.forEach(t => result.push(t.id)); + + expect(result).toEqual(['value1', 'value2', 'value3', 'value4', 'value5', 'value6']); + }); + + it('should return correct result for filter', () => { + const list_1 = new ImmutableIdMap().add(v1, v2, v3, v4, v5, v6); + + let i = 0; + + const result = list_1.filter(t => { i++; return i % 2 === 1; }); + + expect(result).toEqual([v1, v3, v5]); + }); + + it('should add and remove large item set', () => { + const size = 1000; + const items: MockupData[] = []; + + for (let i = 0; i < size; i++) { + items.push(new MockupData('id' + i)); + } + + const list_1 = new ImmutableIdMap(); + const list_2 = list_1.add(...items); + + expect(list_2.toArray()).toEqual(items); + + const list_3 = list_2.remove(...items.map(t => t.id)); + + expect(list_3.size).toEqual(0); + }); +}); diff --git a/src/PinkParrot/app/core/utils/immutable-id-map.ts b/src/PinkParrot/app/core/utils/immutable-id-map.ts new file mode 100644 index 000000000..d2a4398ae --- /dev/null +++ b/src/PinkParrot/app/core/utils/immutable-id-map.ts @@ -0,0 +1,218 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import * as Immutable from 'immutable'; + +export interface WithId { + id: string; +} + +export class ImmutableIdMap { + private readonly items: Immutable.OrderedMap; + + public get size(): number { + return this.items.size; + } + + public get first(): T { + return this.items.first(); + } + + public get last(): T { + return this.items.last(); + } + + constructor(items?: T[] | Immutable.OrderedMap) { + if (Array.isArray(items)) { + this.items = Immutable.OrderedMap(items.map(x => [x.id, x])); + } else { + this.items = items || Immutable.OrderedMap(); + } + + Object.freeze(this); + } + + public get(key: string): T | undefined { + return this.items.get(key, undefined); + } + + public contains(id: string): boolean { + return !!this.items.get(id); + } + + public toArray(): T[] { + return this.items.toArray(); + } + + public map(projection: (item: T, key?: string) => R): R[] { + return this.items.map((v, k) => projection(v!, k)).toArray(); + } + + public filter(projection: (item: T, key?: string) => boolean): T[] { + return this.items.filter((v, k) => projection(v!, k)).toArray(); + } + + public forEach(projection: (item: T, key?: string) => void): void { + this.items.forEach((v, k) => projection(v!, k)); + } + + public add(...items: T[]): ImmutableIdMap { + for (let item of items) { + if (!item || !item.id || this.get(item.id)) { + return this; + } + } + + let newItems = this.items; + + if (items.length > 50) { + newItems = this.items.withMutations(mutable => { + for (let item of items) { + mutable.set(item.id, item); + } + }); + } else { + for (let item of items) { + newItems = newItems.set(item.id, item); + } + } + + return this.cloned(newItems); + } + + public remove(...ids: string[]): ImmutableIdMap { + for (let id of ids) { + if (!id || !this.get(id)) { + return this; + } + } + + let newItems = this.items; + + if (ids.length > 50) { + newItems = this.items.withMutations(mutable => { + for (let id of ids) { + mutable.remove(id); + } + }); + } else { + for (let id of ids) { + newItems = newItems.remove(id); + } + } + + return this.cloned(newItems); + } + + public update(id: string, updater: (item: T) => T): ImmutableIdMap { + const oldItem = this.items.get(id); + + if (!oldItem || !updater) { + return this; + } + + const newItem = updater(oldItem); + + if (!newItem || newItem === oldItem || newItem.id !== oldItem.id) { + return this; + } + + const newItems = this.items.set(id, newItem); + + return this.cloned(newItems); + } + + public bringToFront(ids: string[]): ImmutableIdMap { + return this.moveTo(ids, Number.MAX_VALUE); + } + + public bringForwards(ids: string[]): ImmutableIdMap { + return this.moveTo(ids, 1, true); + } + + public sendBackwards(ids: string[]): ImmutableIdMap { + return this.moveTo(ids, -1, true); + } + + public sendToBack(ids: string[]): ImmutableIdMap { + return this.moveTo(ids, 0); + } + + public moveTo(ids: string[], target: number, relative = false): ImmutableIdMap { + const itemsToStay: ItemToSort[] = []; + const itemsToMove: ItemToSort[] = []; + + this.items.toArray().forEach((item: T, index: number) => { + const itemToAdd: ItemToSort = { isInIds: ids && ids.indexOf(item.id) >= 0, index: index, value: item }; + + if (itemToAdd.isInIds) { + itemsToMove.push(itemToAdd); + } else { + itemsToStay.push(itemToAdd); + } + }); + + if (itemsToMove.length === 0) { + return this; + } + + let isBackwards = false, newIndex = 0; + + if (relative) { + isBackwards = target <= 0; + + let currentIndex = + target > 0 ? + Number.MIN_VALUE : + Number.MAX_VALUE; + + for (let itemFromIds of itemsToMove) { + if (target > 0) { + currentIndex = Math.max(itemFromIds.index, currentIndex); + } else { + currentIndex = Math.min(itemFromIds.index, currentIndex); + } + } + + newIndex = currentIndex + target; + } else { + newIndex = target; + + if (itemsToMove[0].index > newIndex) { + isBackwards = true; + } + } + + const result: any[][] = []; + + for (let item of itemsToStay) { + if ((isBackwards && item.index >= newIndex) || item.index > newIndex) { + break; + } + + result.push([item.value.id, item.value]); + } + + for (let item of itemsToMove) { + result.push([item.value.id, item.value]); + } + + for (let item of itemsToStay) { + if ((isBackwards && item.index >= newIndex) || item.index > newIndex) { + result.push([item.value.id, item.value]); + } + } + + return this.cloned(Immutable.OrderedMap(result)); + } + + private cloned(items: Immutable.OrderedMap): ImmutableIdMap { + return new ImmutableIdMap(items); + } +} + +interface ItemToSort { isInIds: boolean; index: number; value: T; } \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/immutable-list.js.map b/src/PinkParrot/app/core/utils/immutable-list.js.map new file mode 100644 index 000000000..a5935dbef --- /dev/null +++ b/src/PinkParrot/app/core/utils/immutable-list.js.map @@ -0,0 +1 @@ +{"version":3,"file":"immutable-list.js","sourceRoot":"","sources":["immutable-list.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/immutable-list.spec.js.map b/src/PinkParrot/app/core/utils/immutable-list.spec.js.map new file mode 100644 index 000000000..46a9f5bff --- /dev/null +++ b/src/PinkParrot/app/core/utils/immutable-list.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"immutable-list.spec.js","sourceRoot":"","sources":["immutable-list.spec.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/immutable-list.spec.ts b/src/PinkParrot/app/core/utils/immutable-list.spec.ts new file mode 100644 index 000000000..370417a46 --- /dev/null +++ b/src/PinkParrot/app/core/utils/immutable-list.spec.ts @@ -0,0 +1,238 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { ImmutableList } from './../'; + +describe('ImmutableList', () => { + const v1 = 'value1'; + const v2 = 'value2'; + const v3 = 'value3'; + const v4 = 'value4'; + const v5 = 'value5'; + const v6 = 'value6'; + + it('should instantiate without arguments', () => { + const list = new ImmutableList(); + + expect(list).toBeDefined(); + }); + + it('should instantiate from array of items', () => { + const list_1 = new ImmutableList([v1, v2, v3]); + + expect(list_1.size).toBe(3); + expect(list_1.get(0)).toBe(v1); + expect(list_1.get(1)).toBe(v2); + expect(list_1.get(2)).toBe(v3); + }); + + it('should add values to list', () => { + const list_1 = new ImmutableList(); + const list_2 = list_1.add(v1); + const list_3 = list_2.add(v2); + const list_4 = list_3.add(v3); + + expect(list_4.size).toBe(3); + expect(list_4.get(0)).toBe(v1); + expect(list_4.get(1)).toBe(v2); + expect(list_4.get(2)).toBe(v3); + }); + + it('should convert to array', () => { + const list_1 = new ImmutableList(); + const list_2 = list_1.add(v1); + const list_3 = list_2.add(v2); + const list_4 = list_3.add(v3); + + const items = list_4.toArray(); + + expect(items.length).toBe(3); + expect(items[0]).toBe(v1); + expect(items[1]).toBe(v2); + expect(items[2]).toBe(v3); + }); + + it('should return original list when value to add is null', () => { + const list_1 = new ImmutableList(); + const list_2 = list_1.add(null!); + + expect(list_2).toBe(list_1); + }); + + it('should update item', () => { + const newValue = 'v1New'; + + const list_1 = new ImmutableList(); + const list_2 = list_1.add(v1); + const list_3 = list_2.update(v1, t => newValue); + + expect(list_3.size).toBe(1); + expect(list_3.get(0)).toBe(newValue); + }); + + it('should return undefined for invalid index', () => { + const list_1 = new ImmutableList(); + const list_2 = list_1.add(v1); + + expect(list_2.get(-10)).toBeUndefined(); + expect(list_2.get(100)).toBeUndefined(); + }); + + it('should return original list when item to update is null', () => { + const newValue = 'v1New'; + + const list_1 = new ImmutableList(); + const list_2 = list_1.add(v1); + const list_3 = list_2.update(null!, t => newValue); + + expect(list_3).toBe(list_2); + }); + + it('should return original list when updater is null', () => { + const list_1 = new ImmutableList(); + const list_2 = list_1.add(v1); + const list_3 = list_2.update(v1, null!); + + expect(list_3).toBe(list_2); + }); + + it('should return original list when updater returns same item', () => { + const list_1 = new ImmutableList(); + const list_2 = list_1.add(v1); + const list_3 = list_2.update(v1, t => t); + + expect(list_3).toBe(list_2); + }); + + it('should remove values from list', () => { + const list_1 = new ImmutableList(); + const list_2 = list_1.add(v1); + const list_3 = list_2.add(v2); + const list_4 = list_3.remove(v1); + + expect(list_4.size).toBe(1); + expect(list_4.get(0)).toBe(v2); + }); + + it('should return original list when item to remove is null', () => { + const list_1 = new ImmutableList(); + const list_2 = list_1.add(v1); + const list_3 = list_2.remove(null!); + + expect(list_3).toBe(list_2); + }); + + it('should return original list when item to remove does not exists', () => { + const list_1 = new ImmutableList(); + const list_2 = list_1.add(v1); + const list_3 = list_2.remove(v4); + + expect(list_3).toBe(list_2); + }); + + it('should bring to front', () => { + const list_1 = new ImmutableList().add(v1, v2, v3, v4, v5, v6); + const list_2 = list_1.bringToFront([v3, v5]); + + expect(list_2.toArray()).toEqual([v1, v2, v4, v6, v3, v5]); + }); + + it('should bring forwards', () => { + const list_1 = new ImmutableList().add(v1, v2, v3, v4, v5, v6); + const list_2 = list_1.bringForwards([v3, v4]); + + expect(list_2.toArray()).toEqual([v1, v2, v5, v3, v4, v6]); + }); + + it('should send to back', () => { + const list_1 = new ImmutableList().add(v1, v2, v3, v4, v5, v6); + const list_2 = list_1.sendToBack([v3, v5]); + + expect(list_2.toArray()).toEqual([v3, v5, v1, v2, v4, v6]); + }); + + it('should send backwards', () => { + const list_1 = new ImmutableList().add(v1, v2, v3, v4, v5, v6); + const list_2 = list_1.sendBackwards([v3, v5]); + + expect(list_2.toArray()).toEqual([v1, v3, v5, v2, v4, v6]); + }); + + it('should move item', () => { + const list_1 = new ImmutableList().add(v1, v2, v3, v4, v5, v6); + const list_2 = list_1.moveTo([v4], 1); + + expect(list_2.toArray()).toEqual([v1, v4, v2, v3, v5, v6]); + }); + + it('should ignore items that are not found', () => { + const list_1 = new ImmutableList().add(v1, v2, v3, v4, v5, v6); + const list_2 = list_1.bringToFront([v3, 'not found']); + + expect(list_2.toArray()).toEqual([v1, v2, v4, v5, v6, v3]); + }); + + it('should return original list no id found', () => { + const list_1 = new ImmutableList().add(v1, v2, v3, v4, v5, v6); + const list_2 = list_1.sendBackwards(['not found']); + + expect(list_2).toBe(list_1); + }); + + it('should return original list when ids is null', () => { + const list_1 = new ImmutableList().add(v1, v2, v3, v4, v5, v6); + const list_2 = list_1.sendBackwards(null!); + + expect(list_2).toBe(list_1); + }); + + it('should return correct result for map', () => { + const list_1 = new ImmutableList().add(v1, v2, v3, v4, v5, v6); + + const result = list_1.map(t => 'x_' + t); + + expect(result).toEqual(['x_value1', 'x_value2', 'x_value3', 'x_value4', 'x_value5', 'x_value6']); + }); + + it('should return correct result for forEach', () => { + const list_1 = new ImmutableList().add(v1, v2, v3, v4, v5, v6); + + const result: string[] = []; + + list_1.forEach(t => result.push('x_' + t)); + + expect(result).toEqual(['x_value1', 'x_value2', 'x_value3', 'x_value4', 'x_value5', 'x_value6']); + }); + + it('should return correct result for filter', () => { + const list_1 = new ImmutableList().add(v1, v2, v3, v4, v5, v6); + + let i = 0; + + const result = list_1.filter(t => { i++; return i % 2 === 1; }); + + expect(result).toEqual([v1, v3, v5]); + }); + + it('should add and remove large item set', () => { + const size = 1000; + const items: string[] = []; + + for (let i = 0; i < size; i++) { + items.push('id' + i); + } + + const list_1 = new ImmutableList(); + const list_2 = list_1.add(...items); + + expect(list_2.toArray()).toEqual(items); + + const list_3 = list_2.remove(...items); + + expect(list_3.size).toEqual(0); + }); +}); diff --git a/src/PinkParrot/app/core/utils/immutable-list.ts b/src/PinkParrot/app/core/utils/immutable-list.ts new file mode 100644 index 000000000..59783f2a0 --- /dev/null +++ b/src/PinkParrot/app/core/utils/immutable-list.ts @@ -0,0 +1,206 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import * as Immutable from 'immutable'; + +export class ImmutableList { + private readonly items: Immutable.List; + + public get size(): number { + return this.items.size; + } + + constructor(items?: T[] | Immutable.List) { + if (Array.isArray(items)) { + this.items = Immutable.List(items); + } else { + this.items = items || Immutable.List(); + } + + Object.freeze(this); + } + + public get(index: number): T | undefined { + return this.items.get(index, undefined); + } + + public toArray(): T[] { + return this.items.toArray(); + } + + public map(projection: (item: T) => R): R[] { + return this.items.map(v => projection(v!)).toArray(); + } + + public filter(projection: (item: T) => boolean): T[] { + return this.items.filter(v => projection(v!)).toArray(); + } + + public forEach(projection: (item: T) => void): void { + this.items.forEach(v => projection(v!)); + } + + public add(...items: T[]): ImmutableList { + for (let item of items) { + if (!item) { + return this; + } + } + + let newItems = this.items; + + if (items.length > 50) { + newItems = this.items.withMutations(mutable => { + for (let item of items) { + mutable.push(item); + } + }); + } else { + for (let item of items) { + newItems = newItems.push(item); + } + } + + return this.cloned(newItems); + } + + public remove(...items: T[]): ImmutableList { + for (let item of items) { + if (!item || this.items.indexOf(item) < 0) { + return this; + } + } + + let newItems = this.items; + + if (items.length > 50) { + newItems = this.items.withMutations(mutable => { + for (let item of items) { + mutable.remove(mutable.indexOf(item)); + } + }); + } else { + for (let item of items) { + newItems = newItems.remove(newItems.indexOf(item)); + } + } + + return this.cloned(newItems); + } + + public update(item: T, updater: (item: T) => T): ImmutableList { + const index = this.items.indexOf(item); + + if (index < 0 || !updater) { + return this; + } + + const newItem = updater(item); + + if (!newItem || newItem === item) { + return this; + } + + const newItems = this.items.set(index, newItem); + + return this.cloned(newItems); + } + + public bringToFront(items: T[]): ImmutableList { + return this.moveTo(items, Number.MAX_VALUE); + } + + public bringForwards(items: T[]): ImmutableList { + return this.moveTo(items, 1, true); + } + + public sendBackwards(items: T[]): ImmutableList { + return this.moveTo(items, -1, true); + } + + public sendToBack(items: T[]): ImmutableList { + return this.moveTo(items, 0); + } + + public moveTo(items: T[], target: number, relative = false): ImmutableList { + const itemsToStay: ItemToSort[] = []; + const itemsToMove: ItemToSort[] = []; + + const allItems = this.items.toArray(); + + for (let i = 0; i < allItems.length; i++) { + const item = allItems[i]; + + const itemToAdd: ItemToSort = { isInItems: items && items.indexOf(item) >= 0, index: i, value: item }; + + if (itemToAdd.isInItems) { + itemsToMove.push(itemToAdd); + } else { + itemsToStay.push(itemToAdd); + } + } + + if (itemsToMove.length === 0) { + return this; + } + + let isBackwards = false, newIndex = 0; + + if (relative) { + isBackwards = target <= 0; + + let currentIndex = + target > 0 ? + Number.MIN_VALUE : + Number.MAX_VALUE; + + for (let itemFromIds of itemsToMove) { + if (target > 0) { + currentIndex = Math.max(itemFromIds.index, currentIndex); + } else { + currentIndex = Math.min(itemFromIds.index, currentIndex); + } + } + + newIndex = currentIndex + target; + } else { + newIndex = target; + + if (itemsToMove[0].index > newIndex) { + isBackwards = true; + } + } + + const result: T[] = []; + + for (let item of itemsToStay) { + if ((isBackwards && item.index >= newIndex) || item.index > newIndex) { + break; + } + + result.push(item.value); + } + + for (let item of itemsToMove) { + result.push(item.value); + } + + for (let item of itemsToStay) { + if ((isBackwards && item.index >= newIndex) || item.index > newIndex) { + result.push(item.value); + } + } + + return new ImmutableList(result); + } + + private cloned(items: Immutable.List): ImmutableList { + return new ImmutableList(items); + } +} + +interface ItemToSort { isInItems: boolean; index: number; value: T; } \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/immutable-object.js.map b/src/PinkParrot/app/core/utils/immutable-object.js.map new file mode 100644 index 000000000..19308a89b --- /dev/null +++ b/src/PinkParrot/app/core/utils/immutable-object.js.map @@ -0,0 +1 @@ +{"version":3,"file":"immutable-object.js","sourceRoot":"","sources":["immutable-object.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAEH;IAAA;IAcA,CAAC;IAXa,oCAAU,GAApB,cAAyB,CAAC;IAEhB,gCAAM,GAAhB,UAA4C,OAA4C;QACpF,IAAI,MAAM,GAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QAE7B,OAAO,CAAC,MAAM,CAAC,CAAC;QAEhB,MAAM,CAAC,UAAU,EAAE,CAAC;QAEpB,MAAM,CAAC,MAAM,CAAC;IAClB,CAAC;IACL,sBAAC;AAAD,CAAC,AAdD,IAcC;AAdqB,uBAAe,kBAcpC,CAAA"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/immutable-object.spec.js.map b/src/PinkParrot/app/core/utils/immutable-object.spec.js.map new file mode 100644 index 000000000..4c3e50ebd --- /dev/null +++ b/src/PinkParrot/app/core/utils/immutable-object.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"immutable-object.spec.js","sourceRoot":"","sources":["immutable-object.spec.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;;;;;;AAEH,iBAAgC,OAAO,CAAC,CAAA;AAExC;IAA2B,gCAAe;IACtC,sBACW,SAAiB,EACjB,SAAiB;QAExB,iBAAO,CAAC;QAHD,cAAS,GAAT,SAAS,CAAQ;QACjB,cAAS,GAAT,SAAS,CAAQ;IAG5B,CAAC;IAEM,sCAAe,GAAtB,UAAuB,QAAgB;QACnC,MAAM,CAAC,gBAAK,CAAC,MAAM,YAAe,UAAC,CAAe,IAAK,OAAA,CAAC,CAAC,SAAS,GAAG,QAAQ,EAAtB,CAAsB,CAAC,CAAC;IACnF,CAAC;IAEM,4BAAK,GAAZ;QACI,MAAM,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;IAC5D,CAAC;IACL,mBAAC;AAAD,CAAC,AAfD,CAA2B,kBAAe,GAezC;AAED,QAAQ,CAAC,iBAAiB,EAAE;IACxB,EAAE,CAAC,sCAAsC,EAAE;QACvC,IAAM,MAAM,GAAG,IAAI,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAChD,IAAM,MAAM,GAAG,MAAM,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;QAE9C,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACtC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAEtC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACtC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/immutable-object.spec.ts b/src/PinkParrot/app/core/utils/immutable-object.spec.ts new file mode 100644 index 000000000..ff630a3d4 --- /dev/null +++ b/src/PinkParrot/app/core/utils/immutable-object.spec.ts @@ -0,0 +1,38 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { ImmutableObject } from './../'; + +class MockupObject extends ImmutableObject { + constructor( + public property1: string, + public property2: string + ) { + super(); + } + + public changeProperty1(newValue: string): MockupObject { + return super.cloned((x: MockupObject) => x.property1 = newValue); + } + + public clone(): ImmutableObject { + return new MockupObject(this.property1, this.property2); + } +} + +describe('ImmutableObject', () => { + it('should create new instance on update', () => { + const oldObj = new MockupObject('old1', 'old2'); + const newObj = oldObj.changeProperty1('new1'); + + expect(oldObj.property1).toBe('old1'); + expect(oldObj.property2).toBe('old2'); + + expect(newObj.property1).toBe('new1'); + expect(newObj.property2).toBe('old2'); + }); +}); diff --git a/src/PinkParrot/app/core/utils/immutable-object.ts b/src/PinkParrot/app/core/utils/immutable-object.ts new file mode 100644 index 000000000..419eca84c --- /dev/null +++ b/src/PinkParrot/app/core/utils/immutable-object.ts @@ -0,0 +1,22 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +export abstract class ImmutableObject { + public abstract clone(): ImmutableObject; + + protected afterClone() { } + + protected cloned(updater: (instance: ImmutableObject) => void) { + let cloned = this.clone(); + + updater(cloned); + + cloned.afterClone(); + + return cloned; + } +} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/immutable-set.js.map b/src/PinkParrot/app/core/utils/immutable-set.js.map new file mode 100644 index 000000000..7efcc26ee --- /dev/null +++ b/src/PinkParrot/app/core/utils/immutable-set.js.map @@ -0,0 +1 @@ +{"version":3,"file":"immutable-set.js","sourceRoot":"","sources":["immutable-set.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/immutable-set.spec.js.map b/src/PinkParrot/app/core/utils/immutable-set.spec.js.map new file mode 100644 index 000000000..ffb8ae326 --- /dev/null +++ b/src/PinkParrot/app/core/utils/immutable-set.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"immutable-set.spec.js","sourceRoot":"","sources":["immutable-set.spec.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/immutable-set.spec.ts b/src/PinkParrot/app/core/utils/immutable-set.spec.ts new file mode 100644 index 000000000..de7fdf436 --- /dev/null +++ b/src/PinkParrot/app/core/utils/immutable-set.spec.ts @@ -0,0 +1,158 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { ImmutableSet } from './../'; + +describe('ImmutableSet', () => { + it('should instantiate instance from array', () => { + const set_1 = new ImmutableSet(['1', '1', '2', '3']); + + expect(set_1.size).toBe(3); + expect(set_1.contains('1')).toBeTruthy(); + expect(set_1.contains('2')).toBeTruthy(); + expect(set_1.contains('3')).toBeTruthy(); + }); + + it('should add items', () => { + const set_1 = new ImmutableSet(); + const set_2 = set_1.add('1'); + const set_3 = set_2.add('1'); + const set_4 = set_3.add('2'); + const set_5 = set_4.add('3'); + + expect(set_5.size).toBe(3); + expect(set_5.contains('1')).toBeTruthy(); + expect(set_5.contains('2')).toBeTruthy(); + expect(set_5.contains('3')).toBeTruthy(); + }); + + it('should convert to aray', () => { + const set_1 = new ImmutableSet(['a', 'b']); + + const array = set_1.toArray(); + expect(array.length).toBe(2); + expect(array.indexOf('a') >= 0).toBeTruthy(); + expect(array.indexOf('b') >= 0).toBeTruthy(); + }); + + it('should return original set when item to add is null', () => { + const set_1 = new ImmutableSet(); + const set_2 = set_1.add(null!); + + expect(set_2).toBe(set_1); + }); + + it('should return original set when item to add already exists', () => { + const set_1 = new ImmutableSet(); + const set_2 = set_1.add('1'); + const set_3 = set_2.add('1'); + + expect(set_3).toBe(set_2); + }); + + it('should remove item', () => { + const set_1 = new ImmutableSet(); + const set_2 = set_1.add('1'); + const set_3 = set_2.remove('1'); + + expect(set_3.size).toBe(0); + }); + + it('should return original set when item to remove is not found', () => { + const set_1 = new ImmutableSet(); + const set_2 = set_1.add('1'); + const set_3 = set_2.remove('unknown'); + + expect(set_3).toBe(set_2); + }); + + it('should create new set', () => { + const set_1 = new ImmutableSet(); + const set_2 = set_1.add('1'); + const set_3 = set_2.set(['a', 'b']); + + expect(set_3.size).toBe(2); + expect(set_3.contains('a')).toBeTruthy(); + expect(set_3.contains('b')).toBeTruthy(); + }); + + it('should return original set when any item to set is null', () => { + const set_1 = new ImmutableSet(); + const set_2 = set_1.add('1'); + const set_3 = set_2.set(['1', null!]); + + expect(set_3).toBe(set_2); + }); + + it('should return original set when items to set is null', () => { + const set_1 = new ImmutableSet(); + const set_2 = set_1.add('1'); + const set_3 = set_2.set(null!); + + expect(set_3).toBe(set_2); + }); + + it('should return original set when items is same', () => { + const set_1 = new ImmutableSet(); + const set_2 = set_1.add('1'); + const set_3 = set_2.set(['a', 'b']); + const set_4 = set_3.set(['a', 'b']); + + expect(set_4).toBe(set_3); + }); + + it('should remvoe many', () => { + const set_1 = new ImmutableSet(['1', '2', '3', '4']); + const set_2 = set_1.remove('2', '4'); + + expect(set_2.size).toBe(2); + expect(set_2.contains('1')).toBeTruthy(); + expect(set_2.contains('3')).toBeTruthy(); + }); + + it('should return original set when any item to remove is null', () => { + const set_1 = new ImmutableSet(['1', '2', '3', '4']); + const set_2 = set_1.remove('3', null!); + + expect(set_2).toBe(set_1); + }); + + it('should return original set when items to remove is null', () => { + const set_1 = new ImmutableSet(['1', '2', '3', '4']); + const set_2 = set_1.remove(null!); + + expect(set_2).toBe(set_1); + }); + + it('should return correct result for map', () => { + const set_1 = new ImmutableSet(['1', '2', '3', '4']); + + const result = set_1.map(t => t + t); + + expect(result).toEqual(['11', '22', '33', '44']); + }); + + it('should return correct result for forEach', () => { + const set_1 = new ImmutableSet(['1', '2', '3', '4']); + + const result: string[] = []; + + set_1.forEach(t => result.push(t + t)); + + expect(result).toEqual(['11', '22', '33', '44']); + }); + + it('should return correct result for filter', () => { + const set_1 = new ImmutableSet(['1', '2', '3', '4']); + + let i = 0; + + const result = set_1.filter(t => { i++; return i % 2 === 1; }); + + expect(result).toEqual(['1', '3']); + }); +}); diff --git a/src/PinkParrot/app/core/utils/immutable-set.ts b/src/PinkParrot/app/core/utils/immutable-set.ts new file mode 100644 index 000000000..f957386b9 --- /dev/null +++ b/src/PinkParrot/app/core/utils/immutable-set.ts @@ -0,0 +1,92 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import * as Immutable from 'immutable'; + +export class ImmutableSet { + private readonly items: Immutable.Set; + + public get size(): number { + return this.items.size; + } + + constructor(items?: T[] | Immutable.Set) { + if (Array.isArray(items)) { + this.items = Immutable.Set(items); + } else { + this.items = items || Immutable.Set(); + } + + Object.freeze(this); + } + + public contains(item: T): boolean { + return this.items.contains(item); + } + + public toArray(): T[] { + return this.items.toArray(); + } + + public map(projection: (item: T) => R): R[] { + return this.items.map(v => projection(v!)).toArray(); + } + + public filter(projection: (item: T) => boolean): T[] { + return this.items.filter(v => projection(v!)).toArray(); + } + + public forEach(projection: (item: T) => void): void { + this.items.forEach(v => projection(v!)); + } + + public add(item: T): ImmutableSet { + if (!item) { + return this; + } + + const newItems = this.items.add(item); + + return this.cloned(newItems); + } + + public remove(...items: T[]): ImmutableSet { + for (let item of items) { + if (!item) { + return this; + } + } + + const newItems = this.items.subtract(items); + + return this.cloned(newItems); + } + + public set(items: T[]): ImmutableSet { + if (!items) { + return this; + } + + for (let item of items) { + if (!item) { + return this; + } + } + + const newItems = this.items.intersect(items).merge(items); + + return this.cloned(newItems); + } + + private cloned(items: Immutable.Set): ImmutableSet { + if (items !== this.items) { + return new ImmutableSet(items!); + } else { + return this; + } + } +} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/math-helper.js.map b/src/PinkParrot/app/core/utils/math-helper.js.map new file mode 100644 index 000000000..30810c4e1 --- /dev/null +++ b/src/PinkParrot/app/core/utils/math-helper.js.map @@ -0,0 +1 @@ +{"version":3,"file":"math-helper.js","sourceRoot":"","sources":["math-helper.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/math-helper.spec.js.map b/src/PinkParrot/app/core/utils/math-helper.spec.js.map new file mode 100644 index 000000000..66602f447 --- /dev/null +++ b/src/PinkParrot/app/core/utils/math-helper.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"math-helper.spec.js","sourceRoot":"","sources":["math-helper.spec.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/math-helper.spec.ts b/src/PinkParrot/app/core/utils/math-helper.spec.ts new file mode 100644 index 000000000..25bc218d3 --- /dev/null +++ b/src/PinkParrot/app/core/utils/math-helper.spec.ts @@ -0,0 +1,74 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { MathHelper } from './../'; + +describe('MathHelper', () => { + it('should calculate same crc32 for same input', () => { + const crc1 = MathHelper.crc32('input'); + const crc2 = MathHelper.crc32('input'); + + expect(crc1).toBe(crc2); + }); + + it('should calculate different crc32 for different input', () => { + const crc1 = MathHelper.crc32('input1'); + const crc2 = MathHelper.crc32('input2'); + + expect(crc1).not.toBe(crc2); + }); + + it('should calculate different ids', () => { + const guid1 = MathHelper.guid(); + const guid2 = MathHelper.guid(); + + expect(guid1).not.toBe(guid2); + }); + + it('should convert to rad', () => { + expect(MathHelper.toRad(0)).toBe(0); + expect(MathHelper.toRad(180)).toBe(Math.PI * 1); + expect(MathHelper.toRad(360)).toBe(Math.PI * 2); + }); + + it('should convert to degree', () => { + expect(MathHelper.toDegree(0)).toBe(0); + expect(MathHelper.toDegree(Math.PI * 1)).toBe(180); + expect(MathHelper.toDegree(Math.PI * 2)).toBe(360); + }); + + it('should adjust invalid degrees', () => { + expect(MathHelper.toPositiveDegree(36.5 - (1 * 360))).toBe(36.5); + expect(MathHelper.toPositiveDegree(36.5 - (2 * 360))).toBe(36.5); + expect(MathHelper.toPositiveDegree(36.5 + (1 * 360))).toBe(36.5); + expect(MathHelper.toPositiveDegree(36.5 + (2 * 360))).toBe(36.5); + }); + + it('should calculate simple sin', () => { + expect(MathHelper.simpleSin(0)).toBe(0); + expect(MathHelper.simpleSin(90)).toBe(1); + expect(MathHelper.simpleSin(180)).toBe(0); + expect(MathHelper.simpleSin(270)).toBe(1); + }); + + it('should calculate simple cos', () => { + expect(MathHelper.simpleCos(0)).toBe(1); + expect(MathHelper.simpleCos(90)).toBe(0); + expect(MathHelper.simpleCos(180)).toBe(1); + expect(MathHelper.simpleCos(270)).toBe(0); + }); + + it('should calculate multiple of 10', () => { + expect(MathHelper.roundToMultipleOf(13, 10)).toBe(10); + expect(MathHelper.roundToMultipleOf(16, 10)).toBe(20); + }); + + it('should calculate multiple of 2', () => { + expect(MathHelper.roundToMultipleOfTwo(13)).toBe(14); + expect(MathHelper.roundToMultipleOfTwo(12.2)).toBe(12); + }); +}); diff --git a/src/PinkParrot/app/core/utils/math-helper.ts b/src/PinkParrot/app/core/utils/math-helper.ts new file mode 100644 index 000000000..fc4d29b24 --- /dev/null +++ b/src/PinkParrot/app/core/utils/math-helper.ts @@ -0,0 +1,84 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +/* tslint:disable: no-bitwise */ + +export module MathHelper { + const CRC32_TABLE: number[] = []; + + function ensureCrc32Table() { + for (let n = 0; n < 256; n++) { + let c = n; + + for (let k = 0; k < 8; k++) { + c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1)); + } + + CRC32_TABLE[n] = c; + } + } + + ensureCrc32Table(); + + export function crc32(str: string): number { + let crc = 0 ^ (-1); + + for (let i = 0; i < str.length; i++) { + crc = (crc >>> 8) ^ CRC32_TABLE[(crc ^ str.charCodeAt(i)) & 0xFF]; + } + + return (crc ^ (-1)) >>> 0; + } + + export function guid(): string { + return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4(); + } + + export function s4(): string { + return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1); + } + + export function toRad(degree: number): number { + return degree * Math.PI / 180; + } + + export function toDegree(rad: number): number { + return rad * 180 / Math.PI; + } + + export function simpleCos(degree: number): number { + return MathHelper.isSinusRange(MathHelper.toPositiveDegree(degree)) ? 0 : 1; + } + + export function simpleSin(degree: number) { + return MathHelper.isSinusRange(MathHelper.toPositiveDegree(degree)) ? 1 : 0; + } + + export function isSinusRange(degree: number): boolean { + return (degree >= 45 && degree <= 135) || (degree >= 225 && degree <= 315); + } + + export function roundToMultipleOf(value: number, factor: number): number { + return Math.round(value / factor) * factor; + } + + export function roundToMultipleOfTwo(value: number): number { + return Math.round(value / 2) * 2; + } + + export function toPositiveDegree(degree: number): number { + while (degree < 0) { + degree += 360; + } + + while (degree >= 360) { + degree -= 360; + } + + return degree; + } +} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/rect2.js.map b/src/PinkParrot/app/core/utils/rect2.js.map new file mode 100644 index 000000000..f42b06b72 --- /dev/null +++ b/src/PinkParrot/app/core/utils/rect2.js.map @@ -0,0 +1 @@ +{"version":3,"file":"rect2.js","sourceRoot":"","sources":["rect2.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAGH,qBAAyB,QAAQ,CAAC,CAAA;AAElC;IA6DI,eACW,QAAiB,EAAE,IAAI,EACvB,QAAa,EAAE,IAAI;QAD1B,wBAAwB,GAAxB,mBAAwB;QACxB,wBAAoB,GAApB,eAAoB;QADb,aAAQ,GAAR,QAAQ,CAAS;QACjB,aAAQ,GAAR,QAAQ,CAAK;IAExB,CAAC;IA5DD,sBAAW,yBAAM;aAAjB;YACI,MAAM,CAAC,IAAI,WAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAClG,CAAC;;;OAAA;IAED,sBAAW,uBAAI;aAAf;YACI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACrC,CAAC;;;OAAA;IAED,sBAAW,oBAAC;aAAZ;YACI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC3B,CAAC;;;OAAA;IAED,sBAAW,oBAAC;aAAZ;YACI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC3B,CAAC;;;OAAA;IAED,sBAAW,uBAAI;aAAf;YACI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC3B,CAAC;;;OAAA;IAED,sBAAW,sBAAG;aAAd;YACI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC3B,CAAC;;;OAAA;IAED,sBAAW,wBAAK;aAAhB;YACI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACzC,CAAC;;;OAAA;IAED,sBAAW,yBAAM;aAAjB;YACI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACzC,CAAC;;;OAAA;IAED,sBAAW,wBAAK;aAAhB;YACI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACvB,CAAC;;;OAAA;IAED,sBAAW,yBAAM;aAAjB;YACI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACvB,CAAC;;;OAAA;IAED,sBAAW,0BAAO;aAAlB;YACI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjD,CAAC;;;OAAA;IAED,sBAAW,0BAAO;aAAlB;YACI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjD,CAAC;;;OAAA;IAED,sBAAW,0BAAO;aAAlB;YACI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QAC9C,CAAC;;;OAAA;IAED,sBAAW,6BAAU;aAArB;YACI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,MAAM,CAAC,iBAAiB,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,MAAM,CAAC,iBAAiB,CAAC;QAChG,CAAC;;;OAAA;IAQa,oBAAc,GAA5B,UAA6B,IAAmB;QAAnB,oBAAmB,GAAnB,WAAmB;QAC5C,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;YAC7B,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC;QACvB,CAAC;QAED,IAAI,IAAI,GAAG,MAAM,CAAC,SAAS,CAAC;QAC5B,IAAI,IAAI,GAAG,MAAM,CAAC,SAAS,CAAC;QAC5B,IAAI,IAAI,GAAG,MAAM,CAAC,SAAS,CAAC;QAC5B,IAAI,IAAI,GAAG,MAAM,CAAC,SAAS,CAAC;QAE5B,GAAG,CAAC,CAAU,UAAI,EAAJ,aAAI,EAAJ,kBAAI,EAAJ,IAAI,CAAC;YAAd,IAAI,CAAC,aAAA;YACN,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3B,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3B,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3B,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;SAC9B;QAED,MAAM,CAAC,IAAI,KAAK,CAAC,IAAI,WAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,WAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACzG,CAAC;IAEa,qBAAe,GAA7B,UAA8B,KAAqB;QAArB,qBAAqB,GAArB,YAAqB;QAC/C,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;YAC/B,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC;QACvB,CAAC;QAED,IAAI,IAAI,GAAG,MAAM,CAAC,SAAS,CAAC;QAC5B,IAAI,IAAI,GAAG,MAAM,CAAC,SAAS,CAAC;QAC5B,IAAI,IAAI,GAAG,MAAM,CAAC,SAAS,CAAC;QAC5B,IAAI,IAAI,GAAG,MAAM,CAAC,SAAS,CAAC;QAE5B,GAAG,CAAC,CAAU,UAAK,EAAL,eAAK,EAAL,mBAAK,EAAL,IAAK,CAAC;YAAf,IAAI,CAAC,cAAA;YACN,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;YAC9B,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;YAC7B,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;YAC/B,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;SACnC;QAED,MAAM,CAAC,IAAI,KAAK,CAAC,IAAI,WAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,WAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACzG,CAAC;IAEa,mBAAa,GAA3B,UAA4B,QAAc,EAAE,IAAU,EAAE,QAAkB;QACtE,IAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC;QACrB,IAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC;QACrB,IAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;QACjB,IAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;QAEjB,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;YAC1C,MAAM,CAAC,IAAI,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACrC,CAAC;QAED,IAAM,MAAM,GAAG,IAAI,WAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;QAEtD,IAAM,EAAE,GAAG,WAAI,CAAC,aAAa,CAAC,IAAI,WAAI,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;QACxE,IAAM,EAAE,GAAG,WAAI,CAAC,aAAa,CAAC,IAAI,WAAI,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;QACxE,IAAM,EAAE,GAAG,WAAI,CAAC,aAAa,CAAC,IAAI,WAAI,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;QACxE,IAAM,EAAE,GAAG,WAAI,CAAC,aAAa,CAAC,IAAI,WAAI,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;QAExE,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;IAClD,CAAC;IAEM,kBAAE,GAAT,UAAU,CAAQ;QACd,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAChE,CAAC;IAEM,kBAAE,GAAT,UAAU,CAAQ;QACd,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAChE,CAAC;IAEM,wBAAQ,GAAf;QACI,MAAM,CAAC,SAAO,IAAI,CAAC,CAAC,aAAQ,IAAI,CAAC,CAAC,aAAQ,IAAI,CAAC,KAAK,aAAQ,IAAI,CAAC,MAAM,MAAG,CAAC;IAC/E,CAAC;IAEM,wBAAQ,GAAf,UAAgB,CAAO;QACnB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC;IAEM,uBAAO,GAAd,UAAe,CAAS,EAAE,CAAS;QAC/B,MAAM,CAAC,IAAI,KAAK,CAAC,IAAI,WAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,WAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACjI,CAAC;IAEM,wBAAQ,GAAf,UAAgB,CAAO;QACnB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC;IAEM,uBAAO,GAAd,UAAe,CAAS,EAAE,CAAS;QAC/B,MAAM,CAAC,IAAI,KAAK,CAAC,IAAI,WAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,WAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3J,CAAC;IAEM,4BAAY,GAAnB,UAAoB,CAAQ;QACxB,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC;IACxG,CAAC;IAEM,2BAAW,GAAlB,UAAmB,CAAO;QACtB,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC5I,CAAC;IAEM,8BAAc,GAArB,UAAsB,CAAQ;QAC1B,MAAM,CAAC,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC;IAC9K,CAAC;IAEM,yBAAS,GAAhB,UAAiB,CAAQ;QACrB,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1B,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC;QACvB,CAAC;QAED,IAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACnC,IAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAEnC,IAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;QAClF,IAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;QAElF,MAAM,CAAC,IAAI,KAAK,CAAC,IAAI,WAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,WAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;IACzF,CAAC;IAlLa,cAAQ,GAAC,IAAI,GAAG,IAAI,KAAK,CAAC,WAAI,CAAC,IAAI,EAAE,WAAI,CAAC,IAAI,CAAC,CAAC;IAChD,cAAQ,GAAC,KAAK,GAAG,IAAI,KAAK,CAAC,WAAI,CAAC,iBAAiB,EAAE,WAAI,CAAC,iBAAiB,CAAC,CAAC;IAC3E,cAAQ,GAAC,QAAQ,GAAG,IAAI,KAAK,CAAC,WAAI,CAAC,iBAAiB,EAAE,WAAI,CAAC,iBAAiB,CAAC,CAAC;IAiLhG,YAAC;AAAD,CAAC,AApLD,IAoLC;AApLY,aAAK,QAoLjB,CAAA"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/rect2.spec.js.map b/src/PinkParrot/app/core/utils/rect2.spec.js.map new file mode 100644 index 000000000..1657804c6 --- /dev/null +++ b/src/PinkParrot/app/core/utils/rect2.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"rect2.spec.js","sourceRoot":"","sources":["rect2.spec.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/rect2.spec.ts b/src/PinkParrot/app/core/utils/rect2.spec.ts new file mode 100644 index 000000000..6d10ecab4 --- /dev/null +++ b/src/PinkParrot/app/core/utils/rect2.spec.ts @@ -0,0 +1,237 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { + Rect2, + Rotation, + Vec2 +} from './../'; + +describe('Rect2', () => { + it('should provide values from constructor', () => { + const rect = new Rect2(new Vec2(10, 20), new Vec2(50, 30)); + + expect(rect.x).toBe(10); + expect(rect.y).toBe(20); + expect(rect.top).toBe(20); + expect(rect.left).toBe(10); + expect(rect.right).toBe(60); + expect(rect.width).toBe(50); + expect(rect.height).toBe(30); + expect(rect.bottom).toBe(50); + expect(rect.centerX).toBe(35); + expect(rect.centerY).toBe(35); + + expect(rect.size).toEqual(new Vec2(50, 30)); + expect(rect.center).toEqual(new Vec2(35, 35)); + expect(rect.position).toEqual(new Vec2(10, 20)); + + expect(rect.area).toBe(1500); + + expect(rect.toString()).toBe('(x: 10, y: 20, w: 50, h: 30)'); + }); + + it('should calculate isEmpty correctly', () => { + expect(new Rect2(new Vec2(10, 20), new Vec2(50, 30)).isEmpty).toBeFalsy(); + expect(new Rect2(new Vec2(10, 20), new Vec2(-1, 30)).isEmpty).toBeTruthy(); + expect(new Rect2(new Vec2(10, 20), new Vec2(50, -9)).isEmpty).toBeTruthy(); + }); + + it('should calculate isInfinite correctly', () => { + expect(new Rect2(new Vec2(10, 20), new Vec2(50, 30)).isInfinite).toBeFalsy(); + expect(new Rect2(new Vec2(10, 20), new Vec2(Number.POSITIVE_INFINITY, 30)).isInfinite).toBeTruthy(); + expect(new Rect2(new Vec2(10, 20), new Vec2(50, Number.POSITIVE_INFINITY)).isInfinite).toBeTruthy(); + }); + + it('should inflate correctly', () => { + const rect = new Rect2(new Vec2(10, 20), new Vec2(50, 30)); + + const actual1 = rect.inflateV(new Vec2(10, 20)); + const actual2 = rect.inflate(10, 20); + const expected = new Rect2(new Vec2(0, 0), new Vec2(70, 70)); + + expect(actual1).toEqual(expected); + expect(actual2).toEqual(expected); + }); + + it('should deflate correctly', () => { + const rect = new Rect2(new Vec2(10, 20), new Vec2(50, 30)); + + const actual1 = rect.deflateV(new Vec2(25, 15)); + const actual2 = rect.deflate(25, 15); + const expected = new Rect2(new Vec2(35, 35), new Vec2(0, 0)); + + expect(actual1).toEqual(expected); + expect(actual2).toEqual(expected); + }); + + it('should return true for intersection with infinite rect', () => { + const rect = new Rect2(new Vec2(10, 20), new Vec2(50, 30)); + + expect(rect.intersectsWith(Rect2.INFINITE)).toBeTruthy(); + + expect(Rect2.INFINITE.intersectsWith(rect)).toBeTruthy(); + expect(Rect2.INFINITE.intersectsWith(Rect2.INFINITE)).toBeTruthy(); + }); + + it('should return false for intersection with empty rect', () => { + const rect = new Rect2(new Vec2(10, 20), new Vec2(50, 30)); + + expect(rect.intersectsWith(Rect2.EMPTY)).toBeFalsy(); + + expect(Rect2.EMPTY.intersectsWith(rect)).toBeFalsy(); + expect(Rect2.EMPTY.intersectsWith(Rect2.INFINITE)).toBeFalsy(); + }); + + it('should return empty for no intersection', () => { + const rect = new Rect2(new Vec2(10, 20), new Vec2(50, 30)); + const outer = new Rect2(new Vec2(100, 20), new Vec2(50, 30)); + + const actual = rect.intersect(outer); + const expected = Rect2.EMPTY; + + expect(actual).toEqual(expected); + }); + + it('should return result for intersection', () => { + const rect = new Rect2(new Vec2(10, 20), new Vec2(50, 30)); + const inner = new Rect2(new Vec2(35, 35), new Vec2(100, 30)); + + const actual = rect.intersect(inner); + const expected = new Rect2(new Vec2(35, 35), new Vec2(25, 15)); + + expect(actual).toEqual(expected); + }); + + it('should make correct contains by vector tests', () => { + const rect = new Rect2(new Vec2(10, 20), new Vec2(50, 30)); + + expect(rect.containsVec(rect.center)).toBeTruthy(); + expect(rect.containsVec(new Vec2(rect.left, rect.top))).toBeTruthy(); + + expect(rect.containsVec(new Vec2(rect.centerX, 0))).toBeFalsy(); + expect(rect.containsVec(new Vec2(rect.centerX, 100))).toBeFalsy(); + expect(rect.containsVec(new Vec2(100, rect.centerY))).toBeFalsy(); + expect(rect.containsVec(new Vec2(-50, rect.centerY))).toBeFalsy(); + }); + + it('should return true when rect contains other rect', () => { + const rect = new Rect2(new Vec2(400, 400), new Vec2(400, 400)); + const other = new Rect2(new Vec2(500, 500), new Vec2(200, 200)); + + expect(rect.containsRect(other)).toBeTruthy(); + }); + + it('should return false when other rect is too top', () => { + const rect = new Rect2(new Vec2(400, 400), new Vec2(400, 400)); + const other = new Rect2(new Vec2(300, 900), new Vec2(300, 100)); + + expect(rect.containsRect(other)).toBeFalsy(); + }); + + it('should return false when other rect is too bottom', () => { + const rect = new Rect2(new Vec2(400, 400), new Vec2(400, 400)); + const other = new Rect2(new Vec2(300, 900), new Vec2(100, 300)); + + expect(rect.containsRect(other)).toBeFalsy(); + }); + + it('should return false when other rect is too left', () => { + const rect = new Rect2(new Vec2(400, 400), new Vec2(400, 400)); + const other = new Rect2(new Vec2(200, 200), new Vec2(100, 300)); + + expect(rect.containsRect(other)).toBeFalsy(); + }); + + it('should return false when other right is too left', () => { + const rect = new Rect2(new Vec2(400, 400), new Vec2(400, 400)); + const other = new Rect2(new Vec2(900, 200), new Vec2(100, 300)); + + expect(rect.containsRect(other)).toBeFalsy(); + }); + + it('should return empty when creating from null vectors', () => { + const actual = Rect2.createFromVecs(null); + const expected = Rect2.EMPTY; + + expect(actual).toEqual(expected); + }); + + it('should return empty when creating from null rects', () => { + const actual = Rect2.createFromRects(null); + const expected = Rect2.EMPTY; + + expect(actual).toEqual(expected); + }); + + it('should provide valid zero instance', () => { + const actual = Rect2.ZERO; + const expected = new Rect2(new Vec2(0, 0), new Vec2(0, 0)); + + expect(actual).toEqual(expected); + }); + + it('should provide valid empty instance', () => { + const actual = Rect2.EMPTY; + const expected = new Rect2(Vec2.NEGATIVE_INFINITE, Vec2.NEGATIVE_INFINITE); + + expect(actual).toEqual(expected); + }); + + it('should provide valid infinite instance', () => { + const actual = Rect2.INFINITE; + const expected = new Rect2(Vec2.POSITIVE_INFINITE, Vec2.POSITIVE_INFINITE); + + expect(actual).toEqual(expected); + }); + + it('should create correct rect from vectors', () => { + const actual = + Rect2.createFromVecs([ + new Vec2(100, 100), + new Vec2(500, 300), + new Vec2(900, 800)]); + const expected = new Rect2(new Vec2(100, 100), new Vec2(800, 700)); + + expect(actual).toEqual(expected); + }); + + it('should create correct rect from rects', () => { + const actual = + Rect2.createFromRects([ + new Rect2(new Vec2(100, 100), new Vec2(100, 100)), + new Rect2(new Vec2(500, 300), new Vec2(100, 100)), + new Rect2(new Vec2(150, 150), new Vec2(750, 650))]); + const expected = new Rect2(new Vec2(100, 100), new Vec2(800, 700)); + + expect(actual).toEqual(expected); + }); + + it('should create rect from rotation', () => { + const actual = Rect2.createRotated(new Vec2(400, 300), new Vec2(600, 400), Rotation.createFromRadian(Math.PI / 2)); + const expected = new Rect2(new Vec2(500, 200), new Vec2(400, 600)); + + expect(actual).toEqual(expected); + }); + + it('should create rect from zero rotation', () => { + const actual = Rect2.createRotated(new Vec2(400, 300), new Vec2(600, 400), Rotation.ZERO); + const expected = new Rect2(new Vec2(400, 300), new Vec2(600, 400)); + + expect(actual).toEqual(expected); + }); + + it('should make valid equal comparisons', () => { + expect(new Rect2(new Vec2(10, 10), new Vec2(10, 10)).eq(new Rect2(new Vec2(10, 10), new Vec2(10, 10)))).toBeTruthy(); + expect(new Rect2(new Vec2(10, 10), new Vec2(10, 10)).eq(new Rect2(new Vec2(20, 20), new Vec2(20, 20)))).toBeFalsy(); + }); + + it('should make valid not equal comparisons', () => { + expect(new Rect2(new Vec2(10, 10), new Vec2(10, 10)).ne(new Rect2(new Vec2(10, 10), new Vec2(10, 10)))).toBeFalsy(); + expect(new Rect2(new Vec2(10, 10), new Vec2(10, 10)).ne(new Rect2(new Vec2(20, 20), new Vec2(20, 20)))).toBeTruthy(); + }); +}); \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/rect2.ts b/src/PinkParrot/app/core/utils/rect2.ts new file mode 100644 index 000000000..ed8a915fe --- /dev/null +++ b/src/PinkParrot/app/core/utils/rect2.ts @@ -0,0 +1,191 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { Rotation } from './rotation'; +import { Vec2 } from './vec2'; + +export class Rect2 { + public static readonly ZERO = new Rect2(Vec2.ZERO, Vec2.ZERO); + public static readonly EMPTY = new Rect2(Vec2.NEGATIVE_INFINITE, Vec2.NEGATIVE_INFINITE); + public static readonly INFINITE = new Rect2(Vec2.POSITIVE_INFINITE, Vec2.POSITIVE_INFINITE); + + public get center(): Vec2 { + return new Vec2(this.position.x + (0.5 * this.size.x), this.position.y + (0.5 * this.size.y)); + } + + public get area(): number { + return this.size.x * this.size.y; + } + + public get x(): number { + return this.position.x; + } + + public get y(): number { + return this.position.y; + } + + public get left(): number { + return this.position.x; + } + + public get top(): number { + return this.position.y; + } + + public get right(): number { + return this.position.x + this.size.x; + } + + public get bottom(): number { + return this.position.y + this.size.y; + } + + public get width(): number { + return this.size.x; + } + + public get height(): number { + return this.size.y; + } + + public get centerX(): number { + return this.position.x + (0.5 * this.size.x); + } + + public get centerY(): number { + return this.position.y + (0.5 * this.size.y); + } + + public get isEmpty(): boolean { + return this.size.x < 0 || this.size.y < 0; + } + + public get isInfinite(): boolean { + return this.size.x === Number.POSITIVE_INFINITY || this.size.y === Number.POSITIVE_INFINITY; + } + + constructor( + public readonly position: Vec2, + public readonly size: Vec2 + ) { + } + + public static createFromVecs(vecs: Vec2[] | null): Rect2 { + if (!vecs || vecs.length === 0) { + return Rect2.EMPTY; + } + + let minX = Number.MAX_VALUE; + let minY = Number.MAX_VALUE; + let maxX = Number.MIN_VALUE; + let maxY = Number.MIN_VALUE; + + for (let v of vecs) { + minX = Math.min(minX, v.x); + minY = Math.min(minY, v.y); + maxX = Math.max(maxX, v.x); + maxY = Math.max(maxY, v.y); + } + + return new Rect2(new Vec2(minX, minY), new Vec2(Math.max(0, maxX - minX), Math.max(0, maxY - minY))); + } + + public static createFromRects(rects: Rect2[] | null): Rect2 { + if (!rects || rects.length === 0) { + return Rect2.EMPTY; + } + + let minX = Number.MAX_VALUE; + let minY = Number.MAX_VALUE; + let maxX = Number.MIN_VALUE; + let maxY = Number.MIN_VALUE; + + for (let r of rects) { + minX = Math.min(minX, r.left); + minY = Math.min(minY, r.top); + maxX = Math.max(maxX, r.right); + maxY = Math.max(maxY, r.bottom); + } + + return new Rect2(new Vec2(minX, minY), new Vec2(Math.max(0, maxX - minX), Math.max(0, maxY - minY))); + } + + public static createRotated(position: Vec2, size: Vec2, rotation: Rotation): Rect2 { + const x = position.x; + const y = position.y; + const w = size.x; + const h = size.y; + + if (Math.abs(rotation.sin) < Number.EPSILON) { + return new Rect2(position, size); + } + + const center = new Vec2(x + (w * 0.5), y + (h * 0.5)); + + const lt = Vec2.createRotated(new Vec2(x + 0, y + 0), center, rotation); + const rt = Vec2.createRotated(new Vec2(x + w, y + 0), center, rotation); + const rb = Vec2.createRotated(new Vec2(x + w, y + h), center, rotation); + const lb = Vec2.createRotated(new Vec2(x + 0, y + h), center, rotation); + + return Rect2.createFromVecs([lb, lt, rb, rt]); + } + + public eq(r: Rect2): boolean { + return this.position.eq(r.position) && this.size.eq(r.size); + } + + public ne(r: Rect2): boolean { + return this.position.ne(r.position) || this.size.ne(r.size); + } + + public toString(): string { + return `(x: ${this.x}, y: ${this.y}, w: ${this.width}, h: ${this.height})`; + } + + public inflateV(v: Vec2): Rect2 { + return this.inflate(v.x, v.y); + } + + public inflate(w: number, h: number): Rect2 { + return new Rect2(new Vec2(this.position.x - w, this.position.y - h), new Vec2(this.size.x + (2 * w), this.size.y + (2 * h))); + } + + public deflateV(v: Vec2): Rect2 { + return this.deflate(v.x, v.y); + } + + public deflate(w: number, h: number): Rect2 { + return new Rect2(new Vec2(this.position.x + w, this.position.y + h), new Vec2(Math.max(0, this.size.x - (2 * w)), Math.max(0, this.size.y - (2 * h)))); + } + + public containsRect(r: Rect2): boolean { + return r.left >= this.left && r.right <= this.right && r.top >= this.top && r.bottom <= this.bottom; + } + + public containsVec(v: Vec2): boolean { + return v.x >= this.position.x && v.x - this.size.x <= this.position.x && v.y >= this.position.y && v.y - this.size.y <= this.position.y; + } + + public intersectsWith(r: Rect2): boolean { + return !this.isEmpty && !r.isEmpty && ((r.left <= this.right && r.right >= this.left && r.top <= this.bottom && r.bottom >= this.top) || this.isInfinite || r.isInfinite); + } + + public intersect(r: Rect2): Rect2 { + if (!this.intersectsWith(r)) { + return Rect2.EMPTY; + } + + const minX = Math.max(this.x, r.x); + const minY = Math.max(this.y, r.y); + + const w = Math.min(this.position.x + this.size.x, r.position.x + r.size.x) - minX; + const h = Math.min(this.position.y + this.size.y, r.position.y + r.size.y) - minY; + + return new Rect2(new Vec2(minX, minY), new Vec2(Math.max(w, 0.0), Math.max(h, 0.0))); + } +} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/rotation.js.map b/src/PinkParrot/app/core/utils/rotation.js.map new file mode 100644 index 000000000..2de772159 --- /dev/null +++ b/src/PinkParrot/app/core/utils/rotation.js.map @@ -0,0 +1 @@ +{"version":3,"file":"rotation.js","sourceRoot":"","sources":["rotation.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAEH,4BAA2B,eAAe,CAAC,CAAA;AAE3C;IAMI,kBACW,QAAe,EAAE,MAAM,EACvB,QAAe,EAAE,MAAM;QAD9B,wBAAsB,GAAtB,iBAAsB;QACtB,wBAAsB,GAAtB,iBAAsB;QADf,aAAQ,GAAR,QAAQ,CAAO;QACf,aAAQ,GAAR,QAAQ,CAAO;QAEtB,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC5B,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAE5B,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAEa,yBAAgB,GAA9B,UAA+B,MAAc;QACzC,MAAM,CAAC,IAAI,QAAQ,CAAC,MAAM,EAAE,wBAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IAC7D,CAAC;IAEa,yBAAgB,GAA9B,UAA+B,MAAc;QACzC,MAAM,CAAC,IAAI,QAAQ,CAAC,wBAAU,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;IAC1D,CAAC;IAEM,qBAAE,GAAT,UAAU,CAAW;QACjB,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,CAAC;IACpC,CAAC;IAEM,qBAAE,GAAT,UAAU,CAAW;QACjB,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,CAAC;IACpC,CAAC;IAEM,2BAAQ,GAAf;QACI,MAAM,CAAI,IAAI,CAAC,MAAM,WAAG,CAAC;IAC7B,CAAC;IAEM,sBAAG,GAAV,UAAW,CAAW;QAClB,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAC,wBAAU,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IAC1F,CAAC;IAEM,sBAAG,GAAV,UAAW,CAAW;QAClB,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAC,wBAAU,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IAC1F,CAAC;IAEM,yBAAM,GAAb;QACI,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACnD,CAAC;IA7Ca,iBAAQ,GAAC,IAAI,GAAG,QAAQ,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC;IA8C/D,eAAC;AAAD,CAAC,AA/CD,IA+CC;AA/CY,gBAAQ,WA+CpB,CAAA"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/rotation.spec.js.map b/src/PinkParrot/app/core/utils/rotation.spec.js.map new file mode 100644 index 000000000..c6b4b2a29 --- /dev/null +++ b/src/PinkParrot/app/core/utils/rotation.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"rotation.spec.js","sourceRoot":"","sources":["rotation.spec.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/rotation.spec.ts b/src/PinkParrot/app/core/utils/rotation.spec.ts new file mode 100644 index 000000000..d1390f0c4 --- /dev/null +++ b/src/PinkParrot/app/core/utils/rotation.spec.ts @@ -0,0 +1,73 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { Rotation } from './../'; + +describe('Rotation', () => { + it('should sub correctly', () => { + const rotation1 = Rotation.createFromDegree(180); + const rotation2 = Rotation.createFromDegree(45); + + const actual = rotation1.sub(rotation2); + const expected = Rotation.createFromDegree(135); + + expect(actual).toEqual(expected); + }); + + it('should add correctly', () => { + const rotation1 = Rotation.createFromDegree(180); + const rotation2 = Rotation.createFromDegree(45); + + const actual = rotation1.add(rotation2); + const expected = Rotation.createFromDegree(225); + + expect(actual).toEqual(expected); + }); + + it('should calculate negated rotation', () => { + const rotation = Rotation.createFromDegree(180); + + const actual = rotation.negate(); + const expected = Rotation.createFromDegree(-180); + + expect(actual).toEqual(expected); + }); + + it('should create rotation by degree', () => { + const rotation = Rotation.createFromDegree(180); + + expect(rotation.degree).toBe(180); + expect(rotation.radian).toBe(Math.PI); + + expect(rotation.cos).toBe(Math.cos(Math.PI)); + expect(rotation.sin).toBe(Math.sin(Math.PI)); + + expect(rotation.toString()).toBe('180°'); + }); + + it('should create rotation by radian', () => { + const rotation = Rotation.createFromRadian(Math.PI); + + expect(rotation.degree).toBe(180); + expect(rotation.radian).toBe(Math.PI); + + expect(rotation.cos).toBe(Math.cos(Math.PI)); + expect(rotation.sin).toBe(Math.sin(Math.PI)); + + expect(rotation.toString()).toBe('180°'); + }); + + it('should make correct equal comparisons', () => { + expect(Rotation.createFromDegree(123).eq(Rotation.createFromDegree(123))).toBeTruthy(); + expect(Rotation.createFromDegree(123).eq(Rotation.createFromDegree(234))).toBeFalsy(); + }); + + it('should make correct not equal comparisons', () => { + expect(Rotation.createFromDegree(123).ne(Rotation.createFromDegree(123))).toBeFalsy(); + expect(Rotation.createFromDegree(123).ne(Rotation.createFromDegree(234))).toBeTruthy(); + }); +}); \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/rotation.ts b/src/PinkParrot/app/core/utils/rotation.ts new file mode 100644 index 000000000..9eb2652e2 --- /dev/null +++ b/src/PinkParrot/app/core/utils/rotation.ts @@ -0,0 +1,57 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { MathHelper } from './math-helper'; + +export class Rotation { + public static readonly ZERO = Rotation.createFromRadian(0); + + public cos: number; + public sin: number; + + constructor( + public readonly radian: number, + public readonly degree: number + ) { + this.cos = Math.cos(radian); + this.sin = Math.sin(radian); + + Object.freeze(this); + } + + public static createFromRadian(radian: number): Rotation { + return new Rotation(radian, MathHelper.toDegree(radian)); + } + + public static createFromDegree(degree: number): Rotation { + return new Rotation(MathHelper.toRad(degree), degree); + } + + public eq(r: Rotation): boolean { + return this.radian === r.radian; + } + + public ne(r: Rotation): boolean { + return this.radian !== r.radian; + } + + public toString(): string { + return `${this.degree}°`; + } + + public add(r: Rotation): Rotation { + return Rotation.createFromDegree(MathHelper.toPositiveDegree(this.degree + r.degree)); + } + + public sub(r: Rotation): Rotation { + return Rotation.createFromDegree(MathHelper.toPositiveDegree(this.degree - r.degree)); + } + + public negate(): Rotation { + return Rotation.createFromDegree(-this.degree); + } +} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/vec2.js.map b/src/PinkParrot/app/core/utils/vec2.js.map new file mode 100644 index 000000000..5c3d86999 --- /dev/null +++ b/src/PinkParrot/app/core/utils/vec2.js.map @@ -0,0 +1 @@ +{"version":3,"file":"vec2.js","sourceRoot":"","sources":["vec2.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/vec2.spec.js.map b/src/PinkParrot/app/core/utils/vec2.spec.js.map new file mode 100644 index 000000000..bb0f65214 --- /dev/null +++ b/src/PinkParrot/app/core/utils/vec2.spec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"vec2.spec.js","sourceRoot":"","sources":["vec2.spec.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/vec2.spec.ts b/src/PinkParrot/app/core/utils/vec2.spec.ts new file mode 100644 index 000000000..6c153ffa3 --- /dev/null +++ b/src/PinkParrot/app/core/utils/vec2.spec.ts @@ -0,0 +1,159 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { Rotation, Vec2 } from './../'; + +describe('Vec2', () => { + it('should instantiate from x and y value', () => { + const v = new Vec2(10, 20); + + expect(v.x).toBe(10); + expect(v.y).toBe(20); + + expect(v.toString()).toBe('(10, 20)'); + }); + + it('should make valid equal comparisons', () => { + expect(new Vec2(10, 10).eq(new Vec2(10, 10))).toBeTruthy(); + expect(new Vec2(10, 10).eq(new Vec2(20, 20))).toBeFalsy(); + }); + + it('should make valid not equal comparisons', () => { + expect(new Vec2(10, 10).ne(new Vec2(20, 20))).toBeTruthy(); + expect(new Vec2(10, 10).ne(new Vec2(10, 10))).toBeFalsy(); + }); + + it('should calculate multiple of 10', () => { + const actual = new Vec2(13, 16).round(10); + const expected = new Vec2(10, 20); + + expect(actual).toEqual(expected); + }); + + it('should calculate multiple of 2', () => { + const actual = new Vec2(13, 12.2).roundToMultipleOfTwo(); + const expected = new Vec2(14, 12); + + expect(actual).toEqual(expected); + }); + + it('should add by vector correctly', () => { + const actual = new Vec2(15, 12).add(new Vec2(4, 1)); + const expected = new Vec2(19, 13); + + expect(actual).toEqual(expected); + }); + + it('should add by scalar correctly', () => { + const actual = new Vec2(15, 12).addScalar(3); + const expected = new Vec2(18, 15); + + expect(actual).toEqual(expected); + }); + + it('should subtract by vector correctly', () => { + const actual = new Vec2(15, 12).sub(new Vec2(4, 1)); + const expected = new Vec2(11, 11); + + expect(actual).toEqual(expected); + }); + + it('should subtract by scalar correctly', () => { + const actual = new Vec2(15, 12).subScalar(3); + const expected = new Vec2(12, 9); + + expect(actual).toEqual(expected); + }); + + it('should multiply by vector correctly', () => { + const actual = new Vec2(15, 12).mul(new Vec2(4, 2)); + const expected = new Vec2(60, 24); + + expect(actual).toEqual(expected); + }); + + it('should multiply by scalar correctly', () => { + const actual = new Vec2(15, 12).mulScalar(3); + const expected = new Vec2(45, 36); + + expect(actual).toEqual(expected); + }); + + it('should divide by vector correctly', () => { + const actual = new Vec2(15, 12).div(new Vec2(5, 2)); + const expected = new Vec2(3, 6); + + expect(actual).toEqual(expected); + }); + + it('should divide by scalar correctly', () => { + const actual = new Vec2(15, 12).divScalar(3); + const expected = new Vec2(5, 4); + + expect(actual).toEqual(expected); + }); + + it('should negate correctly', () => { + const actual = new Vec2(15, 12).negate(); + const expected = new Vec2(-15, -12); + + expect(actual).toEqual(expected); + }); + + it('should calculate max vector', () => { + const actual = Vec2.max(new Vec2(20, 10), new Vec2(15, 30)); + const expected = new Vec2(20, 30); + + expect(actual).toEqual(expected); + }); + + it('should calculate min vector', () => { + const actual = Vec2.min(new Vec2(20, 10), new Vec2(15, 30)); + const expected = new Vec2(15, 10); + + expect(actual).toEqual(expected); + }); + + it('should calculate length', () => { + const actual = new Vec2(10, 10).length; + const expected = Math.sqrt(200); + + expect(actual).toBe(expected); + }); + + it('should calculate length squared', () => { + const actual = new Vec2(10, 10).lengtSquared; + const expected = 200; + + expect(actual).toBe(expected); + }); + + it('should calculate median', () => { + const actual = Vec2.createMedian(new Vec2(10, 20), new Vec2(20, 20), new Vec2(60, 20)); + const expected = new Vec2(30, 20); + + expect(actual).toEqual(expected); + }); + + it('should calculate rotated vector correctly', () => { + const source = new Vec2(40, 20); + const center = new Vec2(20, 20); + + const rotation = Rotation.createFromRadian(Math.PI / 2); + + const actual = Vec2.createRotated(source, center, rotation); + const expected = new Vec2(20, 40); + + expect(actual).toEqual(expected); + }); + + it('should calculate angles between vectors', () => { + expect(Vec2.angleBetween(new Vec2(1, 0), new Vec2(1, 0))).toBe(0); + expect(Vec2.angleBetween(new Vec2(1, 0), new Vec2(1, 1))).toBe(45); + expect(Vec2.angleBetween(new Vec2(1, 0), new Vec2(0, 1))).toBe(90); + }); +}); \ No newline at end of file diff --git a/src/PinkParrot/app/core/utils/vec2.ts b/src/PinkParrot/app/core/utils/vec2.ts new file mode 100644 index 000000000..676a15c07 --- /dev/null +++ b/src/PinkParrot/app/core/utils/vec2.ts @@ -0,0 +1,127 @@ +/* + * Athene Requirements Center + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import { MathHelper } from './math-helper'; +import { Rotation } from './rotation'; + +export class Vec2 { + public static readonly ZERO = new Vec2(0, 0); + + public static readonly ONE = new Vec2(1, 1); + + public static readonly POSITIVE_INFINITE = new Vec2(Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); + public static readonly NEGATIVE_INFINITE = new Vec2(Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY); + + public get length(): number { + return Math.sqrt(this.x * this.x + this.y * this.y); + } + + public get lengtSquared(): number { + return this.x * this.x + this.y * this.y; + } + + constructor( + public readonly x: number, + public readonly y: number + ) { + Object.freeze(this); + } + + public eq(v: Vec2): boolean { + return this.x === v.x && this.y === v.y; + } + + public ne(v: Vec2): boolean { + return this.x !== v.x || this.y !== v.y; + } + + public toString(): string { + return `(${this.x}, ${this.y})`; + } + + public add(v: Vec2): Vec2 { + return new Vec2(this.x + v.x, this.y + v.y); + } + + public addScalar(s: number): Vec2 { + return new Vec2(this.x + s, this.y + s); + } + + public sub(v: Vec2): Vec2 { + return new Vec2(this.x - v.x, this.y - v.y); + } + + public subScalar(s: number): Vec2 { + return new Vec2(this.x - s, this.y - s); + } + + public mul(v: Vec2): Vec2 { + return new Vec2(this.x * v.x, this.y * v.y); + } + + public mulScalar(s: number): Vec2 { + return new Vec2(this.x * s, this.y * s); + } + + public div(v: Vec2): Vec2 { + return new Vec2(this.x / v.x, this.y / v.y); + } + + public divScalar(s: number): Vec2 { + return new Vec2(this.x / s, this.y / s); + } + + public negate(): Vec2 { + return new Vec2(-this.x, -this.y); + } + + public static max(lhs: Vec2, rhs: Vec2): Vec2 { + return new Vec2(Math.max(lhs.x, rhs.x), Math.max(lhs.y, rhs.y)); + } + + public static min(lhs: Vec2, rhs: Vec2): Vec2 { + return new Vec2(Math.min(lhs.x, rhs.x), Math.min(lhs.y, rhs.y)); + } + + public round(factor = 1): Vec2 { + return new Vec2(MathHelper.roundToMultipleOf(this.x, factor), MathHelper.roundToMultipleOf(this.y, factor)); + } + + public roundToMultipleOfTwo(): Vec2 { + return new Vec2(MathHelper.roundToMultipleOf(this.x, 2), MathHelper.roundToMultipleOf(this.y, 2)); + } + + public static createRotated(vec: Vec2, center: Vec2, rotation: Rotation): Vec2 { + const x = vec.x - center.x; + const y = vec.y - center.y; + + const result = new Vec2( + (x * rotation.cos) - (y * rotation.sin) + center.x, + (x * rotation.sin) + (y * rotation.cos) + center.y); + + return result; + } + + public static createMedian(...vecs: Vec2[]) { + let medianX = 0; + let medianY = 0; + + for (let v of vecs) { + medianX += v.x; + medianY += v.y; + } + + return new Vec2(medianX / vecs.length, medianY / vecs.length); + } + + public static angleBetween(lhs: Vec2, rhs: Vec2): number { + const y = (lhs.x * rhs.y) - (rhs.x * lhs.y); + const x = (lhs.x * rhs.x) + (lhs.y * rhs.y); + + return MathHelper.toPositiveDegree(MathHelper.toDegree(Math.atan2(y, x))); + } +} \ No newline at end of file diff --git a/src/PinkParrot/app/main.js.map b/src/PinkParrot/app/main.js.map new file mode 100644 index 000000000..e56468395 --- /dev/null +++ b/src/PinkParrot/app/main.js.map @@ -0,0 +1 @@ +{"version":3,"file":"main.js","sourceRoot":"","sources":["main.ts"],"names":[],"mappings":";AAAA,QAAO,oBAAoB,CAAC,CAAA;AAE5B,yCAAuC,mCAAmC,CAAC,CAAA;AAC3E,qBAA+B,eAAe,CAAC,CAAA;AAE/C,2BAA0B,cAAc,CAAC,CAAA;AAEzC,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,YAAY,CAAC,CAAC,CAAC;IACnC,qBAAc,EAAE,CAAC;AACrB,CAAC;AAED,iDAAsB,EAAE,CAAC,eAAe,CAAC,sBAAS,CAAC,CAAC"} \ No newline at end of file diff --git a/src/PinkParrot/app/main.ts b/src/PinkParrot/app/main.ts new file mode 100644 index 000000000..5437729ac --- /dev/null +++ b/src/PinkParrot/app/main.ts @@ -0,0 +1,12 @@ +import './theme/theme.scss'; + +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; +import { enableProdMode } from '@angular/core'; + +import { AppModule } from './app.module'; + +if (process.env.ENV === 'production') { + enableProdMode(); +} + +platformBrowserDynamic().bootstrapModule(AppModule); \ No newline at end of file diff --git a/src/PinkParrot/app/polyfills.js.map b/src/PinkParrot/app/polyfills.js.map new file mode 100644 index 000000000..47152f046 --- /dev/null +++ b/src/PinkParrot/app/polyfills.js.map @@ -0,0 +1 @@ +{"version":3,"file":"polyfills.js","sourceRoot":"","sources":["polyfills.ts"],"names":[],"mappings":";AAAA,QAAO,aAAa,CAAC,CAAA;AACrB,QAAO,kBAAkB,CAAC,CAAA;AAE1B,OAAO,CAAC,mBAAmB,CAAC,CAAC;AAE7B,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,YAAY,CAAC,CAAC,CAAC;IACnC,KAAK,CAAC,iBAAiB,CAAC,GAAG,QAAQ,CAAC;IAEpC,OAAO,CAAC,oCAAoC,CAAC,CAAC;AAClD,CAAC"} \ No newline at end of file diff --git a/src/PinkParrot/app/polyfills.ts b/src/PinkParrot/app/polyfills.ts new file mode 100644 index 000000000..cacff420a --- /dev/null +++ b/src/PinkParrot/app/polyfills.ts @@ -0,0 +1,10 @@ +import 'core-js/es6'; +import 'reflect-metadata'; + +require('zone.js/dist/zone'); + +if (process.env.ENV !== 'production') { + Error['stackTraceLimit'] = Infinity; + + require('zone.js/dist/long-stack-trace-zone'); +} \ No newline at end of file diff --git a/src/PinkParrot/app/theme/_bootstrap.scss b/src/PinkParrot/app/theme/_bootstrap.scss new file mode 100644 index 000000000..64a90dcf0 --- /dev/null +++ b/src/PinkParrot/app/theme/_bootstrap.scss @@ -0,0 +1,69 @@ +@import '_mixins.scss'; +@import '_vars.scss'; + +.nav-icon { + & { + margin-top: -0.5rem; + text-align: center; + text-decoration: none; + cursor: default; + } + + span { + display: block; + font-size: 0.8em; + font-weight: normal; + cursor: default; + } +} + +.navbar-light .navbar-nav .nav-link, .btn-icon { + & { + color: $nav-text-color; + } + + &:hover, &:focus { + text-decoration: none; + } + + &:hover { + color: black; + } + + &.disabled { + color: lighten($nav-text-color, 55%); + } +} + +.navbar-light .navbar-nav .nav-link.btn-blue, .btn-icon.btn-blue, .btn-blue { + &:hover { + color: $accent-normal; + } + + &:focus { + color: $accent-dark + } + + &.disabled { + color: lighten($nav-text-color, 55%); + } +} + +.btn-icon { + padding-left: 0.4rem; + padding-right: 0.4rem; + cursor: default; +} + +.navbar-nav .nav-item + .nav-nomargin { + margin-left: 0; + margin-right: -1rem; +} + +.nav-separator { + margin-top: .425rem; + margin-bottom: .425rem; + margin-left: 1.2em; + margin-right: 1.2em; + display: block; +} \ No newline at end of file diff --git a/src/PinkParrot/app/theme/_layout.scss b/src/PinkParrot/app/theme/_layout.scss new file mode 100644 index 000000000..912179c68 --- /dev/null +++ b/src/PinkParrot/app/theme/_layout.scss @@ -0,0 +1,10 @@ +@import '_mixins.scss'; +@import '_vars.scss'; + +body { + overflow: hidden; +} + +.hidden { + display: none; +} \ No newline at end of file diff --git a/src/PinkParrot/app/theme/_mixins.scss b/src/PinkParrot/app/theme/_mixins.scss new file mode 100644 index 000000000..1201fd470 --- /dev/null +++ b/src/PinkParrot/app/theme/_mixins.scss @@ -0,0 +1,306 @@ +@mixin clearfix() { + &:after { + content: ""; + display: table; + clear: both; + } +} + +@mixin flex-box { + display: -webkit-box; + display: -webkit-flex; + display: -moz-flex; + display: -ms-flexbox; + display: flex; +} + +@mixin flex-inline { + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -moz-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; +} + +@mixin flex-flow($values: (row nowrap)) { + -webkit-flex-flow: $values; + -moz-flex-flow: $values; + -ms-flex-flow: $values; + flex-flow: $values; +} + +@mixin flex-grow($int: 0) { + -webkit-box-flex: $int; + -webkit-flex-grow: $int; + -moz-flex-grow: $int; + -ms-flex-positive: $int; + flex-grow: $int; +} + +@mixin inner-border($color: #999) { + -webkit-box-shadow: inset 1px 1px 1px $color; + -moz-box-shadow: inset 1px 1px 1px $color; + box-shadow: inset 1px 1px 1px $color; +} + +@mixin ellipsis() { + -o-text-overflow: ellipsis; + -ms-text-overflow: ellipsis; + text-overflow: ellipsis; +} + +@mixin box-sizing($sizing: border-box) { + -webkit-box-sizing: $sizing; + -ms-box-sizing: $sizing; + -moz-box-sizing: $sizing; + box-sizing: $sizing; +} + +@mixin border-box() { + -webkit-box-sizing: border-box; + -ms-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +@mixin wrap() { + -ms-word-break: normal; + word-break: normal; + -ms-word-wrap: break-word; + word-wrap: break-word; +} + +@mixin placeholder-color($color) { + &::-webkit-input-placeholder { + color: $color; + } + + &:-moz-placeholder { + color: $color; + @include opacity(1.0); + } + + &::-moz-placeholder { + color: $color; + @include opacity(1.0); + } + + &:-ms-input-placeholder { + color: $color; + } +} + +@mixin text-shadow($x-axis: 1px, $y-axis: 1px, $blur: 1px, $color: #000) { + -webkit-text-shadow: $x-axis $y-axis $blur $color; + text-shadow: $x-axis $y-axis $blur $color; +} + +@mixin text-shadow-none() { + -webkit-text-shadow: none; + text-shadow: none; +} + +@mixin box-shadow-colored($axis, $color) { + -webkit-box-shadow: 0 0 $axis $color; + -moz-box-shadow: 0 0 $axis $color; + box-shadow: 0 0 $axis $color; +} + +@mixin box-shadow-none() { + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} + +@mixin box-shadow($x-axis: 0, $y-axis: 1px, $blur: 2px, $alpha: 0.1) { + -webkit-box-shadow: $x-axis $y-axis $blur rgba(0, 0, 0, $alpha); + -moz-box-shadow: $x-axis $y-axis $blur rgba(0, 0, 0, $alpha); + box-shadow: $x-axis $y-axis $blur rgba(0, 0, 0, $alpha); +} + +@mixin box-shadow-colored($x-axis: 0, $y-axis: 1px, $blur: 2px, $colo: #000) { + -webkit-box-shadow: $x-axis $y-axis $blur $color; + -moz-box-shadow: $x-axis $y-axis $blur $color; + box-shadow: $x-axis $y-axis $blur $color; +} + +@mixin box-shadow-inner($x-axis: 0, $y-axis: 1px, $blur: 2px, $alpha: 0.1) { + -webkit-box-shadow: inset $x-axis $y-axis $blur rgba(0, 0, 0, $alpha); + -moz-box-shadow: inset $x-axis $y-axis $blur rgba(0, 0, 0, $alpha); + box-shadow: inset $x-axis $y-axis $blur rgba(0, 0, 0, $alpha); +} + +@mixin box-shadow-raw($shadow) { + -webkit-box-shadow: $shadow; + -moz-box-shadow: $shadow; + box-shadow: $shadow; +} + +@mixin box-shadow-raw($shadow1, $shadow2) { + -webkit-box-shadow: $shadow1, $shadow2; + -moz-box-shadow: $shadow1, $shadow2; + box-shadow: $shadow1, $shadow2; +} + +@mixin border-radius-clip() { + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box; + +} + +@mixin border-radius ($radius: 4px) { + -webkit-border-radius: $radius; + -moz-border-radius: $radius; + border-radius: $radius; + @include border-radius-clip; +} + +@mixin border-radiusn($topright, $bottomright, $bottomleft, $topleft) { + -webkit-border-radius: $topright $bottomright $bottomleft $topleft; + -moz-border-radius: $topright $bottomright $bottomleft $topleft; + border-radius: $topright $bottomright $bottomleft $topleft; + @include border-radius-clip; +} + +@mixin border-radius-left ($radius: 4px) { + -webkit-border-radius: $radius 0 0 $radius; + -moz-border-radius: $radius 0 0 $radius; + border-radius: $radius 0 0 $radius; +} + +@mixin border-radius-right ($radius: 4px) { + -webkit-border-radius: 0 $radius $radius 0; + -moz-border-radius: 0 $radius $radius 0; + border-radius: 0 $radius $radius 0; +} + +@mixin border-radius-bottom ($radius: 4px) { + -webkit-border-radius: 0 0 $radius $radius; + -moz-border-radius: 0 0 $radius $radius; + border-radius: 0 0 $radius $radius; +} + +@mixin border-radius-top ($radius: 4px) { + -webkit-border-radius: $radius $radius 0 0; + -moz-border-radius: $radius $radius 0 0; + border-radius: $radius $radius 0 0; +} + +@mixin animation($animation...) { + -webkit-animation: $animation; + -moz-animation: $animation; + -o-animation: $animation; + animation: $animation; +} + +@mixin transition($transition...) { + -webkit-transition: $transition; + -moz-transition: $transition; + -o-transition: $transition; + transition: $transition; +} + +@mixin transition-delay($transition-delay...) { + -webkit-transition-delay: $transition-delay; + -moz-transition-delay: $transition-delay; + -o-transition-delay: $transition-delay; + transition-delay: $transition-delay; +} + +@mixin transition-duration($transition-duration...) { + -webkit-transition-duration: $transition-duration; + -moz-transition-duration: $transition-duration; + -o-transition-duration: $transition-duration; + transition-duration: $transition-duration; +} + +@mixin rotate($degrees) { + -webkit-transform: rotate($degrees); + -moz-transform: rotate($degrees); + -ms-transform: rotate($degrees); + -o-transform: rotate($degrees); + transform: rotate($degrees); +} + +@mixin scale($ratio) { + -webkit-transform: scale($ratio); + -moz-transform: scale($ratio); + -ms-transform: scale($ratio); + -o-transform: scale($ratio); + transform: scale($ratio); +} + +@mixin translate($x, $y) { + -webkit-transform: translate($x, $y); + -moz-transform: translate($x, $y); + -ms-transform: translate($x, $y); + -o-transform: translate($x, $y); + transform: translate($x, $y); +} + +@mixin skew($x, $y) { + -webkit-transform: skew($x, $y); + -moz-transform: skew($x, $y); + -ms-transform: skewX($x) skewY($y); + -o-transform: skew($x, $y); + transform: skew($x, $y); + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + backface-visibility: hidden; +} + +@mixin translate3d($x, $y, $z) { + -webkit-transform: translate3d($x, $y, $z); + -moz-transform: translate3d($x, $y, $z); + -ms-transform: translate3d($x, $y, $z); + -o-transform: translate3d($x, $y, $z); + transform: translate3d($x, $y, $z); +} + +@mixin absolute($top, $right, $bottom, $left) { + top: $top; + left: $left; + right: $right; + bottom: $bottom; + position: absolute; +} + +@mixin fixed($top, $right, $bottom, $left) { + top: $top; + left: $left; + right: $right; + bottom: $bottom; + position: fixed; +} + +@mixin opacity($value) { + $opacityPercentage: $value * 100; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=$opacityPercentage)"; + -moz-opacity: $value; + -khtml-opacity: $value; + opacity: $value; + filter: alpha(opacity=$opacityPercentage); +} + +@mixin truncate-nowidth() { + @include ellipsis; + display: block; + white-space: nowrap; + overflow: hidden; +} + +@mixin truncate() { + @include truncate-nowidth; + width: auto; + min-width: 0; + max-width: 100%; +} + +@mixin gradient($stop: #EEE, $start: #FFF) { + background: $start; + background: -webkit-gradient(linear, left bottom, left top, color-stop(0, $start), color-stop(1, $stop)); + background: -ms-linear-gradient(bottom, $start, $stop); + background: -moz-linear-gradient(center bottom, $start 0%, $stop 100%); + background: -o-linear-gradient($stop, $start); +} diff --git a/src/PinkParrot/app/theme/_vars.scss b/src/PinkParrot/app/theme/_vars.scss new file mode 100644 index 000000000..08896bc36 --- /dev/null +++ b/src/PinkParrot/app/theme/_vars.scss @@ -0,0 +1,4 @@ +$nav-text-color: #333; + +$accent-normal: blue; +$accent-dark: darkblue; \ No newline at end of file diff --git a/src/PinkParrot/app/theme/theme.scss b/src/PinkParrot/app/theme/theme.scss new file mode 100644 index 000000000..d12a9d38e --- /dev/null +++ b/src/PinkParrot/app/theme/theme.scss @@ -0,0 +1,2 @@ +@import '_bootstrap.scss'; +@import '_layout.scss'; \ No newline at end of file diff --git a/src/PinkParrot/app/theme/vendor.scss b/src/PinkParrot/app/theme/vendor.scss new file mode 100644 index 000000000..07031f251 --- /dev/null +++ b/src/PinkParrot/app/theme/vendor.scss @@ -0,0 +1,7 @@ +$fa-font-path: "~font-awesome/fonts"; + +// Font Awesome +@import './../../node_modules/font-awesome/scss/font-awesome.scss'; + +// Bootstrap +@import './../../node_modules/bootstrap/scss/bootstrap-flex.scss'; \ No newline at end of file diff --git a/src/PinkParrot/app/vendor.js.map b/src/PinkParrot/app/vendor.js.map new file mode 100644 index 000000000..d546f2c4d --- /dev/null +++ b/src/PinkParrot/app/vendor.js.map @@ -0,0 +1 @@ +{"version":3,"file":"vendor.js","sourceRoot":"","sources":["vendor.ts"],"names":[],"mappings":";AAAA,YAAY;AACZ,QAAO,2BAA2B,CAAC,CAAA;AACnC,QAAO,mCAAmC,CAAC,CAAA;AAC3C,QAAO,eAAe,CAAC,CAAA;AACvB,QAAO,iBAAiB,CAAC,CAAA;AACzB,QAAO,eAAe,CAAC,CAAA;AACvB,QAAO,gBAAgB,CAAC,CAAA;AACxB,QAAO,iBAAiB,CAAC,CAAA;AAEzB,OAAO;AACP,QAAO,MAAM,CAAC,CAAA"} \ No newline at end of file diff --git a/src/PinkParrot/app/vendor.ts b/src/PinkParrot/app/vendor.ts new file mode 100644 index 000000000..5d98267d8 --- /dev/null +++ b/src/PinkParrot/app/vendor.ts @@ -0,0 +1,11 @@ +// Angular 2 +import '@angular/platform-browser'; +import '@angular/platform-browser-dynamic'; +import '@angular/core'; +import '@angular/common'; +import '@angular/http'; +import '@angular/forms'; +import '@angular/router'; + +// RxJS +import 'rxjs'; \ No newline at end of file diff --git a/src/PinkParrot/appsettings.json b/src/PinkParrot/appsettings.json index a9348c710..fc6fbd273 100644 --- a/src/PinkParrot/appsettings.json +++ b/src/PinkParrot/appsettings.json @@ -1,13 +1,15 @@ { - "MongoDb": { - "ConnectionString": "mongodb://localhost", - "DatabaseName": "PinkParrot" - }, - "EventStore": { - "IPAddress": "127.0.0.1", - "Port": 1113, - "Prefix": "pinkparrot", - "Username": "admin", - "Password": "changeit" + "stores": { + "mongoDb": { + "connectionString": "mongodb://localhost", + "databaseName": "PinkParrot" + }, + "eventStore": { + "ipAddress": "127.0.0.1", + "port": 1113, + "prefix": "pinkparrot", + "username": "admin", + "password": "changeit" + } } } \ No newline at end of file diff --git a/src/PinkParrot/karma.coverage.conf.js b/src/PinkParrot/karma.coverage.conf.js new file mode 100644 index 000000000..a35988134 --- /dev/null +++ b/src/PinkParrot/karma.coverage.conf.js @@ -0,0 +1 @@ +module.exports = require('./app-config/karma.coverage.conf.js'); \ No newline at end of file diff --git a/src/PinkParrot/package.json b/src/PinkParrot/package.json new file mode 100644 index 000000000..6da04437d --- /dev/null +++ b/src/PinkParrot/package.json @@ -0,0 +1,76 @@ +{ + "name": "pinkparrot", + "version": "1.0.0", + "description": "PinkParrot CMS", + "license": "MIT", + "repository": "https://github.com/SebastianStehle/PinkParrot", + "scripts": { + "test": "karma start", + "test:coverage": "karma start karma.coverage.conf.js", + "test:clean": "rimraf _test-output", + "build": "webpack --config app-config/webpack.prod.js --progress --display-error-details", + "build:clean": "rimraf wwwroot/build" + }, + "dependencies": { + "@angular/common": "2.1.0", + "@angular/compiler": "2.1.0", + "@angular/core": "2.1.0", + "@angular/forms": "2.1.0", + "@angular/http": "2.1.0", + "@angular/platform-browser": "2.1.0", + "@angular/platform-browser-dynamic": "2.1.0", + "@angular/router": "3.1.0", + "bootstrap": "^4.0.0-alpha.2", + "core-js": "^2.4.1", + "reflect-metadata": "^0.1.3", + "rxjs": "5.0.0-beta.12", + "systemjs": "0.19.38", + "zone.js": "^0.6.23", + "font-awesome": "^4.6.3", + "immutable": "^3.8.1", + "mousetrap": "^1.6.0" + }, + "devDependencies": { + "@angularclass/conventions-loader": "^1.0.7", + "@types/core-js": "^0.9.27-alpha", + "@types/jasmine": "^2.2.27-alpha", + "@types/mousetrap": "^1.5.26-alpha", + "@types/node": "^6.0.33", + "awesome-typescript-loader": "^2.2.4", + "css-loader": "^0.25.0", + "exports-loader": "^0.6.3", + "extract-text-webpack-plugin": "^1.0.1", + "file-loader": "^0.9.0", + "font-awesome-sass-loader": "^1.0.1", + "html-loader": "^0.4.3", + "html-webpack-plugin": "^2.22.0", + "istanbul-instrumenter-loader": "^1.0.0", + "jasmine-core": "^2.4.1", + "karma": "^1.1.1", + "karma-chrome-launcher": "^2.0.0", + "karma-cli": "^1.0.0", + "karma-coverage": "^1.1.0", + "karma-htmlfile-reporter": "^0.3.4", + "karma-jasmine": "^1.0.2", + "karma-mocha-reporter": "^2.0.3", + "karma-phantomjs-launcher": "^1.0.0", + "karma-sourcemap-loader": "^0.3.7", + "karma-webpack": "^1.7.0", + "moment": "^2.14.0", + "node-sass": "^3.8.0", + "null-loader": "^0.1.1", + "phantomjs-prebuilt": "^2.1.7", + "raw-loader": "^0.5.1", + "rimraf": "^2.5.3", + "sass-loader": "^4.0.0", + "style-loader": "^0.13.1", + "tslint": "^3.13.0-dev.0", + "tslint-loader": "^2.1.5", + "typemoq": "^0.3.2", + "typescript": "^2.0.0-dev.20160711", + "underscore": "^1.8.3", + "webpack": "^1.13.1", + "webpack-dev-server": "^1.14.1", + "webpack-merge": "^0.14.0" + } +} \ No newline at end of file diff --git a/src/PinkParrot/tsconfig.json b/src/PinkParrot/tsconfig.json new file mode 100644 index 000000000..75bcea575 --- /dev/null +++ b/src/PinkParrot/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "commonjs", + "moduleResolution": "node", + "sourceMap": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "removeComments": false, + "noImplicitAny": true, + "suppressImplicitAnyIndexErrors": true + } +} \ No newline at end of file diff --git a/src/PinkParrot/tslint.json b/src/PinkParrot/tslint.json new file mode 100644 index 000000000..8d40e77ad --- /dev/null +++ b/src/PinkParrot/tslint.json @@ -0,0 +1,92 @@ +{ + "rules": { + "class-name": true, + "comment-format": [ + true, + "check-space" + ], + "curly": true, + "eofline": false, + "forin": true, + "indent": [ + true, + "spaces" + ], + "label-position": true, + "label-undefined": true, + "max-line-length": [ + true, + 240 + ], + "member-access": false, + "member-ordering": [ + true, + "variables-before-functions" + ], + "no-arg": true, + "no-bitwise": true, + "no-console": [ + true, + "debug", + "info", + "time", + "timeEnd", + "trace" + ], + "no-construct": true, + "no-debugger": true, + "no-duplicate-key": true, + "no-duplicate-variable": true, + "no-empty": false, + "no-eval": true, + "no-inferrable-types": true, + "no-shadowed-variable": true, + "no-string-literal": false, + "no-switch-case-fall-through": true, + "no-trailing-whitespace": false, + "no-unreachable": true, + "no-unused-expression": true, + "no-unused-variable": true, + "no-use-before-declare": true, + "no-var-keyword": true, + "object-literal-sort-keys": false, + "one-line": [ + true, + "check-open-brace", + "check-catch", + "check-else", + "check-whitespace" + ], + "quotemark": [ + true, + "single" + ], + "radix": true, + "semicolon": [ + "always" + ], + "triple-equals": [ + true, + "allow-null-check" + ], + "typedef-whitespace": [ + true, + { + "call-signature": "nospace", + "index-signature": "nospace", + "parameter": "nospace", + "property-declaration": "nospace", + "variable-declaration": "nospace" + } + ], + "variable-name": false, + "whitespace": [ + true, + "check-branch", + "check-decl", + "check-operator", + "check-separator", + "check-type" + ] + } +} \ No newline at end of file diff --git a/src/PinkParrot/typings.json b/src/PinkParrot/typings.json new file mode 100644 index 000000000..1fa09e404 --- /dev/null +++ b/src/PinkParrot/typings.json @@ -0,0 +1,7 @@ +ncu{ + "globalDependencies": { + "core-js": "registry:dt/core-js#0.0.0+20160317120654", + "jasmine": "registry:dt/jasmine#2.2.0+20160505161446", + "node": "registry:dt/node#4.0.0+20160509154515" + } +} \ No newline at end of file diff --git a/src/PinkParrot/webpack.config.js b/src/PinkParrot/webpack.config.js new file mode 100644 index 000000000..e91c6eba7 --- /dev/null +++ b/src/PinkParrot/webpack.config.js @@ -0,0 +1 @@ +module.exports = require('./app-config/webpack.dev.js'); \ No newline at end of file diff --git a/src/PinkParrot/wwwroot/index.html b/src/PinkParrot/wwwroot/index.html new file mode 100644 index 000000000..bc47aa5fc --- /dev/null +++ b/src/PinkParrot/wwwroot/index.html @@ -0,0 +1,12 @@ + + + + + Angular With Webpack + + + + + Loading... + + \ No newline at end of file diff --git a/tests/PinkParrot.Infrastructure.Tests/CQRS/Autofac/AutofacDomainObjectFactoryTests.cs b/tests/PinkParrot.Infrastructure.Tests/CQRS/Autofac/AutofacDomainObjectFactoryTests.cs index a5e8a1c38..8c55f3163 100644 --- a/tests/PinkParrot.Infrastructure.Tests/CQRS/Autofac/AutofacDomainObjectFactoryTests.cs +++ b/tests/PinkParrot.Infrastructure.Tests/CQRS/Autofac/AutofacDomainObjectFactoryTests.cs @@ -1,7 +1,12 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +// ========================================================================== +// AutofacDomainObjectFactoryTests.cs +// PinkParrot Headless CMS +// ========================================================================== +// Copyright (c) PinkParrot Group +// All rights reserved. +// ========================================================================== + +using System; using Autofac; using PinkParrot.Infrastructure.CQRS.Events; using Xunit; diff --git a/tests/PinkParrot.Infrastructure.Tests/CQRS/Commands/InMemoryCommandBusTests.cs b/tests/PinkParrot.Infrastructure.Tests/CQRS/Commands/InMemoryCommandBusTests.cs index 5b5e91811..bd62c48d0 100644 --- a/tests/PinkParrot.Infrastructure.Tests/CQRS/Commands/InMemoryCommandBusTests.cs +++ b/tests/PinkParrot.Infrastructure.Tests/CQRS/Commands/InMemoryCommandBusTests.cs @@ -1,6 +1,12 @@ -using System; -using System.Collections.Generic; -using System.Linq; +// ========================================================================== +// InMemoryCommandBusTests.cs +// PinkParrot Headless CMS +// ========================================================================== +// Copyright (c) PinkParrot Group +// All rights reserved. +// ========================================================================== + +using System; using System.Threading.Tasks; using Xunit; diff --git a/tests/PinkParrot.Infrastructure.Tests/CQRS/EnvelopeExtensionsTests.cs b/tests/PinkParrot.Infrastructure.Tests/CQRS/EnvelopeExtensionsTests.cs index f9a8c23d0..4f7706420 100644 --- a/tests/PinkParrot.Infrastructure.Tests/CQRS/EnvelopeExtensionsTests.cs +++ b/tests/PinkParrot.Infrastructure.Tests/CQRS/EnvelopeExtensionsTests.cs @@ -1,8 +1,13 @@ -using System; -using System.Collections.Generic; +// ========================================================================== +// EnvelopeExtensionsTests.cs +// PinkParrot Headless CMS +// ========================================================================== +// Copyright (c) PinkParrot Group +// All rights reserved. +// ========================================================================== + +using System; using System.Globalization; -using System.Linq; -using System.Threading.Tasks; using NodaTime; using Xunit; diff --git a/tests/PinkParrot.Infrastructure.Tests/PropertiesBagTests.cs b/tests/PinkParrot.Infrastructure.Tests/PropertiesBagTests.cs index aa4d7a9ce..7755d0d6f 100644 --- a/tests/PinkParrot.Infrastructure.Tests/PropertiesBagTests.cs +++ b/tests/PinkParrot.Infrastructure.Tests/PropertiesBagTests.cs @@ -7,7 +7,6 @@ // ========================================================================== using System; -using System.Dynamic; using System.Globalization; using System.Linq; using Microsoft.CSharp.RuntimeBinder; diff --git a/tests/PinkParrot.Infrastructure.Tests/project.json b/tests/PinkParrot.Infrastructure.Tests/project.json index 5a4f8da6b..8e33213be 100644 --- a/tests/PinkParrot.Infrastructure.Tests/project.json +++ b/tests/PinkParrot.Infrastructure.Tests/project.json @@ -8,7 +8,6 @@ }, "dependencies": { "dotnet-test-xunit": "2.2.0-preview2-build1029", - "Microsoft.DotNet.Watcher.Tools": "1.0.0-preview2-final", "Moq": "4.6.38-alpha", "PinkParrot.Infrastructure": "1.0.0-*", "xunit": "2.2.0-beta3-build3402" diff --git a/tests/PinkParrot.Write.Tests/Apps/AppCommandHandlerTests.cs b/tests/PinkParrot.Write.Tests/Apps/AppCommandHandlerTests.cs new file mode 100644 index 000000000..e56174f78 --- /dev/null +++ b/tests/PinkParrot.Write.Tests/Apps/AppCommandHandlerTests.cs @@ -0,0 +1,66 @@ +// ========================================================================== +// AppCommandHandlerTests.cs +// PinkParrot Headless CMS +// ========================================================================== +// Copyright (c) PinkParrot Group +// All rights reserved. +// ========================================================================== + +using System; +using System.Threading.Tasks; +using Moq; +using PinkParrot.Infrastructure; +using PinkParrot.Infrastructure.CQRS.Commands; +using PinkParrot.Read.Apps; +using PinkParrot.Read.Apps.Repositories; +using PinkParrot.Write.Apps; +using PinkParrot.Write.Apps.Commands; +using Xunit; + +namespace PinkParrot.Write.Tests.Apps +{ + public class AppCommandHandlerTests + { + private readonly Mock domainObjectFactory = new Mock(); + private readonly Mock domainObjectRepository = new Mock(); + private readonly Mock appRepository = new Mock(); + private readonly AppCommandHandler sut; + + public AppCommandHandlerTests() + { + sut = new AppCommandHandler( + domainObjectFactory.Object, + domainObjectRepository.Object, + appRepository.Object); + } + + [Fact] + public async Task Create_should_throw_if_a_name_with_same_name_already_exists() + { + appRepository.Setup(x => x.FindAppByNameAsync("my-app")).Returns(Task.FromResult(new Mock().Object)).Verifiable(); + + await Assert.ThrowsAsync(async () => await sut.On(new CreateApp { Name = "my-app" })); + + appRepository.VerifyAll(); + } + + [Fact] + public async Task Create_should_create_app_if_name_is_free() + { + var id = Guid.NewGuid(); + + var app = new AppDomainObject(id, 0); + + appRepository.Setup(x => x.FindAppByNameAsync("my-app")).Returns(Task.FromResult(null)).Verifiable(); + + domainObjectFactory.Setup(x => x.CreateNew(typeof(AppDomainObject), id)).Returns(app).Verifiable(); + domainObjectRepository.Setup(x => x.SaveAsync(app, It.IsAny())).Returns(Task.FromResult(true)).Verifiable(); + + await sut.On(new CreateApp { Name = "my-app", AggregateId = id }); + + appRepository.VerifyAll(); + domainObjectFactory.VerifyAll(); + domainObjectRepository.VerifyAll(); + } + } +} diff --git a/tests/PinkParrot.Write.Tests/Apps/AppDomainObjectTest.cs b/tests/PinkParrot.Write.Tests/Apps/AppDomainObjectTests.cs similarity index 97% rename from tests/PinkParrot.Write.Tests/Apps/AppDomainObjectTest.cs rename to tests/PinkParrot.Write.Tests/Apps/AppDomainObjectTests.cs index 26acf3793..c46b3c492 100644 --- a/tests/PinkParrot.Write.Tests/Apps/AppDomainObjectTest.cs +++ b/tests/PinkParrot.Write.Tests/Apps/AppDomainObjectTests.cs @@ -17,7 +17,7 @@ using PinkParrot.Events.Apps; namespace PinkParrot.Write.Tests.Apps { - public class AppDomainObjectTest + public class AppDomainObjectTests { private const string TestName = "app"; private readonly AppDomainObject sut = new AppDomainObject(Guid.NewGuid(), 0); diff --git a/tests/PinkParrot.Write.Tests/Schemas/SchemaDomainObjectTest.cs b/tests/PinkParrot.Write.Tests/Schemas/SchemaDomainObjectTests.cs similarity index 98% rename from tests/PinkParrot.Write.Tests/Schemas/SchemaDomainObjectTest.cs rename to tests/PinkParrot.Write.Tests/Schemas/SchemaDomainObjectTests.cs index 143e00499..66c902b2d 100644 --- a/tests/PinkParrot.Write.Tests/Schemas/SchemaDomainObjectTest.cs +++ b/tests/PinkParrot.Write.Tests/Schemas/SchemaDomainObjectTests.cs @@ -19,14 +19,14 @@ using Xunit; namespace PinkParrot.Write.Tests.Schemas { [Collection("Schema")] - public class SchemaDomainObjectTest + public class SchemaDomainObjectTests { private const string TestName = "schema"; private readonly Guid appId = Guid.NewGuid(); private readonly FieldRegistry registry = new FieldRegistry(); private readonly SchemaDomainObject sut; - public SchemaDomainObjectTest() + public SchemaDomainObjectTests() { sut = new SchemaDomainObject(Guid.NewGuid(), 0, registry); } diff --git a/tests/PinkParrot.Write.Tests/project.json b/tests/PinkParrot.Write.Tests/project.json index 07014c74a..6d539a7a5 100644 --- a/tests/PinkParrot.Write.Tests/project.json +++ b/tests/PinkParrot.Write.Tests/project.json @@ -9,6 +9,7 @@ "dependencies": { "FluentAssertions": "4.15.0", "dotnet-test-xunit": "2.2.0-preview2-build1029", + "Moq": "4.6.38-alpha", "PinkParrot.Core": "1.0.0-*", "PinkParrot.Infrastructure": "1.0.0-*", "PinkParrot.Write": "1.0.0-*", @@ -28,5 +29,8 @@ "tooling": { "defaultNamespace": "PinkParrot.Core.Tests" }, + "tools": { + "Microsoft.DotNet.Watcher.Tools": "1.0.0-preview2-final" + }, "version": "1.0.0-*" } \ No newline at end of file diff --git a/tests/Postman-Collection.json b/tests/Postman-Collection.json new file mode 100644 index 000000000..50af9a9f8 --- /dev/null +++ b/tests/Postman-Collection.json @@ -0,0 +1,145 @@ +{ + "variables": [], + "info": { + "name": "PinkParrot", + "_postman_id": "3534653d-3285-a837-6257-a9454368e761", + "description": "", + "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" + }, + "item": [ + { + "name": "Apps", + "description": "", + "item": [ + { + "name": "{{url}}/api/apps", + "request": { + "url": "{{url}}/api/apps", + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"name\": \"my-app\"\n}" + }, + "description": "" + }, + "response": [] + }, + { + "name": "{{url}}/api/apps", + "request": { + "url": "{{url}}/api/apps", + "method": "GET", + "header": [], + "body": { + "mode": "formdata", + "formdata": [] + }, + "description": "" + }, + "response": [] + } + ] + }, + { + "name": "Schemas", + "description": "", + "item": [ + { + "name": "{{url}}/api/schemas", + "request": { + "url": "{{url}}/api/schemas", + "method": "GET", + "header": [], + "body": { + "mode": "formdata", + "formdata": [] + }, + "description": "Get schemas" + }, + "response": [] + }, + { + "name": "{{url}}/api/schemas/users", + "request": { + "url": "{{url}}/api/schemas/users", + "method": "GET", + "header": [], + "body": { + "mode": "formdata", + "formdata": [] + }, + "description": "Get schema" + }, + "response": [] + }, + { + "name": "{{url}}/api/schemas/users", + "request": { + "url": "{{url}}/api/schemas/users", + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"label\": \"Users\",\n \"hints\": \"All users in our system\"\n}" + }, + "description": "Update user" + }, + "response": [] + }, + { + "name": "{{url}}/api/schemas", + "request": { + "url": "{{url}}/api/schemas", + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"users\"\n}" + }, + "description": "Create schema" + }, + "response": [] + }, + { + "name": "{{url}}/api/schemas/users/fields", + "request": { + "url": "{{url}}/api/schemas/users/fields", + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\": \"number\",\n \"name\": \"age\",\n \"properties\": {\n \"minValue\": 1\n }\n}" + }, + "description": "Creates a field" + }, + "response": [] + } + ] + } + ] +} \ No newline at end of file