getNotFoundUsersIds() {
47 | return notFoundUsersIds;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/github/joumenharzli/surveypoc/repository/dao/DaoException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Joumen Harzli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | */
15 |
16 | package com.github.joumenharzli.surveypoc.repository.dao;
17 |
18 | /**
19 | * This exception encapsulates SQLs related exceptions
20 | *
21 | * @author Joumen Harzli
22 | */
23 | public class DaoException extends RuntimeException {
24 | /**
25 | * Constructs a new runtime exception with the specified detail message and
26 | * cause. Note that the detail message associated with
27 | * {@code cause} is not automatically incorporated in
28 | * this runtime exception's detail message.
29 | *
30 | * @param message the detail message (which is saved for later retrieval
31 | * by the {@link #getMessage()} method).
32 | * @param cause the cause (which is saved for later retrieval by the
33 | * {@link #getCause()} method). (A null value is
34 | * permitted, and indicates that the cause is nonexistent or
35 | * unknown.)
36 | * @since 1.4
37 | */
38 | public DaoException(String message, Throwable cause) {
39 | super(message, cause);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/github/joumenharzli/surveypoc/exception/QuestionNotFoundException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Joumen Harzli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | */
15 |
16 | package com.github.joumenharzli.surveypoc.exception;
17 |
18 | import java.util.List;
19 |
20 | /**
21 | * Question Not Found Exception
22 | *
23 | * @author Joumen Harzli
24 | */
25 | public class QuestionNotFoundException extends RuntimeException {
26 |
27 | private static final String ERROR_MESSAGE = "Questions with ids %s was not found";
28 |
29 | private final List notFoundQuestionsIds;
30 |
31 | /**
32 | * Constructs a new runtime exception with the specified detail message.
33 | * The cause is not initialized, and may subsequently be initialized by a
34 | * call to {@link #initCause}.
35 | *
36 | * @param notFoundQuestionsIds the ids of the not found questions
37 | */
38 | public QuestionNotFoundException(List notFoundQuestionsIds) {
39 | super(String.format(ERROR_MESSAGE, notFoundQuestionsIds));
40 | this.notFoundQuestionsIds = notFoundQuestionsIds;
41 | }
42 |
43 | /**
44 | * @return ids of the not found questions
45 | */
46 | public List getNotFoundQuestionsIds() {
47 | return notFoundQuestionsIds;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/frontend/src/test.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Joumen Harzli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | */
15 |
16 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files
17 |
18 | import 'zone.js/dist/long-stack-trace-zone';
19 | import 'zone.js/dist/proxy.js';
20 | import 'zone.js/dist/sync-test';
21 | import 'zone.js/dist/jasmine-patch';
22 | import 'zone.js/dist/async-test';
23 | import 'zone.js/dist/fake-async-test';
24 | import { getTestBed } from '@angular/core/testing';
25 | import {
26 | BrowserDynamicTestingModule,
27 | platformBrowserDynamicTesting
28 | } from '@angular/platform-browser-dynamic/testing';
29 |
30 | // Unfortunately there's no typing for the `__karma__` variable. Just declare it as any.
31 | declare const __karma__: any;
32 | declare const require: any;
33 |
34 | // Prevent Karma from running prematurely.
35 | __karma__.loaded = function () {};
36 |
37 | // First, initialize the Angular testing environment.
38 | getTestBed().initTestEnvironment(
39 | BrowserDynamicTestingModule,
40 | platformBrowserDynamicTesting()
41 | );
42 | // Then we find all the tests.
43 | const context = require.context('./', true, /\.spec\.ts$/);
44 | // And load the modules.
45 | context.keys().map(context);
46 | // Finally, start Karma to run the tests.
47 | __karma__.start();
48 |
--------------------------------------------------------------------------------
/frontend/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "survey-poc-spring-boot-angular",
3 | "description": "A survey poc using Angular 5, Material, Reactive Forms, Spring Boot..",
4 | "homepage": "https://github.com/joumenharzli/survey-poc-spring-boot-angular",
5 | "author": {
6 | "name": "Joumen Harzli"
7 | },
8 | "version": "0.0.0",
9 | "license": "ALv2",
10 | "scripts": {
11 | "ng": "ng",
12 | "start": "ng serve",
13 | "build": "ng build",
14 | "test": "ng test",
15 | "lint": "ng lint",
16 | "e2e": "ng e2e",
17 | "ci": "ng e2e --watch=false"
18 | },
19 | "dependencies": {
20 | "@angular/animations": "^5.1.3",
21 | "@angular/cdk": "^5.0.3",
22 | "@angular/common": "^5.1.3",
23 | "@angular/compiler": "^5.1.3",
24 | "@angular/core": "^5.1.3",
25 | "@angular/forms": "^5.1.3",
26 | "@angular/http": "^5.1.3",
27 | "@angular/material": "^5.0.3",
28 | "@angular/platform-browser": "^5.1.3",
29 | "@angular/platform-browser-dynamic": "^5.1.3",
30 | "@angular/router": "^5.1.3",
31 | "core-js": "^2.5.3",
32 | "hammerjs": "2.0.8",
33 | "lodash": "^4.17.4",
34 | "rxjs": "^5.5.6",
35 | "web-animations-js": "2.3.1",
36 | "zone.js": "^0.8.19"
37 | },
38 | "devDependencies": {
39 | "@angular/cli": "^1.6.3",
40 | "@angular/compiler-cli": "^5.0.0",
41 | "@angular/language-service": "^5.0.0",
42 | "@types/jasmine": "~2.5.53",
43 | "@types/jasminewd2": "~2.0.2",
44 | "@types/node": "~6.0.60",
45 | "codelyzer": "~3.0.1",
46 | "jasmine-core": "~2.6.2",
47 | "jasmine-spec-reporter": "~4.1.0",
48 | "karma": "~1.7.0",
49 | "karma-chrome-launcher": "~2.1.1",
50 | "karma-cli": "~1.0.1",
51 | "karma-coverage-istanbul-reporter": "^1.2.1",
52 | "karma-jasmine": "~1.1.0",
53 | "karma-jasmine-html-reporter": "^0.2.2",
54 | "protractor": "~5.1.2",
55 | "ts-node": "~3.0.4",
56 | "tslint": "~5.3.2",
57 | "typescript": "~2.4.2"
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/github/joumenharzli/surveypoc/service/dto/QuestionDto.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Joumen Harzli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | */
15 |
16 | package com.github.joumenharzli.surveypoc.service.dto;
17 |
18 | import org.apache.commons.lang3.builder.EqualsBuilder;
19 | import org.apache.commons.lang3.builder.HashCodeBuilder;
20 | import org.apache.commons.lang3.builder.ToStringBuilder;
21 |
22 | /**
23 | * Question Dto
24 | *
25 | * @author Joumen Harzli
26 | */
27 | public class QuestionDto {
28 |
29 | private Long id;
30 | private String label;
31 |
32 | public Long getId() {
33 | return id;
34 | }
35 |
36 | public void setId(Long id) {
37 | this.id = id;
38 | }
39 |
40 | public String getLabel() {
41 | return label;
42 | }
43 |
44 | public void setLabel(String label) {
45 | this.label = label;
46 | }
47 |
48 | @Override
49 | public boolean equals(Object o) {
50 | if (this == o) {
51 | return true;
52 | }
53 |
54 | if (o == null || getClass() != o.getClass()) {
55 | return false;
56 | }
57 |
58 | QuestionDto that = (QuestionDto) o;
59 |
60 | return new EqualsBuilder()
61 | .append(id, that.id)
62 | .isEquals();
63 | }
64 |
65 | @Override
66 | public int hashCode() {
67 | return new HashCodeBuilder(17, 37)
68 | .append(id)
69 | .toHashCode();
70 | }
71 |
72 | @Override
73 | public String toString() {
74 | return new ToStringBuilder(this)
75 | .append("id", id)
76 | .append("label", label)
77 | .toString();
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/frontend/src/styles.scss:
--------------------------------------------------------------------------------
1 | /*!
2 | * Copyright (C) 2018 Joumen Harzli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | */
15 |
16 | @import '~@angular/material/theming';
17 |
18 | // Include the common styles for Angular Material. We include this here so that you only
19 | // have to load a single css file for Angular Material in your app.
20 | // Be sure that you only ever include this mixin once!
21 | @include mat-core();
22 |
23 | // Define the palettes for your theme using the Material Design palettes available in palette.scss
24 | // (imported above). For each palette, you can optionally specify a default, lighter, and darker
25 | // hue.
26 | $candy-app-primary: mat-palette($mat-blue);
27 | $candy-app-accent: mat-palette($mat-pink, A200, A100, A400);
28 |
29 | // The warn palette is optional (defaults to red).
30 | $candy-app-warn: mat-palette($mat-red);
31 |
32 | // Create the theme object (a Sass map containing all of the palettes).
33 | $candy-app-theme: mat-light-theme($candy-app-primary, $candy-app-accent, $candy-app-warn);
34 |
35 | // Include theme styles for core and each component used in your app.
36 | // Alternatively, you can import and @include the theme mixins for each component
37 | // that you are using.
38 | @include angular-material-theme($candy-app-theme);
39 |
40 | body {
41 | font-family: Open Sans, Roboto, Arial, sans-serif;
42 | margin: 0;
43 | background: #fafafa;
44 | }
45 |
46 | .basic-container {
47 | padding: 5px;
48 | }
49 |
50 | .submit-button {
51 | text-align: right;
52 | padding-top: 15px;
53 | }
54 |
55 | .spinner {
56 | width: 50px;
57 | margin: 0 auto;
58 | }
59 |
60 | .sm-spinner {
61 | position: absolute;
62 | right: 110px;
63 | }
64 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/github/joumenharzli/surveypoc/config/LocalizationConfiguration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Joumen Harzli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | */
15 |
16 | package com.github.joumenharzli.surveypoc.config;
17 |
18 | import java.util.Locale;
19 |
20 | import org.springframework.context.annotation.Bean;
21 | import org.springframework.context.annotation.Configuration;
22 | import org.springframework.context.support.ResourceBundleMessageSource;
23 | import org.springframework.web.servlet.LocaleResolver;
24 | import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;
25 |
26 | /**
27 | * Localization Configuration
28 | *
29 | * @author Joumen Harzli
30 | */
31 | @Configuration
32 | public class LocalizationConfiguration {
33 |
34 |
35 | /**
36 | * Use {@code Accept-language} header of the HTTP request to set the client local
37 | *
38 | * If not specified {@code Locale.US} will be used
39 | *
40 | * @return instance of {@link LocaleResolver}
41 | */
42 | @Bean
43 | public LocaleResolver localeResolver() {
44 | AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
45 | localeResolver.setDefaultLocale(Locale.US);
46 | return localeResolver;
47 | }
48 |
49 | /**
50 | * Set the source of i18n messages under "resources/i18n/messages_[locale].properties"
51 | *
52 | * @return instance of {@link ResourceBundleMessageSource}
53 | */
54 | @Bean
55 | public ResourceBundleMessageSource messageSource() {
56 | ResourceBundleMessageSource source = new ResourceBundleMessageSource();
57 | source.setBasenames("i18n/messages");
58 | source.setUseCodeAsDefaultMessage(true);
59 | return source;
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/frontend/src/app/survey/components/survey-form/survey-form.component.html:
--------------------------------------------------------------------------------
1 |
15 |
16 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/github/joumenharzli/surveypoc/domain/User.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Joumen Harzli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | */
15 |
16 | package com.github.joumenharzli.surveypoc.domain;
17 |
18 | import org.apache.commons.lang3.builder.EqualsBuilder;
19 | import org.apache.commons.lang3.builder.HashCodeBuilder;
20 | import org.apache.commons.lang3.builder.ToStringBuilder;
21 |
22 | /**
23 | * User entity
24 | *
25 | * @author Joumen Harzli
26 | */
27 | public class User {
28 |
29 | private Long id;
30 | private String name;
31 |
32 | public User id(Long id) {
33 | this.id = id;
34 | return this;
35 | }
36 |
37 | public User name(String name) {
38 | this.name = name;
39 | return this;
40 | }
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 getName() {
51 | return name;
52 | }
53 |
54 | public void setName(String name) {
55 | this.name = name;
56 | }
57 |
58 | @Override
59 | public boolean equals(Object o) {
60 | if (this == o) {
61 | return true;
62 | }
63 |
64 | if (o == null || getClass() != o.getClass()) {
65 | return false;
66 | }
67 |
68 | User user = (User) o;
69 |
70 | return new EqualsBuilder()
71 | .append(id, user.id)
72 | .isEquals();
73 | }
74 |
75 | @Override
76 | public int hashCode() {
77 | return new HashCodeBuilder(17, 37)
78 | .append(id)
79 | .toHashCode();
80 | }
81 |
82 | @Override
83 | public String toString() {
84 | return new ToStringBuilder(this)
85 | .append("id", id)
86 | .append("name", name)
87 | .toString();
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/github/joumenharzli/surveypoc/repository/dao/UserResponseDao.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Joumen Harzli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | */
15 |
16 | package com.github.joumenharzli.surveypoc.repository.dao;
17 |
18 | import java.util.List;
19 |
20 | import com.github.joumenharzli.surveypoc.domain.UserResponse;
21 |
22 | /**
23 | * User Response Dao
24 | *
25 | * @author Joumen Harzli
26 | */
27 | public interface UserResponseDao {
28 |
29 | /**
30 | * Add a new responses of the user
31 | *
32 | * @param userResponses entities to save
33 | * @return an array of the number of rows affected by each statement
34 | * @throws DaoException if there is an sql exception
35 | * @throws IllegalArgumentException if any given argument is invalid
36 | */
37 | int[] addUserResponses(List userResponses);
38 |
39 | /**
40 | * Update responses of the user
41 | *
42 | * @param userResponses entities to save
43 | * @return an array of the number of rows affected by each statement
44 | * @throws DaoException if there is an sql exception
45 | * @throws IllegalArgumentException if any given argument is invalid
46 | */
47 | int[] updateUserResponses(List userResponses);
48 |
49 | /**
50 | * Find the responses for the provided questions and user
51 | *
52 | * @param userId user who responded
53 | * @param questionsIds questions that the user may responded
54 | * @return list of responses
55 | * @throws DaoException if there is an sql exception
56 | * @throws IllegalArgumentException if any given argument is invalid
57 | */
58 | List findResponsesOfUserByUserIdAndQuestionIds(Long userId, List questionsIds);
59 | }
60 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/github/joumenharzli/surveypoc/domain/Subject.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Joumen Harzli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | */
15 |
16 | package com.github.joumenharzli.surveypoc.domain;
17 |
18 | import org.apache.commons.lang3.builder.EqualsBuilder;
19 | import org.apache.commons.lang3.builder.HashCodeBuilder;
20 | import org.apache.commons.lang3.builder.ToStringBuilder;
21 |
22 | /**
23 | * Subject entity
24 | *
25 | * @author Joumen Harzli
26 | */
27 | public class Subject {
28 |
29 | private Long id;
30 | private String label;
31 |
32 | public Subject id(Long id) {
33 | this.id = id;
34 | return this;
35 | }
36 |
37 | public Subject label(String label) {
38 | this.label = label;
39 | return this;
40 | }
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 getLabel() {
51 | return label;
52 | }
53 |
54 | public void setLabel(String label) {
55 | this.label = label;
56 | }
57 |
58 | @Override
59 | public boolean equals(Object o) {
60 | if (this == o) {
61 | return true;
62 | }
63 |
64 | if (o == null || getClass() != o.getClass()) {
65 | return false;
66 | }
67 |
68 | Subject subject = (Subject) o;
69 |
70 | return new EqualsBuilder()
71 | .append(id, subject.id)
72 | .isEquals();
73 | }
74 |
75 | @Override
76 | public int hashCode() {
77 | return new HashCodeBuilder(17, 37)
78 | .append(id)
79 | .toHashCode();
80 | }
81 |
82 | @Override
83 | public String toString() {
84 | return new ToStringBuilder(this)
85 | .append("id", id)
86 | .append("label", label)
87 | .toString();
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/github/joumenharzli/surveypoc/service/SimpleSubjectService.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Joumen Harzli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | */
15 |
16 | package com.github.joumenharzli.surveypoc.service;
17 |
18 | import java.util.Collections;
19 | import java.util.List;
20 |
21 | import org.slf4j.Logger;
22 | import org.slf4j.LoggerFactory;
23 | import org.springframework.stereotype.Service;
24 |
25 | import com.github.joumenharzli.surveypoc.domain.Question;
26 | import com.github.joumenharzli.surveypoc.repository.dao.QuestionDao;
27 | import com.github.joumenharzli.surveypoc.service.dto.SubjectDto;
28 | import com.github.joumenharzli.surveypoc.service.mapper.SubjectMapper;
29 |
30 | /**
31 | * A simple implementation for {@link SubjectService}
32 | *
33 | * @author Joumen Harzli
34 | */
35 | @Service
36 | public class SimpleSubjectService implements SubjectService {
37 |
38 | private static final Logger LOGGER = LoggerFactory.getLogger(SimpleSubjectService.class);
39 |
40 | private final QuestionDao questionDao;
41 | private final SubjectMapper subjectMapper;
42 |
43 | public SimpleSubjectService(QuestionDao questionDao, SubjectMapper subjectMapper) {
44 | this.questionDao = questionDao;
45 | this.subjectMapper = subjectMapper;
46 | }
47 |
48 | /**
49 | * find all the subjects and their questions
50 | *
51 | * @return a list of the questions with subjects
52 | */
53 | @Override
54 | public List findAllSubjectsAndQuestions() {
55 | LOGGER.debug("Request to get all the subjects and the questions");
56 |
57 | List questions = questionDao.findAllQuestionsAndSubjects();
58 |
59 | if (questions != null) {
60 | return subjectMapper.questionsToSubjectsDto(questions);
61 | }
62 |
63 | return Collections.emptyList();
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/github/joumenharzli/surveypoc/web/error/RestErrorDto.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Joumen Harzli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | */
15 |
16 | package com.github.joumenharzli.surveypoc.web.error;
17 |
18 | import java.io.Serializable;
19 |
20 | import org.apache.commons.lang3.builder.EqualsBuilder;
21 | import org.apache.commons.lang3.builder.HashCodeBuilder;
22 | import org.apache.commons.lang3.builder.ToStringBuilder;
23 |
24 | import io.swagger.annotations.ApiModel;
25 |
26 | /**
27 | * A representation for the rest error
28 | *
29 | * @author Joumen Harzli
30 | */
31 | @ApiModel("RestErrorDto")
32 | public class RestErrorDto implements Serializable {
33 | private String code;
34 | private String message;
35 |
36 | public RestErrorDto(String code, String message) {
37 | this.code = code;
38 | this.message = message;
39 | }
40 |
41 | public String getCode() {
42 | return code;
43 | }
44 |
45 | public String getMessage() {
46 | return message;
47 | }
48 |
49 | @Override
50 | public boolean equals(Object o) {
51 | if (this == o) {
52 | return true;
53 | }
54 |
55 | if (o == null || getClass() != o.getClass()) {
56 | return false;
57 | }
58 |
59 | RestErrorDto that = (RestErrorDto) o;
60 |
61 | return new EqualsBuilder()
62 | .append(code, that.code)
63 | .append(message, that.message)
64 | .isEquals();
65 | }
66 |
67 | @Override
68 | public int hashCode() {
69 | return new HashCodeBuilder(17, 37)
70 | .append(code)
71 | .toHashCode();
72 | }
73 |
74 | @Override
75 | public String toString() {
76 | ToStringBuilder builder = new ToStringBuilder(this)
77 | .append("code", code)
78 | .append("message", message);
79 |
80 | return builder.toString();
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/github/joumenharzli/surveypoc/service/dto/UserResponseForQuestionDto.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Joumen Harzli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | */
15 |
16 | package com.github.joumenharzli.surveypoc.service.dto;
17 |
18 | import javax.validation.constraints.NotNull;
19 |
20 | import org.apache.commons.lang3.builder.EqualsBuilder;
21 | import org.apache.commons.lang3.builder.HashCodeBuilder;
22 | import org.apache.commons.lang3.builder.ToStringBuilder;
23 | import org.hibernate.validator.constraints.NotBlank;
24 |
25 | /**
26 | * User Response For Question Dto
27 | *
28 | * @author Joumen Harzli
29 | */
30 | public class UserResponseForQuestionDto {
31 |
32 |
33 | @NotNull
34 | private Long questionId;
35 |
36 | @NotBlank
37 | private String content;
38 |
39 | public Long getQuestionId() {
40 | return questionId;
41 | }
42 |
43 | public void setQuestionId(Long questionId) {
44 | this.questionId = questionId;
45 | }
46 |
47 | public String getContent() {
48 | return content;
49 | }
50 |
51 | public void setContent(String content) {
52 | this.content = content;
53 | }
54 |
55 | @Override
56 | public boolean equals(Object o) {
57 | if (this == o) {
58 | return true;
59 | }
60 |
61 | if (o == null || getClass() != o.getClass()) {
62 | return false;
63 | }
64 |
65 | UserResponseForQuestionDto that = (UserResponseForQuestionDto) o;
66 |
67 | return new EqualsBuilder()
68 | .append(questionId, that.questionId)
69 | .isEquals();
70 | }
71 |
72 | @Override
73 | public int hashCode() {
74 | return new HashCodeBuilder(17, 37)
75 | .append(questionId)
76 | .toHashCode();
77 | }
78 |
79 | @Override
80 | public String toString() {
81 | return new ToStringBuilder(this)
82 | .append("questionId", questionId)
83 | .append("content", content)
84 | .toString();
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/frontend/src/app/survey/services/survey.service.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Joumen Harzli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | */
15 |
16 | import { Injectable } from '@angular/core';
17 | import { HttpClient } from '@angular/common/http';
18 | import { Observable } from 'rxjs/Observable';
19 |
20 | import { UserResponse, Question, Subject } from '../models/survey.models';
21 |
22 | @Injectable()
23 | export class SurveyService {
24 |
25 | SUBJECT_API = 'http://localhost:8080/api/v1/subjects';
26 | QUESTION_API = 'http://localhost:8080/api/v1/questions';
27 |
28 | constructor(private httpClient: HttpClient) { }
29 |
30 | /**
31 | * Get all the subjects and their questions
32 | *
33 | * @returns {Observable} all the found subjects and their questions
34 | */
35 | getAllSubjectsAndQuestions(): Observable {
36 | return this.httpClient.get(this.SUBJECT_API);
37 | }
38 |
39 | /**
40 | * Get all responses of the connected user for the questions
41 | *
42 | * @param {number[]} questions ids of the questions that the user may responded
43 | * @returns {Observable} the found responses of the connected user for the provided questions
44 | */
45 | getResponsesOfConnectedUserForQuestions(questions: number[]): Observable {
46 | return this.httpClient.get(this.QUESTION_API + '/' + questions.toString() + '/responses/me');
47 | }
48 |
49 | /**
50 | * Add and update the responses of the connected user for the provided questions
51 | *
52 | * @param {UserResponse[]} userResponses new responses of the user
53 | * @returns {Observable} the list of the saved responses of the user
54 | */
55 | saveResponsesOfConnectedUserForQuestions(userResponses: UserResponse[]): Observable {
56 | return this.httpClient.post(this.QUESTION_API + '/responses/me', userResponses);
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/github/joumenharzli/surveypoc/service/UserResponseService.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Joumen Harzli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | */
15 |
16 | package com.github.joumenharzli.surveypoc.service;
17 |
18 | import java.util.List;
19 |
20 | import com.github.joumenharzli.surveypoc.exception.QuestionNotFoundException;
21 | import com.github.joumenharzli.surveypoc.exception.UserNotFoundException;
22 | import com.github.joumenharzli.surveypoc.service.dto.UserResponseForQuestionDto;
23 |
24 | /**
25 | * User Response Service
26 | *
27 | * @author Joumen Harzli
28 | */
29 | public interface UserResponseService {
30 |
31 | /**
32 | * Find the responses for the provided questions and user
33 | *
34 | * @param userId id of the user who responded
35 | * @param questionsIds ids of the questions that the user may responded
36 | * @return list of responses of the user
37 | * @throws UserNotFoundException if no user was found
38 | * @throws QuestionNotFoundException if no question was found
39 | * @throws IllegalArgumentException if any given argument is invalid
40 | */
41 | List findResponsesOfUserForQuestions(Long userId, List questionsIds);
42 |
43 | /**
44 | * Save the responses of the connected user for the provided questions
45 | *
46 | * @param userId id of the user who responded
47 | * @param userResponsesForQuestions questions ids and contents that the connected user entered
48 | * @return List of the saved responses of the user
49 | * @throws UserNotFoundException if no user was found
50 | * @throws QuestionNotFoundException if no question was found
51 | * @throws IllegalArgumentException if any given argument is invalid
52 | */
53 | List saveResponsesOfUserForQuestions(Long userId,
54 | List userResponsesForQuestions);
55 | }
56 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/github/joumenharzli/surveypoc/service/mapper/SubjectMapperDecorator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Joumen Harzli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | */
15 |
16 | package com.github.joumenharzli.surveypoc.service.mapper;
17 |
18 | import java.util.List;
19 | import java.util.stream.Collectors;
20 |
21 | import org.springframework.beans.factory.annotation.Autowired;
22 | import org.springframework.beans.factory.annotation.Qualifier;
23 | import org.springframework.util.Assert;
24 |
25 | import com.github.joumenharzli.surveypoc.domain.Question;
26 | import com.github.joumenharzli.surveypoc.domain.Subject;
27 | import com.github.joumenharzli.surveypoc.service.dto.QuestionDto;
28 | import com.github.joumenharzli.surveypoc.service.dto.SubjectDto;
29 | import com.google.common.collect.Multimap;
30 | import com.google.common.collect.Multimaps;
31 |
32 | /**
33 | * A decorator for the mapper for {@link Subject} and {@link SubjectDto}
34 | * for custom methods
35 | *
36 | * @author Joumen Harzli
37 | */
38 | public abstract class SubjectMapperDecorator implements SubjectMapper {
39 |
40 | @Autowired
41 | @Qualifier("delegate")
42 | private SubjectMapper delegate;
43 |
44 | @Autowired
45 | private QuestionMapper questionMapper;
46 |
47 | @Override
48 | public List questionsToSubjectsDto(List questions) {
49 | Assert.notNull(questions, "Cannot map a null list of questions to a list of subject dtos");
50 |
51 | Multimap multimap = Multimaps.index(questions, Question::getSubject);
52 |
53 | return multimap.keySet().stream().map(subject -> {
54 |
55 | SubjectDto subjectDto = delegate.toDto(subject);
56 |
57 | List questionsDtos = multimap.get(subject).stream()
58 | .map(question -> questionMapper.questionToQuestionDto(question)).collect(Collectors.toList());
59 |
60 | subjectDto.addQuestions(questionsDtos);
61 | return subjectDto;
62 |
63 | }).collect(Collectors.toList());
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/github/joumenharzli/surveypoc/service/dto/UserResponsesForQuestionListDto.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Joumen Harzli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | */
15 |
16 | package com.github.joumenharzli.surveypoc.service.dto;
17 |
18 | import java.util.ArrayList;
19 | import java.util.List;
20 | import javax.validation.Valid;
21 |
22 | import org.apache.commons.lang3.builder.EqualsBuilder;
23 | import org.apache.commons.lang3.builder.HashCodeBuilder;
24 | import org.apache.commons.lang3.builder.ToStringBuilder;
25 | import org.hibernate.validator.constraints.NotEmpty;
26 |
27 | /**
28 | * User Responses List
29 | * A wrapper for a list of user response for question dto
30 | * This useful to apply {@code Bean validations}
31 | *
32 | * @author Joumen Harzli
33 | */
34 | public class UserResponsesForQuestionListDto {
35 |
36 | @Valid
37 | @NotEmpty
38 | private List responses;
39 |
40 | public UserResponsesForQuestionListDto() {
41 | this.responses = new ArrayList<>();
42 | }
43 |
44 | public List getResponses() {
45 | return responses;
46 | }
47 |
48 | public void setResponses(List responses) {
49 | this.responses = responses;
50 | }
51 |
52 | @Override
53 | public boolean equals(Object o) {
54 | if (this == o) {
55 | return true;
56 | }
57 |
58 | if (o == null || getClass() != o.getClass()) {
59 | return false;
60 | }
61 |
62 | UserResponsesForQuestionListDto that = (UserResponsesForQuestionListDto) o;
63 |
64 | return new EqualsBuilder()
65 | .append(responses, that.responses)
66 | .isEquals();
67 | }
68 |
69 | @Override
70 | public int hashCode() {
71 | return new HashCodeBuilder(17, 37)
72 | .append(responses)
73 | .toHashCode();
74 | }
75 |
76 | @Override
77 | public String toString() {
78 | return new ToStringBuilder(this)
79 | .append("responses", responses)
80 | .toString();
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/backend/src/test/java/com/github/joumenharzli/surveypoc/service/mapper/SubjectMapperDecoratorTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Joumen Harzli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | */
15 |
16 | package com.github.joumenharzli.surveypoc.service.mapper;
17 |
18 | import java.util.Arrays;
19 | import java.util.List;
20 |
21 | import org.junit.Assert;
22 | import org.junit.Test;
23 | import org.junit.runner.RunWith;
24 | import org.springframework.beans.factory.annotation.Autowired;
25 | import org.springframework.boot.test.context.SpringBootTest;
26 | import org.springframework.test.context.junit4.SpringRunner;
27 |
28 | import com.github.joumenharzli.surveypoc.domain.Question;
29 | import com.github.joumenharzli.surveypoc.domain.Subject;
30 | import com.github.joumenharzli.surveypoc.service.dto.SubjectDto;
31 |
32 | /**
33 | * SubjectMapperDecoratorTest
34 | *
35 | * @author Joumen Harzli
36 | */
37 | @RunWith(SpringRunner.class)
38 | @SpringBootTest
39 | public class SubjectMapperDecoratorTest {
40 |
41 | @Autowired
42 | SubjectMapper subjectMapper;
43 |
44 | @Test
45 | public void questionsToSubjectsDto() throws Exception {
46 | Question q1 = new Question().id(1L).label("question1").subject(new Subject().id(1L));
47 | Question q2 = new Question().id(2L).label("question2").subject(new Subject().id(1L));
48 | Question q3 = new Question().id(3L).label("question3").subject(new Subject().id(2L));
49 |
50 | List subjects = subjectMapper.questionsToSubjectsDto(Arrays.asList(q1, q2, q3));
51 |
52 | Assert.assertNotNull(subjects);
53 | Assert.assertEquals(subjects.size(), 2);
54 | subjects.forEach((this::assertSubjectDtoAndItsQuestionsNotNull));
55 | }
56 |
57 | private void assertSubjectDtoAndItsQuestionsNotNull(SubjectDto subjectDto) {
58 |
59 | Assert.assertNotNull(subjectDto.getQuestions());
60 | subjectDto.getQuestions().forEach((questionDto -> {
61 | Assert.assertNotNull(questionDto.getId());
62 | Assert.assertNotNull(questionDto.getLabel());
63 | }));
64 |
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/github/joumenharzli/surveypoc/config/WebSecurityConfiguration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Joumen Harzli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | */
15 |
16 | package com.github.joumenharzli.surveypoc.config;
17 |
18 | import org.springframework.context.annotation.Bean;
19 | import org.springframework.context.annotation.Configuration;
20 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
21 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
22 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
23 | import org.springframework.web.cors.CorsConfiguration;
24 | import org.springframework.web.cors.CorsConfigurationSource;
25 | import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
26 |
27 | /**
28 | * WebSecurity Configuration
29 | *
30 | * @author Joumen Harzli
31 | */
32 | @Configuration
33 | @EnableWebSecurity
34 | public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
35 |
36 | /**
37 | * Override this method to configure the {@link HttpSecurity}. Typically subclasses
38 | * should not invoke this method by calling super as it may override their
39 | * configuration. The default configuration is:
40 | *
41 | *
42 | * http.authorizeRequests().anyRequest().authenticated().and().formLogin().and().httpBasic();
43 | *
44 | *
45 | * @param http the {@link HttpSecurity} to modify
46 | * @throws Exception if an error occurs
47 | */
48 | @Override
49 | protected void configure(HttpSecurity http) throws Exception {
50 | http
51 | .cors()
52 | .and()
53 | .csrf()
54 | .disable()
55 | .authorizeRequests()
56 | .antMatchers("/v2/api-docs/**", "/swagger-resources/configuration/ui", "/swagger-ui.html").permitAll();
57 | }
58 |
59 | @Bean
60 | CorsConfigurationSource corsConfigurationSource() {
61 | UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
62 | source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
63 | return source;
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/github/joumenharzli/surveypoc/service/mapper/UserResponseMapper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Joumen Harzli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | */
15 |
16 | package com.github.joumenharzli.surveypoc.service.mapper;
17 |
18 | import java.util.List;
19 | import java.util.stream.Collectors;
20 |
21 | import org.mapstruct.Mapper;
22 | import org.mapstruct.Mapping;
23 | import org.springframework.stereotype.Service;
24 |
25 | import com.github.joumenharzli.surveypoc.domain.User;
26 | import com.github.joumenharzli.surveypoc.domain.UserResponse;
27 | import com.github.joumenharzli.surveypoc.service.dto.UserResponseForQuestionDto;
28 |
29 | /**
30 | * Mapper for {@link UserResponse} and {@link UserResponseForQuestionDto}
31 | *
32 | * @author Joumen Harzli
33 | */
34 | @Mapper(componentModel = "spring")
35 | @Service
36 | public interface UserResponseMapper {
37 |
38 | @Mapping(source = "question.id", target = "questionId")
39 | UserResponseForQuestionDto userResponseToUserResponseForQuestionDto(UserResponse entity);
40 |
41 | List userResponseListToUserResponseForQuestionDtoList(List entity);
42 |
43 |
44 | @Mapping(source = "userResponseForQuestion.questionId", target = "question.id")
45 | UserResponse userResponseForQuestionDtoToUserResponse(UserResponseForQuestionDto userResponseForQuestion);
46 |
47 | default List userResponsesForQuestionsDtoToUserResponsesList(List userResponseForQuestions,
48 | User user) {
49 |
50 | return userResponseForQuestions.stream()
51 | .map(
52 | userResponseForQuestionDto -> {
53 | UserResponse userResponse = userResponseForQuestionDtoToUserResponse(userResponseForQuestionDto);
54 | userResponse.setUser(user);
55 | return userResponse;
56 | })
57 | .collect(Collectors.toList());
58 | }
59 |
60 | default List userResponsesForQuestionsToQuestionsIdsList(List userResponsesForQuestions) {
61 | return userResponsesForQuestions.stream()
62 | .map(UserResponseForQuestionDto::getQuestionId)
63 | .collect(Collectors.toList());
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/github/joumenharzli/surveypoc/web/SubjectResource.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Joumen Harzli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | */
15 |
16 | package com.github.joumenharzli.surveypoc.web;
17 |
18 | import java.util.List;
19 |
20 | import org.slf4j.Logger;
21 | import org.slf4j.LoggerFactory;
22 | import org.springframework.web.bind.annotation.GetMapping;
23 | import org.springframework.web.bind.annotation.RequestMapping;
24 | import org.springframework.web.bind.annotation.RestController;
25 |
26 | import com.codahale.metrics.annotation.Timed;
27 | import com.github.joumenharzli.surveypoc.service.SubjectService;
28 | import com.github.joumenharzli.surveypoc.service.dto.SubjectDto;
29 | import com.github.joumenharzli.surveypoc.web.error.RestFieldsErrorsDto;
30 |
31 | import io.swagger.annotations.ApiOperation;
32 | import io.swagger.annotations.ApiResponse;
33 | import io.swagger.annotations.ApiResponses;
34 |
35 | /**
36 | * Rest resource for subject entity
37 | *
38 | * @author Joumen Harzli
39 | */
40 | @RestController
41 | @RequestMapping("/api/v1/subjects")
42 | public class SubjectResource {
43 |
44 | private static final Logger LOGGER = LoggerFactory.getLogger(SubjectResource.class);
45 |
46 | private final SubjectService subjectService;
47 |
48 | public SubjectResource(SubjectService subjectService) {
49 | this.subjectService = subjectService;
50 | }
51 |
52 | /**
53 | * GET /subjects : get all the find all the subjects and their questions.
54 | *
55 | * @return the ResponseEntity with status 200 (OK) and the list the subjects and their questions
56 | */
57 | @ApiOperation(notes = "Returns all the found subjects and their questions.",
58 | value = "Get all subjects and questions",
59 | nickname = "findAllSubjectsAndQuestions")
60 | @ApiResponses({
61 | /* We need to inject {@link RestFieldsErrorsDto} at least one so springfox can added it globally */
62 | @ApiResponse(code = 400, message = "Request content is invalid", response = RestFieldsErrorsDto.class)
63 | })
64 | @Timed
65 | @GetMapping
66 | public List findAllSubjectsAndQuestions() {
67 | LOGGER.debug("REST request to get all the subjects and the questions");
68 |
69 | return subjectService.findAllSubjectsAndQuestions();
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/github/joumenharzli/surveypoc/repository/dao/JdbcUserDao.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Joumen Harzli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | */
15 |
16 | package com.github.joumenharzli.surveypoc.repository.dao;
17 |
18 | import java.util.List;
19 | import java.util.stream.Collectors;
20 |
21 | import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
22 | import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
23 | import org.springframework.stereotype.Repository;
24 | import org.springframework.util.Assert;
25 |
26 | /**
27 | * JDBC implementation for {@link UserDao}
28 | *
29 | * @author Joumen Harzli
30 | */
31 | @Repository
32 | public class JdbcUserDao implements UserDao {
33 |
34 | private static final String FIND_USERS_BY_IDS = "SELECT u.id AS id FROM users u WHERE id IN (:users_ids)";
35 |
36 | private final NamedParameterJdbcTemplate parameterJdbcTemplate;
37 |
38 | public JdbcUserDao(NamedParameterJdbcTemplate parameterJdbcTemplate) {
39 | this.parameterJdbcTemplate = parameterJdbcTemplate;
40 | }
41 |
42 | /**
43 | * Returns the list of ids of the not found users using ids
44 | *
45 | * @param usersIds ids of the users to check
46 | * @return a list of the ids of the not found users
47 | * @throws DaoException if there is an sql exception
48 | * @throws IllegalArgumentException if any given argument is invalid
49 | */
50 | @Override
51 | public List findNonExistingUsersByUsersIds(List usersIds) {
52 |
53 | Assert.notEmpty(usersIds, "Ids of the users cannot be null or empty");
54 | usersIds.forEach(userId -> Assert.notNull(userId, "Id of the user cannot be null"));
55 |
56 | MapSqlParameterSource parameters = new MapSqlParameterSource();
57 | parameters.addValue("users_ids", usersIds);
58 |
59 | try {
60 | List foundUsersId = parameterJdbcTemplate.query(FIND_USERS_BY_IDS, parameters,
61 | (rs, rowNum) -> rs.getLong(1));
62 |
63 | //@formatter:off
64 | return usersIds.stream()
65 | .filter(id -> !foundUsersId.contains(id))
66 | .collect(Collectors.toList());
67 | //@formatter:on
68 |
69 | } catch (Exception exception) {
70 | throw new DaoException("Unable to find users by ids", exception);
71 | }
72 |
73 | }
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/github/joumenharzli/surveypoc/web/error/RestFieldErrorDto.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Joumen Harzli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | */
15 |
16 | package com.github.joumenharzli.surveypoc.web.error;
17 |
18 | import java.io.Serializable;
19 |
20 | import org.apache.commons.lang3.builder.EqualsBuilder;
21 | import org.apache.commons.lang3.builder.HashCodeBuilder;
22 | import org.apache.commons.lang3.builder.ToStringBuilder;
23 |
24 | /**
25 | * A representation for the rest field error
26 | *
27 | * @author Joumen Harzli
28 | */
29 | public class RestFieldErrorDto implements Serializable {
30 |
31 | private String field;
32 | private String code;
33 | private String message;
34 |
35 | public RestFieldErrorDto(String field, String code, String message) {
36 | this.field = field;
37 | this.code = code;
38 | this.message = message;
39 | }
40 |
41 | public String getField() {
42 | return field;
43 | }
44 |
45 | public void setField(String field) {
46 | this.field = field;
47 | }
48 |
49 | public String getCode() {
50 | return code;
51 | }
52 |
53 | public void setCode(String code) {
54 | this.code = code;
55 | }
56 |
57 | public String getMessage() {
58 | return message;
59 | }
60 |
61 | public void setMessage(String message) {
62 | this.message = message;
63 | }
64 |
65 | @Override
66 | public boolean equals(Object o) {
67 | if (this == o) {
68 | return true;
69 | }
70 |
71 | if (o == null || getClass() != o.getClass()) {
72 | return false;
73 | }
74 |
75 | RestFieldErrorDto that = (RestFieldErrorDto) o;
76 |
77 | return new EqualsBuilder()
78 | .append(field, that.field)
79 | .append(code, that.code)
80 | .append(message, that.message)
81 | .isEquals();
82 | }
83 |
84 | @Override
85 | public int hashCode() {
86 | return new HashCodeBuilder(17, 37)
87 | .append(field)
88 | .append(code)
89 | .append(message)
90 | .toHashCode();
91 | }
92 |
93 | @Override
94 | public String toString() {
95 | return new ToStringBuilder(this)
96 | .append("field", field)
97 | .append("code", code)
98 | .append("message", message)
99 | .toString();
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/github/joumenharzli/surveypoc/domain/Question.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Joumen Harzli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | */
15 |
16 | package com.github.joumenharzli.surveypoc.domain;
17 |
18 | import org.apache.commons.lang3.builder.EqualsBuilder;
19 | import org.apache.commons.lang3.builder.HashCodeBuilder;
20 | import org.apache.commons.lang3.builder.ToStringBuilder;
21 |
22 | /**
23 | * Question entity
24 | *
25 | * @author Joumen Harzli
26 | */
27 | public class Question {
28 |
29 | private Long id;
30 | private String label;
31 | private Subject subject;
32 |
33 | public Question id(Long id) {
34 | this.id = id;
35 | return this;
36 | }
37 |
38 | public Question label(String label) {
39 | this.label = label;
40 | return this;
41 | }
42 |
43 | public Question subject(Subject subject) {
44 | this.subject = subject;
45 | return this;
46 | }
47 |
48 | public Long getId() {
49 | return id;
50 | }
51 |
52 | public void setId(Long id) {
53 | this.id = id;
54 | }
55 |
56 | public String getLabel() {
57 | return label;
58 | }
59 |
60 | public void setLabel(String label) {
61 | this.label = label;
62 | }
63 |
64 | public Subject getSubject() {
65 | return subject;
66 | }
67 |
68 | public void setSubject(Subject subject) {
69 | this.subject = subject;
70 | }
71 |
72 | public Long getSubjectId() {
73 | if (subject == null) {
74 | return null;
75 | }
76 | return subject.getId();
77 | }
78 |
79 | @Override
80 | public boolean equals(Object o) {
81 | if (this == o) {
82 | return true;
83 | }
84 |
85 | if (o == null || getClass() != o.getClass()) {
86 | return false;
87 | }
88 |
89 | Question question = (Question) o;
90 |
91 | return new EqualsBuilder()
92 | .append(id, question.id)
93 | .isEquals();
94 | }
95 |
96 | @Override
97 | public int hashCode() {
98 | return new HashCodeBuilder(17, 37)
99 | .append(id)
100 | .toHashCode();
101 | }
102 |
103 | @Override
104 | public String toString() {
105 | return new ToStringBuilder(this)
106 | .append("id", id)
107 | .append("label", label)
108 | .append("subject", subject)
109 | .toString();
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/backend/src/main/resources/logback-spring.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
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 |
48 |
49 |
50 | true
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/github/joumenharzli/surveypoc/service/dto/SubjectDto.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Joumen Harzli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | */
15 |
16 | package com.github.joumenharzli.surveypoc.service.dto;
17 |
18 | import java.util.ArrayList;
19 | import java.util.List;
20 |
21 | import org.apache.commons.lang3.builder.EqualsBuilder;
22 | import org.apache.commons.lang3.builder.HashCodeBuilder;
23 | import org.apache.commons.lang3.builder.ToStringBuilder;
24 | import org.springframework.util.Assert;
25 |
26 | /**
27 | * Subject Dto
28 | *
29 | * @author Joumen Harzli
30 | */
31 | public class SubjectDto {
32 | private Long id;
33 | private String label;
34 | private List questions;
35 |
36 | public Long getId() {
37 | return id;
38 | }
39 |
40 | public void setId(Long id) {
41 | this.id = id;
42 | }
43 |
44 | public String getLabel() {
45 | return label;
46 | }
47 |
48 | public void setLabel(String label) {
49 | this.label = label;
50 | }
51 |
52 | public void addQuestions(List questions) {
53 | Assert.notNull(questions, String.format("Cannot add null questions to subject %s", this.toString()));
54 | if (!questions.isEmpty()) {
55 | questions.forEach(this::addQuestion);
56 | }
57 | }
58 |
59 | public void addQuestion(QuestionDto question) {
60 | Assert.notNull(question, String.format("Cannot add null question to the list of questions in the subject %s",
61 | this.toString()));
62 |
63 | if (questions == null) {
64 | questions = new ArrayList<>();
65 | }
66 | questions.add(question);
67 | }
68 |
69 | public List getQuestions() {
70 | return questions;
71 | }
72 |
73 | public void setQuestions(List questions) {
74 | this.questions = questions;
75 | }
76 |
77 | @Override
78 | public boolean equals(Object o) {
79 | if (this == o) {
80 | return true;
81 | }
82 |
83 | if (o == null || getClass() != o.getClass()) {
84 | return false;
85 | }
86 |
87 | SubjectDto that = (SubjectDto) o;
88 |
89 | return new EqualsBuilder()
90 | .append(id, that.id)
91 | .isEquals();
92 | }
93 |
94 | @Override
95 | public int hashCode() {
96 | return new HashCodeBuilder(17, 37)
97 | .append(id)
98 | .toHashCode();
99 | }
100 |
101 | @Override
102 | public String toString() {
103 | return new ToStringBuilder(this)
104 | .append("id", id)
105 | .append("label", label)
106 | .append("questions", questions)
107 | .toString();
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/github/joumenharzli/surveypoc/web/error/RestFieldsErrorsDto.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Joumen Harzli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | */
15 |
16 | package com.github.joumenharzli.surveypoc.web.error;
17 |
18 | import java.io.Serializable;
19 | import java.util.ArrayList;
20 | import java.util.List;
21 |
22 | import org.apache.commons.lang3.builder.EqualsBuilder;
23 | import org.apache.commons.lang3.builder.HashCodeBuilder;
24 | import org.apache.commons.lang3.builder.ToStringBuilder;
25 | import org.springframework.util.Assert;
26 |
27 | import io.swagger.annotations.ApiModel;
28 |
29 | /**
30 | * A representation for the rest fields errors list
31 | *
32 | * @author Joumen Harzli
33 | */
34 | @ApiModel("RestFieldsErrorsDto")
35 | public class RestFieldsErrorsDto extends RestErrorDto implements Serializable {
36 |
37 | private List fieldsErrors;
38 |
39 | /**
40 | * Constructor for the rest fields errors entity
41 | */
42 | public RestFieldsErrorsDto(String code, String message) {
43 | super(code, message);
44 | fieldsErrors = new ArrayList<>();
45 | }
46 |
47 | /**
48 | * Add a rest field error to the list of fields errors
49 | *
50 | * @param error error to add to the list
51 | */
52 | public void addError(RestFieldErrorDto error) {
53 | Assert.notNull(error, "Cannot add a null error to the list of fields errors");
54 |
55 | if (fieldsErrors == null) {
56 | fieldsErrors = new ArrayList<>();
57 | }
58 |
59 | fieldsErrors.add(error);
60 | }
61 |
62 | /**
63 | * Get the list of the fields errors
64 | *
65 | * @return list of fields errors
66 | */
67 | public List getFieldsErrors() {
68 | return fieldsErrors;
69 | }
70 |
71 | @Override
72 | public boolean equals(Object o) {
73 | if (this == o) {
74 | return true;
75 | }
76 |
77 | if (o == null || getClass() != o.getClass()) {
78 | return false;
79 | }
80 |
81 | RestFieldsErrorsDto that = (RestFieldsErrorsDto) o;
82 |
83 | return new EqualsBuilder()
84 | .appendSuper(super.equals(o))
85 | .append(fieldsErrors, that.fieldsErrors)
86 | .isEquals();
87 | }
88 |
89 | @Override
90 | public int hashCode() {
91 | return new HashCodeBuilder(17, 37)
92 | .appendSuper(super.hashCode())
93 | .append(fieldsErrors)
94 | .toHashCode();
95 | }
96 |
97 | @Override
98 | public String toString() {
99 | return new ToStringBuilder(this)
100 | .append("fieldsErrors", fieldsErrors)
101 | .toString();
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/frontend/src/app/material.module.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Joumen Harzli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | */
15 |
16 | import { NgModule } from '@angular/core';
17 | import { CommonModule } from '@angular/common';
18 |
19 | import { A11yModule } from '@angular/cdk/a11y';
20 | import { BidiModule } from '@angular/cdk/bidi';
21 | import { ObserversModule } from '@angular/cdk/observers';
22 | import { OverlayModule } from '@angular/cdk/overlay';
23 | import { PlatformModule } from '@angular/cdk/platform';
24 | import { PortalModule } from '@angular/cdk/portal';
25 | import { ScrollDispatchModule } from '@angular/cdk/scrolling';
26 | import { CdkStepperModule } from '@angular/cdk/stepper';
27 | import { CdkTableModule } from '@angular/cdk/table';
28 | import {
29 | MatAutocompleteModule,
30 | MatButtonModule,
31 | MatButtonToggleModule,
32 | MatCardModule,
33 | MatCheckboxModule,
34 | MatChipsModule,
35 | MatDatepickerModule,
36 | MatDialogModule,
37 | MatExpansionModule,
38 | MatGridListModule,
39 | MatIconModule,
40 | MatInputModule,
41 | MatListModule,
42 | MatMenuModule,
43 | MatNativeDateModule,
44 | MatProgressBarModule,
45 | MatProgressSpinnerModule,
46 | MatRadioModule,
47 | MatRippleModule,
48 | MatSelectModule,
49 | MatSidenavModule,
50 | MatSliderModule,
51 | MatSlideToggleModule,
52 | MatSnackBarModule,
53 | MatStepperModule,
54 | MatTableModule,
55 | MatTabsModule,
56 | MatToolbarModule,
57 | MatTooltipModule,
58 | } from '@angular/material';
59 |
60 |
61 | @NgModule({
62 | exports: [
63 | // CDK
64 | A11yModule,
65 | BidiModule,
66 | ObserversModule,
67 | OverlayModule,
68 | PlatformModule,
69 | PortalModule,
70 | ScrollDispatchModule,
71 | CdkStepperModule,
72 | CdkTableModule,
73 |
74 | // Material
75 | MatAutocompleteModule,
76 | MatButtonModule,
77 | MatButtonToggleModule,
78 | MatCardModule,
79 | MatCheckboxModule,
80 | MatChipsModule,
81 | MatDatepickerModule,
82 | MatDialogModule,
83 | MatExpansionModule,
84 | MatGridListModule,
85 | MatIconModule,
86 | MatInputModule,
87 | MatListModule,
88 | MatMenuModule,
89 | MatProgressBarModule,
90 | MatProgressSpinnerModule,
91 | MatRadioModule,
92 | MatRippleModule,
93 | MatSelectModule,
94 | MatSidenavModule,
95 | MatSlideToggleModule,
96 | MatSliderModule,
97 | MatSnackBarModule,
98 | MatStepperModule,
99 | MatTableModule,
100 | MatTabsModule,
101 | MatToolbarModule,
102 | MatTooltipModule,
103 | MatNativeDateModule,
104 | ]
105 | })
106 | export class MaterialModule { }
107 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/github/joumenharzli/surveypoc/domain/UserResponse.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Joumen Harzli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | */
15 |
16 | package com.github.joumenharzli.surveypoc.domain;
17 |
18 | import org.apache.commons.lang3.builder.EqualsBuilder;
19 | import org.apache.commons.lang3.builder.HashCodeBuilder;
20 | import org.apache.commons.lang3.builder.ToStringBuilder;
21 |
22 | /**
23 | * User Response entity
24 | *
25 | * @author Joumen Harzli
26 | */
27 | public class UserResponse {
28 |
29 | private String content;
30 | private Question question;
31 | private User user;
32 |
33 | public UserResponse content(String content) {
34 | this.content = content;
35 | return this;
36 | }
37 |
38 | public UserResponse user(User user) {
39 | this.user = user;
40 | return this;
41 | }
42 |
43 | public UserResponse question(Question question) {
44 | this.question = question;
45 | return this;
46 | }
47 |
48 | public String getContent() {
49 | return content;
50 | }
51 |
52 | public void setContent(String content) {
53 | this.content = content;
54 | }
55 |
56 | public Question getQuestion() {
57 | return question;
58 | }
59 |
60 | public void setQuestion(Question question) {
61 | this.question = question;
62 | }
63 |
64 | public Long getQuestionId() {
65 | if (this.question == null) {
66 | return null;
67 | }
68 | return question.getId();
69 | }
70 |
71 | public Long getUserId() {
72 | if (this.user == null) {
73 | return null;
74 | }
75 | return user.getId();
76 | }
77 |
78 | public User getUser() {
79 | return user;
80 | }
81 |
82 | public void setUser(User user) {
83 | this.user = user;
84 | }
85 |
86 | @Override
87 | public boolean equals(Object o) {
88 | if (this == o) {
89 | return true;
90 | }
91 |
92 | if (o == null || getClass() != o.getClass()) {
93 | return false;
94 | }
95 |
96 | UserResponse that = (UserResponse) o;
97 |
98 | return new EqualsBuilder()
99 | .append(question, that.question)
100 | .append(user, that.user)
101 | .isEquals();
102 | }
103 |
104 | @Override
105 | public int hashCode() {
106 | return new HashCodeBuilder(17, 37)
107 | .append(question)
108 | .append(user)
109 | .toHashCode();
110 | }
111 |
112 | @Override
113 | public String toString() {
114 | return new ToStringBuilder(this)
115 | .append("content", content)
116 | .append("question", question)
117 | .append("user", user)
118 | .toString();
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/frontend/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "rulesDirectory": [
3 | "node_modules/codelyzer"
4 | ],
5 | "rules": {
6 | "arrow-return-shorthand": true,
7 | "callable-types": true,
8 | "class-name": true,
9 | "comment-format": [
10 | true,
11 | "check-space"
12 | ],
13 | "curly": true,
14 | "eofline": true,
15 | "forin": true,
16 | "import-blacklist": [
17 | true,
18 | "rxjs"
19 | ],
20 | "import-spacing": true,
21 | "indent": [
22 | true,
23 | "spaces"
24 | ],
25 | "interface-over-type-literal": true,
26 | "label-position": true,
27 | "max-line-length": [
28 | true,
29 | 140
30 | ],
31 | "member-access": false,
32 | "member-ordering": [
33 | true,
34 | {
35 | "order": [
36 | "static-field",
37 | "instance-field",
38 | "static-method",
39 | "instance-method"
40 | ]
41 | }
42 | ],
43 | "no-arg": true,
44 | "no-bitwise": true,
45 | "no-console": [
46 | true,
47 | "debug",
48 | "info",
49 | "time",
50 | "timeEnd",
51 | "trace"
52 | ],
53 | "no-construct": true,
54 | "no-debugger": true,
55 | "no-duplicate-super": true,
56 | "no-empty": false,
57 | "no-empty-interface": true,
58 | "no-eval": true,
59 | "no-inferrable-types": [
60 | true,
61 | "ignore-params"
62 | ],
63 | "no-misused-new": true,
64 | "no-non-null-assertion": true,
65 | "no-shadowed-variable": true,
66 | "no-string-literal": false,
67 | "no-string-throw": true,
68 | "no-switch-case-fall-through": true,
69 | "no-trailing-whitespace": true,
70 | "no-unnecessary-initializer": true,
71 | "no-unused-expression": true,
72 | "no-use-before-declare": true,
73 | "no-var-keyword": true,
74 | "object-literal-sort-keys": false,
75 | "one-line": [
76 | true,
77 | "check-open-brace",
78 | "check-catch",
79 | "check-else",
80 | "check-whitespace"
81 | ],
82 | "prefer-const": true,
83 | "quotemark": [
84 | true,
85 | "single"
86 | ],
87 | "radix": true,
88 | "semicolon": [
89 | true,
90 | "always"
91 | ],
92 | "triple-equals": [
93 | true,
94 | "allow-null-check"
95 | ],
96 | "typedef-whitespace": [
97 | true,
98 | {
99 | "call-signature": "nospace",
100 | "index-signature": "nospace",
101 | "parameter": "nospace",
102 | "property-declaration": "nospace",
103 | "variable-declaration": "nospace"
104 | }
105 | ],
106 | "typeof-compare": true,
107 | "unified-signatures": true,
108 | "variable-name": false,
109 | "whitespace": [
110 | true,
111 | "check-branch",
112 | "check-decl",
113 | "check-operator",
114 | "check-separator",
115 | "check-type"
116 | ],
117 | "directive-selector": [
118 | true,
119 | "attribute",
120 | "app",
121 | "camelCase"
122 | ],
123 | "component-selector": [
124 | true,
125 | "element",
126 | "app",
127 | "kebab-case"
128 | ],
129 | "use-input-property-decorator": true,
130 | "use-output-property-decorator": true,
131 | "use-host-property-decorator": true,
132 | "no-input-rename": true,
133 | "no-output-rename": true,
134 | "use-life-cycle-interface": true,
135 | "use-pipe-transform-interface": true,
136 | "component-class-suffix": true,
137 | "directive-class-suffix": true,
138 | "no-access-missing-member": true,
139 | "templates-use-public": true,
140 | "invoke-injectable": true
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/github/joumenharzli/surveypoc/config/MetricsConfiguration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Joumen Harzli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | */
15 |
16 | package com.github.joumenharzli.surveypoc.config;
17 |
18 | import java.lang.management.ManagementFactory;
19 |
20 | import org.springframework.context.annotation.Bean;
21 | import org.springframework.context.annotation.Configuration;
22 |
23 | import com.codahale.metrics.JmxReporter;
24 | import com.codahale.metrics.JvmAttributeGaugeSet;
25 | import com.codahale.metrics.MetricRegistry;
26 | import com.codahale.metrics.health.HealthCheckRegistry;
27 | import com.codahale.metrics.jvm.*;
28 | import com.ryantenney.metrics.spring.config.annotation.EnableMetrics;
29 | import com.ryantenney.metrics.spring.config.annotation.MetricsConfigurerAdapter;
30 | import com.zaxxer.hikari.HikariDataSource;
31 |
32 | /**
33 | * Configuration of Dropwizard metrics
34 | * Those configurations are accessible via {@code /metrics} endpoint
35 | * or via the JMX
36 | *
37 | * @author Joumen Harzli
38 | */
39 | @EnableMetrics(proxyTargetClass = true)
40 | @Configuration
41 | public class MetricsConfiguration extends MetricsConfigurerAdapter {
42 |
43 | private static final String PROP_METRIC_REG_JVM_MEMORY = "jvm.memory";
44 | private static final String PROP_METRIC_REG_JVM_GARBAGE = "jvm.garbage";
45 | private static final String PROP_METRIC_REG_JVM_THREADS = "jvm.threads";
46 | private static final String PROP_METRIC_REG_JVM_FILES = "jvm.files";
47 | private static final String PROP_METRIC_REG_JVM_BUFFERS = "jvm.buffers";
48 | private static final String PROP_METRIC_REG_JVM_ATTRIBUTE_SET = "jvm.attributes";
49 |
50 | private final HikariDataSource hikariDataSource;
51 |
52 | public MetricsConfiguration(HikariDataSource hikariDataSource) {
53 | this.hikariDataSource = hikariDataSource;
54 | }
55 |
56 | @Bean
57 | @Override
58 | public MetricRegistry getMetricRegistry() {
59 | MetricRegistry metricRegistry = new MetricRegistry();
60 |
61 | registerJVMMetrics(metricRegistry);
62 | registerDatasourceMetrics(metricRegistry);
63 | reportMetricsViaJMX(metricRegistry);
64 |
65 | return metricRegistry;
66 | }
67 |
68 | @Bean
69 | @Override
70 | public HealthCheckRegistry getHealthCheckRegistry() {
71 | return new HealthCheckRegistry();
72 | }
73 |
74 | private void registerJVMMetrics(MetricRegistry metricRegistry) {
75 | metricRegistry.register(PROP_METRIC_REG_JVM_MEMORY, new MemoryUsageGaugeSet());
76 | metricRegistry.register(PROP_METRIC_REG_JVM_GARBAGE, new GarbageCollectorMetricSet());
77 | metricRegistry.register(PROP_METRIC_REG_JVM_THREADS, new ThreadStatesGaugeSet());
78 | metricRegistry.register(PROP_METRIC_REG_JVM_FILES, new FileDescriptorRatioGauge());
79 | metricRegistry.register(PROP_METRIC_REG_JVM_BUFFERS, new BufferPoolMetricSet(ManagementFactory.getPlatformMBeanServer()));
80 | metricRegistry.register(PROP_METRIC_REG_JVM_ATTRIBUTE_SET, new JvmAttributeGaugeSet());
81 | }
82 |
83 | private void registerDatasourceMetrics(MetricRegistry metricRegistry) {
84 | hikariDataSource.setMetricRegistry(metricRegistry);
85 | }
86 |
87 | private void reportMetricsViaJMX(MetricRegistry metricRegistry) {
88 | JmxReporter jmxReporter = JmxReporter.forRegistry(metricRegistry).build();
89 | jmxReporter.start();
90 | }
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/frontend/src/app/survey/containers/survey-container/survey-container.component.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Joumen Harzli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | */
15 |
16 | import { Component, OnInit } from '@angular/core';
17 | import { FormArray, FormBuilder, Validators } from '@angular/forms';
18 | import { findIndex, flatMap } from 'lodash';
19 | import 'rxjs/add/operator/switchMap';
20 |
21 | import { SurveyService } from '../../services/survey.service';
22 | import { Subject, UserResponse, Question } from '../../models/survey.models';
23 | import { MatSnackBar } from '@angular/material';
24 | import { FieldError } from '../../../shared/models/field-error.model';
25 | import { RestError } from '../../../shared/models/rest-error.model';
26 |
27 | @Component({
28 | selector: 'app-survey-container',
29 | templateUrl: './survey-container.component.html'
30 | })
31 | export class SurveyContainerComponent implements OnInit {
32 |
33 | loading = false;
34 | submitting = false;
35 | error = null;
36 |
37 | subjects: Subject[] = [];
38 | responses: UserResponse[] = [];
39 | fieldsErrors: FieldError[];
40 |
41 | constructor(private httpService: SurveyService, private snackBar: MatSnackBar) { }
42 |
43 | ngOnInit() {
44 | this.loadAllSubjectsAndQuestionsAndResponses();
45 | }
46 |
47 | loadAllSubjectsAndQuestionsAndResponses() {
48 | this.loading = true;
49 | this.error = null;
50 | this.httpService.getAllSubjectsAndQuestions()
51 | .switchMap(subjects => this.loadResponsesOfConnectedUserForQuestions(subjects),
52 | (subjects, responses) => ({ subjects: subjects, responses: responses }))
53 | .subscribe((result) => {
54 | this.subjects = result.subjects;
55 | this.responses = result.responses;
56 | this.loading = false;
57 | }, (error) => this.handleHttpError(error));
58 | }
59 |
60 | /**
61 | * handle the form submition
62 | *
63 | * @param responses of the user
64 | * @memberof AppComponent
65 | */
66 | submitForm(responses) {
67 | this.submitting = true;
68 | this.httpService.saveResponsesOfConnectedUserForQuestions(responses)
69 | .subscribe((savedResponses) => {
70 | this.responses = savedResponses;
71 | this.loading = false;
72 | this.submitting = false;
73 | this.openSnackBar('Responses submitted');
74 | }, (error) => this.handleHttpError(error));
75 | }
76 |
77 | loadResponsesOfConnectedUserForQuestions(subjects: Subject[]) {
78 | const questionIds = flatMap(subjects, subject => subject.questions).map(question => question.id);
79 | return this.httpService.getResponsesOfConnectedUserForQuestions(questionIds);
80 | }
81 |
82 | handleHttpError(errorResponse) {
83 | const error = errorResponse.error as RestError;
84 |
85 | if (error && error.message) {
86 | if (error.code === 'error.validation') {
87 | this.fieldsErrors = error.fieldsErrors;
88 | }
89 | const errorMessage = error.message;
90 | this.error = error;
91 | this.openSnackBar(errorMessage);
92 | } else {
93 | this.error = errorResponse;
94 | this.openSnackBar('Failed to connect to the server');
95 | }
96 | this.submitting = false;
97 | this.loading = false;
98 | }
99 |
100 | openSnackBar(message) {
101 | this.snackBar.open(message, 'Close', {
102 | duration: 2000,
103 | horizontalPosition: 'left'
104 | });
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/github/joumenharzli/surveypoc/repository/dao/JdbcQuestionDao.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Joumen Harzli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | */
15 |
16 | package com.github.joumenharzli.surveypoc.repository.dao;
17 |
18 | import java.util.List;
19 | import java.util.stream.Collectors;
20 |
21 | import org.simpleflatmapper.jdbc.spring.JdbcTemplateMapperFactory;
22 | import org.springframework.jdbc.core.JdbcTemplate;
23 | import org.springframework.jdbc.core.ResultSetExtractor;
24 | import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
25 | import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
26 | import org.springframework.stereotype.Repository;
27 | import org.springframework.util.Assert;
28 |
29 | import com.github.joumenharzli.surveypoc.domain.Question;
30 |
31 | /**
32 | * JDBC implementation for {@link QuestionDao}
33 | *
34 | * @author Joumen Harzli
35 | */
36 | @Repository
37 | public class JdbcQuestionDao implements QuestionDao {
38 |
39 | private static final String SELECT_QUESTIONS_AND_SUBJECTS = "SELECT q.id AS id, q.label AS label, s.id AS subject_id, " +
40 | " s.label AS subject_label FROM questions q" +
41 | " LEFT OUTER JOIN subjects s ON q.subject_id = s.id" +
42 | " ORDER BY id";
43 |
44 | private static final String FIND_QUESTIONS_BY_IDS = "SELECT q.id AS id FROM questions q WHERE id IN (:questions_ids)";
45 |
46 | private final NamedParameterJdbcTemplate parameterJdbcTemplate;
47 | private final JdbcTemplate jdbcTemplate;
48 |
49 | private final ResultSetExtractor> selectQuestionAndSubjectResultSetExtractor =
50 | JdbcTemplateMapperFactory
51 | .newInstance()
52 | .addKeys("id", "subject_id")
53 | .newResultSetExtractor(Question.class);
54 |
55 | public JdbcQuestionDao(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate parameterJdbcTemplate) {
56 | this.jdbcTemplate = jdbcTemplate;
57 | this.parameterJdbcTemplate = parameterJdbcTemplate;
58 | }
59 |
60 | /**
61 | * find all questions with their subjects
62 | *
63 | * @return a list of the questions with subjects
64 | * @throws DaoException if there is an sql exception
65 | */
66 | @Override
67 | public List findAllQuestionsAndSubjects() {
68 | try {
69 | return jdbcTemplate.query(SELECT_QUESTIONS_AND_SUBJECTS, selectQuestionAndSubjectResultSetExtractor);
70 | } catch (Exception exception) {
71 | throw new DaoException("Unable to find subjects and questions", exception);
72 | }
73 | }
74 |
75 | /**
76 | * Returns the list of ids of the not found questions using ids
77 | *
78 | * @param questionsIds ids of the questions to check
79 | * @return a list of the ids of the not found questions
80 | * @throws DaoException if there is an sql exception
81 | * @throws IllegalArgumentException if any given argument is invalid
82 | */
83 | @Override
84 | public List findNonExistingQuestionsByQuestionsIds(List questionsIds) {
85 |
86 | Assert.notEmpty(questionsIds, "Ids of the questions cannot be null or empty");
87 | questionsIds.forEach(questionId -> Assert.notNull(questionId, "Id of the question cannot be null"));
88 |
89 | MapSqlParameterSource parameters = new MapSqlParameterSource();
90 | parameters.addValue("questions_ids", questionsIds);
91 |
92 | try {
93 | List foundQuestionsId = parameterJdbcTemplate.query(FIND_QUESTIONS_BY_IDS, parameters,
94 | (rs, rowNum) -> rs.getLong(1));
95 |
96 | //@formatter:off
97 | return questionsIds.stream()
98 | .filter(id -> !foundQuestionsId.contains(id))
99 | .collect(Collectors.toList());
100 | //@formatter:on
101 | } catch (Exception exception) {
102 | throw new DaoException("Unable to find questions by ids", exception);
103 | }
104 |
105 | }
106 |
107 | }
108 |
--------------------------------------------------------------------------------
/backend/src/main/java/com/github/joumenharzli/surveypoc/config/SwaggerConfiguration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Joumen Harzli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | */
15 |
16 | package com.github.joumenharzli.surveypoc.config;
17 |
18 | import java.util.Arrays;
19 | import java.util.Collections;
20 |
21 | import org.springframework.context.annotation.Bean;
22 | import org.springframework.context.annotation.Configuration;
23 | import org.springframework.core.annotation.AnnotationUtils;
24 | import org.springframework.http.HttpStatus;
25 | import org.springframework.http.MediaType;
26 | import org.springframework.web.bind.annotation.RequestMethod;
27 |
28 | import com.github.joumenharzli.surveypoc.web.error.RestErrorDto;
29 | import com.github.joumenharzli.surveypoc.web.error.RestFieldsErrorsDto;
30 | import com.google.common.collect.Sets;
31 |
32 | import io.swagger.annotations.ApiModel;
33 | import springfox.documentation.builders.*;
34 | import springfox.documentation.schema.ModelRef;
35 | import springfox.documentation.service.ApiInfo;
36 | import springfox.documentation.service.Contact;
37 | import springfox.documentation.service.Parameter;
38 | import springfox.documentation.service.ResponseMessage;
39 | import springfox.documentation.spi.DocumentationType;
40 | import springfox.documentation.spring.web.plugins.Docket;
41 | import springfox.documentation.swagger2.annotations.EnableSwagger2;
42 |
43 | /**
44 | * Swagger Configuration
45 | *
46 | * @author Joumen Harzli
47 | */
48 | @Configuration
49 | @EnableSwagger2
50 | public class SwaggerConfiguration {
51 |
52 |
53 | @Bean
54 | public Docket api() {
55 | return new Docket(DocumentationType.SWAGGER_2)
56 | .apiInfo(apiInfo())
57 | .globalOperationParameters(Collections.singletonList(acceptLanguageHeader()))
58 | .useDefaultResponseMessages(false)
59 | .globalResponseMessage(RequestMethod.GET, Arrays.asList(badRequest(), internalServerError()))
60 | .globalResponseMessage(RequestMethod.POST, Arrays.asList(badRequest(), internalServerError()))
61 | .groupName("api")
62 | .produces(Sets.newHashSet(MediaType.APPLICATION_JSON_VALUE))
63 | .consumes(Sets.newHashSet(MediaType.APPLICATION_JSON_VALUE))
64 | .select()
65 | .apis(RequestHandlerSelectors.basePackage("com.github.joumenharzli"))
66 | .paths(PathSelectors.any())
67 | .build();
68 | }
69 |
70 | private ApiInfo apiInfo() {
71 | return new ApiInfoBuilder()
72 | .title("Survey API")
73 | .description("This is a survey api where you can see the list of subject and questions and respond to them")
74 | .contact(new Contact("Joumen Ali Harzli",
75 | "https://github.com/joumenharzli/survey-example-spring-boot-angular",
76 | ""))
77 | .license("Apache License Version 2.0")
78 | .licenseUrl("https://github.com/joumenharzli/survey-example-spring-boot-angular/blob/master/LICENSE")
79 | .version("1.0")
80 | .build();
81 |
82 | }
83 |
84 | private Parameter acceptLanguageHeader() {
85 | return new ParameterBuilder()
86 | .name("Accept-language")
87 | .description("Use the specified locale instead of English US")
88 | .modelRef(new ModelRef("string"))
89 | .parameterType("header")
90 | .required(false)
91 | .build();
92 | }
93 |
94 |
95 | private ResponseMessage internalServerError() {
96 | return responseMessage(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Something unexpected went wrong", RestErrorDto.class);
97 | }
98 |
99 | private ResponseMessage badRequest() {
100 | return responseMessage(HttpStatus.BAD_REQUEST.value(), "Request content is invalid", RestFieldsErrorsDto.class);
101 | }
102 |
103 | private ResponseMessage responseMessage(int status, String message, Class clazz) {
104 | return new ResponseMessageBuilder()
105 | .code(status)
106 | .message(message)
107 | .responseModel(new ModelRef(AnnotationUtils.findAnnotation(clazz, ApiModel.class).value()))
108 | .build();
109 | }
110 |
111 | }
112 |
--------------------------------------------------------------------------------
/backend/src/test/java/com/github/joumenharzli/surveypoc/repository/dao/UserResponseDaoTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Joumen Harzli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 | * in compliance with the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License
10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 | * or implied. See the License for the specific language governing permissions and limitations under
12 | * the License.
13 | *
14 | */
15 |
16 | package com.github.joumenharzli.surveypoc.repository.dao;
17 |
18 | import java.util.Arrays;
19 | import java.util.List;
20 |
21 | import org.apache.commons.lang3.RandomStringUtils;
22 | import org.junit.Assert;
23 | import org.junit.Before;
24 | import org.junit.Test;
25 | import org.junit.runner.RunWith;
26 | import org.springframework.beans.factory.annotation.Autowired;
27 | import org.springframework.boot.test.context.SpringBootTest;
28 | import org.springframework.jdbc.core.JdbcTemplate;
29 | import org.springframework.test.context.junit4.SpringRunner;
30 | import org.springframework.test.jdbc.JdbcTestUtils;
31 |
32 | import com.github.joumenharzli.surveypoc.domain.Question;
33 | import com.github.joumenharzli.surveypoc.domain.User;
34 | import com.github.joumenharzli.surveypoc.domain.UserResponse;
35 |
36 | /**
37 | * UserResponseDaoTest
38 | *
39 | * @author Joumen Harzli
40 | */
41 | @RunWith(SpringRunner.class)
42 | @SpringBootTest
43 | public class UserResponseDaoTest {
44 |
45 | @Autowired
46 | UserResponseDao userResponseDao;
47 |
48 | @Autowired
49 | JdbcTemplate jdbcTemplate;
50 |
51 | @Before
52 | public void init() {
53 | JdbcTestUtils.deleteFromTables(jdbcTemplate, "user_responses");
54 | }
55 |
56 | @Test
57 | public void addUserResponsesTest() throws Exception {
58 |
59 | Long userId = 1L;
60 | Long question1Id = 3L;
61 | Long question2Id = 4L;
62 | String responseContent = RandomStringUtils.randomAlphabetic(5);
63 |
64 | int[] result = addUserResponses(userId, question1Id, question2Id, responseContent, responseContent);
65 | Arrays.stream(result).forEach((updatedRow) -> Assert.assertEquals(updatedRow, 1));
66 |
67 | List userResponses = findResponsesOfUserForQuestions(userId, question1Id, question2Id);
68 | userResponses.forEach((userResponse -> Assert.assertEquals(userResponse.getContent(), responseContent)));
69 | }
70 |
71 | @Test
72 | public void updateUserResponsesTest() {
73 |
74 | Long userId = 1L;
75 | Long question1Id = 3L;
76 | Long question2Id = 4L;
77 |
78 | String nonUpdatedContent = RandomStringUtils.randomAlphabetic(5);
79 | String updatedContent = RandomStringUtils.randomAlphabetic(5);
80 |
81 | addUserResponses(userId, question1Id, question2Id, nonUpdatedContent, nonUpdatedContent);
82 |
83 | List userResponses = findResponsesOfUserForQuestions(userId, question1Id, question2Id);
84 | userResponses.forEach((userResponse -> userResponse.setContent(updatedContent)));
85 |
86 | int[] result = userResponseDao.updateUserResponses(userResponses);
87 | Arrays.stream(result).forEach((updatedRow) -> Assert.assertEquals(updatedRow, 1));
88 |
89 | List updatedUserResponses = findResponsesOfUserForQuestions(userId, question1Id, question2Id);
90 | updatedUserResponses.forEach((userResponse -> Assert.assertEquals(userResponse.getContent(), updatedContent)));
91 |
92 | }
93 |
94 | private int[] addUserResponses(Long userId, Long question1Id, Long question2Id,
95 | String response1Content, String response2Content) {
96 | UserResponse userResponse1 = createUserResponse(userId, question1Id, response1Content);
97 | UserResponse userResponse2 = createUserResponse(userId, question2Id, response2Content);
98 |
99 | return userResponseDao.addUserResponses(Arrays.asList(userResponse1, userResponse2));
100 | }
101 |
102 | private List findResponsesOfUserForQuestions(Long userId, Long question1Id, Long question2Id) {
103 | return userResponseDao.findResponsesOfUserByUserIdAndQuestionIds(userId,
104 | Arrays.asList(question1Id, question2Id));
105 | }
106 |
107 | private UserResponse createUserResponse(Long userId, Long questionId, String responseContent) {
108 | return new UserResponse()
109 | .user(createUser(userId))
110 | .question(createQuestion(questionId))
111 | .content(responseContent);
112 | }
113 |
114 | private Question createQuestion(Long questionId) {
115 | return new Question()
116 | .id(questionId);
117 | }
118 |
119 | private User createUser(Long userId) {
120 | return new User()
121 | .id(userId);
122 | }
123 |
124 | }
125 |
--------------------------------------------------------------------------------
/frontend/src/favicon.ico:
--------------------------------------------------------------------------------
1 | h &