├── .editorconfig
├── .gitattributes
├── .gitignore
├── .huskyrc
├── .jhipster
├── BloodPressure.json
├── Points.json
├── Preferences.json
└── Weigth.json
├── .mvn
└── wrapper
│ ├── MavenWrapperDownloader.java
│ ├── maven-wrapper.jar
│ └── maven-wrapper.properties
├── .prettierignore
├── .prettierrc
├── .yo-rc.json
├── 21-points.jh
├── Procfile
├── README.md
├── mvnw
├── mvnw.cmd
├── package-lock.json
├── package.json
├── pom.xml
├── postcss.config.js
├── src
├── main
│ ├── docker
│ │ ├── .dockerignore
│ │ ├── Dockerfile
│ │ ├── app.yml
│ │ ├── elasticsearch.yml
│ │ ├── entrypoint.sh
│ │ ├── mysql.yml
│ │ └── sonar.yml
│ ├── java
│ │ └── com
│ │ │ └── robmelfi
│ │ │ └── health
│ │ │ ├── ApplicationWebXml.java
│ │ │ ├── TwentyOnePointsReactApp.java
│ │ │ ├── aop
│ │ │ └── logging
│ │ │ │ └── LoggingAspect.java
│ │ │ ├── config
│ │ │ ├── ApplicationProperties.java
│ │ │ ├── AsyncConfiguration.java
│ │ │ ├── CacheConfiguration.java
│ │ │ ├── CloudDatabaseConfiguration.java
│ │ │ ├── Constants.java
│ │ │ ├── DatabaseConfiguration.java
│ │ │ ├── DateTimeFormatConfiguration.java
│ │ │ ├── DefaultProfileUtil.java
│ │ │ ├── ElasticsearchConfiguration.java
│ │ │ ├── JacksonConfiguration.java
│ │ │ ├── LiquibaseConfiguration.java
│ │ │ ├── LocaleConfiguration.java
│ │ │ ├── LoggingAspectConfiguration.java
│ │ │ ├── LoggingConfiguration.java
│ │ │ ├── MetricsConfiguration.java
│ │ │ ├── SecurityConfiguration.java
│ │ │ ├── WebConfigurer.java
│ │ │ ├── audit
│ │ │ │ ├── AuditEventConverter.java
│ │ │ │ └── package-info.java
│ │ │ └── package-info.java
│ │ │ ├── domain
│ │ │ ├── AbstractAuditingEntity.java
│ │ │ ├── Authority.java
│ │ │ ├── BloodPressure.java
│ │ │ ├── PersistentAuditEvent.java
│ │ │ ├── Points.java
│ │ │ ├── Preferences.java
│ │ │ ├── User.java
│ │ │ ├── Weigth.java
│ │ │ ├── enumeration
│ │ │ │ └── Units.java
│ │ │ └── package-info.java
│ │ │ ├── repository
│ │ │ ├── AuthorityRepository.java
│ │ │ ├── BloodPressureRepository.java
│ │ │ ├── CustomAuditEventRepository.java
│ │ │ ├── PersistenceAuditEventRepository.java
│ │ │ ├── PointsRepository.java
│ │ │ ├── PreferencesRepository.java
│ │ │ ├── UserRepository.java
│ │ │ ├── WeigthRepository.java
│ │ │ ├── package-info.java
│ │ │ └── search
│ │ │ │ ├── BloodPressureSearchRepository.java
│ │ │ │ ├── PointsSearchRepository.java
│ │ │ │ ├── PreferencesSearchRepository.java
│ │ │ │ ├── UserSearchRepository.java
│ │ │ │ ├── WeigthSearchRepository.java
│ │ │ │ └── package-info.java
│ │ │ ├── security
│ │ │ ├── AuthoritiesConstants.java
│ │ │ ├── DomainUserDetailsService.java
│ │ │ ├── SecurityUtils.java
│ │ │ ├── SpringSecurityAuditorAware.java
│ │ │ ├── UserNotActivatedException.java
│ │ │ ├── jwt
│ │ │ │ ├── JWTConfigurer.java
│ │ │ │ ├── JWTFilter.java
│ │ │ │ └── TokenProvider.java
│ │ │ └── package-info.java
│ │ │ ├── service
│ │ │ ├── AuditEventService.java
│ │ │ ├── BloodPressureService.java
│ │ │ ├── MailService.java
│ │ │ ├── PointsService.java
│ │ │ ├── PreferencesService.java
│ │ │ ├── UserService.java
│ │ │ ├── WeigthService.java
│ │ │ ├── dto
│ │ │ │ ├── BloodPressureByPeriodDTO.java
│ │ │ │ ├── BloodPressureDTO.java
│ │ │ │ ├── PasswordChangeDTO.java
│ │ │ │ ├── PointsDTO.java
│ │ │ │ ├── PointsPerMonthDTO.java
│ │ │ │ ├── PointsPerWeekDTO.java
│ │ │ │ ├── PreferencesDTO.java
│ │ │ │ ├── UserDTO.java
│ │ │ │ ├── WeigthByPeriodDTO.java
│ │ │ │ ├── WeigthDTO.java
│ │ │ │ └── package-info.java
│ │ │ ├── mapper
│ │ │ │ ├── BloodPressureMapper.java
│ │ │ │ ├── EntityMapper.java
│ │ │ │ ├── PointsMapper.java
│ │ │ │ ├── PreferencesMapper.java
│ │ │ │ ├── UserMapper.java
│ │ │ │ ├── WeigthMapper.java
│ │ │ │ └── package-info.java
│ │ │ ├── package-info.java
│ │ │ └── util
│ │ │ │ └── RandomUtil.java
│ │ │ └── web
│ │ │ └── rest
│ │ │ ├── AccountResource.java
│ │ │ ├── AuditResource.java
│ │ │ ├── BloodPressureResource.java
│ │ │ ├── LogsResource.java
│ │ │ ├── PointsResource.java
│ │ │ ├── PreferencesResource.java
│ │ │ ├── UserJWTController.java
│ │ │ ├── UserResource.java
│ │ │ ├── WeigthResource.java
│ │ │ ├── errors
│ │ │ ├── BadRequestAlertException.java
│ │ │ ├── CustomParameterizedException.java
│ │ │ ├── EmailAlreadyUsedException.java
│ │ │ ├── EmailNotFoundException.java
│ │ │ ├── ErrorConstants.java
│ │ │ ├── ExceptionTranslator.java
│ │ │ ├── FieldErrorVM.java
│ │ │ ├── InternalServerErrorException.java
│ │ │ ├── InvalidPasswordException.java
│ │ │ ├── LoginAlreadyUsedException.java
│ │ │ └── package-info.java
│ │ │ ├── package-info.java
│ │ │ ├── util
│ │ │ ├── HeaderUtil.java
│ │ │ └── PaginationUtil.java
│ │ │ └── vm
│ │ │ ├── KeyAndPasswordVM.java
│ │ │ ├── LoggerVM.java
│ │ │ ├── LoginVM.java
│ │ │ ├── ManagedUserVM.java
│ │ │ └── package-info.java
│ ├── jib
│ │ └── entrypoint.sh
│ ├── resources
│ │ ├── .h2.server.properties
│ │ ├── banner.txt
│ │ ├── config
│ │ │ ├── application-dev.yml
│ │ │ ├── application-heroku.yml
│ │ │ ├── application-prod.yml
│ │ │ ├── application-tls.yml
│ │ │ ├── application.yml
│ │ │ ├── bootstrap-heroku.yml
│ │ │ ├── liquibase
│ │ │ │ ├── authorities.csv
│ │ │ │ ├── changelog
│ │ │ │ │ ├── 00000000000000_initial_schema.xml
│ │ │ │ │ ├── 20181012140436_added_entity_Points.xml
│ │ │ │ │ ├── 20181012140436_added_entity_constraints_Points.xml
│ │ │ │ │ ├── 20181012140437_added_entity_Weigth.xml
│ │ │ │ │ ├── 20181012140437_added_entity_constraints_Weigth.xml
│ │ │ │ │ ├── 20181012140438_added_entity_BloodPressure.xml
│ │ │ │ │ ├── 20181012140438_added_entity_constraints_BloodPressure.xml
│ │ │ │ │ ├── 20181012140439_added_entity_Preferences.xml
│ │ │ │ │ └── 20181012140439_added_entity_constraints_Preferences.xml
│ │ │ │ ├── master.xml
│ │ │ │ ├── users.csv
│ │ │ │ └── users_authorities.csv
│ │ │ └── tls
│ │ │ │ └── keystore.p12
│ │ ├── i18n
│ │ │ └── messages.properties
│ │ ├── logback-spring.xml
│ │ └── templates
│ │ │ ├── error.html
│ │ │ └── mail
│ │ │ ├── activationEmail.html
│ │ │ ├── creationEmail.html
│ │ │ └── passwordResetEmail.html
│ └── webapp
│ │ ├── 404.html
│ │ ├── app
│ │ ├── _bootstrap-variables.scss
│ │ ├── app.scss
│ │ ├── app.tsx
│ │ ├── config
│ │ │ ├── axios-interceptor.ts
│ │ │ ├── constants.ts
│ │ │ ├── devtools.tsx
│ │ │ ├── error-middleware.ts
│ │ │ ├── icon-loader.ts
│ │ │ ├── logger-middleware.ts
│ │ │ ├── notification-middleware.ts
│ │ │ └── store.ts
│ │ ├── entities
│ │ │ ├── blood-pressure
│ │ │ │ ├── blood-pressure-delete-dialog.tsx
│ │ │ │ ├── blood-pressure-detail.tsx
│ │ │ │ ├── blood-pressure-home.tsx
│ │ │ │ ├── blood-pressure-update.tsx
│ │ │ │ ├── blood-pressure.reducer.ts
│ │ │ │ ├── blood-pressure.tsx
│ │ │ │ └── index.tsx
│ │ │ ├── index.tsx
│ │ │ ├── points
│ │ │ │ ├── index.tsx
│ │ │ │ ├── point.scss
│ │ │ │ ├── points-delete-dialog.tsx
│ │ │ │ ├── points-detail.tsx
│ │ │ │ ├── points-home.tsx
│ │ │ │ ├── points-update.tsx
│ │ │ │ ├── points.reducer.ts
│ │ │ │ └── points.tsx
│ │ │ ├── preferences
│ │ │ │ ├── index.tsx
│ │ │ │ ├── preferences-delete-dialog.tsx
│ │ │ │ ├── preferences-detail.tsx
│ │ │ │ ├── preferences-update.tsx
│ │ │ │ ├── preferences.reducer.ts
│ │ │ │ └── preferences.tsx
│ │ │ └── weigth
│ │ │ │ ├── index.tsx
│ │ │ │ ├── weigth-delete-dialog.tsx
│ │ │ │ ├── weigth-detail.tsx
│ │ │ │ ├── weigth-home.tsx
│ │ │ │ ├── weigth-update.tsx
│ │ │ │ ├── weigth.reducer.ts
│ │ │ │ └── weigth.tsx
│ │ ├── index.tsx
│ │ ├── modules
│ │ │ ├── about
│ │ │ │ ├── about.scss
│ │ │ │ └── about.tsx
│ │ │ ├── account
│ │ │ │ ├── activate
│ │ │ │ │ ├── activate.reducer.ts
│ │ │ │ │ └── activate.tsx
│ │ │ │ ├── index.tsx
│ │ │ │ ├── password-reset
│ │ │ │ │ ├── finish
│ │ │ │ │ │ └── password-reset-finish.tsx
│ │ │ │ │ ├── init
│ │ │ │ │ │ └── password-reset-init.tsx
│ │ │ │ │ └── password-reset.reducer.ts
│ │ │ │ ├── password
│ │ │ │ │ ├── password.reducer.ts
│ │ │ │ │ └── password.tsx
│ │ │ │ ├── register
│ │ │ │ │ ├── register.reducer.ts
│ │ │ │ │ └── register.tsx
│ │ │ │ └── settings
│ │ │ │ │ ├── settings.reducer.ts
│ │ │ │ │ └── settings.tsx
│ │ │ ├── administration
│ │ │ │ ├── administration.reducer.ts
│ │ │ │ ├── audits
│ │ │ │ │ └── audits.tsx
│ │ │ │ ├── configuration
│ │ │ │ │ └── configuration.tsx
│ │ │ │ ├── docs
│ │ │ │ │ └── docs.tsx
│ │ │ │ ├── health
│ │ │ │ │ ├── health-modal.tsx
│ │ │ │ │ └── health.tsx
│ │ │ │ ├── index.tsx
│ │ │ │ ├── logs
│ │ │ │ │ └── logs.tsx
│ │ │ │ ├── metrics
│ │ │ │ │ ├── metrics-modal.tsx
│ │ │ │ │ ├── metrics.tsx
│ │ │ │ │ └── thread-item.tsx
│ │ │ │ └── user-management
│ │ │ │ │ ├── index.tsx
│ │ │ │ │ ├── user-management-delete-dialog.tsx
│ │ │ │ │ ├── user-management-detail.tsx
│ │ │ │ │ ├── user-management-update.tsx
│ │ │ │ │ ├── user-management.reducer.ts
│ │ │ │ │ └── user-management.tsx
│ │ │ ├── history
│ │ │ │ ├── CustomToolbar.js
│ │ │ │ ├── history.scss
│ │ │ │ └── history.tsx
│ │ │ ├── home
│ │ │ │ ├── home.scss
│ │ │ │ └── home.tsx
│ │ │ └── login
│ │ │ │ ├── login-modal.tsx
│ │ │ │ ├── login.tsx
│ │ │ │ └── logout.tsx
│ │ ├── routes.tsx
│ │ ├── shared
│ │ │ ├── auth
│ │ │ │ └── private-route.tsx
│ │ │ ├── error
│ │ │ │ ├── error-boundary-route.tsx
│ │ │ │ └── error-boundary.tsx
│ │ │ ├── layout
│ │ │ │ ├── footer
│ │ │ │ │ ├── footer.scss
│ │ │ │ │ └── footer.tsx
│ │ │ │ ├── header
│ │ │ │ │ ├── header-components.tsx
│ │ │ │ │ ├── header.scss
│ │ │ │ │ ├── header.tsx
│ │ │ │ │ └── menus
│ │ │ │ │ │ ├── account.tsx
│ │ │ │ │ │ ├── admin.tsx
│ │ │ │ │ │ ├── entities.tsx
│ │ │ │ │ │ └── index.ts
│ │ │ │ └── password
│ │ │ │ │ ├── password-strength-bar.scss
│ │ │ │ │ └── password-strength-bar.tsx
│ │ │ ├── model
│ │ │ │ ├── blood-pressure-chart.tsx
│ │ │ │ ├── blood-pressure.model.ts
│ │ │ │ ├── points-this-week.model.ts
│ │ │ │ ├── points.model.ts
│ │ │ │ ├── preferences.model.ts
│ │ │ │ ├── user.model.ts
│ │ │ │ ├── weigth-chart.tsx
│ │ │ │ └── weigth.model.ts
│ │ │ ├── reducers
│ │ │ │ ├── action-type.util.ts
│ │ │ │ ├── application-profile.ts
│ │ │ │ ├── authentication.ts
│ │ │ │ └── index.ts
│ │ │ └── util
│ │ │ │ ├── date-utils.ts
│ │ │ │ ├── entity-utils.ts
│ │ │ │ ├── pagination.constants.ts
│ │ │ │ └── url-utils.ts
│ │ └── typings.d.ts
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ ├── manifest.webapp
│ │ ├── robots.txt
│ │ ├── static
│ │ └── images
│ │ │ ├── 21-points-logo.png
│ │ │ ├── hipster.png
│ │ │ ├── hipster192.png
│ │ │ ├── hipster256.png
│ │ │ ├── hipster2x.png
│ │ │ ├── hipster384.png
│ │ │ ├── hipster512.png
│ │ │ ├── logo-21-points.png
│ │ │ ├── logo-jhipster-react.svg
│ │ │ └── logo-jhipster.png
│ │ └── swagger-ui
│ │ ├── dist
│ │ └── images
│ │ │ └── throbber.gif
│ │ └── index.html
└── test
│ ├── java
│ └── com
│ │ └── robmelfi
│ │ └── health
│ │ ├── config
│ │ ├── WebConfigurerTest.java
│ │ └── WebConfigurerTestController.java
│ │ ├── repository
│ │ ├── CustomAuditEventRepositoryIntTest.java
│ │ └── search
│ │ │ ├── BloodPressureSearchRepositoryMockConfiguration.java
│ │ │ ├── PointsSearchRepositoryMockConfiguration.java
│ │ │ ├── PreferencesSearchRepositoryMockConfiguration.java
│ │ │ ├── UserSearchRepositoryMockConfiguration.java
│ │ │ └── WeigthSearchRepositoryMockConfiguration.java
│ │ ├── security
│ │ ├── DomainUserDetailsServiceIntTest.java
│ │ ├── SecurityUtilsUnitTest.java
│ │ └── jwt
│ │ │ ├── JWTFilterTest.java
│ │ │ └── TokenProviderTest.java
│ │ ├── service
│ │ ├── MailServiceIntTest.java
│ │ └── UserServiceIntTest.java
│ │ └── web
│ │ └── rest
│ │ ├── AccountResourceIntTest.java
│ │ ├── AuditResourceIntTest.java
│ │ ├── BloodPressureResourceIntTest.java
│ │ ├── LogsResourceIntTest.java
│ │ ├── PointsResourceIntTest.java
│ │ ├── PreferencesResourceIntTest.java
│ │ ├── TestUtil.java
│ │ ├── UserJWTControllerIntTest.java
│ │ ├── UserResourceIntTest.java
│ │ ├── WeigthResourceIntTest.java
│ │ ├── errors
│ │ ├── ExceptionTranslatorIntTest.java
│ │ └── ExceptionTranslatorTestController.java
│ │ └── util
│ │ └── PaginationUtilUnitTest.java
│ ├── javascript
│ ├── e2e
│ │ ├── entities
│ │ │ ├── blood-pressure
│ │ │ │ ├── blood-pressure-update.page-object.ts
│ │ │ │ ├── blood-pressure.page-object.ts
│ │ │ │ └── blood-pressure.spec.ts
│ │ │ ├── points
│ │ │ │ ├── points-update.page-object.ts
│ │ │ │ ├── points.page-object.ts
│ │ │ │ └── points.spec.ts
│ │ │ ├── preferences
│ │ │ │ ├── preferences-update.page-object.ts
│ │ │ │ ├── preferences.page-object.ts
│ │ │ │ └── preferences.spec.ts
│ │ │ └── weigth
│ │ │ │ ├── weigth-update.page-object.ts
│ │ │ │ ├── weigth.page-object.ts
│ │ │ │ └── weigth.spec.ts
│ │ ├── modules
│ │ │ ├── account
│ │ │ │ └── account.spec.ts
│ │ │ └── administration
│ │ │ │ └── administration.spec.ts
│ │ ├── page-objects
│ │ │ ├── base-component.ts
│ │ │ ├── navbar-page.ts
│ │ │ ├── password-page.ts
│ │ │ ├── register-page.ts
│ │ │ ├── settings-page.ts
│ │ │ └── signin-page.ts
│ │ └── util
│ │ │ └── utils.ts
│ ├── jest.conf.js
│ ├── protractor.conf.js
│ └── spec
│ │ ├── app
│ │ ├── config
│ │ │ ├── axios-interceptor.spec.ts
│ │ │ └── notification-middleware.spec.ts
│ │ ├── entities
│ │ │ ├── blood-pressure
│ │ │ │ └── blood-pressure-reducer.spec.ts
│ │ │ ├── points
│ │ │ │ └── points-reducer.spec.ts
│ │ │ ├── preferences
│ │ │ │ └── preferences-reducer.spec.ts
│ │ │ └── weigth
│ │ │ │ └── weigth-reducer.spec.ts
│ │ ├── modules
│ │ │ ├── account
│ │ │ │ ├── activate
│ │ │ │ │ └── activate.reducer.spec.ts
│ │ │ │ ├── password
│ │ │ │ │ └── password.reducer.spec.ts
│ │ │ │ ├── register
│ │ │ │ │ └── register.reducer.spec.ts
│ │ │ │ └── settings
│ │ │ │ │ └── settings.reducer.spec.ts
│ │ │ └── administration
│ │ │ │ ├── administration.reducer.spec.ts
│ │ │ │ └── user-management
│ │ │ │ └── user-management.reducer.spec.ts
│ │ ├── shared
│ │ │ ├── auth
│ │ │ │ └── private-route.spec.tsx
│ │ │ ├── error
│ │ │ │ ├── error-boundary-route.spec.tsx
│ │ │ │ └── error-boundary.spec.tsx
│ │ │ ├── layout
│ │ │ │ └── header
│ │ │ │ │ ├── header.spec.tsx
│ │ │ │ │ └── menus
│ │ │ │ │ └── account.spec.tsx
│ │ │ ├── reducers
│ │ │ │ ├── application-profile.spec.ts
│ │ │ │ └── authentication.spec.ts
│ │ │ └── util
│ │ │ │ └── entity-utils.spec.ts
│ │ └── utils.ts
│ │ ├── enzyme-setup.ts
│ │ └── storage-mock.ts
│ └── resources
│ ├── config
│ └── application.yml
│ ├── i18n
│ └── messages_en.properties
│ ├── logback.xml
│ └── templates
│ └── mail
│ └── testEmail.html
├── tsconfig.e2e.json
├── tsconfig.json
├── tsconfig.test.json
├── tslint.json
└── webpack
├── logo-jhipster.png
├── utils.js
├── webpack.common.js
├── webpack.dev.js
└── webpack.prod.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # editorconfig.org
4 |
5 | root = true
6 |
7 | [*]
8 |
9 | # Change these settings to your own preference
10 | indent_style = space
11 | indent_size = 4
12 | max_line_length = 180
13 |
14 | # We recommend you to keep these unchanged
15 | end_of_line = lf
16 | charset = utf-8
17 | trim_trailing_whitespace = true
18 | insert_final_newline = true
19 |
20 | [*.{ts,tsx,js,jsx,json,css,scss,sql,ejs}]
21 | indent_style = space
22 | indent_size = 2
23 |
24 | [*.md]
25 | trim_trailing_whitespace = false
26 |
--------------------------------------------------------------------------------
/.huskyrc:
--------------------------------------------------------------------------------
1 | {
2 | "hooks": {
3 | "pre-commit": "lint-staged"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/.jhipster/BloodPressure.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "BloodPressure",
3 | "fields": [
4 | {
5 | "fieldName": "timestamp",
6 | "fieldType": "ZonedDateTime",
7 | "fieldValidateRules": [
8 | "required"
9 | ]
10 | },
11 | {
12 | "fieldName": "systolic",
13 | "fieldType": "Integer",
14 | "fieldValidateRules": [
15 | "required"
16 | ]
17 | },
18 | {
19 | "fieldName": "diastolic",
20 | "fieldType": "Integer",
21 | "fieldValidateRules": [
22 | "required"
23 | ]
24 | }
25 | ],
26 | "relationships": [
27 | {
28 | "relationshipType": "many-to-one",
29 | "relationshipValidateRules": "required",
30 | "relationshipName": "user",
31 | "otherEntityName": "user",
32 | "otherEntityField": "login"
33 | }
34 | ],
35 | "changelogDate": "20181012140438",
36 | "entityTableName": "blood_pressure",
37 | "dto": "mapstruct",
38 | "pagination": "infinite-scroll",
39 | "service": "serviceClass",
40 | "jpaMetamodelFiltering": false,
41 | "fluentMethods": true,
42 | "clientRootFolder": "",
43 | "applications": "*"
44 | }
--------------------------------------------------------------------------------
/.jhipster/Points.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Points",
3 | "fields": [
4 | {
5 | "fieldName": "date",
6 | "fieldType": "LocalDate",
7 | "fieldValidateRules": [
8 | "required"
9 | ]
10 | },
11 | {
12 | "fieldName": "excercise",
13 | "fieldType": "Integer"
14 | },
15 | {
16 | "fieldName": "meals",
17 | "fieldType": "Integer"
18 | },
19 | {
20 | "fieldName": "alcohol",
21 | "fieldType": "Integer"
22 | },
23 | {
24 | "fieldName": "notes",
25 | "fieldType": "String",
26 | "fieldValidateRules": [
27 | "maxlength"
28 | ],
29 | "fieldValidateRulesMaxlength": 140
30 | }
31 | ],
32 | "relationships": [
33 | {
34 | "relationshipType": "many-to-one",
35 | "relationshipValidateRules": "required",
36 | "relationshipName": "user",
37 | "otherEntityName": "user",
38 | "otherEntityField": "login"
39 | }
40 | ],
41 | "changelogDate": "20181012140436",
42 | "entityTableName": "points",
43 | "dto": "mapstruct",
44 | "pagination": "pagination",
45 | "service": "serviceClass",
46 | "jpaMetamodelFiltering": false,
47 | "fluentMethods": true,
48 | "clientRootFolder": "",
49 | "applications": "*"
50 | }
--------------------------------------------------------------------------------
/.jhipster/Preferences.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Preferences",
3 | "fields": [
4 | {
5 | "fieldName": "weeklyGoal",
6 | "fieldType": "Integer",
7 | "fieldValidateRules": [
8 | "required",
9 | "min",
10 | "max"
11 | ],
12 | "fieldValidateRulesMin": 10,
13 | "fieldValidateRulesMax": 21
14 | },
15 | {
16 | "fieldName": "weightUnits",
17 | "fieldType": "Units",
18 | "fieldValues": "KG,LB",
19 | "fieldValidateRules": [
20 | "required"
21 | ]
22 | }
23 | ],
24 | "relationships": [
25 | {
26 | "relationshipType": "one-to-one",
27 | "relationshipName": "user",
28 | "otherEntityName": "user",
29 | "otherEntityField": "login",
30 | "ownerSide": true,
31 | "otherEntityRelationshipName": "preferences"
32 | }
33 | ],
34 | "changelogDate": "20181012140439",
35 | "entityTableName": "preferences",
36 | "dto": "mapstruct",
37 | "pagination": "no",
38 | "service": "serviceClass",
39 | "jpaMetamodelFiltering": false,
40 | "fluentMethods": true,
41 | "clientRootFolder": "",
42 | "applications": "*"
43 | }
--------------------------------------------------------------------------------
/.jhipster/Weigth.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Weigth",
3 | "fields": [
4 | {
5 | "fieldName": "timestamp",
6 | "fieldType": "ZonedDateTime",
7 | "fieldValidateRules": [
8 | "required"
9 | ]
10 | },
11 | {
12 | "fieldName": "weight",
13 | "fieldType": "Double",
14 | "fieldValidateRules": [
15 | "required"
16 | ]
17 | }
18 | ],
19 | "relationships": [
20 | {
21 | "relationshipType": "many-to-one",
22 | "relationshipValidateRules": "required",
23 | "relationshipName": "user",
24 | "otherEntityName": "user",
25 | "otherEntityField": "login"
26 | }
27 | ],
28 | "changelogDate": "20181012140437",
29 | "entityTableName": "weigth",
30 | "dto": "mapstruct",
31 | "pagination": "infinite-scroll",
32 | "service": "serviceClass",
33 | "jpaMetamodelFiltering": false,
34 | "fluentMethods": true,
35 | "clientRootFolder": "",
36 | "applications": "*"
37 | }
--------------------------------------------------------------------------------
/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robmelfi/21-points-react/a310a2762d7ddab3440588dbe3dcb22c338823ed/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | target
3 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | # Prettier configuration
2 |
3 | printWidth: 140
4 | singleQuote: true
5 | tabWidth: 2
6 | useTabs: false
7 |
8 | # js and ts rules:
9 | arrowParens: avoid
10 |
11 | # jsx and tsx rules:
12 | jsxBracketSameLine: false
13 |
--------------------------------------------------------------------------------
/.yo-rc.json:
--------------------------------------------------------------------------------
1 | {
2 | "generator-jhipster": {
3 | "promptValues": {
4 | "packageName": "com.robmelfi.health"
5 | },
6 | "jhipsterVersion": "5.4.1",
7 | "applicationType": "monolith",
8 | "baseName": "TwentyOnePointsReact",
9 | "packageName": "com.robmelfi.health",
10 | "packageFolder": "com/robmelfi/health",
11 | "serverPort": "8080",
12 | "authenticationType": "jwt",
13 | "cacheProvider": "ehcache",
14 | "enableHibernateCache": true,
15 | "websocket": false,
16 | "databaseType": "sql",
17 | "devDatabaseType": "h2Disk",
18 | "prodDatabaseType": "mysql",
19 | "searchEngine": "elasticsearch",
20 | "messageBroker": false,
21 | "serviceDiscoveryType": false,
22 | "buildTool": "maven",
23 | "enableSwaggerCodegen": false,
24 | "jwtSecretKey": "MjExZTE1MjEzMzQwM2JiMmU2ZjgzOWE3YzFhMjAxZjA2NTUxZDQ1N2MzYzI1ZjE0ZTRhMjExZWEyYjI3YmE5OThhNzYzNTNlNzhhMDE1YzRiNGYwZDNkMGE1ZjViNzQ0MTU1ZWJiMmM5ZjY1NDVkOTg3ZDg0OTNkMzNmYTBkYTk=",
25 | "clientFramework": "react",
26 | "useSass": true,
27 | "clientPackageManager": "npm",
28 | "testFrameworks": [
29 | "protractor"
30 | ],
31 | "jhiPrefix": "jhi",
32 | "enableTranslation": false,
33 | "herokuAppName": "twentyone-points-react",
34 | "herokuDeployType": "git"
35 | }
36 | }
--------------------------------------------------------------------------------
/21-points.jh:
--------------------------------------------------------------------------------
1 |
2 | entity Points {
3 | date LocalDate required
4 | excercise Integer
5 | meals Integer
6 | alcohol Integer
7 | notes String maxlength(140)
8 | }
9 |
10 | entity Weigth {
11 | timestamp ZonedDateTime required
12 | weight Double required
13 | }
14 |
15 | entity BloodPressure {
16 | timestamp ZonedDateTime required
17 | systolic Integer required
18 | diastolic Integer required
19 | }
20 |
21 | enum Units {
22 | KG, LB
23 | }
24 |
25 | entity Preferences {
26 | weeklyGoal Integer required min(10) max(21)
27 | weightUnits Units required
28 | }
29 |
30 | relationship OneToOne {
31 | Preferences { user(login) } to User
32 | }
33 |
34 | relationship ManyToOne {
35 | Points { user(login) required } to User
36 | Weigth { user(login) required } to User
37 | BloodPressure { user(login) required } to User
38 | }
39 |
40 | dto * with mapstruct
41 | service * with serviceClass
42 | paginate Points with pagination
43 | paginate BloodPressure, Weigth with infinite-scroll
44 |
45 |
46 |
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | web: java $JAVA_OPTS -Xmx256m -jar target/*.war --spring.profiles.active=prod,heroku,no-liquibase --server.port=$PORT
2 | release: cp -R src/main/resources/config config && ./mvnw liquibase:update -Pheroku
3 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: []
3 | };
4 |
--------------------------------------------------------------------------------
/src/main/docker/.dockerignore:
--------------------------------------------------------------------------------
1 | # https://docs.docker.com/engine/reference/builder/#dockerignore-file
2 | classes/
3 | generated-sources/
4 | generated-test-sources/
5 | h2db/
6 | maven-archiver/
7 | maven-status/
8 | reports/
9 | surefire-reports/
10 | test-classes/
11 | test-results/
12 | www/
13 | !*.jar
14 | !*.war
15 |
--------------------------------------------------------------------------------
/src/main/docker/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:8-jre-alpine
2 |
3 | ENV SPRING_OUTPUT_ANSI_ENABLED=ALWAYS \
4 | JHIPSTER_SLEEP=0 \
5 | JAVA_OPTS=""
6 |
7 | # Add a jhipster user to run our application so that it doesn't need to run as root
8 | RUN adduser -D -s /bin/sh jhipster
9 | WORKDIR /home/jhipster
10 |
11 | ADD entrypoint.sh entrypoint.sh
12 | RUN chmod 755 entrypoint.sh && chown jhipster:jhipster entrypoint.sh
13 | USER jhipster
14 |
15 | ENTRYPOINT ["./entrypoint.sh"]
16 |
17 | EXPOSE 8080
18 |
19 | ADD *.war app.war
20 |
21 |
--------------------------------------------------------------------------------
/src/main/docker/app.yml:
--------------------------------------------------------------------------------
1 | version: '2'
2 | services:
3 | twentyonepointsreact-app:
4 | image: twentyonepointsreact
5 | environment:
6 | # - _JAVA_OPTIONS=-Xmx512m -Xms256m
7 | - SPRING_PROFILES_ACTIVE=prod,swagger
8 | - SPRING_DATASOURCE_URL=jdbc:mysql://twentyonepointsreact-mysql:3306/twentyonepointsreact?useUnicode=true&characterEncoding=utf8&useSSL=false
9 | - JHIPSTER_SLEEP=10 # gives time for the database to boot before the application
10 | - SPRING_DATA_JEST_URI=http://twentyonepointsreact-elasticsearch:9200
11 | ports:
12 | - 8080:8080
13 | twentyonepointsreact-mysql:
14 | extends:
15 | file: mysql.yml
16 | service: twentyonepointsreact-mysql
17 | twentyonepointsreact-elasticsearch:
18 | extends:
19 | file: elasticsearch.yml
20 | service: twentyonepointsreact-elasticsearch
21 |
--------------------------------------------------------------------------------
/src/main/docker/elasticsearch.yml:
--------------------------------------------------------------------------------
1 | version: '2'
2 | services:
3 | twentyonepointsreact-elasticsearch:
4 | image: elasticsearch:5.6.5
5 | # volumes:
6 | # - ~/volumes/jhipster/TwentyOnePointsReact/elasticsearch/:/usr/share/elasticsearch/data/
7 | ports:
8 | - 9200:9200
9 | - 9300:9300
10 | command: -Enetwork.host=0.0.0.0 -Ediscovery.type=single-node
11 | environment:
12 | - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
13 |
--------------------------------------------------------------------------------
/src/main/docker/entrypoint.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | echo "The application will start in ${JHIPSTER_SLEEP}s..." && sleep ${JHIPSTER_SLEEP}
4 | exec java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar "${HOME}/app.war" "$@"
5 |
--------------------------------------------------------------------------------
/src/main/docker/mysql.yml:
--------------------------------------------------------------------------------
1 | version: '2'
2 | services:
3 | twentyonepointsreact-mysql:
4 | image: mysql:5.7.20
5 | # volumes:
6 | # - ~/volumes/jhipster/TwentyOnePointsReact/mysql/:/var/lib/mysql/
7 | environment:
8 | - MYSQL_USER=root
9 | - MYSQL_ALLOW_EMPTY_PASSWORD=yes
10 | - MYSQL_DATABASE=twentyonepointsreact
11 | ports:
12 | - 3306:3306
13 | command: mysqld --lower_case_table_names=1 --skip-ssl --character_set_server=utf8mb4 --explicit_defaults_for_timestamp
14 |
--------------------------------------------------------------------------------
/src/main/docker/sonar.yml:
--------------------------------------------------------------------------------
1 | version: '2'
2 | services:
3 | twentyonepointsreact-sonar:
4 | image: sonarqube:7.1-alpine
5 | ports:
6 | - 9001:9000
7 | - 9092:9092
8 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/ApplicationWebXml.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health;
2 |
3 | import com.robmelfi.health.config.DefaultProfileUtil;
4 | import org.springframework.boot.builder.SpringApplicationBuilder;
5 | import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
6 |
7 | /**
8 | * This is a helper Java class that provides an alternative to creating a web.xml.
9 | * This will be invoked only when the application is deployed to a Servlet container like Tomcat, JBoss etc.
10 | */
11 | public class ApplicationWebXml extends SpringBootServletInitializer {
12 |
13 | @Override
14 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
15 | /**
16 | * set a default to use when no profile is configured.
17 | */
18 | DefaultProfileUtil.addDefaultProfile(application.application());
19 | return application.sources(TwentyOnePointsReactApp.class);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/config/ApplicationProperties.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.config;
2 |
3 | import org.springframework.boot.context.properties.ConfigurationProperties;
4 |
5 | /**
6 | * Properties specific to Twenty One Points React.
7 | *
8 | * Properties are configured in the application.yml file.
9 | * See {@link io.github.jhipster.config.JHipsterProperties} for a good example.
10 | */
11 | @ConfigurationProperties(prefix = "application", ignoreUnknownFields = false)
12 | public class ApplicationProperties {
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/config/CloudDatabaseConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.config;
2 |
3 | import io.github.jhipster.config.JHipsterConstants;
4 |
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 | import org.springframework.cloud.config.java.AbstractCloudConfig;
8 | import org.springframework.context.annotation.*;
9 |
10 | import javax.sql.DataSource;
11 |
12 | @Configuration
13 | @Profile(JHipsterConstants.SPRING_PROFILE_CLOUD)
14 | public class CloudDatabaseConfiguration extends AbstractCloudConfig {
15 |
16 | private final Logger log = LoggerFactory.getLogger(CloudDatabaseConfiguration.class);
17 |
18 | @Bean
19 | public DataSource dataSource() {
20 | log.info("Configuring JDBC datasource from a cloud provider");
21 | return connectionFactory().dataSource();
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/config/Constants.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.config;
2 |
3 | /**
4 | * Application constants.
5 | */
6 | public final class Constants {
7 |
8 | // Regex for acceptable logins
9 | public static final String LOGIN_REGEX = "^[_.@A-Za-z0-9-]*$";
10 |
11 | public static final String SYSTEM_ACCOUNT = "system";
12 | public static final String ANONYMOUS_USER = "anonymoususer";
13 | public static final String DEFAULT_LANGUAGE = "en";
14 |
15 | private Constants() {
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/config/DatabaseConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.config;
2 |
3 | import io.github.jhipster.config.JHipsterConstants;
4 | import io.github.jhipster.config.h2.H2ConfigurationHelper;
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 | import org.springframework.context.annotation.Bean;
8 | import org.springframework.context.annotation.Configuration;
9 | import org.springframework.context.annotation.Profile;
10 | import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
11 |
12 | import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
13 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
14 | import org.springframework.transaction.annotation.EnableTransactionManagement;
15 |
16 | import java.sql.SQLException;
17 |
18 | @Configuration
19 | @EnableJpaRepositories("com.robmelfi.health.repository")
20 | @EnableJpaAuditing(auditorAwareRef = "springSecurityAuditorAware")
21 | @EnableTransactionManagement
22 | @EnableElasticsearchRepositories("com.robmelfi.health.repository.search")
23 | public class DatabaseConfiguration {
24 |
25 | private final Logger log = LoggerFactory.getLogger(DatabaseConfiguration.class);
26 |
27 |
28 | /**
29 | * Open the TCP port for the H2 database, so it is available remotely.
30 | *
31 | * @return the H2 database TCP server
32 | * @throws SQLException if the server failed to start
33 | */
34 | @Bean(initMethod = "start", destroyMethod = "stop")
35 | @Profile(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)
36 | public Object h2TCPServer() throws SQLException {
37 | log.debug("Starting H2 database");
38 | return H2ConfigurationHelper.createServer();
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/config/DateTimeFormatConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.config;
2 |
3 | import org.springframework.context.annotation.Configuration;
4 | import org.springframework.format.FormatterRegistry;
5 | import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar;
6 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
7 |
8 | /**
9 | * Configure the converters to use the ISO format for dates by default.
10 | */
11 | @Configuration
12 | public class DateTimeFormatConfiguration implements WebMvcConfigurer {
13 |
14 | @Override
15 | public void addFormatters(FormatterRegistry registry) {
16 | DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
17 | registrar.setUseIsoFormat(true);
18 | registrar.registerFormatters(registry);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/config/DefaultProfileUtil.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.config;
2 |
3 | import io.github.jhipster.config.JHipsterConstants;
4 |
5 | import org.springframework.boot.SpringApplication;
6 | import org.springframework.core.env.Environment;
7 |
8 | import java.util.*;
9 |
10 | /**
11 | * Utility class to load a Spring profile to be used as default
12 | * when there is no spring.profiles.active
set in the environment or as command line argument.
13 | * If the value is not available in application.yml
then dev
profile will be used as default.
14 | */
15 | public final class DefaultProfileUtil {
16 |
17 | private static final String SPRING_PROFILE_DEFAULT = "spring.profiles.default";
18 |
19 | private DefaultProfileUtil() {
20 | }
21 |
22 | /**
23 | * Set a default to use when no profile is configured.
24 | *
25 | * @param app the Spring application
26 | */
27 | public static void addDefaultProfile(SpringApplication app) {
28 | Map defProperties = new HashMap<>();
29 | /*
30 | * The default profile to use when no other profiles are defined
31 | * This cannot be set in the application.yml
file.
32 | * See https://github.com/spring-projects/spring-boot/issues/1219
33 | */
34 | defProperties.put(SPRING_PROFILE_DEFAULT, JHipsterConstants.SPRING_PROFILE_DEVELOPMENT);
35 | app.setDefaultProperties(defProperties);
36 | }
37 |
38 | /**
39 | * Get the profiles that are applied else get default profiles.
40 | *
41 | * @param env spring environment
42 | * @return profiles
43 | */
44 | public static String[] getActiveProfiles(Environment env) {
45 | String[] profiles = env.getActiveProfiles();
46 | if (profiles.length == 0) {
47 | return env.getDefaultProfiles();
48 | }
49 | return profiles;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/config/JacksonConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.config;
2 |
3 | import com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module;
4 | import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
5 | import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
6 | import com.fasterxml.jackson.module.afterburner.AfterburnerModule;
7 |
8 | import org.springframework.context.annotation.Bean;
9 | import org.springframework.context.annotation.Configuration;
10 | import org.zalando.problem.ProblemModule;
11 | import org.zalando.problem.violations.ConstraintViolationProblemModule;
12 |
13 | @Configuration
14 | public class JacksonConfiguration {
15 |
16 | /**
17 | * Support for Java date and time API.
18 | * @return the corresponding Jackson module.
19 | */
20 | @Bean
21 | public JavaTimeModule javaTimeModule() {
22 | return new JavaTimeModule();
23 | }
24 |
25 | @Bean
26 | public Jdk8Module jdk8TimeModule() {
27 | return new Jdk8Module();
28 | }
29 |
30 |
31 | /*
32 | * Support for Hibernate types in Jackson.
33 | */
34 | @Bean
35 | public Hibernate5Module hibernate5Module() {
36 | return new Hibernate5Module();
37 | }
38 |
39 | /*
40 | * Jackson Afterburner module to speed up serialization/deserialization.
41 | */
42 | @Bean
43 | public AfterburnerModule afterburnerModule() {
44 | return new AfterburnerModule();
45 | }
46 |
47 | /*
48 | * Module for serialization/deserialization of RFC7807 Problem.
49 | */
50 | @Bean
51 | ProblemModule problemModule() {
52 | return new ProblemModule();
53 | }
54 |
55 | /*
56 | * Module for serialization/deserialization of ConstraintViolationProblem.
57 | */
58 | @Bean
59 | ConstraintViolationProblemModule constraintViolationProblemModule() {
60 | return new ConstraintViolationProblemModule();
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/config/LocaleConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.config;
2 |
3 | import io.github.jhipster.config.locale.AngularCookieLocaleResolver;
4 |
5 | import org.springframework.context.annotation.Bean;
6 | import org.springframework.context.annotation.Configuration;
7 | import org.springframework.web.servlet.LocaleResolver;
8 | import org.springframework.web.servlet.config.annotation.*;
9 | import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
10 |
11 | @Configuration
12 | public class LocaleConfiguration implements WebMvcConfigurer {
13 |
14 | @Bean(name = "localeResolver")
15 | public LocaleResolver localeResolver() {
16 | AngularCookieLocaleResolver cookieLocaleResolver = new AngularCookieLocaleResolver();
17 | cookieLocaleResolver.setCookieName("NG_TRANSLATE_LANG_KEY");
18 | return cookieLocaleResolver;
19 | }
20 |
21 | @Override
22 | public void addInterceptors(InterceptorRegistry registry) {
23 | LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
24 | localeChangeInterceptor.setParamName("language");
25 | registry.addInterceptor(localeChangeInterceptor);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/config/LoggingAspectConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.config;
2 |
3 | import com.robmelfi.health.aop.logging.LoggingAspect;
4 |
5 | import io.github.jhipster.config.JHipsterConstants;
6 |
7 | import org.springframework.context.annotation.*;
8 | import org.springframework.core.env.Environment;
9 |
10 | @Configuration
11 | @EnableAspectJAutoProxy
12 | public class LoggingAspectConfiguration {
13 |
14 | @Bean
15 | @Profile(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)
16 | public LoggingAspect loggingAspect(Environment env) {
17 | return new LoggingAspect(env);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/config/audit/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Audit specific code.
3 | */
4 | package com.robmelfi.health.config.audit;
5 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/config/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Spring Framework configuration files.
3 | */
4 | package com.robmelfi.health.config;
5 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/domain/Authority.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.domain;
2 |
3 | import org.hibernate.annotations.Cache;
4 | import org.hibernate.annotations.CacheConcurrencyStrategy;
5 | import javax.persistence.Entity;
6 | import javax.persistence.Id;
7 | import javax.persistence.Table;
8 | import javax.persistence.Column;
9 | import javax.validation.constraints.NotNull;
10 | import javax.validation.constraints.Size;
11 | import java.io.Serializable;
12 |
13 | /**
14 | * An authority (a security role) used by Spring Security.
15 | */
16 | @Entity
17 | @Table(name = "jhi_authority")
18 | @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
19 | public class Authority implements Serializable {
20 |
21 | private static final long serialVersionUID = 1L;
22 |
23 | @NotNull
24 | @Size(max = 50)
25 | @Id
26 | @Column(length = 50)
27 | private String name;
28 |
29 | public String getName() {
30 | return name;
31 | }
32 |
33 | public void setName(String name) {
34 | this.name = name;
35 | }
36 |
37 | @Override
38 | public boolean equals(Object o) {
39 | if (this == o) {
40 | return true;
41 | }
42 | if (o == null || getClass() != o.getClass()) {
43 | return false;
44 | }
45 |
46 | Authority authority = (Authority) o;
47 |
48 | return !(name != null ? !name.equals(authority.name) : authority.name != null);
49 | }
50 |
51 | @Override
52 | public int hashCode() {
53 | return name != null ? name.hashCode() : 0;
54 | }
55 |
56 | @Override
57 | public String toString() {
58 | return "Authority{" +
59 | "name='" + name + '\'' +
60 | "}";
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/domain/PersistentAuditEvent.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.domain;
2 |
3 | import javax.persistence.*;
4 | import javax.validation.constraints.NotNull;
5 | import java.io.Serializable;
6 | import java.time.Instant;
7 | import java.util.HashMap;
8 | import java.util.Map;
9 |
10 | /**
11 | * Persist AuditEvent managed by the Spring Boot actuator.
12 | *
13 | * @see org.springframework.boot.actuate.audit.AuditEvent
14 | */
15 | @Entity
16 | @Table(name = "jhi_persistent_audit_event")
17 | public class PersistentAuditEvent implements Serializable {
18 |
19 | private static final long serialVersionUID = 1L;
20 |
21 | @Id
22 | @GeneratedValue(strategy = GenerationType.IDENTITY)
23 | @Column(name = "event_id")
24 | private Long id;
25 |
26 | @NotNull
27 | @Column(nullable = false)
28 | private String principal;
29 |
30 | @Column(name = "event_date")
31 | private Instant auditEventDate;
32 |
33 | @Column(name = "event_type")
34 | private String auditEventType;
35 |
36 | @ElementCollection
37 | @MapKeyColumn(name = "name")
38 | @Column(name = "value")
39 | @CollectionTable(name = "jhi_persistent_audit_evt_data", joinColumns=@JoinColumn(name="event_id"))
40 | private Map data = new HashMap<>();
41 |
42 | public Long getId() {
43 | return id;
44 | }
45 |
46 | public void setId(Long id) {
47 | this.id = id;
48 | }
49 |
50 | public String getPrincipal() {
51 | return principal;
52 | }
53 |
54 | public void setPrincipal(String principal) {
55 | this.principal = principal;
56 | }
57 |
58 | public Instant getAuditEventDate() {
59 | return auditEventDate;
60 | }
61 |
62 | public void setAuditEventDate(Instant auditEventDate) {
63 | this.auditEventDate = auditEventDate;
64 | }
65 |
66 | public String getAuditEventType() {
67 | return auditEventType;
68 | }
69 |
70 | public void setAuditEventType(String auditEventType) {
71 | this.auditEventType = auditEventType;
72 | }
73 |
74 | public Map getData() {
75 | return data;
76 | }
77 |
78 | public void setData(Map data) {
79 | this.data = data;
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/domain/enumeration/Units.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.domain.enumeration;
2 |
3 | /**
4 | * The Units enumeration.
5 | */
6 | public enum Units {
7 | KG, LB
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/domain/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * JPA domain objects.
3 | */
4 | package com.robmelfi.health.domain;
5 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/repository/AuthorityRepository.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.repository;
2 |
3 | import com.robmelfi.health.domain.Authority;
4 |
5 | import org.springframework.data.jpa.repository.JpaRepository;
6 |
7 | /**
8 | * Spring Data JPA repository for the Authority entity.
9 | */
10 | public interface AuthorityRepository extends JpaRepository {
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/repository/BloodPressureRepository.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.repository;
2 |
3 | import com.robmelfi.health.domain.BloodPressure;
4 | import org.springframework.data.domain.Page;
5 | import org.springframework.data.domain.Pageable;
6 | import org.springframework.data.jpa.repository.*;
7 | import org.springframework.stereotype.Repository;
8 |
9 | import java.time.ZonedDateTime;
10 | import java.util.List;
11 |
12 | /**
13 | * Spring Data repository for the BloodPressure entity.
14 | */
15 | @SuppressWarnings("unused")
16 | @Repository
17 | public interface BloodPressureRepository extends JpaRepository {
18 |
19 | @Query("select blood_pressure from BloodPressure blood_pressure where blood_pressure.user.login = ?#{principal.username} order by blood_pressure.timestamp desc")
20 | Page findByUserIsCurrentUser(Pageable pageable);
21 |
22 | Page findAllByOrderByTimestampDesc(Pageable pageable);
23 |
24 | List findAllByTimestampBetweenOrderByTimestampDesc(ZonedDateTime firstDate, ZonedDateTime secondDate);
25 |
26 | List findAllByTimestampBetweenAndUserLoginOrderByTimestampDesc(ZonedDateTime firstDate, ZonedDateTime secondDate, String login);
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/repository/PersistenceAuditEventRepository.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.repository;
2 |
3 | import com.robmelfi.health.domain.PersistentAuditEvent;
4 | import org.springframework.data.domain.Page;
5 | import org.springframework.data.domain.Pageable;
6 | import org.springframework.data.jpa.repository.JpaRepository;
7 |
8 | import java.time.Instant;
9 | import java.util.List;
10 |
11 | /**
12 | * Spring Data JPA repository for the PersistentAuditEvent entity.
13 | */
14 | public interface PersistenceAuditEventRepository extends JpaRepository {
15 |
16 | List findByPrincipal(String principal);
17 |
18 | List findByAuditEventDateAfter(Instant after);
19 |
20 | List findByPrincipalAndAuditEventDateAfter(String principal, Instant after);
21 |
22 | List findByPrincipalAndAuditEventDateAfterAndAuditEventType(String principal, Instant after, String type);
23 |
24 | Page findAllByAuditEventDateBetween(Instant fromDate, Instant toDate, Pageable pageable);
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/repository/PointsRepository.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.repository;
2 |
3 | import com.robmelfi.health.domain.Points;
4 | import org.springframework.data.domain.Page;
5 | import org.springframework.data.domain.Pageable;
6 | import org.springframework.data.jpa.repository.*;
7 | import org.springframework.stereotype.Repository;
8 |
9 | import java.time.LocalDate;
10 | import java.util.List;
11 |
12 | /**
13 | * Spring Data repository for the Points entity.
14 | */
15 | @SuppressWarnings("unused")
16 | @Repository
17 | public interface PointsRepository extends JpaRepository {
18 |
19 | @Query("select points from Points points where points.user.login = ?#{principal.username} order by points.date desc")
20 | Page findByUserIsCurrentUser(Pageable pageable);
21 |
22 | Page findAllByOrderByDateDesc(Pageable pageable);
23 |
24 | List findAllByDateBetweenAndUserLogin(LocalDate fierstDate, LocalDate secondDate, String user);
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/repository/PreferencesRepository.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.repository;
2 |
3 | import com.robmelfi.health.domain.Preferences;
4 | import org.springframework.data.jpa.repository.*;
5 | import org.springframework.stereotype.Repository;
6 |
7 | import java.util.Optional;
8 |
9 |
10 | /**
11 | * Spring Data repository for the Preferences entity.
12 | */
13 | @SuppressWarnings("unused")
14 | @Repository
15 | public interface PreferencesRepository extends JpaRepository {
16 | Optional findOneByUserLogin(String login);
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/repository/UserRepository.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.repository;
2 |
3 | import com.robmelfi.health.domain.User;
4 |
5 | import org.springframework.cache.annotation.Cacheable;
6 | import org.springframework.data.domain.Page;
7 | import org.springframework.data.domain.Pageable;
8 | import org.springframework.data.jpa.repository.EntityGraph;
9 | import org.springframework.data.jpa.repository.JpaRepository;
10 | import org.springframework.stereotype.Repository;
11 | import java.util.List;
12 | import java.util.Optional;
13 | import java.time.Instant;
14 |
15 | /**
16 | * Spring Data JPA repository for the User entity.
17 | */
18 | @Repository
19 | public interface UserRepository extends JpaRepository {
20 |
21 | String USERS_BY_LOGIN_CACHE = "usersByLogin";
22 |
23 | String USERS_BY_EMAIL_CACHE = "usersByEmail";
24 |
25 | Optional findOneByActivationKey(String activationKey);
26 |
27 | List findAllByActivatedIsFalseAndCreatedDateBefore(Instant dateTime);
28 |
29 | Optional findOneByResetKey(String resetKey);
30 |
31 | Optional findOneByEmailIgnoreCase(String email);
32 |
33 | Optional findOneByLogin(String login);
34 |
35 | @EntityGraph(attributePaths = "authorities")
36 | Optional findOneWithAuthoritiesById(Long id);
37 |
38 | @EntityGraph(attributePaths = "authorities")
39 | @Cacheable(cacheNames = USERS_BY_LOGIN_CACHE)
40 | Optional findOneWithAuthoritiesByLogin(String login);
41 |
42 | @EntityGraph(attributePaths = "authorities")
43 | @Cacheable(cacheNames = USERS_BY_EMAIL_CACHE)
44 | Optional findOneWithAuthoritiesByEmail(String email);
45 |
46 | Page findAllByLoginNot(Pageable pageable, String login);
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/repository/WeigthRepository.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.repository;
2 |
3 | import com.robmelfi.health.domain.Weigth;
4 | import org.springframework.data.domain.Page;
5 | import org.springframework.data.domain.Pageable;
6 | import org.springframework.data.jpa.repository.*;
7 | import org.springframework.stereotype.Repository;
8 |
9 | import java.time.ZonedDateTime;
10 | import java.util.List;
11 |
12 | /**
13 | * Spring Data repository for the Weigth entity.
14 | */
15 | @SuppressWarnings("unused")
16 | @Repository
17 | public interface WeigthRepository extends JpaRepository {
18 |
19 | @Query("select weigth from Weigth weigth where weigth.user.login = ?#{principal.username} order by weight.timestamp desc")
20 | Page findByUserIsCurrentUser(Pageable pageable);
21 |
22 | Page findAllByOrderByTimestampDesc(Pageable pageable);
23 |
24 | List findAllByTimestampBetweenOrderByTimestampDesc(ZonedDateTime firstDate, ZonedDateTime secondDate);
25 |
26 | List findAllByTimestampBetweenAndUserLoginOrderByTimestampDesc(ZonedDateTime firstDate, ZonedDateTime secondDate, String login);
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/repository/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Spring Data JPA repositories.
3 | */
4 | package com.robmelfi.health.repository;
5 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/repository/search/BloodPressureSearchRepository.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.repository.search;
2 |
3 | import com.robmelfi.health.domain.BloodPressure;
4 | import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
5 |
6 | /**
7 | * Spring Data Elasticsearch repository for the BloodPressure entity.
8 | */
9 | public interface BloodPressureSearchRepository extends ElasticsearchRepository {
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/repository/search/PointsSearchRepository.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.repository.search;
2 |
3 | import com.robmelfi.health.domain.Points;
4 | import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
5 |
6 | /**
7 | * Spring Data Elasticsearch repository for the Points entity.
8 | */
9 | public interface PointsSearchRepository extends ElasticsearchRepository {
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/repository/search/PreferencesSearchRepository.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.repository.search;
2 |
3 | import com.robmelfi.health.domain.Preferences;
4 | import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
5 |
6 | /**
7 | * Spring Data Elasticsearch repository for the Preferences entity.
8 | */
9 | public interface PreferencesSearchRepository extends ElasticsearchRepository {
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/repository/search/UserSearchRepository.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.repository.search;
2 |
3 | import com.robmelfi.health.domain.User;
4 | import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
5 |
6 | /**
7 | * Spring Data Elasticsearch repository for the User entity.
8 | */
9 | public interface UserSearchRepository extends ElasticsearchRepository {
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/repository/search/WeigthSearchRepository.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.repository.search;
2 |
3 | import com.robmelfi.health.domain.Weigth;
4 | import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
5 |
6 | /**
7 | * Spring Data Elasticsearch repository for the Weigth entity.
8 | */
9 | public interface WeigthSearchRepository extends ElasticsearchRepository {
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/repository/search/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Spring Data Elasticsearch repositories.
3 | */
4 | package com.robmelfi.health.repository.search;
5 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/security/AuthoritiesConstants.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.security;
2 |
3 | /**
4 | * Constants for Spring Security authorities.
5 | */
6 | public final class AuthoritiesConstants {
7 |
8 | public static final String ADMIN = "ROLE_ADMIN";
9 |
10 | public static final String USER = "ROLE_USER";
11 |
12 | public static final String ANONYMOUS = "ROLE_ANONYMOUS";
13 |
14 | private AuthoritiesConstants() {
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/security/SpringSecurityAuditorAware.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.security;
2 |
3 | import com.robmelfi.health.config.Constants;
4 |
5 | import java.util.Optional;
6 |
7 | import org.springframework.data.domain.AuditorAware;
8 | import org.springframework.stereotype.Component;
9 |
10 | /**
11 | * Implementation of AuditorAware based on Spring Security.
12 | */
13 | @Component
14 | public class SpringSecurityAuditorAware implements AuditorAware {
15 |
16 | @Override
17 | public Optional getCurrentAuditor() {
18 | return Optional.of(SecurityUtils.getCurrentUserLogin().orElse(Constants.SYSTEM_ACCOUNT));
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/security/UserNotActivatedException.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.security;
2 |
3 | import org.springframework.security.core.AuthenticationException;
4 |
5 | /**
6 | * This exception is thrown in case of a not activated user trying to authenticate.
7 | */
8 | public class UserNotActivatedException extends AuthenticationException {
9 |
10 | private static final long serialVersionUID = 1L;
11 |
12 | public UserNotActivatedException(String message) {
13 | super(message);
14 | }
15 |
16 | public UserNotActivatedException(String message, Throwable t) {
17 | super(message, t);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/security/jwt/JWTConfigurer.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.security.jwt;
2 |
3 | import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
4 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
5 | import org.springframework.security.web.DefaultSecurityFilterChain;
6 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
7 |
8 | public class JWTConfigurer extends SecurityConfigurerAdapter {
9 |
10 | private TokenProvider tokenProvider;
11 |
12 | public JWTConfigurer(TokenProvider tokenProvider) {
13 | this.tokenProvider = tokenProvider;
14 | }
15 |
16 | @Override
17 | public void configure(HttpSecurity http) throws Exception {
18 | JWTFilter customFilter = new JWTFilter(tokenProvider);
19 | http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/security/jwt/JWTFilter.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.security.jwt;
2 |
3 | import org.springframework.security.core.Authentication;
4 | import org.springframework.security.core.context.SecurityContextHolder;
5 | import org.springframework.util.StringUtils;
6 | import org.springframework.web.filter.GenericFilterBean;
7 |
8 | import javax.servlet.FilterChain;
9 | import javax.servlet.ServletException;
10 | import javax.servlet.ServletRequest;
11 | import javax.servlet.ServletResponse;
12 | import javax.servlet.http.HttpServletRequest;
13 | import java.io.IOException;
14 |
15 | /**
16 | * Filters incoming requests and installs a Spring Security principal if a header corresponding to a valid user is
17 | * found.
18 | */
19 | public class JWTFilter extends GenericFilterBean {
20 |
21 | public static final String AUTHORIZATION_HEADER = "Authorization";
22 |
23 | private TokenProvider tokenProvider;
24 |
25 | public JWTFilter(TokenProvider tokenProvider) {
26 | this.tokenProvider = tokenProvider;
27 | }
28 |
29 | @Override
30 | public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
31 | throws IOException, ServletException {
32 | HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
33 | String jwt = resolveToken(httpServletRequest);
34 | if (StringUtils.hasText(jwt) && this.tokenProvider.validateToken(jwt)) {
35 | Authentication authentication = this.tokenProvider.getAuthentication(jwt);
36 | SecurityContextHolder.getContext().setAuthentication(authentication);
37 | }
38 | filterChain.doFilter(servletRequest, servletResponse);
39 | }
40 |
41 | private String resolveToken(HttpServletRequest request){
42 | String bearerToken = request.getHeader(AUTHORIZATION_HEADER);
43 | if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
44 | return bearerToken.substring(7, bearerToken.length());
45 | }
46 | return null;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/security/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Spring Security configuration.
3 | */
4 | package com.robmelfi.health.security;
5 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/service/AuditEventService.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.service;
2 |
3 | import com.robmelfi.health.config.audit.AuditEventConverter;
4 | import com.robmelfi.health.repository.PersistenceAuditEventRepository;
5 | import org.springframework.boot.actuate.audit.AuditEvent;
6 | import org.springframework.data.domain.Page;
7 | import org.springframework.data.domain.Pageable;
8 | import org.springframework.stereotype.Service;
9 | import org.springframework.transaction.annotation.Transactional;
10 |
11 | import java.time.Instant;
12 | import java.util.Optional;
13 |
14 | /**
15 | * Service for managing audit events.
16 | *
17 | * This is the default implementation to support SpringBoot Actuator AuditEventRepository
18 | */
19 | @Service
20 | @Transactional
21 | public class AuditEventService {
22 |
23 | private final PersistenceAuditEventRepository persistenceAuditEventRepository;
24 |
25 | private final AuditEventConverter auditEventConverter;
26 |
27 | public AuditEventService(
28 | PersistenceAuditEventRepository persistenceAuditEventRepository,
29 | AuditEventConverter auditEventConverter) {
30 |
31 | this.persistenceAuditEventRepository = persistenceAuditEventRepository;
32 | this.auditEventConverter = auditEventConverter;
33 | }
34 |
35 | public Page findAll(Pageable pageable) {
36 | return persistenceAuditEventRepository.findAll(pageable)
37 | .map(auditEventConverter::convertToAuditEvent);
38 | }
39 |
40 | public Page findByDates(Instant fromDate, Instant toDate, Pageable pageable) {
41 | return persistenceAuditEventRepository.findAllByAuditEventDateBetween(fromDate, toDate, pageable)
42 | .map(auditEventConverter::convertToAuditEvent);
43 | }
44 |
45 | public Optional find(Long id) {
46 | return Optional.ofNullable(persistenceAuditEventRepository.findById(id))
47 | .filter(Optional::isPresent)
48 | .map(Optional::get)
49 | .map(auditEventConverter::convertToAuditEvent);
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/service/dto/BloodPressureByPeriodDTO.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.service.dto;
2 |
3 | import com.robmelfi.health.domain.BloodPressure;
4 |
5 | import java.util.List;
6 |
7 | public class BloodPressureByPeriodDTO {
8 | private String period;
9 | private List readings;
10 |
11 | public BloodPressureByPeriodDTO(String period, List readings) {
12 | this.period = period;
13 | this.readings = readings;
14 | }
15 |
16 | public String getPeriod() {
17 | return period;
18 | }
19 |
20 | public void setPeriod(String period) {
21 | this.period = period;
22 | }
23 |
24 | public List getReadings() {
25 | return readings;
26 | }
27 |
28 | public void setReadings(List readings) {
29 | this.readings = readings;
30 | }
31 |
32 | @Override
33 | public String toString() {
34 | return "BloodPressureByPeriod{" +
35 | "period='" + period + '\'' +
36 | ", readings=" + readings +
37 | '}';
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/service/dto/PasswordChangeDTO.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.service.dto;
2 |
3 | /**
4 | * A DTO representing a password change required data - current and new password.
5 | */
6 | public class PasswordChangeDTO {
7 | private String currentPassword;
8 | private String newPassword;
9 |
10 | public PasswordChangeDTO() {
11 | // Empty constructor needed for Jackson.
12 | }
13 |
14 | public PasswordChangeDTO(String currentPassword, String newPassword) {
15 | this.currentPassword = currentPassword;
16 | this.newPassword = newPassword;
17 | }
18 |
19 | public String getCurrentPassword() {
20 |
21 | return currentPassword;
22 | }
23 |
24 | public void setCurrentPassword(String currentPassword) {
25 | this.currentPassword = currentPassword;
26 | }
27 |
28 | public String getNewPassword() {
29 | return newPassword;
30 | }
31 |
32 | public void setNewPassword(String newPassword) {
33 | this.newPassword = newPassword;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/service/dto/PointsPerMonthDTO.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.service.dto;
2 |
3 | import com.robmelfi.health.domain.Points;
4 |
5 | import java.time.YearMonth;
6 | import java.util.List;
7 |
8 | public class PointsPerMonthDTO {
9 | private YearMonth month;
10 | private List points;
11 |
12 | public PointsPerMonthDTO(YearMonth yearWithMonth, List points) {
13 | this.month = yearWithMonth;
14 | this.points = points;
15 | }
16 |
17 | public YearMonth getMonth() {
18 | return month;
19 | }
20 |
21 | public void setMonth(YearMonth month) {
22 | this.month = month;
23 | }
24 |
25 | public List getPoints() {
26 | return points;
27 | }
28 |
29 | public void setPoints(List points) {
30 | this.points = points;
31 | }
32 |
33 | @Override
34 | public String toString() {
35 | return "PointsPerMonth{" +
36 | "month=" + month +
37 | ", points=" + points +
38 | '}';
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/service/dto/PointsPerWeekDTO.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.service.dto;
2 |
3 | import java.time.LocalDate;
4 |
5 | public class PointsPerWeekDTO {
6 | private LocalDate week;
7 | private Integer points;
8 |
9 | public PointsPerWeekDTO(LocalDate week, Integer points) {
10 | this.week = week;
11 | this.points = points;
12 | }
13 |
14 | public LocalDate getWeek() {
15 | return week;
16 | }
17 |
18 | public void setWeek(LocalDate week) {
19 | this.week = week;
20 | }
21 |
22 | public Integer getPoints() {
23 | return points;
24 | }
25 |
26 | public void setPoints(Integer points) {
27 | this.points = points;
28 | }
29 |
30 | @Override
31 | public String toString() {
32 | return "PointsThisWeek{" +
33 | "points=" + points +
34 | ", week=" + week +
35 | "}";
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/service/dto/WeigthByPeriodDTO.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.service.dto;
2 |
3 | import com.robmelfi.health.domain.Weigth;
4 |
5 | import java.util.List;
6 |
7 | public class WeigthByPeriodDTO {
8 | private String period;
9 | private List weighIns;
10 |
11 | public WeigthByPeriodDTO(String period, List weighIns) {
12 | this.period = period;
13 | this.weighIns = weighIns;
14 | }
15 |
16 | public String getPeriod() {
17 | return period;
18 | }
19 |
20 | public void setPeriod(String period) {
21 | this.period = period;
22 | }
23 |
24 | public List getWeighIns() {
25 | return weighIns;
26 | }
27 |
28 | public void setWeighIns(List weighIns) {
29 | this.weighIns = weighIns;
30 | }
31 |
32 | @Override
33 | public String toString() {
34 | return "WeightByPeriod{" +
35 | "period='" + period + '\'' +
36 | ", weighIns=" + weighIns +
37 | '}';
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/service/dto/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Data Transfer Objects.
3 | */
4 | package com.robmelfi.health.service.dto;
5 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/service/mapper/BloodPressureMapper.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.service.mapper;
2 |
3 | import com.robmelfi.health.domain.*;
4 | import com.robmelfi.health.service.dto.BloodPressureDTO;
5 |
6 | import org.mapstruct.*;
7 |
8 | /**
9 | * Mapper for the entity BloodPressure and its DTO BloodPressureDTO.
10 | */
11 | @Mapper(componentModel = "spring", uses = {UserMapper.class})
12 | public interface BloodPressureMapper extends EntityMapper {
13 |
14 | @Mapping(source = "user.id", target = "userId")
15 | @Mapping(source = "user.login", target = "userLogin")
16 | BloodPressureDTO toDto(BloodPressure bloodPressure);
17 |
18 | @Mapping(source = "userId", target = "user")
19 | BloodPressure toEntity(BloodPressureDTO bloodPressureDTO);
20 |
21 | default BloodPressure fromId(Long id) {
22 | if (id == null) {
23 | return null;
24 | }
25 | BloodPressure bloodPressure = new BloodPressure();
26 | bloodPressure.setId(id);
27 | return bloodPressure;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/service/mapper/EntityMapper.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.service.mapper;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * Contract for a generic dto to entity mapper.
7 | *
8 | * @param - DTO type parameter.
9 | * @param - Entity type parameter.
10 | */
11 |
12 | public interface EntityMapper {
13 |
14 | E toEntity(D dto);
15 |
16 | D toDto(E entity);
17 |
18 | List toEntity(List dtoList);
19 |
20 | List toDto(List entityList);
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/service/mapper/PointsMapper.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.service.mapper;
2 |
3 | import com.robmelfi.health.domain.*;
4 | import com.robmelfi.health.service.dto.PointsDTO;
5 |
6 | import org.mapstruct.*;
7 |
8 | /**
9 | * Mapper for the entity Points and its DTO PointsDTO.
10 | */
11 | @Mapper(componentModel = "spring", uses = {UserMapper.class})
12 | public interface PointsMapper extends EntityMapper {
13 |
14 | @Mapping(source = "user.id", target = "userId")
15 | @Mapping(source = "user.login", target = "userLogin")
16 | PointsDTO toDto(Points points);
17 |
18 | @Mapping(source = "userId", target = "user")
19 | Points toEntity(PointsDTO pointsDTO);
20 |
21 | default Points fromId(Long id) {
22 | if (id == null) {
23 | return null;
24 | }
25 | Points points = new Points();
26 | points.setId(id);
27 | return points;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/service/mapper/PreferencesMapper.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.service.mapper;
2 |
3 | import com.robmelfi.health.domain.*;
4 | import com.robmelfi.health.service.dto.PreferencesDTO;
5 |
6 | import org.mapstruct.*;
7 |
8 | /**
9 | * Mapper for the entity Preferences and its DTO PreferencesDTO.
10 | */
11 | @Mapper(componentModel = "spring", uses = {UserMapper.class})
12 | public interface PreferencesMapper extends EntityMapper {
13 |
14 | @Mapping(source = "user.id", target = "userId")
15 | @Mapping(source = "user.login", target = "userLogin")
16 | PreferencesDTO toDto(Preferences preferences);
17 |
18 | @Mapping(source = "userId", target = "user")
19 | Preferences toEntity(PreferencesDTO preferencesDTO);
20 |
21 | default Preferences fromId(Long id) {
22 | if (id == null) {
23 | return null;
24 | }
25 | Preferences preferences = new Preferences();
26 | preferences.setId(id);
27 | return preferences;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/service/mapper/WeigthMapper.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.service.mapper;
2 |
3 | import com.robmelfi.health.domain.*;
4 | import com.robmelfi.health.service.dto.WeigthDTO;
5 |
6 | import org.mapstruct.*;
7 |
8 | /**
9 | * Mapper for the entity Weigth and its DTO WeigthDTO.
10 | */
11 | @Mapper(componentModel = "spring", uses = {UserMapper.class})
12 | public interface WeigthMapper extends EntityMapper {
13 |
14 | @Mapping(source = "user.id", target = "userId")
15 | @Mapping(source = "user.login", target = "userLogin")
16 | WeigthDTO toDto(Weigth weigth);
17 |
18 | @Mapping(source = "userId", target = "user")
19 | Weigth toEntity(WeigthDTO weigthDTO);
20 |
21 | default Weigth fromId(Long id) {
22 | if (id == null) {
23 | return null;
24 | }
25 | Weigth weigth = new Weigth();
26 | weigth.setId(id);
27 | return weigth;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/service/mapper/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * MapStruct mappers for mapping domain objects and Data Transfer Objects.
3 | */
4 | package com.robmelfi.health.service.mapper;
5 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/service/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Service layer beans.
3 | */
4 | package com.robmelfi.health.service;
5 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/service/util/RandomUtil.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.service.util;
2 |
3 | import org.apache.commons.lang3.RandomStringUtils;
4 |
5 | import java.security.SecureRandom;
6 |
7 | /**
8 | * Utility class for generating random Strings.
9 | */
10 | public final class RandomUtil {
11 | private static final SecureRandom SECURE_RANDOM = new SecureRandom();
12 |
13 | private static final int DEF_COUNT = 20;
14 |
15 | static {
16 | SECURE_RANDOM.nextBytes(new byte[64]);
17 | }
18 |
19 | private RandomUtil() {
20 | }
21 |
22 | private static String generateRandomAlphanumericString() {
23 | return RandomStringUtils.random(DEF_COUNT, 0, 0, true, true, null, SECURE_RANDOM);
24 | }
25 |
26 | /**
27 | * Generate a password.
28 | *
29 | * @return the generated password
30 | */
31 | public static String generatePassword() {
32 | return generateRandomAlphanumericString();
33 | }
34 |
35 | /**
36 | * Generate an activation key.
37 | *
38 | * @return the generated activation key
39 | */
40 | public static String generateActivationKey() {
41 | return generateRandomAlphanumericString();
42 | }
43 |
44 | /**
45 | * Generate a reset key.
46 | *
47 | * @return the generated reset key
48 | */
49 | public static String generateResetKey() {
50 | return generateRandomAlphanumericString();
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/web/rest/LogsResource.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.web.rest;
2 |
3 | import com.robmelfi.health.web.rest.vm.LoggerVM;
4 |
5 | import ch.qos.logback.classic.Level;
6 | import ch.qos.logback.classic.LoggerContext;
7 | import com.codahale.metrics.annotation.Timed;
8 | import org.slf4j.LoggerFactory;
9 | import org.springframework.http.HttpStatus;
10 | import org.springframework.web.bind.annotation.*;
11 |
12 | import java.util.List;
13 | import java.util.stream.Collectors;
14 |
15 | /**
16 | * Controller for view and managing Log Level at runtime.
17 | */
18 | @RestController
19 | @RequestMapping("/management")
20 | public class LogsResource {
21 |
22 | @GetMapping("/logs")
23 | @Timed
24 | public List getList() {
25 | LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
26 | return context.getLoggerList()
27 | .stream()
28 | .map(LoggerVM::new)
29 | .collect(Collectors.toList());
30 | }
31 |
32 | @PutMapping("/logs")
33 | @ResponseStatus(HttpStatus.NO_CONTENT)
34 | @Timed
35 | public void changeLevel(@RequestBody LoggerVM jsonLogger) {
36 | LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
37 | context.getLogger(jsonLogger.getName()).setLevel(Level.valueOf(jsonLogger.getLevel()));
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/web/rest/errors/BadRequestAlertException.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.web.rest.errors;
2 |
3 | import org.zalando.problem.AbstractThrowableProblem;
4 | import org.zalando.problem.Status;
5 |
6 | import java.net.URI;
7 | import java.util.HashMap;
8 | import java.util.Map;
9 |
10 | public class BadRequestAlertException extends AbstractThrowableProblem {
11 |
12 | private static final long serialVersionUID = 1L;
13 |
14 | private final String entityName;
15 |
16 | private final String errorKey;
17 |
18 | public BadRequestAlertException(String defaultMessage, String entityName, String errorKey) {
19 | this(ErrorConstants.DEFAULT_TYPE, defaultMessage, entityName, errorKey);
20 | }
21 |
22 | public BadRequestAlertException(URI type, String defaultMessage, String entityName, String errorKey) {
23 | super(type, defaultMessage, Status.BAD_REQUEST, null, null, null, getAlertParameters(entityName, errorKey));
24 | this.entityName = entityName;
25 | this.errorKey = errorKey;
26 | }
27 |
28 | public String getEntityName() {
29 | return entityName;
30 | }
31 |
32 | public String getErrorKey() {
33 | return errorKey;
34 | }
35 |
36 | private static Map getAlertParameters(String entityName, String errorKey) {
37 | Map parameters = new HashMap<>();
38 | parameters.put("message", "error." + errorKey);
39 | parameters.put("params", entityName);
40 | return parameters;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/web/rest/errors/CustomParameterizedException.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.web.rest.errors;
2 |
3 | import org.zalando.problem.AbstractThrowableProblem;
4 |
5 | import java.util.HashMap;
6 | import java.util.Map;
7 |
8 | import static org.zalando.problem.Status.BAD_REQUEST;
9 |
10 | /**
11 | * Custom, parameterized exception, which can be translated on the client side.
12 | * For example:
13 | *
14 | *
15 | * throw new CustomParameterizedException("myCustomError", "hello", "world");
16 | *
17 | *
18 | * Can be translated with:
19 | *
20 | *
21 | * "error.myCustomError" : "The server says {{param0}} to {{param1}}"
22 | *
23 | */
24 | public class CustomParameterizedException extends AbstractThrowableProblem {
25 |
26 | private static final long serialVersionUID = 1L;
27 |
28 | private static final String PARAM = "param";
29 |
30 | public CustomParameterizedException(String message, String... params) {
31 | this(message, toParamMap(params));
32 | }
33 |
34 | public CustomParameterizedException(String message, Map paramMap) {
35 | super(ErrorConstants.PARAMETERIZED_TYPE, "Parameterized Exception", BAD_REQUEST, null, null, null, toProblemParameters(message, paramMap));
36 | }
37 |
38 | public static Map toParamMap(String... params) {
39 | Map paramMap = new HashMap<>();
40 | if (params != null && params.length > 0) {
41 | for (int i = 0; i < params.length; i++) {
42 | paramMap.put(PARAM + i, params[i]);
43 | }
44 | }
45 | return paramMap;
46 | }
47 |
48 | public static Map toProblemParameters(String message, Map paramMap) {
49 | Map parameters = new HashMap<>();
50 | parameters.put("message", message);
51 | parameters.put("params", paramMap);
52 | return parameters;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/web/rest/errors/EmailAlreadyUsedException.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.web.rest.errors;
2 |
3 | public class EmailAlreadyUsedException extends BadRequestAlertException {
4 |
5 | private static final long serialVersionUID = 1L;
6 |
7 | public EmailAlreadyUsedException() {
8 | super(ErrorConstants.EMAIL_ALREADY_USED_TYPE, "Email is already in use!", "userManagement", "emailexists");
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/web/rest/errors/EmailNotFoundException.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.web.rest.errors;
2 |
3 | import org.zalando.problem.AbstractThrowableProblem;
4 | import org.zalando.problem.Status;
5 |
6 | public class EmailNotFoundException extends AbstractThrowableProblem {
7 |
8 | private static final long serialVersionUID = 1L;
9 |
10 | public EmailNotFoundException() {
11 | super(ErrorConstants.EMAIL_NOT_FOUND_TYPE, "Email address not registered", Status.BAD_REQUEST);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/web/rest/errors/ErrorConstants.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.web.rest.errors;
2 |
3 | import java.net.URI;
4 |
5 | public final class ErrorConstants {
6 |
7 | public static final String ERR_CONCURRENCY_FAILURE = "error.concurrencyFailure";
8 | public static final String ERR_VALIDATION = "error.validation";
9 | public static final String PROBLEM_BASE_URL = "https://www.jhipster.tech/problem";
10 | public static final URI DEFAULT_TYPE = URI.create(PROBLEM_BASE_URL + "/problem-with-message");
11 | public static final URI CONSTRAINT_VIOLATION_TYPE = URI.create(PROBLEM_BASE_URL + "/constraint-violation");
12 | public static final URI PARAMETERIZED_TYPE = URI.create(PROBLEM_BASE_URL + "/parameterized");
13 | public static final URI ENTITY_NOT_FOUND_TYPE = URI.create(PROBLEM_BASE_URL + "/entity-not-found");
14 | public static final URI INVALID_PASSWORD_TYPE = URI.create(PROBLEM_BASE_URL + "/invalid-password");
15 | public static final URI EMAIL_ALREADY_USED_TYPE = URI.create(PROBLEM_BASE_URL + "/email-already-used");
16 | public static final URI LOGIN_ALREADY_USED_TYPE = URI.create(PROBLEM_BASE_URL + "/login-already-used");
17 | public static final URI EMAIL_NOT_FOUND_TYPE = URI.create(PROBLEM_BASE_URL + "/email-not-found");
18 |
19 | private ErrorConstants() {
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/web/rest/errors/FieldErrorVM.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.web.rest.errors;
2 |
3 | import java.io.Serializable;
4 |
5 | public class FieldErrorVM implements Serializable {
6 |
7 | private static final long serialVersionUID = 1L;
8 |
9 | private final String objectName;
10 |
11 | private final String field;
12 |
13 | private final String message;
14 |
15 | public FieldErrorVM(String dto, String field, String message) {
16 | this.objectName = dto;
17 | this.field = field;
18 | this.message = message;
19 | }
20 |
21 | public String getObjectName() {
22 | return objectName;
23 | }
24 |
25 | public String getField() {
26 | return field;
27 | }
28 |
29 | public String getMessage() {
30 | return message;
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/web/rest/errors/InternalServerErrorException.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.web.rest.errors;
2 |
3 | import org.zalando.problem.AbstractThrowableProblem;
4 | import org.zalando.problem.Status;
5 |
6 | /**
7 | * Simple exception with a message, that returns an Internal Server Error code.
8 | */
9 | public class InternalServerErrorException extends AbstractThrowableProblem {
10 |
11 | private static final long serialVersionUID = 1L;
12 |
13 | public InternalServerErrorException(String message) {
14 | super(ErrorConstants.DEFAULT_TYPE, message, Status.INTERNAL_SERVER_ERROR);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/web/rest/errors/InvalidPasswordException.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.web.rest.errors;
2 |
3 | import org.zalando.problem.AbstractThrowableProblem;
4 | import org.zalando.problem.Status;
5 |
6 | public class InvalidPasswordException extends AbstractThrowableProblem {
7 |
8 | private static final long serialVersionUID = 1L;
9 |
10 | public InvalidPasswordException() {
11 | super(ErrorConstants.INVALID_PASSWORD_TYPE, "Incorrect password", Status.BAD_REQUEST);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/web/rest/errors/LoginAlreadyUsedException.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.web.rest.errors;
2 |
3 | public class LoginAlreadyUsedException extends BadRequestAlertException {
4 |
5 | private static final long serialVersionUID = 1L;
6 |
7 | public LoginAlreadyUsedException() {
8 | super(ErrorConstants.LOGIN_ALREADY_USED_TYPE, "Login name already used!", "userManagement", "userexists");
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/web/rest/errors/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Specific errors used with Zalando's "problem-spring-web" library.
3 | *
4 | * More information on https://github.com/zalando/problem-spring-web
5 | */
6 | package com.robmelfi.health.web.rest.errors;
7 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/web/rest/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Spring MVC REST controllers.
3 | */
4 | package com.robmelfi.health.web.rest;
5 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/web/rest/util/HeaderUtil.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.web.rest.util;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 | import org.springframework.http.HttpHeaders;
6 |
7 | /**
8 | * Utility class for HTTP headers creation.
9 | */
10 | public final class HeaderUtil {
11 |
12 | private static final Logger log = LoggerFactory.getLogger(HeaderUtil.class);
13 |
14 | private static final String APPLICATION_NAME = "twentyOnePointsReactApp";
15 |
16 | private HeaderUtil() {
17 | }
18 |
19 | public static HttpHeaders createAlert(String message, String param) {
20 | HttpHeaders headers = new HttpHeaders();
21 | headers.add("X-" + APPLICATION_NAME + "-alert", message);
22 | headers.add("X-" + APPLICATION_NAME + "-params", param);
23 | return headers;
24 | }
25 |
26 | public static HttpHeaders createEntityCreationAlert(String entityName, String param) {
27 | return createAlert("A new " + entityName + " is created with identifier " + param, param);
28 | }
29 |
30 | public static HttpHeaders createEntityUpdateAlert(String entityName, String param) {
31 | return createAlert("A " + entityName + " is updated with identifier " + param, param);
32 | }
33 |
34 | public static HttpHeaders createEntityDeletionAlert(String entityName, String param) {
35 | return createAlert("A " + entityName + " is deleted with identifier " + param, param);
36 | }
37 |
38 | public static HttpHeaders createFailureAlert(String entityName, String errorKey, String defaultMessage) {
39 | log.error("Entity processing failed, {}", defaultMessage);
40 | HttpHeaders headers = new HttpHeaders();
41 | headers.add("X-" + APPLICATION_NAME + "-error", defaultMessage);
42 | headers.add("X-" + APPLICATION_NAME + "-params", entityName);
43 | return headers;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/web/rest/vm/KeyAndPasswordVM.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.web.rest.vm;
2 |
3 | /**
4 | * View Model object for storing the user's key and password.
5 | */
6 | public class KeyAndPasswordVM {
7 |
8 | private String key;
9 |
10 | private String newPassword;
11 |
12 | public String getKey() {
13 | return key;
14 | }
15 |
16 | public void setKey(String key) {
17 | this.key = key;
18 | }
19 |
20 | public String getNewPassword() {
21 | return newPassword;
22 | }
23 |
24 | public void setNewPassword(String newPassword) {
25 | this.newPassword = newPassword;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/web/rest/vm/LoggerVM.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.web.rest.vm;
2 |
3 | import ch.qos.logback.classic.Logger;
4 |
5 | /**
6 | * View Model object for storing a Logback logger.
7 | */
8 | public class LoggerVM {
9 |
10 | private String name;
11 |
12 | private String level;
13 |
14 | public LoggerVM(Logger logger) {
15 | this.name = logger.getName();
16 | this.level = logger.getEffectiveLevel().toString();
17 | }
18 |
19 | public LoggerVM() {
20 | // Empty public constructor used by Jackson.
21 | }
22 |
23 | public String getName() {
24 | return name;
25 | }
26 |
27 | public void setName(String name) {
28 | this.name = name;
29 | }
30 |
31 | public String getLevel() {
32 | return level;
33 | }
34 |
35 | public void setLevel(String level) {
36 | this.level = level;
37 | }
38 |
39 | @Override
40 | public String toString() {
41 | return "LoggerVM{" +
42 | "name='" + name + '\'' +
43 | ", level='" + level + '\'' +
44 | '}';
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/web/rest/vm/LoginVM.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.web.rest.vm;
2 |
3 | import javax.validation.constraints.NotNull;
4 | import javax.validation.constraints.Size;
5 |
6 | /**
7 | * View Model object for storing a user's credentials.
8 | */
9 | public class LoginVM {
10 |
11 | @NotNull
12 | @Size(min = 1, max = 50)
13 | private String username;
14 |
15 | @NotNull
16 | @Size(min = ManagedUserVM.PASSWORD_MIN_LENGTH, max = ManagedUserVM.PASSWORD_MAX_LENGTH)
17 | private String password;
18 |
19 | private Boolean rememberMe;
20 |
21 | public String getUsername() {
22 | return username;
23 | }
24 |
25 | public void setUsername(String username) {
26 | this.username = username;
27 | }
28 |
29 | public String getPassword() {
30 | return password;
31 | }
32 |
33 | public void setPassword(String password) {
34 | this.password = password;
35 | }
36 |
37 | public Boolean isRememberMe() {
38 | return rememberMe;
39 | }
40 |
41 | public void setRememberMe(Boolean rememberMe) {
42 | this.rememberMe = rememberMe;
43 | }
44 |
45 | @Override
46 | public String toString() {
47 | return "LoginVM{" +
48 | "username='" + username + '\'' +
49 | ", rememberMe=" + rememberMe +
50 | '}';
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/web/rest/vm/ManagedUserVM.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.web.rest.vm;
2 |
3 | import com.robmelfi.health.service.dto.UserDTO;
4 | import javax.validation.constraints.Size;
5 |
6 | /**
7 | * View Model extending the UserDTO, which is meant to be used in the user management UI.
8 | */
9 | public class ManagedUserVM extends UserDTO {
10 |
11 | public static final int PASSWORD_MIN_LENGTH = 4;
12 |
13 | public static final int PASSWORD_MAX_LENGTH = 100;
14 |
15 | @Size(min = PASSWORD_MIN_LENGTH, max = PASSWORD_MAX_LENGTH)
16 | private String password;
17 |
18 | public ManagedUserVM() {
19 | // Empty constructor needed for Jackson.
20 | }
21 |
22 | public String getPassword() {
23 | return password;
24 | }
25 |
26 | public void setPassword(String password) {
27 | this.password = password;
28 | }
29 |
30 | @Override
31 | public String toString() {
32 | return "ManagedUserVM{" +
33 | "} " + super.toString();
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/com/robmelfi/health/web/rest/vm/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * View Models used by Spring MVC REST controllers.
3 | */
4 | package com.robmelfi.health.web.rest.vm;
5 |
--------------------------------------------------------------------------------
/src/main/jib/entrypoint.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | echo "The application will start in ${JHIPSTER_SLEEP}s..." && sleep ${JHIPSTER_SLEEP}
4 | exec java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -cp /app/resources/:/app/classes/:/app/libs/* "com.robmelfi.health.TwentyOnePointsReactApp" "$@"
5 |
--------------------------------------------------------------------------------
/src/main/resources/.h2.server.properties:
--------------------------------------------------------------------------------
1 | #H2 Server Properties
2 | 0=JHipster H2 (Disk)|org.h2.Driver|jdbc\:h2\:file\:./target/h2db/db/twentyonepointsreact|TwentyOnePointsReact
3 | webAllowOthers=true
4 | webPort=8082
5 | webSSL=false
6 |
--------------------------------------------------------------------------------
/src/main/resources/banner.txt:
--------------------------------------------------------------------------------
1 |
2 | ${AnsiColor.GREEN} ██╗${AnsiColor.BLUE} ██╗ ██╗ ████████╗ ███████╗ ██████╗ ████████╗ ████████╗ ███████╗
3 | ${AnsiColor.GREEN} ██║${AnsiColor.BLUE} ██║ ██║ ╚══██╔══╝ ██╔═══██╗ ██╔════╝ ╚══██╔══╝ ██╔═════╝ ██╔═══██╗
4 | ${AnsiColor.GREEN} ██║${AnsiColor.BLUE} ████████║ ██║ ███████╔╝ ╚█████╗ ██║ ██████╗ ███████╔╝
5 | ${AnsiColor.GREEN}██╗ ██║${AnsiColor.BLUE} ██╔═══██║ ██║ ██╔════╝ ╚═══██╗ ██║ ██╔═══╝ ██╔══██║
6 | ${AnsiColor.GREEN}╚██████╔╝${AnsiColor.BLUE} ██║ ██║ ████████╗ ██║ ██████╔╝ ██║ ████████╗ ██║ ╚██╗
7 | ${AnsiColor.GREEN} ╚═════╝ ${AnsiColor.BLUE} ╚═╝ ╚═╝ ╚═══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══════╝ ╚═╝ ╚═╝
8 |
9 | ${AnsiColor.BRIGHT_BLUE}:: JHipster 🤓 :: Running Spring Boot ${spring-boot.version} ::
10 | :: https://www.jhipster.tech ::${AnsiColor.DEFAULT}
11 |
--------------------------------------------------------------------------------
/src/main/resources/config/application-heroku.yml:
--------------------------------------------------------------------------------
1 | # ===================================================================
2 | # Spring Boot configuration for the "heroku" profile.
3 | #
4 | # This configuration overrides the application.yml file.
5 | # ===================================================================
6 |
7 | # ===================================================================
8 | # Standard Spring Boot properties.
9 | # Full reference is available at:
10 | # http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html
11 | # ===================================================================
12 |
13 | eureka:
14 | instance:
15 | hostname: twentyone-points-react-dev.herokuapp.com
16 | non-secure-port: 80
17 | prefer-ip-address: false
18 | client:
19 | service-url:
20 | defaultZone: ${JHIPSTER_REGISTRY_URL}/eureka/
21 |
22 | spring:
23 | datasource:
24 | type: com.zaxxer.hikari.HikariDataSource
25 | url: ${JDBC_DATABASE_URL}
26 | username: ${JDBC_DATABASE_USERNAME}
27 | password: ${JDBC_DATABASE_PASSWORD}
28 | hikari:
29 | maximumPoolSize: 8
30 | data:
31 | jest:
32 | uri: ${BONSAI_URL}
33 |
--------------------------------------------------------------------------------
/src/main/resources/config/application-tls.yml:
--------------------------------------------------------------------------------
1 | # ===================================================================
2 | # Activate this profile to enable TLS and HTTP/2.
3 | #
4 | # JHipster has generated a self-signed certificate, which will be used to encrypt traffic.
5 | # As your browser will not understand this certificate, you will need to import it.
6 | #
7 | # Another (easiest) solution with Chrome is to enable the "allow-insecure-localhost" flag
8 | # at chrome://flags/#allow-insecure-localhost
9 | # ===================================================================
10 | server:
11 | ssl:
12 | key-store: classpath:config/tls/keystore.p12
13 | key-store-password: password
14 | key-store-type: PKCS12
15 | key-alias: selfsigned
16 | jhipster:
17 | http:
18 | version: V_2_0
19 |
--------------------------------------------------------------------------------
/src/main/resources/config/bootstrap-heroku.yml:
--------------------------------------------------------------------------------
1 | # ===================================================================
2 | # Spring Cloud Config bootstrap configuration for the "heroku" profile
3 | # ===================================================================
4 |
5 | spring:
6 | cloud:
7 | config:
8 | fail-fast: true
9 | uri: ${JHIPSTER_REGISTRY_URL}/config
10 |
--------------------------------------------------------------------------------
/src/main/resources/config/liquibase/authorities.csv:
--------------------------------------------------------------------------------
1 | name
2 | ROLE_ADMIN
3 | ROLE_USER
4 |
--------------------------------------------------------------------------------
/src/main/resources/config/liquibase/changelog/20181012140436_added_entity_constraints_Points.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
9 |
10 |
11 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/main/resources/config/liquibase/changelog/20181012140437_added_entity_Weigth.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/src/main/resources/config/liquibase/changelog/20181012140437_added_entity_constraints_Weigth.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
9 |
10 |
11 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/main/resources/config/liquibase/changelog/20181012140438_added_entity_BloodPressure.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/src/main/resources/config/liquibase/changelog/20181012140438_added_entity_constraints_BloodPressure.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
9 |
10 |
11 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/main/resources/config/liquibase/changelog/20181012140439_added_entity_Preferences.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/src/main/resources/config/liquibase/changelog/20181012140439_added_entity_constraints_Preferences.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
9 |
10 |
11 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/main/resources/config/liquibase/master.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/main/resources/config/liquibase/users.csv:
--------------------------------------------------------------------------------
1 | id;login;password_hash;first_name;last_name;email;image_url;activated;lang_key;created_by;last_modified_by
2 | 1;system;$2a$10$mE.qmcV0mFU5NcKh73TZx.z4ueI/.bDWbj0T1BYyqP481kGGarKLG;System;System;system@localhost;;true;en;system;system
3 | 2;anonymoususer;$2a$10$j8S5d7Sr7.8VTOYNviDPOeWX8KcYILUVJBsYV83Y5NtECayypx9lO;Anonymous;User;anonymous@localhost;;true;en;system;system
4 | 3;admin;$2a$10$gSAhZrxMllrbgj/kkK9UceBPpChGWJA7SYIb1Mqo.n5aNLq1/oRrC;Administrator;Administrator;admin@localhost;;true;en;system;system
5 | 4;user;$2a$10$VEjxo0jq2YG9Rbk2HmX9S.k1uZBGYUHdUcid3g/vfiEl7lwWgOH/K;User;User;user@localhost;;true;en;system;system
6 |
--------------------------------------------------------------------------------
/src/main/resources/config/liquibase/users_authorities.csv:
--------------------------------------------------------------------------------
1 | user_id;authority_name
2 | 1;ROLE_ADMIN
3 | 1;ROLE_USER
4 | 3;ROLE_ADMIN
5 | 3;ROLE_USER
6 | 4;ROLE_USER
7 |
--------------------------------------------------------------------------------
/src/main/resources/config/tls/keystore.p12:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robmelfi/21-points-react/a310a2762d7ddab3440588dbe3dcb22c338823ed/src/main/resources/config/tls/keystore.p12
--------------------------------------------------------------------------------
/src/main/resources/i18n/messages.properties:
--------------------------------------------------------------------------------
1 | # Error page
2 | error.title=Your request cannot be processed
3 | error.subtitle=Sorry, an error has occurred.
4 | error.status=Status:
5 | error.message=Message:
6 |
7 | # Activation email
8 | email.activation.title=21-Points Health Account Activation
9 | email.activation.greeting=Dear {0}
10 | email.activation.text1=Your 21-Points Health account has been created, please click on the URL below to activate it:
11 | email.activation.text2=Regards,
12 | email.signature=21-Points Health
13 |
14 | # Creation email
15 | email.creation.text1=Your 21-Points Health account has been created, please click on the URL below to access it:
16 |
17 | # Reset email
18 | email.reset.title=21-Points Health Password Reset
19 | email.reset.greeting=Dear {0}
20 | email.reset.text1=For your 21-Points Health account a password reset was requested, please click on the URL below to reset it:
21 | email.reset.text2=Regards,
22 |
--------------------------------------------------------------------------------
/src/main/resources/templates/mail/activationEmail.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 21-Points Health activation
5 |
6 |
7 |
8 |
9 |
10 | Dear
11 |
12 |
13 | Your JHipster account has been created, please click on the URL below to activate it:
14 |
15 |
16 | Activation Link
18 |
19 |
20 | Regards,
21 |
22 | JHipster.
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/main/resources/templates/mail/creationEmail.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | JHipster creation
5 |
6 |
7 |
8 |
9 |
10 | Dear
11 |
12 |
13 | Your JHipster account has been created, please click on the URL below to access it:
14 |
15 |
16 |
17 | Login link
19 |
20 |
21 |
22 | Regards,
23 |
24 | JHipster.
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/main/resources/templates/mail/passwordResetEmail.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | JHipster password reset
5 |
6 |
7 |
8 |
9 |
10 | Dear
11 |
12 |
13 | For your JHipster account a password reset was requested, please click on the URL below to reset it:
14 |
15 |
16 | Login link
18 |
19 |
20 | Regards,
21 |
22 | JHipster.
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/main/webapp/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Page Not Found
6 |
7 |
8 |
55 |
56 |
57 | Page Not Found
58 | Sorry, but the page you were trying to view does not exist.
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/src/main/webapp/app/_bootstrap-variables.scss:
--------------------------------------------------------------------------------
1 | /*
2 | * Bootstrap overrides https://v4-alpha.getbootstrap.com/getting-started/options/
3 | * All values defined in bootstrap source
4 | * https://github.com/twbs/bootstrap/blob/v4-dev/scss/_variables.scss can be overwritten here
5 | * Make sure not to add !default to values here
6 | */
7 |
8 | // Options:
9 | // Quickly modify global styling by enabling or disabling optional features.
10 | $enable-rounded: true;
11 | $enable-shadows: false;
12 | $enable-gradients: false;
13 | $enable-transitions: true;
14 | $enable-hover-media-query: false;
15 | $enable-grid-classes: true;
16 | $enable-print-styles: true;
17 |
18 | // Components:
19 | // Define common padding and border radius sizes and more.
20 |
21 | $border-radius: 0.15rem;
22 | $border-radius-lg: 0.125rem;
23 | $border-radius-sm: 0.1rem;
24 |
25 | // Body:
26 | // Settings for the `` element.
27 |
28 | $body-bg: #fff;
29 | $primary-color: #009688;
30 |
--------------------------------------------------------------------------------
/src/main/webapp/app/config/axios-interceptor.ts:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 | import { getBasePath, Storage } from 'react-jhipster';
3 |
4 | import { SERVER_API_URL } from 'app/config/constants';
5 |
6 | const TIMEOUT = 1000000; // 10000
7 | const setupAxiosInterceptors = onUnauthenticated => {
8 | const onRequestSuccess = config => {
9 | const token = Storage.local.get('jhi-authenticationToken') || Storage.session.get('jhi-authenticationToken');
10 | if (token) {
11 | config.headers.Authorization = `Bearer ${token}`;
12 | }
13 | config.timeout = TIMEOUT;
14 | config.url = `${SERVER_API_URL}${config.url}`;
15 | return config;
16 | };
17 | const onResponseSuccess = response => response;
18 | const onResponseError = err => {
19 | const status = err.status || err.response.status;
20 | if (status === 403 || status === 401) {
21 | onUnauthenticated();
22 | }
23 | return Promise.reject(err);
24 | };
25 | axios.interceptors.request.use(onRequestSuccess);
26 | axios.interceptors.response.use(onResponseSuccess, onResponseError);
27 | };
28 |
29 | export default setupAxiosInterceptors;
30 |
--------------------------------------------------------------------------------
/src/main/webapp/app/config/constants.ts:
--------------------------------------------------------------------------------
1 | const config = {
2 | VERSION: process.env.VERSION
3 | };
4 |
5 | export default config;
6 |
7 | export const SERVER_API_URL = process.env.SERVER_API_URL;
8 |
9 | export const AUTHORITIES = {
10 | ADMIN: 'ROLE_ADMIN',
11 | USER: 'ROLE_USER'
12 | };
13 |
14 | export const messages = {
15 | DATA_ERROR_ALERT: 'Internal Error'
16 | };
17 |
18 | export const APP_DATE_FORMAT = 'DD/MM/YY HH:mm';
19 | export const APP_TIMESTAMP_FORMAT = 'DD/MM/YY HH:mm:ss';
20 | export const APP_LOCAL_DATE_FORMAT = 'DD/MM/YYYY';
21 | export const APP_LOCAL_DATETIME_FORMAT = 'YYYY-MM-DDThh:mm';
22 | export const APP_WHOLE_NUMBER_FORMAT = '0,0';
23 | export const APP_TWO_DIGITS_AFTER_POINT_NUMBER_FORMAT = '0,0.[00]';
24 |
--------------------------------------------------------------------------------
/src/main/webapp/app/config/devtools.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createDevTools } from 'redux-devtools';
3 | import LogMonitor from 'redux-devtools-log-monitor';
4 | import DockMonitor from 'redux-devtools-dock-monitor';
5 | // You can toggle visibility of devTools with ctrl + H
6 | // and change their position with ctrl + Q
7 | export default createDevTools(
8 |
9 |
10 |
11 | );
12 |
--------------------------------------------------------------------------------
/src/main/webapp/app/config/error-middleware.ts:
--------------------------------------------------------------------------------
1 | import { isPromise } from 'react-jhipster';
2 |
3 | const getErrorMessage = errorData => {
4 | let message = errorData.message;
5 | if (errorData.fieldErrors) {
6 | errorData.fieldErrors.forEach(fErr => {
7 | message += `\nfield: ${fErr.field}, Object: ${fErr.objectName}, message: ${fErr.message}\n`;
8 | });
9 | }
10 | return message;
11 | };
12 |
13 | export default () => next => action => {
14 | // If not a promise, continue on
15 | if (!isPromise(action.payload)) {
16 | return next(action);
17 | }
18 |
19 | /**
20 | *
21 | * The error middleware serves to dispatch the initial pending promise to
22 | * the promise middleware, but adds a `catch`.
23 | * It need not run in production
24 | */
25 | if (process.env.NODE_ENV === 'development') {
26 | // Dispatch initial pending promise, but catch any errors
27 | return next(action).catch(error => {
28 | console.error(`${action.type} caught at middleware with reason: ${JSON.stringify(error.message)}.`);
29 | if (error && error.response && error.response.data) {
30 | const message = getErrorMessage(error.response.data);
31 | console.error(`Actual cause: ${message}`);
32 | }
33 |
34 | return Promise.reject(error);
35 | });
36 | }
37 | return next(action);
38 | };
39 |
--------------------------------------------------------------------------------
/src/main/webapp/app/config/logger-middleware.ts:
--------------------------------------------------------------------------------
1 | export default () => next => action => {
2 | if (process.env.NODE_ENV !== 'production') {
3 | const { type, payload, meta } = action;
4 |
5 | console.groupCollapsed(type);
6 | // tslint:disable-next-line
7 | console.log('Payload:', payload);
8 | // tslint:disable-next-line
9 | console.log('Meta:', meta);
10 | console.groupEnd();
11 | }
12 |
13 | return next(action);
14 | };
15 |
--------------------------------------------------------------------------------
/src/main/webapp/app/config/store.ts:
--------------------------------------------------------------------------------
1 | import { createStore, applyMiddleware, compose } from 'redux';
2 | import promiseMiddleware from 'redux-promise-middleware';
3 | import thunkMiddleware from 'redux-thunk';
4 | import reducer, { IRootState } from 'app/shared/reducers';
5 | import DevTools from './devtools';
6 | import errorMiddleware from './error-middleware';
7 | import notificationMiddleware from './notification-middleware';
8 | import loggerMiddleware from './logger-middleware';
9 | import { loadingBarMiddleware } from 'react-redux-loading-bar';
10 |
11 | const defaultMiddlewares = [
12 | thunkMiddleware,
13 | errorMiddleware,
14 | notificationMiddleware,
15 | promiseMiddleware(),
16 | loadingBarMiddleware(),
17 | loggerMiddleware
18 | ];
19 | const composedMiddlewares = middlewares =>
20 | process.env.NODE_ENV === 'development'
21 | ? compose(
22 | applyMiddleware(...defaultMiddlewares, ...middlewares),
23 | DevTools.instrument()
24 | )
25 | : compose(applyMiddleware(...defaultMiddlewares, ...middlewares));
26 |
27 | const initialize = (initialState?: IRootState, middlewares = []) => createStore(reducer, initialState, composedMiddlewares(middlewares));
28 |
29 | export default initialize;
30 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/blood-pressure/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Switch } from 'react-router-dom';
3 |
4 | import ErrorBoundaryRoute from 'app/shared/error/error-boundary-route';
5 |
6 | import BloodPressure from './blood-pressure';
7 | import BloodPressureDetail from './blood-pressure-detail';
8 | import BloodPressureUpdate from './blood-pressure-update';
9 | import BloodPressureDeleteDialog from './blood-pressure-delete-dialog';
10 |
11 | const Routes = ({ match }) => (
12 | <>
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | >
21 | );
22 |
23 | export default Routes;
24 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Switch } from 'react-router-dom';
3 |
4 | // tslint:disable-next-line:no-unused-variable
5 | import ErrorBoundaryRoute from 'app/shared/error/error-boundary-route';
6 |
7 | import Points from './points';
8 | import Weigth from './weigth';
9 | import BloodPressure from './blood-pressure';
10 | import Preferences from './preferences';
11 | /* jhipster-needle-add-route-import - JHipster will add routes here */
12 |
13 | const Routes = ({ match }) => (
14 |
15 |
16 | {/* prettier-ignore */}
17 |
18 |
19 |
20 |
21 | {/* jhipster-needle-add-route-path - JHipster will routes here */}
22 |
23 |
24 | );
25 |
26 | export default Routes;
27 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/points/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Switch } from 'react-router-dom';
3 |
4 | import ErrorBoundaryRoute from 'app/shared/error/error-boundary-route';
5 |
6 | import Points from './points';
7 | import PointsDetail from './points-detail';
8 | import PointsUpdate from './points-update';
9 | import PointsDeleteDialog from './points-delete-dialog';
10 |
11 | const Routes = ({ match }) => (
12 | <>
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | >
21 | );
22 |
23 | export default Routes;
24 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/points/point.scss:
--------------------------------------------------------------------------------
1 | .truncate {
2 | width: 180px;
3 | white-space: nowrap;
4 | overflow: hidden;
5 | text-overflow: ellipsis;
6 | cursor: pointer;
7 |
8 | &.cal-day-notes {
9 | width: 150px;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/points/points-home.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Link } from 'react-router-dom';
3 |
4 | import { Row, Col, Alert, Progress } from 'reactstrap';
5 | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
6 | import moment from 'moment';
7 |
8 | const pointsHome = props => (
9 |
10 |
11 |
12 | Points for the week of {moment(props.pointsThisWeek.week).format('ll')}
13 | Points for {moment(props.pointsThisWeek.week).format('ll')}
14 |
15 |
16 |
17 | Add Points
18 |
19 |
20 |
21 |
22 |
23 |
27 | { !props.pointsThisWeek.points && No points yet this week, better get moving!}
28 |
29 |
30 |
31 | );
32 |
33 | export default pointsHome;
34 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/preferences/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Switch } from 'react-router-dom';
3 |
4 | import ErrorBoundaryRoute from 'app/shared/error/error-boundary-route';
5 |
6 | import Preferences from './preferences';
7 | import PreferencesDetail from './preferences-detail';
8 | import PreferencesUpdate from './preferences-update';
9 | import PreferencesDeleteDialog from './preferences-delete-dialog';
10 |
11 | const Routes = ({ match }) => (
12 | <>
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | >
21 | );
22 |
23 | export default Routes;
24 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/weigth/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Switch } from 'react-router-dom';
3 |
4 | import ErrorBoundaryRoute from 'app/shared/error/error-boundary-route';
5 |
6 | import Weigth from './weigth';
7 | import WeigthDetail from './weigth-detail';
8 | import WeigthUpdate from './weigth-update';
9 | import WeigthDeleteDialog from './weigth-delete-dialog';
10 |
11 | const Routes = ({ match }) => (
12 | <>
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | >
21 | );
22 |
23 | export default Routes;
24 |
--------------------------------------------------------------------------------
/src/main/webapp/app/entities/weigth/weigth-home.tsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Link } from 'react-router-dom';
3 | import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, Area, AreaChart } from 'recharts';
4 |
5 | import { Row, Col, Alert, Progress } from 'reactstrap';
6 |
7 | import { IWeigthChart } from 'app/shared/model/weigth-chart';
8 |
9 | export interface IWeigthHomeProp {
10 | weigthChart: IWeigthChart;
11 | }
12 |
13 | class WeigthHome extends Component {
14 |
15 | render () {
16 |
17 | let graph = No blood pressure readings found. [TO DO: graph];
18 |
19 | if (this.props.weigthChart.data.length !== 0) {
20 | graph = (
21 |
22 |
24 |
25 |
28 |
29 |
30 |
33 |
34 | );
35 | }
36 |
37 | return (
38 |
39 |
40 |
41 | Weight:
42 |
43 |
44 |
45 | Add Weight
46 |
47 |
48 |
49 |
50 |
51 | {graph}
52 |
53 |
54 |
55 | );
56 | }
57 | }
58 |
59 | export default WeigthHome;
60 |
--------------------------------------------------------------------------------
/src/main/webapp/app/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import { Provider } from 'react-redux';
4 | import { bindActionCreators } from 'redux';
5 | import { AppContainer } from 'react-hot-loader';
6 |
7 | import DevTools from './config/devtools';
8 | import initStore from './config/store';
9 | import setupAxiosInterceptors from './config/axios-interceptor';
10 | import { clearAuthentication } from './shared/reducers/authentication';
11 | import ErrorBoundary from './shared/error/error-boundary';
12 | import AppComponent from './app';
13 | import { loadIcons } from './config/icon-loader';
14 |
15 | const devTools = process.env.NODE_ENV === 'development' ? : null;
16 |
17 | const store = initStore();
18 |
19 | const actions = bindActionCreators({ clearAuthentication }, store.dispatch);
20 | setupAxiosInterceptors(() => actions.clearAuthentication('login.error.unauthorized'));
21 |
22 | loadIcons();
23 |
24 | const rootEl = document.getElementById('root');
25 |
26 | const render = Component =>
27 | ReactDOM.render(
28 |
29 |
30 |
31 |
32 | {/* If this slows down the app in dev disable it and enable when required */}
33 | {devTools}
34 |
35 |
36 |
37 |
38 | ,
39 | rootEl
40 | );
41 |
42 | render(AppComponent);
43 |
44 | // This is quite unstable
45 | // if (module.hot) {
46 | // module.hot.accept('./app', () => {
47 | // const NextApp = require<{ default: typeof AppComponent }>('./app').default;
48 | // render(NextApp);
49 | // });
50 | // }
51 |
--------------------------------------------------------------------------------
/src/main/webapp/app/modules/about/about.scss:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robmelfi/21-points-react/a310a2762d7ddab3440588dbe3dcb22c338823ed/src/main/webapp/app/modules/about/about.scss
--------------------------------------------------------------------------------
/src/main/webapp/app/modules/account/activate/activate.reducer.ts:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 |
3 | import { REQUEST, SUCCESS, FAILURE } from 'app/shared/reducers/action-type.util';
4 |
5 | export const ACTION_TYPES = {
6 | ACTIVATE_ACCOUNT: 'activate/ACTIVATE_ACCOUNT',
7 | RESET: 'activate/RESET'
8 | };
9 |
10 | const initialState = {
11 | activationSuccess: false,
12 | activationFailure: false
13 | };
14 |
15 | export type ActivateState = Readonly;
16 |
17 | // Reducer
18 | export default (state: ActivateState = initialState, action): ActivateState => {
19 | switch (action.type) {
20 | case REQUEST(ACTION_TYPES.ACTIVATE_ACCOUNT):
21 | return {
22 | ...state
23 | };
24 | case FAILURE(ACTION_TYPES.ACTIVATE_ACCOUNT):
25 | return {
26 | ...state,
27 | activationFailure: true
28 | };
29 | case SUCCESS(ACTION_TYPES.ACTIVATE_ACCOUNT):
30 | return {
31 | ...state,
32 | activationSuccess: true
33 | };
34 | case ACTION_TYPES.RESET:
35 | return {
36 | ...initialState
37 | };
38 | default:
39 | return state;
40 | }
41 | };
42 |
43 | // Actions
44 | export const activateAction = key => ({
45 | type: ACTION_TYPES.ACTIVATE_ACCOUNT,
46 | payload: axios.get('api/activate?key=' + key)
47 | });
48 |
49 | export const reset = () => ({
50 | type: ACTION_TYPES.RESET
51 | });
52 |
--------------------------------------------------------------------------------
/src/main/webapp/app/modules/account/activate/activate.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { connect } from 'react-redux';
3 | import { Link, RouteComponentProps } from 'react-router-dom';
4 | import { Row, Col, Alert } from 'reactstrap';
5 | import { getUrlParameter } from 'react-jhipster';
6 |
7 | import { IRootState } from 'app/shared/reducers';
8 | import { activateAction, reset } from './activate.reducer';
9 |
10 | const successAlert = (
11 |
12 | Your user account has been activated. Please
13 |
14 | sign in
15 | .
16 |
17 | );
18 |
19 | const failureAlert = (
20 |
21 | Your user could not be activated. Please use the registration form to sign up.
22 |
23 | );
24 |
25 | export interface IActivateProps extends StateProps, DispatchProps, RouteComponentProps<{ key: any }> {}
26 |
27 | export class ActivatePage extends React.Component {
28 | componentWillUnmount() {
29 | this.props.reset();
30 | }
31 |
32 | componentDidMount() {
33 | const key = getUrlParameter('key', this.props.location.search);
34 | this.props.activateAction(key);
35 | }
36 |
37 | render() {
38 | const { activationSuccess, activationFailure } = this.props;
39 |
40 | return (
41 |
42 |
43 |
44 | Activation
45 | {activationSuccess ? successAlert : undefined}
46 | {activationFailure ? failureAlert : undefined}
47 |
48 |
49 |
50 | );
51 | }
52 | }
53 |
54 | const mapStateToProps = ({ activate }: IRootState) => ({
55 | activationSuccess: activate.activationSuccess,
56 | activationFailure: activate.activationFailure
57 | });
58 |
59 | const mapDispatchToProps = { activateAction, reset };
60 |
61 | type StateProps = ReturnType;
62 | type DispatchProps = typeof mapDispatchToProps;
63 |
64 | export default connect(
65 | mapStateToProps,
66 | mapDispatchToProps
67 | )(ActivatePage);
68 |
--------------------------------------------------------------------------------
/src/main/webapp/app/modules/account/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import ErrorBoundaryRoute from 'app/shared/error/error-boundary-route';
4 |
5 | import Settings from './settings/settings';
6 | import Password from './password/password';
7 |
8 | const Routes = ({ match }) => (
9 |
10 |
11 |
12 |
13 | );
14 |
15 | export default Routes;
16 |
--------------------------------------------------------------------------------
/src/main/webapp/app/modules/account/password-reset/init/password-reset-init.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import { connect } from 'react-redux';
4 | import { AvForm, AvField } from 'availity-reactstrap-validation';
5 | import { Button, Alert, Col, Row } from 'reactstrap';
6 |
7 | import { IRootState } from 'app/shared/reducers';
8 | import { handlePasswordResetInit, reset } from '../password-reset.reducer';
9 |
10 | export type IPasswordResetInitProps = DispatchProps;
11 |
12 | export class PasswordResetInit extends React.Component {
13 | componentWillUnmount() {
14 | this.props.reset();
15 | }
16 |
17 | handleValidSubmit = (event, values) => {
18 | this.props.handlePasswordResetInit(values.email);
19 | event.preventDefault();
20 | };
21 |
22 | render() {
23 | return (
24 |
25 |
26 |
27 | Reset your password
28 |
29 | Enter the email address you used to register
30 |
31 |
32 |
43 |
46 |
47 |
48 |
49 |
50 | );
51 | }
52 | }
53 |
54 | const mapDispatchToProps = { handlePasswordResetInit, reset };
55 |
56 | type DispatchProps = typeof mapDispatchToProps;
57 |
58 | export default connect(
59 | null,
60 | mapDispatchToProps
61 | )(PasswordResetInit);
62 |
--------------------------------------------------------------------------------
/src/main/webapp/app/modules/account/password/password.reducer.ts:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 |
3 | import { REQUEST, SUCCESS, FAILURE } from 'app/shared/reducers/action-type.util';
4 |
5 | export const ACTION_TYPES = {
6 | UPDATE_PASSWORD: 'account/UPDATE_PASSWORD',
7 | RESET: 'account/RESET'
8 | };
9 |
10 | const initialState = {
11 | loading: false,
12 | errorMessage: null,
13 | updateSuccess: false,
14 | updateFailure: false
15 | };
16 |
17 | export type PasswordState = Readonly;
18 |
19 | // Reducer
20 | export default (state: PasswordState = initialState, action): PasswordState => {
21 | switch (action.type) {
22 | case REQUEST(ACTION_TYPES.UPDATE_PASSWORD):
23 | return {
24 | ...initialState,
25 | errorMessage: null,
26 | updateSuccess: false,
27 | loading: true
28 | };
29 | case FAILURE(ACTION_TYPES.UPDATE_PASSWORD):
30 | return {
31 | ...initialState,
32 | loading: false,
33 | updateSuccess: false,
34 | updateFailure: true
35 | };
36 | case SUCCESS(ACTION_TYPES.UPDATE_PASSWORD):
37 | return {
38 | ...initialState,
39 | loading: false,
40 | updateSuccess: true,
41 | updateFailure: false
42 | };
43 | case ACTION_TYPES.RESET:
44 | return {
45 | ...initialState
46 | };
47 | default:
48 | return state;
49 | }
50 | };
51 |
52 | // Actions
53 | const apiUrl = 'api/account';
54 |
55 | export const savePassword = (currentPassword, newPassword) => ({
56 | type: ACTION_TYPES.UPDATE_PASSWORD,
57 | payload: axios.post(`${apiUrl}/change-password`, { currentPassword, newPassword }),
58 | meta: {
59 | successMessage: 'Password changed!',
60 | errorMessage: 'An error has occurred! The password could not be changed.'
61 | }
62 | });
63 |
64 | export const reset = () => ({
65 | type: ACTION_TYPES.RESET
66 | });
67 |
--------------------------------------------------------------------------------
/src/main/webapp/app/modules/account/register/register.reducer.ts:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 |
3 | import { REQUEST, SUCCESS, FAILURE } from 'app/shared/reducers/action-type.util';
4 |
5 | export const ACTION_TYPES = {
6 | CREATE_ACCOUNT: 'register/CREATE_ACCOUNT',
7 | RESET: 'register/RESET'
8 | };
9 |
10 | const initialState = {
11 | loading: false,
12 | registrationSuccess: false,
13 | registrationFailure: false,
14 | errorMessage: null
15 | };
16 |
17 | export type RegisterState = Readonly;
18 |
19 | // Reducer
20 | export default (state: RegisterState = initialState, action): RegisterState => {
21 | switch (action.type) {
22 | case REQUEST(ACTION_TYPES.CREATE_ACCOUNT):
23 | return {
24 | ...state,
25 | loading: true
26 | };
27 | case FAILURE(ACTION_TYPES.CREATE_ACCOUNT):
28 | return {
29 | ...initialState,
30 | registrationFailure: true,
31 | errorMessage: action.payload.response.data.errorKey
32 | };
33 | case SUCCESS(ACTION_TYPES.CREATE_ACCOUNT):
34 | return {
35 | ...initialState,
36 | registrationSuccess: true
37 | };
38 | case ACTION_TYPES.RESET:
39 | return {
40 | ...initialState
41 | };
42 | default:
43 | return state;
44 | }
45 | };
46 |
47 | // Actions
48 | export const handleRegister = (login, email, password, langKey = 'en') => ({
49 | type: ACTION_TYPES.CREATE_ACCOUNT,
50 | payload: axios.post('api/register', { login, email, password, langKey }),
51 | meta: {
52 | successMessage: 'Registration saved! Please check your email for confirmation.'
53 | }
54 | });
55 |
56 | export const reset = () => ({
57 | type: ACTION_TYPES.RESET
58 | });
59 |
--------------------------------------------------------------------------------
/src/main/webapp/app/modules/account/settings/settings.reducer.ts:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 |
3 | import { REQUEST, SUCCESS, FAILURE } from 'app/shared/reducers/action-type.util';
4 | import { getSession } from 'app/shared/reducers/authentication';
5 |
6 | export const ACTION_TYPES = {
7 | UPDATE_ACCOUNT: 'account/UPDATE_ACCOUNT',
8 | RESET: 'account/RESET'
9 | };
10 |
11 | const initialState = {
12 | loading: false,
13 | errorMessage: null,
14 | updateSuccess: false,
15 | updateFailure: false
16 | };
17 |
18 | export type SettingsState = Readonly;
19 |
20 | // Reducer
21 | export default (state: SettingsState = initialState, action): SettingsState => {
22 | switch (action.type) {
23 | case REQUEST(ACTION_TYPES.UPDATE_ACCOUNT):
24 | return {
25 | ...state,
26 | errorMessage: null,
27 | updateSuccess: false,
28 | loading: true
29 | };
30 | case FAILURE(ACTION_TYPES.UPDATE_ACCOUNT):
31 | return {
32 | ...state,
33 | loading: false,
34 | updateSuccess: false,
35 | updateFailure: true
36 | };
37 | case SUCCESS(ACTION_TYPES.UPDATE_ACCOUNT):
38 | return {
39 | ...state,
40 | loading: false,
41 | updateSuccess: true,
42 | updateFailure: false
43 | };
44 | case ACTION_TYPES.RESET:
45 | return {
46 | ...initialState
47 | };
48 | default:
49 | return state;
50 | }
51 | };
52 |
53 | // Actions
54 | const apiUrl = 'api/account';
55 |
56 | export const saveAccountSettings = account => async dispatch => {
57 | await dispatch({
58 | type: ACTION_TYPES.UPDATE_ACCOUNT,
59 | payload: axios.post(apiUrl, account),
60 | meta: {
61 | successMessage: 'Settings saved!'
62 | }
63 | });
64 | dispatch(getSession());
65 | };
66 |
67 | export const reset = () => ({
68 | type: ACTION_TYPES.RESET
69 | });
70 |
--------------------------------------------------------------------------------
/src/main/webapp/app/modules/administration/docs/docs.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const DocsPage = () => (
4 |
5 |
6 |
7 | );
8 |
9 | export default DocsPage;
10 |
--------------------------------------------------------------------------------
/src/main/webapp/app/modules/administration/health/health-modal.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Table, Modal, ModalHeader, ModalBody, ModalFooter, Button } from 'reactstrap';
3 |
4 | const formatDiskSpaceOutput = rawValue => {
5 | // Should display storage space in an human readable unit
6 | const val = rawValue / 1073741824;
7 | if (val > 1) {
8 | // Value
9 | return val.toFixed(2) + ' GB';
10 | } else {
11 | return (rawValue / 1048576).toFixed(2) + ' MB';
12 | }
13 | };
14 |
15 | const HealthModal = ({ handleClose, healthObject, showModal }) => {
16 | const data = healthObject.details || {};
17 | return (
18 |
19 | {healthObject.name}
20 |
21 |
22 |
23 |
24 | Name |
25 | Value |
26 |
27 |
28 |
29 | {Object.keys(data).map((key, index) => (
30 |
31 | {key} |
32 | {healthObject.name === 'diskSpace' ? formatDiskSpaceOutput(data[key]) : JSON.stringify(data[key])} |
33 |
34 | ))}
35 |
36 |
37 |
38 |
39 |
42 |
43 |
44 | );
45 | };
46 |
47 | export default HealthModal;
48 |
--------------------------------------------------------------------------------
/src/main/webapp/app/modules/administration/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import ErrorBoundaryRoute from 'app/shared/error/error-boundary-route';
4 | import UserManagement from './user-management';
5 | import Logs from './logs/logs';
6 | import Health from './health/health';
7 | import Metrics from './metrics/metrics';
8 | import Configuration from './configuration/configuration';
9 | import Audits from './audits/audits';
10 | import Docs from './docs/docs';
11 |
12 | const Routes = ({ match }) => (
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | );
23 |
24 | export default Routes;
25 |
--------------------------------------------------------------------------------
/src/main/webapp/app/modules/administration/metrics/thread-item.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Collapse, Card, CardBody, Row } from 'reactstrap';
3 |
4 | export interface IThreadItemProps {
5 | threadDumpInfo: any;
6 | }
7 |
8 | export interface IThreadItemState {
9 | collapse: boolean;
10 | }
11 |
12 | export class ThreadItem extends React.Component {
13 | state: IThreadItemState = {
14 | collapse: false
15 | };
16 |
17 | toggleStackTrace = () => {
18 | this.setState({
19 | collapse: !this.state.collapse
20 | });
21 | };
22 |
23 | render() {
24 | const { threadDumpInfo } = this.props;
25 |
26 | return (
27 |
49 | );
50 | }
51 | }
52 |
53 | export default ThreadItem;
54 |
--------------------------------------------------------------------------------
/src/main/webapp/app/modules/administration/user-management/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Switch } from 'react-router-dom';
3 |
4 | import ErrorBoundaryRoute from 'app/shared/error/error-boundary-route';
5 | import UserManagement from './user-management';
6 | import UserManagementDetail from './user-management-detail';
7 | import UserManagementUpdate from './user-management-update';
8 | import UserManagementDeleteDialog from './user-management-delete-dialog';
9 |
10 | const Routes = ({ match }) => (
11 | <>
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | >
20 | );
21 |
22 | export default Routes;
23 |
--------------------------------------------------------------------------------
/src/main/webapp/app/modules/administration/user-management/user-management-delete-dialog.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { connect } from 'react-redux';
3 | import { RouteComponentProps } from 'react-router-dom';
4 | import { Modal, ModalHeader, ModalBody, ModalFooter, Button } from 'reactstrap';
5 | import { ICrudGetAction, ICrudDeleteAction } from 'react-jhipster';
6 | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
7 |
8 | import { IUser } from 'app/shared/model/user.model';
9 | import { getUser, deleteUser } from './user-management.reducer';
10 | import { IRootState } from 'app/shared/reducers';
11 |
12 | export interface IUserManagementDeleteDialogProps extends StateProps, DispatchProps, RouteComponentProps<{ login: string }> {}
13 |
14 | export class UserManagementDeleteDialog extends React.Component {
15 | componentDidMount() {
16 | this.props.getUser(this.props.match.params.login);
17 | }
18 |
19 | confirmDelete = event => {
20 | this.props.deleteUser(this.props.user.login);
21 | this.handleClose(event);
22 | };
23 |
24 | handleClose = event => {
25 | event.stopPropagation();
26 | this.props.history.goBack();
27 | };
28 |
29 | render() {
30 | const { user } = this.props;
31 | return (
32 |
33 | Confirm delete operation
34 | Are you sure you want to delete this User?
35 |
36 |
39 |
42 |
43 |
44 | );
45 | }
46 | }
47 |
48 | const mapStateToProps = (storeState: IRootState) => ({
49 | user: storeState.userManagement.user
50 | });
51 |
52 | const mapDispatchToProps = { getUser, deleteUser };
53 |
54 | type StateProps = ReturnType;
55 | type DispatchProps = typeof mapDispatchToProps;
56 |
57 | export default connect(
58 | mapStateToProps,
59 | mapDispatchToProps
60 | )(UserManagementDeleteDialog);
61 |
--------------------------------------------------------------------------------
/src/main/webapp/app/modules/history/CustomToolbar.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robmelfi/21-points-react/a310a2762d7ddab3440588dbe3dcb22c338823ed/src/main/webapp/app/modules/history/CustomToolbar.js
--------------------------------------------------------------------------------
/src/main/webapp/app/modules/history/history.scss:
--------------------------------------------------------------------------------
1 | .calendar {
2 | height: 700px;
3 | width: 100%;
4 | }
5 |
6 | .event {
7 | background-color: #008000;
8 | border: none;
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/webapp/app/modules/home/home.scss:
--------------------------------------------------------------------------------
1 | /* ==========================================================================
2 | Main page styles
3 | ========================================================================== */
4 | .hipster {
5 | display: inline-block;
6 | width: 100%;
7 | height: 497px;
8 | background: url('../../../static/images/logo-jhipster-react.svg') no-repeat center top;
9 | background-size: contain;
10 | }
11 |
12 | .heart {
13 | display: inline-block;
14 | width: 347px;
15 | height: 347px !important;
16 | background: url('../../../static/images/21-points-logo.png') no-repeat center top;
17 | background-size: contain;
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/webapp/app/modules/login/login.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { connect } from 'react-redux';
3 | import { Redirect, RouteComponentProps } from 'react-router-dom';
4 |
5 | import { IRootState } from 'app/shared/reducers';
6 | import { login } from 'app/shared/reducers/authentication';
7 | import LoginModal from './login-modal';
8 |
9 | export interface ILoginProps extends StateProps, DispatchProps, RouteComponentProps<{}> {}
10 |
11 | export interface ILoginState {
12 | showModal: boolean;
13 | }
14 |
15 | export class Login extends React.Component {
16 | state: ILoginState = {
17 | showModal: this.props.showModal
18 | };
19 |
20 | componentDidUpdate(prevProps: ILoginProps, prevState) {
21 | if (this.props !== prevProps) {
22 | this.setState({ showModal: this.props.showModal });
23 | }
24 | }
25 |
26 | handleLogin = (username, password, rememberMe = false) => {
27 | this.props.login(username, password, rememberMe);
28 | };
29 |
30 | handleClose = () => {
31 | this.setState({ showModal: false });
32 | };
33 |
34 | render() {
35 | const { location, isAuthenticated } = this.props;
36 | const { from } = location.state || { from: { pathname: '/', search: location.search } };
37 | const { showModal } = this.state;
38 | if (isAuthenticated) {
39 | return ;
40 | }
41 | return (
42 |
43 | );
44 | }
45 | }
46 |
47 | const mapStateToProps = ({ authentication }: IRootState) => ({
48 | isAuthenticated: authentication.isAuthenticated,
49 | loginError: authentication.loginError,
50 | showModal: authentication.showModalLogin
51 | });
52 |
53 | const mapDispatchToProps = { login };
54 |
55 | type StateProps = ReturnType;
56 | type DispatchProps = typeof mapDispatchToProps;
57 |
58 | export default connect(
59 | mapStateToProps,
60 | mapDispatchToProps
61 | )(Login);
62 |
--------------------------------------------------------------------------------
/src/main/webapp/app/modules/login/logout.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { connect } from 'react-redux';
3 | import { Redirect } from 'react-router-dom';
4 |
5 | import { IRootState } from 'app/shared/reducers';
6 | import { logout } from 'app/shared/reducers/authentication';
7 |
8 | export interface ILogoutProps extends StateProps, DispatchProps {}
9 |
10 | export class Logout extends React.Component {
11 | componentDidMount() {
12 | this.props.logout();
13 | }
14 |
15 | render() {
16 | return (
17 |
18 |
Logged out successfully!
19 |
24 |
25 | );
26 | }
27 | }
28 |
29 | const mapStateToProps = (storeState: IRootState) => ({});
30 |
31 | const mapDispatchToProps = { logout };
32 |
33 | type StateProps = ReturnType;
34 | type DispatchProps = typeof mapDispatchToProps;
35 |
36 | export default connect(
37 | mapStateToProps,
38 | mapDispatchToProps
39 | )(Logout);
40 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/error/error-boundary-route.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Route, RouteProps } from 'react-router-dom';
3 | import ErrorBoundary from 'app/shared/error/error-boundary';
4 |
5 | export const ErrorBoundaryRoute = ({ component: Component, ...rest }: RouteProps) => {
6 | const encloseInErrorBoundary = props => (
7 |
8 |
9 |
10 | );
11 |
12 | if (!Component) throw new Error(`A component needs to be specified for path ${(rest as any).path}`);
13 |
14 | return ;
15 | };
16 |
17 | export default ErrorBoundaryRoute;
18 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/error/error-boundary.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | interface IErrorBoundaryProps {
4 | readonly children: JSX.Element | JSX.Element[];
5 | }
6 |
7 | interface IErrorBoundaryState {
8 | readonly error: any;
9 | readonly errorInfo: any;
10 | }
11 |
12 | class ErrorBoundary extends React.Component {
13 | readonly state: IErrorBoundaryState = { error: undefined, errorInfo: undefined };
14 |
15 | componentDidCatch(error, errorInfo) {
16 | this.setState({
17 | error,
18 | errorInfo
19 | });
20 | }
21 |
22 | render() {
23 | const { error, errorInfo } = this.state;
24 | if (errorInfo) {
25 | const errorDetails =
26 | process.env.NODE_ENV === 'development' ? (
27 |
28 | {error && error.toString()}
29 |
30 | {errorInfo.componentStack}
31 |
32 | ) : (
33 | undefined
34 | );
35 | return (
36 |
37 |
An unexpected error has occurred.
38 | {errorDetails}
39 |
40 | );
41 | }
42 | return this.props.children;
43 | }
44 | }
45 |
46 | export default ErrorBoundary;
47 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/layout/footer/footer.scss:
--------------------------------------------------------------------------------
1 | .footer {
2 | bottom: 0;
3 | left: 0;
4 | color: #666;
5 | background: #eee;
6 | border-top: 1px solid silver;
7 | position: fixed;
8 | width: 100%;
9 | padding: 10px;
10 | padding-bottom: 0;
11 | text-align: center;
12 | z-index: 2;
13 | font-size: 0.9em;
14 |
15 | p {
16 | margin-bottom: 7px;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/layout/footer/footer.tsx:
--------------------------------------------------------------------------------
1 | import './footer.scss';
2 |
3 | import React from 'react';
4 |
5 | import { Col, Row } from 'reactstrap';
6 |
7 | const Footer = props => (
8 |
19 | );
20 |
21 | export default Footer;
22 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/layout/header/header-components.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import { UncontrolledDropdown, DropdownToggle, DropdownMenu, NavItem, NavLink, NavbarBrand } from 'reactstrap';
4 | import { NavLink as Link } from 'react-router-dom';
5 |
6 | import { library } from '@fortawesome/fontawesome-svg-core';
7 | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
8 | import { faStar, faCalendarAlt } from '@fortawesome/free-solid-svg-icons';
9 |
10 | library.add(faStar);
11 |
12 | import appConfig from 'app/config/constants';
13 |
14 | export const NavDropdown = props => (
15 |
16 |
17 |
18 | {props.name}
19 |
20 |
21 | {props.children}
22 |
23 |
24 | );
25 |
26 | export const BrandIcon = props => (
27 |
28 |

29 |
30 | );
31 |
32 | export const Brand = props => (
33 |
34 |
35 | 21-Points Health
36 | v{appConfig.VERSION}
37 |
38 | );
39 |
40 | export const Home = props => (
41 |
42 |
43 |
44 | Home
45 |
46 |
47 | );
48 |
49 | export const About = props => (
50 |
51 |
52 |
53 | About
54 |
55 |
56 | );
57 |
58 | export const History = props => (
59 |
60 |
61 |
62 | History
63 |
64 |
65 | );
66 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/layout/header/menus/account.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { DropdownItem } from 'reactstrap';
3 | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
4 | import { NavLink as Link } from 'react-router-dom';
5 |
6 | import { NavDropdown } from '../header-components';
7 |
8 | const accountMenuItemsAuthenticated = (
9 | <>
10 |
11 | Settings
12 |
13 |
14 | Password
15 |
16 |
17 | Sign out
18 |
19 | >
20 | );
21 |
22 | const accountMenuItems = (
23 | <>
24 |
25 | Sign in
26 |
27 |
28 | Register
29 |
30 | >
31 | );
32 |
33 | export const AccountMenu = ({ isAuthenticated = false }) => (
34 |
37 | );
38 |
39 | export default AccountMenu;
40 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/layout/header/menus/admin.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { DropdownItem } from 'reactstrap';
3 | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
4 | import { NavLink as Link } from 'react-router-dom';
5 | import { NavDropdown } from '../header-components';
6 |
7 | const adminMenuItems = (
8 | <>
9 |
10 | User management
11 |
12 |
13 | Metrics
14 |
15 |
16 | Health
17 |
18 |
19 | Configuration
20 |
21 |
22 | Audits
23 |
24 | {/* jhipster-needle-add-element-to-admin-menu - JHipster will add entities to the admin menu here */}
25 |
26 | Logs
27 |
28 | >
29 | );
30 |
31 | const swaggerItem = (
32 |
33 | API
34 |
35 | );
36 |
37 | const databaseItem = (
38 |
39 | Database
40 |
41 | );
42 |
43 | export const AdminMenu = ({ showSwagger, showDatabase }) => (
44 |
50 | );
51 |
52 | export default AdminMenu;
53 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/layout/header/menus/entities.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { DropdownItem } from 'reactstrap';
3 | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
4 |
5 | import { NavLink as Link } from 'react-router-dom';
6 | import { NavDropdown } from '../header-components';
7 |
8 | export const EntitiesMenu = props => (
9 | // tslint:disable-next-line:jsx-self-close
10 |
25 | );
26 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/layout/header/menus/index.ts:
--------------------------------------------------------------------------------
1 | export * from './account';
2 | export * from './admin';
3 | export * from './entities';
4 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/layout/password/password-strength-bar.scss:
--------------------------------------------------------------------------------
1 | /* ==========================================================================
2 | start Password strength bar style
3 | ========================================================================== */
4 | ul#strength {
5 | display: inline;
6 | list-style: none;
7 | margin: 0;
8 | margin-left: 15px;
9 | padding: 0;
10 | vertical-align: 2px;
11 | }
12 |
13 | .point {
14 | background: #ddd;
15 | border-radius: 2px;
16 | display: inline-block;
17 | height: 5px;
18 | margin-right: 1px;
19 | width: 20px;
20 | &:last-child {
21 | margin: 0 !important;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/layout/password/password-strength-bar.tsx:
--------------------------------------------------------------------------------
1 | import './password-strength-bar.scss';
2 |
3 | import React from 'react';
4 |
5 | export interface IPasswordStrengthBarProps {
6 | password: string;
7 | }
8 |
9 | export const PasswordStrengthBar = ({ password }: IPasswordStrengthBarProps) => {
10 | const colors = ['#F00', '#F90', '#FF0', '#9F0', '#0F0'];
11 |
12 | const measureStrength = (p: string): number => {
13 | let force = 0;
14 | const regex = /[$-/:-?{-~!"^_`\[\]]/g;
15 | const flags = {
16 | lowerLetters: /[a-z]+/.test(p),
17 | upperLetters: /[A-Z]+/.test(p),
18 | numbers: /[0-9]+/.test(p),
19 | symbols: regex.test(p)
20 | };
21 |
22 | const passedMatches = Object.values(flags).filter((isMatchedFlag: boolean) => !!isMatchedFlag).length;
23 |
24 | force += 2 * p.length + (p.length >= 10 ? 1 : 0);
25 | force += passedMatches * 10;
26 |
27 | // penality (short password)
28 | force = p.length <= 6 ? Math.min(force, 10) : force;
29 |
30 | // penality (poor variety of characters)
31 | force = passedMatches === 1 ? Math.min(force, 10) : force;
32 | force = passedMatches === 2 ? Math.min(force, 20) : force;
33 | force = passedMatches === 3 ? Math.min(force, 40) : force;
34 |
35 | return force;
36 | };
37 |
38 | const getColor = (s: number): any => {
39 | let idx = 0;
40 | if (s <= 10) {
41 | idx = 0;
42 | } else if (s <= 20) {
43 | idx = 1;
44 | } else if (s <= 30) {
45 | idx = 2;
46 | } else if (s <= 40) {
47 | idx = 3;
48 | } else {
49 | idx = 4;
50 | }
51 | return { idx: idx + 1, col: colors[idx] };
52 | };
53 |
54 | const getPoints = force => {
55 | const pts = [];
56 | for (let i = 0; i < 5; i++) {
57 | pts.push();
58 | }
59 | return pts;
60 | };
61 |
62 | const strength = getColor(measureStrength(password));
63 | const points = getPoints(strength);
64 |
65 | return (
66 |
67 |
Password strength:
68 |
69 |
70 | );
71 | };
72 |
73 | export default PasswordStrengthBar;
74 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/model/blood-pressure-chart.tsx:
--------------------------------------------------------------------------------
1 |
2 | export interface IBloodPressureChart {
3 | title?: string;
4 | yAxis?: {
5 | label?: string
6 | };
7 | data?: Array<{ timestamp: string, d: number, s: number }>;
8 | interval?: number;
9 | }
10 |
11 | export const defaultValue = {
12 | title: '',
13 | yAxis: {
14 | label: ''
15 | },
16 | data: [],
17 | interval: 0
18 | };
19 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/model/blood-pressure.model.ts:
--------------------------------------------------------------------------------
1 | import { Moment } from 'moment';
2 |
3 | export interface IBloodPressure {
4 | id?: number;
5 | timestamp?: Moment;
6 | systolic?: number;
7 | diastolic?: number;
8 | userLogin?: string;
9 | userId?: number;
10 | }
11 |
12 | export const defaultValue: Readonly = {};
13 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/model/points-this-week.model.ts:
--------------------------------------------------------------------------------
1 | import { Moment } from 'moment';
2 |
3 | export interface IPointsThisWeek {
4 | week?: Moment;
5 | points?: number;
6 | }
7 |
8 | export const defaultValue: Readonly = {};
9 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/model/points.model.ts:
--------------------------------------------------------------------------------
1 | import { Moment } from 'moment';
2 |
3 | export interface IPoints {
4 | id?: number;
5 | date?: Moment;
6 | excercise?: number;
7 | meals?: number;
8 | alcohol?: number;
9 | notes?: string;
10 | userLogin?: string;
11 | userId?: number;
12 | }
13 |
14 | export const defaultValue: Readonly = {};
15 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/model/preferences.model.ts:
--------------------------------------------------------------------------------
1 | export const enum Units {
2 | KG = 'KG',
3 | LB = 'LB'
4 | }
5 |
6 | export interface IPreferences {
7 | id?: number;
8 | weeklyGoal?: number;
9 | weightUnits?: Units;
10 | userLogin?: string;
11 | userId?: number;
12 | }
13 |
14 | export const defaultValue: Readonly = {};
15 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/model/user.model.ts:
--------------------------------------------------------------------------------
1 | export interface IUser {
2 | id?: any;
3 | login?: string;
4 | firstName?: string;
5 | lastName?: string;
6 | email?: string;
7 | activated?: boolean;
8 | langKey?: string;
9 | authorities?: any[];
10 | createdBy?: string;
11 | createdDate?: Date;
12 | lastModifiedBy?: string;
13 | lastModifiedDate?: Date;
14 | password?: string;
15 | }
16 |
17 | export const defaultValue: Readonly = {
18 | id: null,
19 | login: null,
20 | firstName: null,
21 | lastName: null,
22 | email: null,
23 | activated: false,
24 | langKey: null,
25 | authorities: null,
26 | createdBy: null,
27 | createdDate: null,
28 | lastModifiedBy: null,
29 | lastModifiedDate: null,
30 | password: null
31 | };
32 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/model/weigth-chart.tsx:
--------------------------------------------------------------------------------
1 |
2 | export interface IWeigthChart {
3 | title?: string;
4 | yAxis?: {
5 | label?: string
6 | };
7 | data?: Array<{ timestamp: string, w: number }>;
8 | interval?: number;
9 | }
10 |
11 | export const defaultValue = {
12 | title: '',
13 | yAxis: {
14 | label: ''
15 | },
16 | data: [],
17 | interval: 0
18 | };
19 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/model/weigth.model.ts:
--------------------------------------------------------------------------------
1 | import { Moment } from 'moment';
2 |
3 | export interface IWeigth {
4 | id?: number;
5 | timestamp?: Moment;
6 | weight?: number;
7 | userLogin?: string;
8 | userId?: number;
9 | }
10 |
11 | export const defaultValue: Readonly = {};
12 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/reducers/action-type.util.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Appends REQUEST asyc action type
3 | */
4 |
5 | export const REQUEST = actionType => `${actionType}_PENDING`;
6 |
7 | /**
8 | * Appends SUCCESS asyc action type
9 | */
10 |
11 | export const SUCCESS = actionType => `${actionType}_FULFILLED`;
12 |
13 | /**
14 | * Appends FAILURE asyc action type
15 | */
16 |
17 | export const FAILURE = actionType => `${actionType}_REJECTED`;
18 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/reducers/application-profile.ts:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 |
3 | import { SUCCESS } from 'app/shared/reducers/action-type.util';
4 |
5 | export const ACTION_TYPES = {
6 | GET_PROFILE: 'applicationProfile/GET_PROFILE'
7 | };
8 |
9 | const initialState = {
10 | ribbonEnv: '',
11 | inProduction: true,
12 | isSwaggerEnabled: false
13 | };
14 |
15 | export type ApplicationProfileState = Readonly;
16 |
17 | export default (state: ApplicationProfileState = initialState, action): ApplicationProfileState => {
18 | switch (action.type) {
19 | case SUCCESS(ACTION_TYPES.GET_PROFILE):
20 | const { data } = action.payload;
21 | return {
22 | ...state,
23 | ribbonEnv: data['display-ribbon-on-profiles'],
24 | inProduction: data.activeProfiles.includes('prod'),
25 | isSwaggerEnabled: data.activeProfiles.includes('swagger')
26 | };
27 | default:
28 | return state;
29 | }
30 | };
31 |
32 | export const getProfile = () => ({
33 | type: ACTION_TYPES.GET_PROFILE,
34 | payload: axios.get('management/info')
35 | });
36 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/util/date-utils.ts:
--------------------------------------------------------------------------------
1 | import moment from 'moment';
2 |
3 | import { APP_LOCAL_DATETIME_FORMAT } from 'app/config/constants';
4 |
5 | export const convertDateTimeFromServer = date => (date ? moment(date).format(APP_LOCAL_DATETIME_FORMAT) : null);
6 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/util/entity-utils.ts:
--------------------------------------------------------------------------------
1 | import pick from 'lodash/pick';
2 |
3 | /**
4 | * Removes fields with an 'id' field that equals ''.
5 | * This function was created to prevent entities to be sent to
6 | * the server with relationship fields with empty an empty id and thus
7 | * resulting in a 500.
8 | *
9 | * @param entity Object to clean.
10 | */
11 | export const cleanEntity = entity => {
12 | const keysToKeep = Object.keys(entity).filter(k => !(entity[k] instanceof Object) || (entity[k]['id'] !== '' && entity[k]['id'] !== -1));
13 |
14 | return pick(entity, keysToKeep);
15 | };
16 |
17 | /**
18 | * Simply map a list of element to a list a object with the element as id.
19 | *
20 | * @param idList Elements to map.
21 | * @returns The list of objects with mapped ids.
22 | */
23 | export const mapIdList = (idList: ReadonlyArray) =>
24 | idList.filter((entityId: any) => entityId !== '').map((entityId: any) => ({ id: entityId }));
25 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/util/pagination.constants.ts:
--------------------------------------------------------------------------------
1 | export const ITEMS_PER_PAGE = 20;
2 |
--------------------------------------------------------------------------------
/src/main/webapp/app/shared/util/url-utils.ts:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robmelfi/21-points-react/a310a2762d7ddab3440588dbe3dcb22c338823ed/src/main/webapp/app/shared/util/url-utils.ts
--------------------------------------------------------------------------------
/src/main/webapp/app/typings.d.ts:
--------------------------------------------------------------------------------
1 | declare module '*.json' {
2 | const value: any;
3 | export default value;
4 | }
5 |
--------------------------------------------------------------------------------
/src/main/webapp/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robmelfi/21-points-react/a310a2762d7ddab3440588dbe3dcb22c338823ed/src/main/webapp/favicon.ico
--------------------------------------------------------------------------------
/src/main/webapp/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 21 Points Health - React
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
20 |
21 |
24 |
34 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/src/main/webapp/manifest.webapp:
--------------------------------------------------------------------------------
1 | {
2 | "name": "TwentyOnePointsReact",
3 | "short_name": "TwentyOnePointsReact",
4 | "icons": [
5 | {
6 | "src": "./content/images/hipster192.png",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | },
10 | {
11 | "src": "./content/images/hipster256.png",
12 | "sizes": "256x256",
13 | "type": "image/png"
14 | },
15 | {
16 | "src": "./content/images/hipster384.png",
17 | "sizes": "384x384",
18 | "type": "image/png"
19 | },
20 | {
21 | "src": "./content/images/hipster512.png",
22 | "sizes": "512x512",
23 | "type": "image/png"
24 | }
25 | ],
26 | "theme_color": "#000000",
27 | "background_color": "#e0e0e0",
28 | "start_url": "/index.html",
29 | "display": "standalone",
30 | "orientation": "portrait"
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/webapp/robots.txt:
--------------------------------------------------------------------------------
1 | # robotstxt.org/
2 |
3 | User-agent: *
4 | Disallow: /api/account
5 | Disallow: /api/account/change-password
6 | Disallow: /api/account/sessions
7 | Disallow: /api/audits/
8 | Disallow: /api/logs/
9 | Disallow: /api/users/
10 | Disallow: /management/
11 | Disallow: /v2/api-docs/
12 |
--------------------------------------------------------------------------------
/src/main/webapp/static/images/21-points-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robmelfi/21-points-react/a310a2762d7ddab3440588dbe3dcb22c338823ed/src/main/webapp/static/images/21-points-logo.png
--------------------------------------------------------------------------------
/src/main/webapp/static/images/hipster.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robmelfi/21-points-react/a310a2762d7ddab3440588dbe3dcb22c338823ed/src/main/webapp/static/images/hipster.png
--------------------------------------------------------------------------------
/src/main/webapp/static/images/hipster192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robmelfi/21-points-react/a310a2762d7ddab3440588dbe3dcb22c338823ed/src/main/webapp/static/images/hipster192.png
--------------------------------------------------------------------------------
/src/main/webapp/static/images/hipster256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robmelfi/21-points-react/a310a2762d7ddab3440588dbe3dcb22c338823ed/src/main/webapp/static/images/hipster256.png
--------------------------------------------------------------------------------
/src/main/webapp/static/images/hipster2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robmelfi/21-points-react/a310a2762d7ddab3440588dbe3dcb22c338823ed/src/main/webapp/static/images/hipster2x.png
--------------------------------------------------------------------------------
/src/main/webapp/static/images/hipster384.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robmelfi/21-points-react/a310a2762d7ddab3440588dbe3dcb22c338823ed/src/main/webapp/static/images/hipster384.png
--------------------------------------------------------------------------------
/src/main/webapp/static/images/hipster512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robmelfi/21-points-react/a310a2762d7ddab3440588dbe3dcb22c338823ed/src/main/webapp/static/images/hipster512.png
--------------------------------------------------------------------------------
/src/main/webapp/static/images/logo-21-points.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robmelfi/21-points-react/a310a2762d7ddab3440588dbe3dcb22c338823ed/src/main/webapp/static/images/logo-21-points.png
--------------------------------------------------------------------------------
/src/main/webapp/static/images/logo-jhipster.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robmelfi/21-points-react/a310a2762d7ddab3440588dbe3dcb22c338823ed/src/main/webapp/static/images/logo-jhipster.png
--------------------------------------------------------------------------------
/src/main/webapp/swagger-ui/dist/images/throbber.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robmelfi/21-points-react/a310a2762d7ddab3440588dbe3dcb22c338823ed/src/main/webapp/swagger-ui/dist/images/throbber.gif
--------------------------------------------------------------------------------
/src/test/java/com/robmelfi/health/config/WebConfigurerTestController.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.config;
2 |
3 | import org.springframework.web.bind.annotation.GetMapping;
4 | import org.springframework.web.bind.annotation.RestController;
5 |
6 | @RestController
7 | public class WebConfigurerTestController {
8 |
9 | @GetMapping("/api/test-cors")
10 | public void testCorsOnApiPath() {
11 | }
12 |
13 | @GetMapping("/test/test-cors")
14 | public void testCorsOnOtherPath() {
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/test/java/com/robmelfi/health/repository/search/BloodPressureSearchRepositoryMockConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.repository.search;
2 |
3 | import org.springframework.boot.test.mock.mockito.MockBean;
4 | import org.springframework.context.annotation.Configuration;
5 |
6 | /**
7 | * Configure a Mock version of BloodPressureSearchRepository to test the
8 | * application without starting Elasticsearch.
9 | */
10 | @Configuration
11 | public class BloodPressureSearchRepositoryMockConfiguration {
12 |
13 | @MockBean
14 | private BloodPressureSearchRepository mockBloodPressureSearchRepository;
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/test/java/com/robmelfi/health/repository/search/PointsSearchRepositoryMockConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.repository.search;
2 |
3 | import org.springframework.boot.test.mock.mockito.MockBean;
4 | import org.springframework.context.annotation.Configuration;
5 |
6 | /**
7 | * Configure a Mock version of PointsSearchRepository to test the
8 | * application without starting Elasticsearch.
9 | */
10 | @Configuration
11 | public class PointsSearchRepositoryMockConfiguration {
12 |
13 | @MockBean
14 | private PointsSearchRepository mockPointsSearchRepository;
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/test/java/com/robmelfi/health/repository/search/PreferencesSearchRepositoryMockConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.repository.search;
2 |
3 | import org.springframework.boot.test.mock.mockito.MockBean;
4 | import org.springframework.context.annotation.Configuration;
5 |
6 | /**
7 | * Configure a Mock version of PreferencesSearchRepository to test the
8 | * application without starting Elasticsearch.
9 | */
10 | @Configuration
11 | public class PreferencesSearchRepositoryMockConfiguration {
12 |
13 | @MockBean
14 | private PreferencesSearchRepository mockPreferencesSearchRepository;
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/test/java/com/robmelfi/health/repository/search/UserSearchRepositoryMockConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.repository.search;
2 |
3 | import org.springframework.boot.test.mock.mockito.MockBean;
4 | import org.springframework.context.annotation.Configuration;
5 |
6 | /**
7 | * Configure a Mock version of UserSearchRepository to test the
8 | * application without starting Elasticsearch.
9 | */
10 | @Configuration
11 | public class UserSearchRepositoryMockConfiguration {
12 |
13 | @MockBean
14 | private UserSearchRepository mockUserSearchRepository;
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/test/java/com/robmelfi/health/repository/search/WeigthSearchRepositoryMockConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.robmelfi.health.repository.search;
2 |
3 | import org.springframework.boot.test.mock.mockito.MockBean;
4 | import org.springframework.context.annotation.Configuration;
5 |
6 | /**
7 | * Configure a Mock version of WeigthSearchRepository to test the
8 | * application without starting Elasticsearch.
9 | */
10 | @Configuration
11 | public class WeigthSearchRepositoryMockConfiguration {
12 |
13 | @MockBean
14 | private WeigthSearchRepository mockWeigthSearchRepository;
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/test/javascript/e2e/entities/blood-pressure/blood-pressure-update.page-object.ts:
--------------------------------------------------------------------------------
1 | import { element, by, ElementFinder } from 'protractor';
2 |
3 | export default class BloodPressureUpdatePage {
4 | pageTitle: ElementFinder = element(by.id('twentyOnePointsReactApp.bloodPressure.home.createOrEditLabel'));
5 | saveButton: ElementFinder = element(by.id('save-entity'));
6 | cancelButton: ElementFinder = element(by.id('cancel-save'));
7 | timestampInput: ElementFinder = element(by.css('input#blood-pressure-timestamp'));
8 | systolicInput: ElementFinder = element(by.css('input#blood-pressure-systolic'));
9 | diastolicInput: ElementFinder = element(by.css('input#blood-pressure-diastolic'));
10 | userSelect: ElementFinder = element(by.css('select#blood-pressure-user'));
11 |
12 | getPageTitle() {
13 | return this.pageTitle;
14 | }
15 |
16 | async setTimestampInput(timestamp) {
17 | await this.timestampInput.sendKeys(timestamp);
18 | }
19 |
20 | async getTimestampInput() {
21 | return this.timestampInput.getAttribute('value');
22 | }
23 |
24 | async setSystolicInput(systolic) {
25 | await this.systolicInput.sendKeys(systolic);
26 | }
27 |
28 | async getSystolicInput() {
29 | return this.systolicInput.getAttribute('value');
30 | }
31 |
32 | async setDiastolicInput(diastolic) {
33 | await this.diastolicInput.sendKeys(diastolic);
34 | }
35 |
36 | async getDiastolicInput() {
37 | return this.diastolicInput.getAttribute('value');
38 | }
39 |
40 | async userSelectLastOption() {
41 | await this.userSelect
42 | .all(by.tagName('option'))
43 | .last()
44 | .click();
45 | }
46 |
47 | async userSelectOption(option) {
48 | await this.userSelect.sendKeys(option);
49 | }
50 |
51 | getUserSelect() {
52 | return this.userSelect;
53 | }
54 |
55 | async getUserSelectedOption() {
56 | return this.userSelect.element(by.css('option:checked')).getText();
57 | }
58 |
59 | async save() {
60 | await this.saveButton.click();
61 | }
62 |
63 | async cancel() {
64 | await this.cancelButton.click();
65 | }
66 |
67 | getSaveButton() {
68 | return this.saveButton;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/test/javascript/e2e/entities/blood-pressure/blood-pressure.page-object.ts:
--------------------------------------------------------------------------------
1 | import { element, by, ElementFinder } from 'protractor';
2 |
3 | import { waitUntilCount, waitUntilDisplayed } from '../../util/utils';
4 |
5 | export default class BloodPressureComponentsPage {
6 | createButton: ElementFinder = element(by.id('jh-create-entity'));
7 | deleteButtons = element.all(by.css('div table .btn-danger'));
8 | title: ElementFinder = element(by.id('blood-pressure-heading'));
9 |
10 | async clickOnCreateButton() {
11 | await this.createButton.click();
12 | }
13 |
14 | async clickOnLastDeleteButton() {
15 | await this.deleteButtons.last().click();
16 | }
17 |
18 | async countDeleteButtons() {
19 | return this.deleteButtons.count();
20 | }
21 |
22 | getTitle() {
23 | return this.title;
24 | }
25 |
26 | async waitUntilLoaded() {
27 | await waitUntilDisplayed(this.deleteButtons.first());
28 | }
29 |
30 | async waitUntilDeleteButtonsLength(length) {
31 | await waitUntilCount(this.deleteButtons, length);
32 | }
33 | }
34 |
35 | export class BloodPressureDeleteDialog {
36 | private dialogTitle: ElementFinder = element(by.id('twentyOnePointsReactApp.bloodPressure.delete.question'));
37 | private confirmButton = element(by.id('jhi-confirm-delete-bloodPressure'));
38 |
39 | getDialogTitle() {
40 | return this.dialogTitle;
41 | }
42 |
43 | async clickOnConfirmButton() {
44 | await this.confirmButton.click();
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/test/javascript/e2e/entities/points/points.page-object.ts:
--------------------------------------------------------------------------------
1 | import { element, by, ElementFinder } from 'protractor';
2 |
3 | import { waitUntilCount, waitUntilDisplayed } from '../../util/utils';
4 |
5 | export default class PointsComponentsPage {
6 | createButton: ElementFinder = element(by.id('jh-create-entity'));
7 | deleteButtons = element.all(by.css('div table .btn-danger'));
8 | title: ElementFinder = element(by.id('points-heading'));
9 |
10 | async clickOnCreateButton() {
11 | await this.createButton.click();
12 | }
13 |
14 | async clickOnLastDeleteButton() {
15 | await this.deleteButtons.last().click();
16 | }
17 |
18 | async countDeleteButtons() {
19 | return this.deleteButtons.count();
20 | }
21 |
22 | getTitle() {
23 | return this.title;
24 | }
25 |
26 | async waitUntilLoaded() {
27 | await waitUntilDisplayed(this.deleteButtons.first());
28 | }
29 |
30 | async waitUntilDeleteButtonsLength(length) {
31 | await waitUntilCount(this.deleteButtons, length);
32 | }
33 | }
34 |
35 | export class PointsDeleteDialog {
36 | private dialogTitle: ElementFinder = element(by.id('twentyOnePointsReactApp.points.delete.question'));
37 | private confirmButton = element(by.id('jhi-confirm-delete-points'));
38 |
39 | getDialogTitle() {
40 | return this.dialogTitle;
41 | }
42 |
43 | async clickOnConfirmButton() {
44 | await this.confirmButton.click();
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/test/javascript/e2e/entities/preferences/preferences-update.page-object.ts:
--------------------------------------------------------------------------------
1 | import { element, by, ElementFinder } from 'protractor';
2 |
3 | export default class PreferencesUpdatePage {
4 | pageTitle: ElementFinder = element(by.id('twentyOnePointsReactApp.preferences.home.createOrEditLabel'));
5 | saveButton: ElementFinder = element(by.id('save-entity'));
6 | cancelButton: ElementFinder = element(by.id('cancel-save'));
7 | weeklyGoalInput: ElementFinder = element(by.css('input#preferences-weeklyGoal'));
8 | weightUnitsSelect: ElementFinder = element(by.css('select#preferences-weightUnits'));
9 | userSelect: ElementFinder = element(by.css('select#preferences-user'));
10 |
11 | getPageTitle() {
12 | return this.pageTitle;
13 | }
14 |
15 | async setWeeklyGoalInput(weeklyGoal) {
16 | await this.weeklyGoalInput.sendKeys(weeklyGoal);
17 | }
18 |
19 | async getWeeklyGoalInput() {
20 | return this.weeklyGoalInput.getAttribute('value');
21 | }
22 |
23 | async setWeightUnitsSelect(weightUnits) {
24 | await this.weightUnitsSelect.sendKeys(weightUnits);
25 | }
26 |
27 | async getWeightUnitsSelect() {
28 | return this.weightUnitsSelect.element(by.css('option:checked')).getText();
29 | }
30 |
31 | async weightUnitsSelectLastOption() {
32 | await this.weightUnitsSelect
33 | .all(by.tagName('option'))
34 | .last()
35 | .click();
36 | }
37 | async userSelectLastOption() {
38 | await this.userSelect
39 | .all(by.tagName('option'))
40 | .last()
41 | .click();
42 | }
43 |
44 | async userSelectOption(option) {
45 | await this.userSelect.sendKeys(option);
46 | }
47 |
48 | getUserSelect() {
49 | return this.userSelect;
50 | }
51 |
52 | async getUserSelectedOption() {
53 | return this.userSelect.element(by.css('option:checked')).getText();
54 | }
55 |
56 | async save() {
57 | await this.saveButton.click();
58 | }
59 |
60 | async cancel() {
61 | await this.cancelButton.click();
62 | }
63 |
64 | getSaveButton() {
65 | return this.saveButton;
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/test/javascript/e2e/entities/preferences/preferences.page-object.ts:
--------------------------------------------------------------------------------
1 | import { element, by, ElementFinder } from 'protractor';
2 |
3 | import { waitUntilCount, waitUntilDisplayed } from '../../util/utils';
4 |
5 | export default class PreferencesComponentsPage {
6 | createButton: ElementFinder = element(by.id('jh-create-entity'));
7 | deleteButtons = element.all(by.css('div table .btn-danger'));
8 | title: ElementFinder = element(by.id('preferences-heading'));
9 |
10 | async clickOnCreateButton() {
11 | await this.createButton.click();
12 | }
13 |
14 | async clickOnLastDeleteButton() {
15 | await this.deleteButtons.last().click();
16 | }
17 |
18 | async countDeleteButtons() {
19 | return this.deleteButtons.count();
20 | }
21 |
22 | getTitle() {
23 | return this.title;
24 | }
25 |
26 | async waitUntilLoaded() {
27 | await waitUntilDisplayed(this.deleteButtons.first());
28 | }
29 |
30 | async waitUntilDeleteButtonsLength(length) {
31 | await waitUntilCount(this.deleteButtons, length);
32 | }
33 | }
34 |
35 | export class PreferencesDeleteDialog {
36 | private dialogTitle: ElementFinder = element(by.id('twentyOnePointsReactApp.preferences.delete.question'));
37 | private confirmButton = element(by.id('jhi-confirm-delete-preferences'));
38 |
39 | getDialogTitle() {
40 | return this.dialogTitle;
41 | }
42 |
43 | async clickOnConfirmButton() {
44 | await this.confirmButton.click();
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/test/javascript/e2e/entities/weigth/weigth-update.page-object.ts:
--------------------------------------------------------------------------------
1 | import { element, by, ElementFinder } from 'protractor';
2 |
3 | export default class WeigthUpdatePage {
4 | pageTitle: ElementFinder = element(by.id('twentyOnePointsReactApp.weigth.home.createOrEditLabel'));
5 | saveButton: ElementFinder = element(by.id('save-entity'));
6 | cancelButton: ElementFinder = element(by.id('cancel-save'));
7 | timestampInput: ElementFinder = element(by.css('input#weigth-timestamp'));
8 | weightInput: ElementFinder = element(by.css('input#weigth-weight'));
9 | userSelect: ElementFinder = element(by.css('select#weigth-user'));
10 |
11 | getPageTitle() {
12 | return this.pageTitle;
13 | }
14 |
15 | async setTimestampInput(timestamp) {
16 | await this.timestampInput.sendKeys(timestamp);
17 | }
18 |
19 | async getTimestampInput() {
20 | return this.timestampInput.getAttribute('value');
21 | }
22 |
23 | async setWeightInput(weight) {
24 | await this.weightInput.sendKeys(weight);
25 | }
26 |
27 | async getWeightInput() {
28 | return this.weightInput.getAttribute('value');
29 | }
30 |
31 | async userSelectLastOption() {
32 | await this.userSelect
33 | .all(by.tagName('option'))
34 | .last()
35 | .click();
36 | }
37 |
38 | async userSelectOption(option) {
39 | await this.userSelect.sendKeys(option);
40 | }
41 |
42 | getUserSelect() {
43 | return this.userSelect;
44 | }
45 |
46 | async getUserSelectedOption() {
47 | return this.userSelect.element(by.css('option:checked')).getText();
48 | }
49 |
50 | async save() {
51 | await this.saveButton.click();
52 | }
53 |
54 | async cancel() {
55 | await this.cancelButton.click();
56 | }
57 |
58 | getSaveButton() {
59 | return this.saveButton;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/test/javascript/e2e/entities/weigth/weigth.page-object.ts:
--------------------------------------------------------------------------------
1 | import { element, by, ElementFinder } from 'protractor';
2 |
3 | import { waitUntilCount, waitUntilDisplayed } from '../../util/utils';
4 |
5 | export default class WeigthComponentsPage {
6 | createButton: ElementFinder = element(by.id('jh-create-entity'));
7 | deleteButtons = element.all(by.css('div table .btn-danger'));
8 | title: ElementFinder = element(by.id('weigth-heading'));
9 |
10 | async clickOnCreateButton() {
11 | await this.createButton.click();
12 | }
13 |
14 | async clickOnLastDeleteButton() {
15 | await this.deleteButtons.last().click();
16 | }
17 |
18 | async countDeleteButtons() {
19 | return this.deleteButtons.count();
20 | }
21 |
22 | getTitle() {
23 | return this.title;
24 | }
25 |
26 | async waitUntilLoaded() {
27 | await waitUntilDisplayed(this.deleteButtons.first());
28 | }
29 |
30 | async waitUntilDeleteButtonsLength(length) {
31 | await waitUntilCount(this.deleteButtons, length);
32 | }
33 | }
34 |
35 | export class WeigthDeleteDialog {
36 | private dialogTitle: ElementFinder = element(by.id('twentyOnePointsReactApp.weigth.delete.question'));
37 | private confirmButton = element(by.id('jhi-confirm-delete-weigth'));
38 |
39 | getDialogTitle() {
40 | return this.dialogTitle;
41 | }
42 |
43 | async clickOnConfirmButton() {
44 | await this.confirmButton.click();
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/test/javascript/e2e/page-objects/base-component.ts:
--------------------------------------------------------------------------------
1 | import { ElementFinder } from 'protractor';
2 |
3 | import { isDisplayed, isHidden, waitUntilDisplayed, waitUntilHidden } from '../util/utils';
4 | /**
5 | * Base ui component class that other components should inherit from.
6 | */
7 | export default class BasePage {
8 | /**
9 | * This class property enables use of specific functions 'isDisplayed' and 'waitUntilDisplayed'
10 | */
11 | selector: ElementFinder = undefined;
12 |
13 | constructor(selector?) {
14 | this.selector = selector;
15 | }
16 |
17 | checkSelectorExist() {
18 | if (this.selector === undefined) {
19 | throw new TypeError(
20 | `Class '${this.constructor.name}' ` +
21 | `extends 'UIComponent' possibly 'Page' Object Class and have to implement abstract property 'selector' ` +
22 | `when 'isDisplayed' or 'waitUntilDisplayed' are used`
23 | );
24 | }
25 | }
26 |
27 | /**
28 | * @returns Function which resolves to boolean
29 | */
30 | isDisplayed() {
31 | this.checkSelectorExist();
32 | return isDisplayed(this.selector);
33 | }
34 |
35 | isHidden() {
36 | this.checkSelectorExist();
37 | return isHidden(this.selector);
38 | }
39 |
40 | /**
41 | * Wait until this page is displayed.
42 | */
43 | async waitUntilDisplayed() {
44 | this.checkSelectorExist();
45 | await waitUntilDisplayed(this.selector, this.constructor.name);
46 | }
47 |
48 | async waitUntilHidden() {
49 | this.checkSelectorExist();
50 | await waitUntilHidden(this.selector, this.constructor.name);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/test/javascript/e2e/page-objects/password-page.ts:
--------------------------------------------------------------------------------
1 | import { ElementFinder, browser, $ } from 'protractor';
2 |
3 | import BasePage from './base-component';
4 |
5 | const selector: ElementFinder = $('#password-form');
6 | export default class PasswordPage extends BasePage {
7 | selector: ElementFinder;
8 | currentPassword: ElementFinder = this.selector.$('#currentPassword');
9 | newPassword: ElementFinder = this.selector.$('#newPassword');
10 | confirmPassword: ElementFinder = this.selector.$('#confirmPassword');
11 | saveButton: ElementFinder = this.selector.$('button[type=submit]');
12 | title: ElementFinder = $('#password-title');
13 |
14 | constructor() {
15 | super(selector);
16 | this.selector = selector;
17 | }
18 |
19 | async get() {
20 | await browser.get('#/account/password');
21 | await this.waitUntilDisplayed();
22 | }
23 |
24 | async getTitle() {
25 | return this.title.getAttribute('id');
26 | }
27 |
28 | async setCurrentPassword(password: string) {
29 | await this.currentPassword.sendKeys(password);
30 | }
31 |
32 | async clearCurrentPassword() {
33 | await this.currentPassword.clear();
34 | }
35 |
36 | async setNewPassword(newPassword: string) {
37 | await this.newPassword.sendKeys(newPassword);
38 | }
39 |
40 | async clearNewPassword() {
41 | await this.newPassword.clear();
42 | }
43 |
44 | async setConfirmPassword(confirmPassword: string) {
45 | await this.confirmPassword.sendKeys(confirmPassword);
46 | }
47 |
48 | async clearConfirmPassword() {
49 | await this.confirmPassword.clear();
50 | }
51 |
52 | async autoChangePassword(currentPassword: string, newPassword: string, confirmPassword: string) {
53 | await this.setCurrentPassword(currentPassword);
54 | await this.setNewPassword(newPassword);
55 | await this.setConfirmPassword(confirmPassword);
56 | await this.save();
57 | }
58 |
59 | async save() {
60 | await this.saveButton.click();
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/test/javascript/e2e/page-objects/register-page.ts:
--------------------------------------------------------------------------------
1 | import { ElementFinder, browser, $ } from 'protractor';
2 |
3 | import BasePage from './base-component';
4 |
5 | const selector: ElementFinder = $('#register-form');
6 | export default class RegisterPage extends BasePage {
7 | selector: ElementFinder;
8 | username: ElementFinder = this.selector.$('#username');
9 | email: ElementFinder = this.selector.$('#email');
10 | firstPassword: ElementFinder = this.selector.$('#firstPassword');
11 | secondPassword: ElementFinder = this.selector.$('#secondPassword');
12 | saveButton: ElementFinder = this.selector.$('button[type=submit]');
13 | title: ElementFinder = $('#register-title');
14 |
15 | constructor() {
16 | super(selector);
17 | this.selector = selector;
18 | }
19 |
20 | async get() {
21 | await browser.get('#/register');
22 | await this.waitUntilDisplayed();
23 | }
24 |
25 | async getTitle() {
26 | return this.title.getAttribute('id');
27 | }
28 |
29 | async setUserName(username: string) {
30 | await this.username.sendKeys(username);
31 | }
32 |
33 | async setEmail(email: string) {
34 | await this.email.sendKeys(email);
35 | }
36 |
37 | async setFirstPassword(password: string) {
38 | await this.firstPassword.sendKeys(password);
39 | }
40 |
41 | async setSecondPassword(password: string) {
42 | await this.secondPassword.sendKeys(password);
43 | }
44 |
45 | async autoSignUpUsing(username: string, email: string, password: string) {
46 | await this.setUserName(username);
47 | await this.setEmail(email);
48 | await this.setFirstPassword(password);
49 | await this.setSecondPassword(password);
50 | await this.save();
51 | }
52 |
53 | async save() {
54 | await this.saveButton.click();
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/test/javascript/e2e/page-objects/settings-page.ts:
--------------------------------------------------------------------------------
1 | import { $, browser, ElementFinder } from 'protractor';
2 | import { promise } from 'selenium-webdriver';
3 |
4 | import BasePage from './base-component';
5 |
6 | const selector: ElementFinder = $('#settings-form');
7 | export default class SettingsPage extends BasePage {
8 | selector: ElementFinder;
9 | firstName: ElementFinder = this.selector.$('#firstName');
10 | lastName: ElementFinder = this.selector.$('#lastName');
11 | email: ElementFinder = this.selector.$('#email');
12 | saveButton: ElementFinder = this.selector.$('button[type=submit]');
13 | title: ElementFinder = $('#settings-title');
14 |
15 | constructor() {
16 | super(selector);
17 | this.selector = selector;
18 | }
19 |
20 | async get() {
21 | await browser.get('#/account/settings');
22 | await this.waitUntilDisplayed();
23 | }
24 |
25 | async getTitle() {
26 | return this.title.getAttribute('id');
27 | }
28 |
29 | async setFirstName(firstName) {
30 | await this.firstName.sendKeys(firstName);
31 | }
32 |
33 | async setLastName(lastName) {
34 | await this.lastName.sendKeys(lastName);
35 | }
36 |
37 | async setEmail(email) {
38 | await this.email.sendKeys(email);
39 | }
40 |
41 | async clearEmail() {
42 | await this.email.clear();
43 | }
44 |
45 | async save() {
46 | await this.saveButton.click();
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/test/javascript/e2e/page-objects/signin-page.ts:
--------------------------------------------------------------------------------
1 | import { $, browser, ElementFinder } from 'protractor';
2 |
3 | import BasePage from './base-component';
4 |
5 | const selector: ElementFinder = $('#login-page');
6 | export default class SignInPage extends BasePage {
7 | selector: ElementFinder;
8 | username: ElementFinder = this.selector.$('#username');
9 | password: ElementFinder = this.selector.$('#password');
10 | loginButton: ElementFinder = this.selector.$('button[type=submit]');
11 | title: ElementFinder = this.selector.$('#login-title');
12 |
13 | constructor() {
14 | super(selector);
15 | this.selector = selector;
16 | }
17 |
18 | async get() {
19 | await browser.get('#/login');
20 | await this.waitUntilDisplayed();
21 | }
22 |
23 | async getTitle() {
24 | return this.title.getAttribute('id');
25 | }
26 |
27 | async setUserName(username: string) {
28 | await this.username.sendKeys(username);
29 | }
30 |
31 | async clearUserName() {
32 | await this.username.clear();
33 | }
34 |
35 | async setPassword(password: string) {
36 | await this.password.sendKeys(password);
37 | }
38 |
39 | async clearPassword() {
40 | await this.password.clear();
41 | }
42 |
43 | async autoSignInUsing(username: string, password: string) {
44 | await this.setUserName(username);
45 | await this.setPassword(password);
46 | await this.login();
47 | }
48 |
49 | async autoSignOut() {
50 | await browser.get('#/logout');
51 | }
52 |
53 | async login() {
54 | await this.loginButton.click();
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/test/javascript/jest.conf.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | transform: {
3 | '^.+\\.tsx?$': 'ts-jest'
4 | },
5 | rootDir: '../../../',
6 | testURL: 'http://localhost/',
7 | coverageDirectory: '/target/test-results/',
8 | testMatch: ['/src/test/javascript/spec/**/+(*.)+(spec.ts?(x))'],
9 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
10 | moduleNameMapper: {
11 | 'app/(.*)': '/src/main/webapp/app/$1',
12 | '\\.(css|scss)$': 'identity-obj-proxy'
13 | },
14 | reporters: [
15 | 'default',
16 | [ 'jest-junit', { output: './target/test-results/jest/TESTS-results.xml' } ]
17 | ],
18 | testResultsProcessor: 'jest-sonar-reporter',
19 | testPathIgnorePatterns: [
20 | '/node_modules/'
21 | ],
22 | setupFiles: [
23 | '/src/test/javascript/spec/enzyme-setup.ts',
24 | '/src/test/javascript/spec/storage-mock.ts'
25 | ],
26 | snapshotSerializers: ['enzyme-to-json/serializer'],
27 | globals: {
28 | 'ts-jest': {
29 | tsConfigFile: './tsconfig.test.json'
30 | }
31 | }
32 | };
33 |
--------------------------------------------------------------------------------
/src/test/javascript/protractor.conf.js:
--------------------------------------------------------------------------------
1 | const os = require('os');
2 |
3 | exports.config = {
4 | allScriptsTimeout: 20000,
5 |
6 | specs: [
7 | './e2e/modules/account/*.spec.ts',
8 | './e2e/modules/administration/*.spec.ts',
9 | './e2e/entities/**/*.spec.ts'
10 | /* jhipster-needle-add-protractor-tests - JHipster will add protractors tests here */
11 | ],
12 |
13 | capabilities: {
14 | browserName: 'chrome',
15 | chromeOptions: {
16 | args: process.env.JHI_E2E_HEADLESS
17 | ? [ '--headless', '--disable-gpu', '--window-size=800,600' ]
18 | : [ '--disable-gpu', '--window-size=800,600' ]
19 | }
20 | },
21 |
22 | directConnect: true,
23 |
24 | baseUrl: 'http://localhost:8080/',
25 |
26 | framework: 'mocha',
27 |
28 | SELENIUM_PROMISE_MANAGER: false,
29 |
30 | mochaOpts: {
31 | reporter: 'spec',
32 | slow: 3000,
33 | ui: 'bdd',
34 | timeout: 30000
35 | },
36 |
37 | beforeLaunch () {
38 | require('ts-node').register({
39 | project: './tsconfig.e2e.json'
40 | });
41 | },
42 |
43 | onPrepare () {
44 | // @ts-ignore
45 | browser.driver.manage().window().setSize(1280, 1024);
46 | // @ts-ignore
47 | browser.ignoreSynchronization = true;
48 | // Disable animations
49 | // @ts-ignore
50 | browser.executeScript('document.body.className += " notransition";');
51 | const chai = require('chai');
52 | const chaiAsPromised = require('chai-as-promised');
53 | chai.use(chaiAsPromised);
54 | // @ts-ignore
55 | global.chai = chai;
56 | }
57 | };
58 |
--------------------------------------------------------------------------------
/src/test/javascript/spec/app/config/axios-interceptor.spec.ts:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 | import sinon from 'sinon';
3 |
4 | import setupAxiosInterceptors from 'app/config/axios-interceptor';
5 |
6 | describe('Axios Interceptor', () => {
7 | describe('setupAxiosInterceptors', () => {
8 | const client = axios;
9 | const onUnauthenticated = sinon.spy();
10 | setupAxiosInterceptors(onUnauthenticated);
11 |
12 | it('onRequestSuccess is called on fullfilled request', () => {
13 | expect((client.interceptors.request as any).handlers[0].fulfilled({ data: 'foo', url: '/test' })).toMatchObject({
14 | data: 'foo',
15 | timeout: 1000000
16 | });
17 | });
18 | it('onResponseSuccess is called on fullfilled response', () => {
19 | expect((client.interceptors.response as any).handlers[0].fulfilled({ data: 'foo' })).toEqual({ data: 'foo' });
20 | });
21 | it('onResponseError is called on rejected response', () => {
22 | (client.interceptors.response as any).handlers[0].rejected({
23 | response: {
24 | statusText: 'NotFound',
25 | status: 403,
26 | data: { message: 'Page not found' }
27 | }
28 | });
29 | expect(onUnauthenticated.calledOnce).toBe(true);
30 | });
31 | });
32 | });
33 |
--------------------------------------------------------------------------------
/src/test/javascript/spec/app/shared/error/error-boundary-route.spec.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Route } from 'react-router-dom';
3 | import { shallow, mount } from 'enzyme';
4 |
5 | import ErrorBoundaryRoute from 'app/shared/error/error-boundary-route';
6 |
7 | const ErrorComp = () => {
8 | throw new Error('test');
9 | };
10 |
11 | describe('error-boundary-route component', () => {
12 | beforeEach(() => {
13 | // ignore console and jsdom errors
14 | jest.spyOn((window as any)._virtualConsole, 'emit').mockImplementation(() => false);
15 | jest.spyOn((window as any).console, 'error').mockImplementation(() => false);
16 | });
17 |
18 | // All tests will go here
19 | it('Should throw error when no component is provided', () => {
20 | expect(() => shallow()).toThrow(Error);
21 | });
22 |
23 | it('Should render fallback component when an uncaught error is thrown from component', () => {
24 | const route = shallow();
25 | const renderedRoute = route.find(Route);
26 | expect(renderedRoute.length).toEqual(1);
27 | expect(renderedRoute.props().path).toEqual('/');
28 | expect(renderedRoute.props().render).toBeDefined();
29 | const renderFn: Function = renderedRoute.props().render;
30 | const comp = mount(
31 | renderFn({
32 | location: '/'
33 | })
34 | );
35 | expect(comp.length).toEqual(1);
36 | expect(comp.html()).toEqual('An unexpected error has occurred.
');
37 | });
38 | });
39 |
--------------------------------------------------------------------------------
/src/test/javascript/spec/app/shared/error/error-boundary.spec.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { shallow, mount } from 'enzyme';
3 |
4 | import ErrorBoundary from 'app/shared/error/error-boundary';
5 |
6 | const ErrorComp = () => {
7 | throw new Error('test');
8 | };
9 |
10 | describe('error component', () => {
11 | beforeEach(() => {
12 | // ignore console and jsdom errors
13 | jest.spyOn((window as any)._virtualConsole, 'emit').mockImplementation(() => false);
14 | jest.spyOn((window as any).console, 'error').mockImplementation(() => false);
15 | });
16 |
17 | it('Should throw an error when componnet is not enclosed in Error Boundary', () => {
18 | expect(() => shallow()).toThrow(Error);
19 | });
20 |
21 | it('Should call Error Boundary componentDidCatch method', () => {
22 | const spy = jest.spyOn(ErrorBoundary.prototype, 'componentDidCatch');
23 | mount(
24 |
25 |
26 |
27 | );
28 | expect(spy).toHaveBeenCalled();
29 | });
30 | });
31 |
--------------------------------------------------------------------------------
/src/test/javascript/spec/app/shared/layout/header/menus/account.spec.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { shallow } from 'enzyme';
3 |
4 | import { NavDropdown } from 'app/shared/layout/header/header-components';
5 | import { AccountMenu } from 'app/shared/layout/header/menus';
6 |
7 | describe('AccountMenu', () => {
8 | let mountedWrapper;
9 |
10 | const authenticatedWrapper = () => {
11 | if (!mountedWrapper) {
12 | mountedWrapper = shallow();
13 | }
14 | return mountedWrapper;
15 | };
16 | const guestWrapper = () => {
17 | if (!mountedWrapper) {
18 | mountedWrapper = shallow();
19 | }
20 | return mountedWrapper;
21 | };
22 |
23 | beforeEach(() => {
24 | mountedWrapper = undefined;
25 | });
26 |
27 | // All tests will go here
28 |
29 | it('Renders a authenticated AccountMenu component', () => {
30 | const dropdown = authenticatedWrapper().find(NavDropdown);
31 | expect(dropdown).toHaveLength(1);
32 | expect(dropdown.find({ to: '/login' })).toHaveLength(0);
33 | expect(dropdown.find({ to: '/logout' })).toHaveLength(1);
34 | });
35 |
36 | it('Renders a guest AccountMenu component', () => {
37 | const dropdown = guestWrapper().find(NavDropdown);
38 | expect(dropdown).toHaveLength(1);
39 | expect(dropdown.find({ to: '/login' })).toHaveLength(1);
40 | expect(dropdown.find({ to: '/logout' })).toHaveLength(0);
41 | });
42 | });
43 |
--------------------------------------------------------------------------------
/src/test/javascript/spec/app/shared/util/entity-utils.spec.ts:
--------------------------------------------------------------------------------
1 | import { cleanEntity, mapIdList } from 'app/shared/util/entity-utils';
2 |
3 | describe('Entity utils', () => {
4 | describe('cleanEntity', () => {
5 | it('should not remove fields with an id', () => {
6 | const entityA = {
7 | a: {
8 | id: 5
9 | }
10 | };
11 | const entityB = {
12 | a: {
13 | id: '5'
14 | }
15 | };
16 |
17 | expect(cleanEntity({ ...entityA })).toEqual(entityA);
18 | expect(cleanEntity({ ...entityB })).toEqual(entityB);
19 | });
20 |
21 | it('should remove fields with an empty id', () => {
22 | const entity = {
23 | a: {
24 | id: ''
25 | }
26 | };
27 |
28 | expect(cleanEntity({ ...entity })).toEqual({});
29 | });
30 |
31 | it('should not remove fields that are not objects', () => {
32 | const entity = {
33 | a: '',
34 | b: 5,
35 | c: [],
36 | d: '5'
37 | };
38 |
39 | expect(cleanEntity({ ...entity })).toEqual(entity);
40 | });
41 | });
42 |
43 | describe('mapIdList', () => {
44 | it("should map ids no matter the element's type", () => {
45 | const ids = ['jhipster', '', 1, { key: 'value' }];
46 |
47 | expect(mapIdList(ids)).toEqual([{ id: 'jhipster' }, { id: 1 }, { id: { key: 'value' } }]);
48 | });
49 |
50 | it('should return an empty array', () => {
51 | const ids = [];
52 |
53 | expect(mapIdList(ids)).toEqual([]);
54 | });
55 | });
56 | });
57 |
--------------------------------------------------------------------------------
/src/test/javascript/spec/app/utils.ts:
--------------------------------------------------------------------------------
1 | // A dirty way to remove functions and undefined from an object for comparison
2 | export const cleanupObj = obj => JSON.parse(JSON.stringify(obj));
3 |
--------------------------------------------------------------------------------
/src/test/javascript/spec/enzyme-setup.ts:
--------------------------------------------------------------------------------
1 | import { configure } from 'enzyme';
2 | import Adapter from 'enzyme-adapter-react-16';
3 |
4 | // React 16 Enzyme adapter
5 | configure({ adapter: new Adapter() });
6 |
--------------------------------------------------------------------------------
/src/test/javascript/spec/storage-mock.ts:
--------------------------------------------------------------------------------
1 | let StorageMock = () => {
2 | let storage = {};
3 | return {
4 | getItem: key => (key in storage ? storage[key] : null),
5 | setItem: (key, value) => (storage[key] = value || ''),
6 | removeItem: key => delete storage[key],
7 | clear: () => (storage = {})
8 | };
9 | };
10 |
11 | Object.defineProperty(window, 'localStorage', {
12 | value: StorageMock()
13 | });
14 |
15 | Object.defineProperty(window, 'sessionStorage', {
16 | value: StorageMock()
17 | });
18 |
--------------------------------------------------------------------------------
/src/test/resources/i18n/messages_en.properties:
--------------------------------------------------------------------------------
1 | email.test.title=test title
2 |
--------------------------------------------------------------------------------
/src/test/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/src/test/resources/templates/mail/testEmail.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/tsconfig.e2e.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig",
3 | "compilerOptions": {
4 | "module": "commonjs",
5 | "types": [
6 | "chai",
7 | "mocha"
8 | ]
9 | },
10 | "include": [
11 | "src/main/webapp/app/**/*",
12 | "src/test/javascript/e2e/**/*"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "jsx": "react",
4 | "target": "es5",
5 | "module": "esnext",
6 | "moduleResolution": "node",
7 | "sourceMap": true,
8 | "emitDecoratorMetadata": true,
9 | "experimentalDecorators": true,
10 | "removeComments": false,
11 | "noImplicitAny": false,
12 | "suppressImplicitAnyIndexErrors": true,
13 | "outDir": "target/www/app",
14 | "lib": ["es2015", "es2017", "dom"],
15 | "typeRoots": [
16 | "node_modules/@types"
17 | ],
18 | "types": ["webpack-env", "jest"],
19 | "allowJs": true,
20 | "checkJs": false,
21 | "baseUrl": "./",
22 | "paths": {
23 | "app/*": ["src/main/webapp/app/*"]
24 | },
25 | "importHelpers": true,
26 | "esModuleInterop": true,
27 | "allowSyntheticDefaultImports": true
28 | },
29 | "include": [
30 | "src/main/webapp/app/typing.d.ts",
31 | "src/main/webapp/app/**/*",
32 | "src/test/javascript/spec/**/*"
33 | ],
34 | "exclude": [
35 | "node_modules"
36 | ]
37 | }
38 |
--------------------------------------------------------------------------------
/tsconfig.test.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig",
3 | "compilerOptions": {
4 | "module": "commonjs",
5 | "allowSyntheticDefaultImports": false
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/webpack/utils.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | const path = require('path');
3 |
4 | module.exports = {
5 | parseVersion,
6 | root,
7 | isExternalLib
8 | };
9 |
10 | const parseString = require('xml2js').parseString;
11 | // return the version number from `pom.xml` file
12 | function parseVersion() {
13 | let version = null;
14 | const pomXml = fs.readFileSync('pom.xml', 'utf8');
15 | parseString(pomXml, (err, result) => {
16 | if (result.project.version && result.project.version[0]) {
17 | version = result.project.version[0];
18 | } else if (result.project.parent && result.project.parent[0] && result.project.parent[0].version && result.project.parent[0].version[0]) {
19 | version = result.project.parent[0].version[0];
20 | }
21 | });
22 | if (version === null) {
23 | throw new Error('pom.xml is malformed. No version is defined');
24 | }
25 | return version;
26 | }
27 |
28 | const _root = path.resolve(__dirname, '..');
29 |
30 | function root(args) {
31 | args = Array.prototype.slice.call(arguments, 0);
32 | return path.join.apply(path, [_root].concat(args));
33 | }
34 |
35 | function isExternalLib(module, check = /node_modules/) {
36 | const req = module.userRequest;
37 | if (typeof req !== 'string') {
38 | return false;
39 | }
40 | return req.search(check) >= 0;
41 | }
42 |
--------------------------------------------------------------------------------