├── .npmrc ├── src └── main │ ├── js │ └── app │ │ ├── service │ │ └── baseUrl.js │ │ ├── constants │ │ ├── actionType.js │ │ └── routes.js │ │ ├── axios │ │ └── url.js │ │ ├── action │ │ └── actions.js │ │ ├── reduser │ │ ├── redusers.js │ │ ├── localeReduser.js │ │ └── reduser.js │ │ ├── index.jsx │ │ ├── components │ │ ├── pages │ │ │ ├── home.jsx │ │ │ ├── state.jsx │ │ │ ├── upload.jsx │ │ │ ├── webSocket.jsx │ │ │ └── rest.jsx │ │ ├── locale.jsx │ │ └── layout.jsx │ │ ├── router │ │ └── routerSwitch.jsx │ │ ├── application │ │ ├── localeProvider.jsx │ │ └── application.jsx │ │ └── i18n │ │ ├── messages-ru.js │ │ └── messages-en.js │ ├── webapp │ └── WEB-INF │ │ ├── jboss-web.xml │ │ └── web.xml │ ├── java │ └── ru │ │ └── impressionbit │ │ └── server │ │ ├── domain │ │ ├── Message.java │ │ └── User.java │ │ ├── Main.java │ │ ├── controller │ │ ├── IndexController.java │ │ ├── WebSocketController.java │ │ ├── RestController.java │ │ └── UploaderController.java │ │ ├── configuration │ │ └── WebSocketConfig.java │ │ └── service │ │ └── ORMUserService.java │ └── resources │ └── application.yml ├── image └── image.jpg ├── .babelrc ├── gradle ├── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties └── gradle ├── .gitignore ├── webpack.config.idea.js ├── README.md ├── package.json ├── gradlew.bat ├── webpack.config.babel.js └── gradlew /.npmrc: -------------------------------------------------------------------------------- 1 | registry=https://registry.npmjs.org/ -------------------------------------------------------------------------------- /src/main/js/app/service/baseUrl.js: -------------------------------------------------------------------------------- 1 | export const baseUrl = window.location.origin; -------------------------------------------------------------------------------- /image/image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/impressionBit/react-start/HEAD/image/image.jpg -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["env", "react"], 3 | "plugins": ["transform-decorators-legacy"] 4 | } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/impressionBit/react-start/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /src/main/js/app/constants/actionType.js: -------------------------------------------------------------------------------- 1 | // Action types 2 | export const SET_VALUE = 'SET_VALUE'; 3 | export const SET_LOCALE = 'SET_LOCALE'; -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/jboss-web.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | /application 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .gradle 3 | *.iml 4 | build 5 | node_modules 6 | npm-debug.log 7 | logs/ 8 | out/ 9 | /src/main/resources/templates/ 10 | /src/main/resources/static/ 11 | package-lock.json -------------------------------------------------------------------------------- /src/main/js/app/axios/url.js: -------------------------------------------------------------------------------- 1 | import {baseUrl} from 'app/service/baseUrl' 2 | 3 | const api = `${baseUrl}/api/`; 4 | 5 | // url 6 | export const rest = `${api}rest`; 7 | 8 | // upload 9 | export const upload = `${api}upload`; -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.8.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /src/main/js/app/action/actions.js: -------------------------------------------------------------------------------- 1 | import * as actionType from "app/constants/actionType"; 2 | 3 | // action 4 | export const setValue = (value = '') => ({type: actionType.SET_VALUE, value}); 5 | export const setLocale = (locale = '') => ({type: actionType.SET_LOCALE, locale}); -------------------------------------------------------------------------------- /src/main/js/app/reduser/redusers.js: -------------------------------------------------------------------------------- 1 | import {combineReducers} from 'redux'; 2 | 3 | import {reducer} from 'app/reduser/reduser'; 4 | import localeReducer from 'app/reduser/localeReduser'; 5 | 6 | export const reducers = combineReducers({ 7 | state: reducer, 8 | intl: localeReducer, 9 | }); -------------------------------------------------------------------------------- /src/main/java/ru/impressionbit/server/domain/Message.java: -------------------------------------------------------------------------------- 1 | package ru.impressionbit.server.domain; 2 | 3 | public class Message { 4 | 5 | private String message; 6 | 7 | public Message(String message) { 8 | this.message = message; 9 | } 10 | 11 | public String getMessage() { 12 | return message; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/js/app/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import Application from 'app/application/application'; 4 | 5 | const {document} = window; 6 | 7 | function render() { 8 | ReactDOM.render(, window.document.getElementById('root')); 9 | } 10 | 11 | document.addEventListener('DOMContentLoaded', render); 12 | -------------------------------------------------------------------------------- /src/main/java/ru/impressionbit/server/Main.java: -------------------------------------------------------------------------------- 1 | package ru.impressionbit.server; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class Main { 8 | public static void main(String[] args) { 9 | SpringApplication.run(Main.class, args); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /webpack.config.idea.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | // Add module resolution for IDEA coding assistance 4 | module.exports = { 5 | resolve: { 6 | extensions: ['.js', '.jsx'], 7 | // Select JS sources 8 | modules: [ 9 | path.join(__dirname, 'node_modules'), 10 | path.join(__dirname, 'src/main/js') 11 | ], 12 | symlinks: false 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /src/main/java/ru/impressionbit/server/controller/IndexController.java: -------------------------------------------------------------------------------- 1 | package ru.impressionbit.server.controller; 2 | 3 | import org.springframework.stereotype.Controller; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | 6 | @Controller 7 | public class IndexController { 8 | 9 | @RequestMapping("/application/**") 10 | public String forward() { 11 | return "forward:/"; 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /src/main/js/app/reduser/localeReduser.js: -------------------------------------------------------------------------------- 1 | import * as actionType from "../constants/actionType"; 2 | 3 | const initialState = {locale: 'en'}; 4 | 5 | // reducer locale 6 | export default (state = initialState, action = {}) => { 7 | if (action.type === actionType.SET_LOCALE) { 8 | const newState = Object.assign({}, state); 9 | newState.locale = action.locale; 10 | return newState; 11 | } 12 | return state; 13 | }; -------------------------------------------------------------------------------- /src/main/js/app/reduser/reduser.js: -------------------------------------------------------------------------------- 1 | import * as actionType from 'app/constants/actionType'; 2 | 3 | export const initialState = {value: ' '}; 4 | 5 | // reducer 6 | export const reducer = (state = initialState, action = {}) => { 7 | if (action.type === actionType.SET_VALUE) { 8 | const newState = Object.assign({}, state); 9 | newState.value = action.value; 10 | return newState; 11 | } 12 | return state; 13 | }; 14 | -------------------------------------------------------------------------------- /src/main/js/app/constants/routes.js: -------------------------------------------------------------------------------- 1 | // Get public path 2 | const publicPath = process.env.ASSET_PATH; 3 | 4 | // Index route 5 | export const index = () => `/${publicPath}/`; 6 | 7 | // Index route 8 | export const state = () => `/${publicPath}/state`; 9 | 10 | // Index route 11 | export const rest = () => `/${publicPath}/rest`; 12 | 13 | // Index websocket 14 | export const webSocket = () => `/${publicPath}/websocket`; 15 | 16 | // Index upload 17 | export const upload = () => `/${publicPath}/upload`; 18 | -------------------------------------------------------------------------------- /src/main/js/app/components/pages/home.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {connect} from 'react-redux'; 3 | import {FormattedMessage} from 'react-intl'; 4 | import {Jumbotron} from 'reactstrap'; 5 | 6 | export function HomeLayout() { 7 | 8 | return ( 9 | 10 |

11 |
12 | ); 13 | } 14 | 15 | const mapStateToProps = state => ({ 16 | value: state.state.value 17 | }); 18 | 19 | export default connect(mapStateToProps)(HomeLayout); -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | index.html 11 | index.jsp 12 | index.gsp 13 | 14 | 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-start 2 | Basic configuration of the project using React + Redux + Bootstrap. 3 | 4 | ![front](https://raw.githubusercontent.com/impressionBit/react-start/master/image/image.jpg) 5 | 6 | ### Start project 7 | - install [java version 1.8](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) 8 | - install [node.js](https://nodejs.org/en/download/current/) 9 | - Open CMD 10 | - Go to to project folder 11 | - Run cmd `npm i` 12 | - Run cmd `gradle build` 13 | - Run cmd `gradle bootRun` 14 | - Open [http://localhost:8090/application/](http://localhost:8090/application/) 15 | 16 | -------------------------------------------------------------------------------- /src/main/java/ru/impressionbit/server/domain/User.java: -------------------------------------------------------------------------------- 1 | package ru.impressionbit.server.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonAutoDetect; 4 | import javax.persistence.*; 5 | 6 | @Entity 7 | @Table(name = "USER") 8 | @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) 9 | public class User { 10 | 11 | @Id 12 | @GeneratedValue(strategy = GenerationType.IDENTITY) 13 | @Column(name = "ID") 14 | private Integer id; 15 | 16 | @Column(name = "NAME") 17 | private String name; 18 | 19 | @Column(name = "ROLE") 20 | private String role; 21 | 22 | @Column(name = "PASSWORD") 23 | private String password; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/js/app/router/routerSwitch.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Switch, Route} from 'react-router'; 3 | import * as routes from 'app/constants/routes'; 4 | import HomeLayout from 'app/components/pages/home'; 5 | import StateLayout from 'app/components/pages/state'; 6 | import RestLayout from 'app/components/pages/rest'; 7 | import WebSocketLayout from 'app/components/pages/webSocket'; 8 | import UploadLayout from 'app/components/pages/upload'; 9 | 10 | export default () => ( 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | ); -------------------------------------------------------------------------------- /src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | profiles: 3 | active: development 4 | jpa: 5 | show-sql: true 6 | generate-ddl: true 7 | hibernate: 8 | ddl-auto: update 9 | data: 10 | rest: 11 | base-path: /api 12 | 13 | --- 14 | spring: 15 | servlet: 16 | multipart: 17 | max-file-size: 100MB 18 | max-request-size: 100MB 19 | 20 | --- 21 | 22 | server: 23 | address: 0.0.0.0 24 | port: 8090 25 | 26 | --- 27 | 28 | spring: 29 | profiles: development 30 | datasource: 31 | url: jdbc:hsqldb:file:~/db/Server 32 | username: developer 33 | password: developer 34 | driverClassName: org.hsqldb.jdbcDriver 35 | 36 | --- 37 | 38 | spring: 39 | profiles: production 40 | datasource: 41 | url: jdbc:hsqldb:mem:Server;sql.syntax_pgs=true 42 | username: production 43 | password: production 44 | driverClassName: org.hsqldb.jdbcDriver -------------------------------------------------------------------------------- /src/main/js/app/application/localeProvider.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {connect} from "react-redux"; 3 | import en from 'react-intl/locale-data/en'; 4 | import ru from 'react-intl/locale-data/ru'; 5 | import {IntlProvider, addLocaleData} from 'react-intl' 6 | import messageEn from 'app/i18n/messages-en'; 7 | import messageRu from 'app/i18n/messages-ru'; 8 | 9 | function intlLocaleProviderComponent(props) { 10 | const {locale, children} = props; 11 | const message = {en: messageEn, ru: messageRu}; 12 | addLocaleData([...en, ...ru]); 13 | return ( 14 | 18 | {children} 19 | 20 | ); 21 | } 22 | 23 | const mapStateToProps = state => ({ 24 | locale: state.intl.locale 25 | }); 26 | 27 | export default connect(mapStateToProps)(intlLocaleProviderComponent); -------------------------------------------------------------------------------- /src/main/js/app/application/application.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {createBrowserHistory} from 'history'; 3 | import {Provider} from 'react-redux'; 4 | import {createStore, applyMiddleware} from 'redux'; 5 | import {withRouter} from 'react-router-dom'; 6 | import {routerMiddleware, ConnectedRouter} from 'react-router-redux'; 7 | import {composeWithDevTools} from 'redux-devtools-extension'; 8 | import LocaleProvider from 'app/application/localeProvider' 9 | import IndexLayout from 'app/components/layout'; 10 | import {reducers} from 'app/reduser/redusers'; 11 | 12 | export default function Application() { 13 | const WrappedPage = withRouter(IndexLayout); 14 | const history = createBrowserHistory(); 15 | 16 | return ( 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | ) 25 | }; -------------------------------------------------------------------------------- /src/main/java/ru/impressionbit/server/configuration/WebSocketConfig.java: -------------------------------------------------------------------------------- 1 | package ru.impressionbit.server.configuration; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.messaging.simp.config.MessageBrokerRegistry; 5 | import org.springframework.scheduling.annotation.EnableScheduling; 6 | import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; 7 | import org.springframework.web.socket.config.annotation.StompEndpointRegistry; 8 | import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; 9 | 10 | @Configuration 11 | @EnableScheduling 12 | @EnableWebSocketMessageBroker 13 | public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { 14 | 15 | @Override 16 | public void configureMessageBroker(MessageBrokerRegistry config) { 17 | config.enableSimpleBroker("/server"); 18 | config.setApplicationDestinationPrefixes("/client"); 19 | } 20 | 21 | @Override 22 | public void registerStompEndpoints(StompEndpointRegistry registry) { 23 | registry.addEndpoint("/endpoint").setAllowedOrigins("*").withSockJS(); 24 | } 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/ru/impressionbit/server/controller/WebSocketController.java: -------------------------------------------------------------------------------- 1 | package ru.impressionbit.server.controller; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.messaging.handler.annotation.MessageMapping; 7 | import org.springframework.messaging.handler.annotation.SendTo; 8 | import org.springframework.messaging.simp.SimpMessageSendingOperations; 9 | import org.springframework.stereotype.Controller; 10 | 11 | import ru.impressionbit.server.domain.Message; 12 | 13 | @Controller 14 | public class WebSocketController { 15 | 16 | private Logger log = LoggerFactory.getLogger(WebSocketController.class); 17 | 18 | private final SimpMessageSendingOperations messagingTemplate; 19 | 20 | @Autowired 21 | public WebSocketController(SimpMessageSendingOperations messagingTemplate) { 22 | this.messagingTemplate = messagingTemplate; 23 | } 24 | 25 | @MessageMapping("/message") 26 | @SendTo("/server/message") 27 | public void getAndSendMessage(String message) { 28 | try { 29 | String answer = "WebSocket get message : " + message; 30 | log.info(answer); 31 | messagingTemplate.convertAndSend("/server/message", new Message(answer)); 32 | } catch (Exception e) { 33 | log.error(String.valueOf(e)); 34 | } 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/js/app/i18n/messages-ru.js: -------------------------------------------------------------------------------- 1 | // RU messages 2 | export default { 3 | //NavBar 4 | 'app.react.start': 'Реакт старт', 5 | 'app.rest.title': 'Рест', 6 | 'app.state.title': 'Стейт', 7 | 'app.webSocket.title': 'Вебсокеты', 8 | 'app.upload.title': 'Загрузка', 9 | 'app.home.title': 'Главная', 10 | 'app.language': 'Язык', 11 | 12 | // Page layout 13 | 'app.page.main.text': 'Базовая конфигурация проекта с использованием React + Redux + Bootstrap.', 14 | 'app.page.state.text': 'Чтение и запись данных в стейт приложения.', 15 | 'app.page.upload.text': 'Загрузка файлов на сервер.', 16 | 'app.page.rest.text.first': 'Получаем с сервера данные из базы данных таблицы пользователя.', 17 | 'app.page.rest.text.second': 'Реализована возможность добавления и удаления пользователей.', 18 | 'app.page.websocket.text': 'Обмен сообщениями в стиле WebSocket включая использование STOMP в качестве суб-протокола.', 19 | 20 | // Page Users 21 | 'app.user.table.title': 'Пользователи', 22 | 'app.user.table.id': 'ID', 23 | 'app.user.table.name': 'Имя', 24 | 'app.user.table.role': 'Роль', 25 | 'app.user.table.password': 'Пароль', 26 | 'app.user.table.delete': 'Удалить', 27 | 'app.user.table.add': 'Добавить пользователя', 28 | 29 | // Page Websocket 30 | 'app.websocket.input.message': 'Введите сообщение', 31 | 'app.websocket.button.send': 'Отправить сообщение', 32 | 33 | // Page upload 34 | 'app.upload.input.message': 'Загрузите изображение', 35 | }; 36 | -------------------------------------------------------------------------------- /src/main/js/app/i18n/messages-en.js: -------------------------------------------------------------------------------- 1 | // EN Messages 2 | export default { 3 | //NavBar 4 | 'app.react.start': 'ReactStart', 5 | 'app.rest.title': 'Rest', 6 | 'app.state.title': 'State', 7 | 'app.webSocket.title': 'WebSocket', 8 | 'app.upload.title': 'Upload', 9 | 'app.home.title': 'Home', 10 | 'app.language': 'Language', 11 | 12 | // Page layout 13 | 'app.page.main.text': 'Basic configuration of the project using React + Redux + Bootstrap.', 14 | 'app.page.state.text': 'Reading and writing data in the application state.', 15 | 'app.page.upload.text': 'Uploading files to the server.', 16 | 'app.page.rest.text.first': 'We get data from the database of the user table from the server.', 17 | 'app.page.rest.text.second': 'Implemented the ability to add and remove users.', 18 | 'app.page.websocket.text': 'Messaging in the style of WebSocket including the use of STOMP as a sub-protocol.', 19 | 20 | // Page Users 21 | 'app.user.table.title': 'Users', 22 | 'app.user.table.id': 'ID', 23 | 'app.user.table.name': 'Name', 24 | 'app.user.table.role': 'Role', 25 | 'app.user.table.password': 'Password', 26 | 'app.user.table.delete': 'Delete', 27 | 'app.user.table.add': 'Add user', 28 | 29 | // Page Websocket 30 | 'app.websocket.input.message': 'Input message', 31 | 'app.websocket.button.send': 'Send message', 32 | 33 | // Page layout 34 | 'app.state.input.message': 'The message entered in this field will be saved in the application state', 35 | 36 | // Page upload 37 | 'app.upload.input.message': 'Load image', 38 | }; 39 | -------------------------------------------------------------------------------- /src/main/java/ru/impressionbit/server/service/ORMUserService.java: -------------------------------------------------------------------------------- 1 | package ru.impressionbit.server.service; 2 | 3 | import org.springframework.stereotype.Repository; 4 | import javax.persistence.EntityManager; 5 | import javax.persistence.PersistenceContext; 6 | import javax.persistence.TypedQuery; 7 | import java.util.List; 8 | import org.springframework.transaction.annotation.Transactional; 9 | 10 | import ru.impressionbit.server.domain.User; 11 | 12 | @Repository 13 | @Transactional 14 | public class ORMUserService { 15 | 16 | @PersistenceContext 17 | private EntityManager entityManager; 18 | 19 | public List queryFindAllUsersJPA() { 20 | String query = "from User order by id"; 21 | TypedQuery typedQuery = entityManager.createQuery(query, User.class); 22 | return typedQuery.getResultList(); 23 | } 24 | 25 | public List insertUser(String name, String role, String password) { 26 | String qlString = "insert into User (name, role, password) values (?,?,?)"; 27 | entityManager.createNativeQuery(qlString) 28 | .setParameter(1, name) 29 | .setParameter(2, role) 30 | .setParameter(3, password) 31 | .executeUpdate(); 32 | return queryFindAllUsersJPA(); 33 | } 34 | 35 | public List deleteUserById(Integer id) { 36 | String query = "delete from User u where u.id=:id"; 37 | entityManager.createQuery(query) 38 | .setParameter("id", id) 39 | .executeUpdate(); 40 | return queryFindAllUsersJPA(); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-start", 3 | "version": "1.0.0", 4 | "description": "QuickStart", 5 | "private": true, 6 | "main": "index.js", 7 | "author": "ImpressionBit", 8 | "license": "ISC", 9 | "dependencies": { 10 | "axios": "^0.18.0", 11 | "bootstrap": "^4.1.1", 12 | "history": "^4.7.2", 13 | "intl": "^1.2.5", 14 | "react": "^16.4.0", 15 | "react-dom": "^16.4.0", 16 | "react-intl": "^2.4.0", 17 | "react-redux": "^5.0.7", 18 | "react-router": "^4.2.0", 19 | "react-router-dom": "^4.2.2", 20 | "react-router-redux": "^5.0.0-alpha.9", 21 | "react-spinners": "^0.4.5", 22 | "react-stomp": "^3.2.0", 23 | "reactstrap": "^6.3.1", 24 | "redux": "^3.7.2" 25 | }, 26 | "devDependencies": { 27 | "babel-core": "^6.26.0", 28 | "babel-loader": "^7.1.4", 29 | "babel-plugin-react-intl": "^2.4.0", 30 | "babel-plugin-transform-decorators-legacy": "^1.3.5", 31 | "babel-polyfill": "^6.26.0", 32 | "babel-preset-env": "^1.7.0", 33 | "babel-preset-react": "^6.24.1", 34 | "css-loader": "^0.28.11", 35 | "file-loader": "^1.1.11", 36 | "html-loader": "^1.0.0-alpha.0", 37 | "html-webpack-plugin": "^3.2.0", 38 | "html-webpack-template": "^6.2.0", 39 | "less": "^3.0.4", 40 | "less-loader": "^4.1.0", 41 | "mini-css-extract-plugin": "^0.4.0", 42 | "redux-devtools-extension": "^2.13.2", 43 | "style-loader": "^0.20.3", 44 | "webpack": "^4.17.2", 45 | "webpack-cli": "^2.1.4", 46 | "webpack-dev-server": "^3.1.7" 47 | }, 48 | "scripts": { 49 | "build": "webpack --mode production", 50 | "start": "webpack-dev-server --mode development" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/ru/impressionbit/server/controller/RestController.java: -------------------------------------------------------------------------------- 1 | package ru.impressionbit.server.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.data.rest.webmvc.RepositoryRestController; 5 | import org.springframework.stereotype.Controller; 6 | import org.springframework.web.bind.annotation.*; 7 | 8 | import ru.impressionbit.server.domain.User; 9 | import ru.impressionbit.server.service.ORMUserService; 10 | 11 | import java.util.List; 12 | 13 | @RepositoryRestController 14 | @Controller 15 | public class RestController { 16 | 17 | private final ORMUserService ormUserService; 18 | 19 | @Autowired 20 | public RestController(ORMUserService ormUserService) { 21 | this.ormUserService = ormUserService; 22 | } 23 | 24 | @RequestMapping( 25 | value = "/api/rest", 26 | method = RequestMethod.GET) 27 | @ResponseBody 28 | public List ormFindAllUsers() { 29 | return ormUserService.queryFindAllUsersJPA(); 30 | } 31 | 32 | @RequestMapping( 33 | value = "/api/rest", 34 | method = RequestMethod.PUT) 35 | @ResponseBody 36 | public List ormInsertUserById( 37 | @RequestParam(value = "name") String name, 38 | @RequestParam(value = "role") String role, 39 | @RequestParam(value = "password") String password 40 | ) { 41 | return ormUserService.insertUser(name, role, password); 42 | } 43 | 44 | @RequestMapping( 45 | value = "/api/rest", 46 | method = RequestMethod.DELETE) 47 | @ResponseBody 48 | public List ormDeleteUserById(@RequestParam(value = "id") Integer id) { 49 | return ormUserService.deleteUserById(id); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/js/app/components/pages/state.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {connect} from 'react-redux'; 3 | import { 4 | Alert, 5 | Container, 6 | Row, 7 | Col, 8 | Input, 9 | Jumbotron 10 | } from 'reactstrap'; 11 | import {FormattedMessage, injectIntl} from "react-intl"; 12 | import {setValue} from "app/action/actions"; 13 | 14 | export function StateLayout(props) { 15 | 16 | const {intl, state, setValue} = props; 17 | return ( 18 |
19 | 20 |
21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | setValue(value.target.value)}/> 35 |
36 | 37 |
38 | 39 | 40 | 41 | {state.value} 42 | 43 | 44 | 45 |
46 | 47 |
48 | ); 49 | } 50 | 51 | const mapStateToProps = state => ({ 52 | state: state.state 53 | }); 54 | 55 | const mapDispatchToProps = dispatch => ({ 56 | setValue: value => dispatch(setValue(value)) 57 | }); 58 | 59 | export default connect(mapStateToProps, mapDispatchToProps)(injectIntl(StateLayout)); -------------------------------------------------------------------------------- /src/main/js/app/components/locale.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {connect} from "react-redux"; 3 | import {FormattedMessage} from 'react-intl'; 4 | import { 5 | Dropdown, 6 | DropdownItem, 7 | DropdownToggle, 8 | DropdownMenu, 9 | } from 'reactstrap'; 10 | 11 | import {setLocale} from 'app/action/actions'; 12 | 13 | class Locale extends React.Component { 14 | 15 | constructor(props) { 16 | super(props); 17 | this.toggle = this.toggle.bind(this); 18 | this.state = { 19 | open: false, 20 | locale: props.state.locale 21 | }; 22 | } 23 | 24 | toggle() { 25 | this.setState({ 26 | open: !this.state.open 27 | }); 28 | } 29 | 30 | setLanguage(locale) { 31 | this.setState({locale}); 32 | this.props.setLocale(locale); 33 | } 34 | 35 | render() { 36 | const {open, locale} = this.state; 37 | return ( 38 | 39 | 40 | 41 | 42 | 43 | this.setLanguage('ru')}>RU 45 | this.setLanguage('en')}>EN 47 | 48 | 49 | ); 50 | } 51 | } 52 | 53 | const mapStateToProps = state => ({ 54 | state: state.intl 55 | }); 56 | 57 | const mapDispatchToProps = dispatch => ({ 58 | setLocale: locale => dispatch(setLocale(locale)) 59 | }); 60 | 61 | 62 | export default connect(mapStateToProps, mapDispatchToProps)(Locale); -------------------------------------------------------------------------------- /src/main/js/app/components/layout.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import 'bootstrap/dist/css/bootstrap.css'; 3 | import { 4 | Button, 5 | Nav, 6 | Navbar, 7 | NavbarBrand, 8 | NavItem, 9 | } from 'reactstrap'; 10 | import Locale from 'app/components/locale'; 11 | import {FormattedMessage} from 'react-intl'; 12 | import * as routers from 'app/constants/routes' 13 | import ApplicationRouter from 'app/router/routerSwitch'; 14 | 15 | export default function IndexLayout(props) { 16 | 17 | return ( 18 |
19 | 20 | 21 | 35 | 38 | 39 | 40 |
41 | ); 42 | } 43 | -------------------------------------------------------------------------------- /src/main/js/app/components/pages/upload.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | Container, 4 | Row, 5 | Col, 6 | Jumbotron 7 | } from 'reactstrap'; 8 | import Dropzone from 'react-dropzone'; 9 | import request from 'superagent'; 10 | import {upload} from 'app/axios/url'; 11 | import {FormattedMessage, injectIntl} from 'react-intl'; 12 | 13 | export class UploadLayout extends React.Component { 14 | constructor(props) { 15 | super(props); 16 | 17 | this.state = { 18 | image: undefined 19 | }; 20 | 21 | this.dropHandler = this.dropHandler.bind(this); 22 | } 23 | 24 | dropHandler(file) { 25 | const jsonFile = new FormData(); 26 | jsonFile.append('file', file[0]); 27 | jsonFile.append('name', file[0].name); 28 | 29 | request.post(upload) 30 | .send(jsonFile) 31 | .then(response => { 32 | this.setState({image: response.text}) 33 | }); 34 | } 35 | 36 | render() { 37 | const {image} = this.state; 38 | return ( 39 |
40 | 41 |
42 |
43 | 44 | 45 | 46 | 51 |
52 |
53 | 54 | 55 | {image ? (image) : (
)} 56 | 57 | 58 | 59 | 60 |
61 | ); 62 | } 63 | } 64 | 65 | export default injectIntl(UploadLayout); -------------------------------------------------------------------------------- /src/main/java/ru/impressionbit/server/controller/UploaderController.java: -------------------------------------------------------------------------------- 1 | package ru.impressionbit.server.controller; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.http.MediaType; 6 | import org.springframework.http.ResponseEntity; 7 | import org.springframework.stereotype.Controller; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.bind.annotation.RequestMethod; 10 | import org.springframework.web.bind.annotation.RequestParam; 11 | import org.springframework.web.bind.annotation.ResponseBody; 12 | import org.springframework.web.multipart.MultipartFile; 13 | 14 | import javax.imageio.ImageIO; 15 | import java.awt.image.BufferedImage; 16 | import java.io.ByteArrayOutputStream; 17 | import java.io.InputStream; 18 | import java.util.Base64; 19 | 20 | @Controller 21 | public class UploaderController { 22 | 23 | private Logger log = LoggerFactory.getLogger(WebSocketController.class); 24 | 25 | @RequestMapping(value = "/api/upload", method = RequestMethod.POST) 26 | @ResponseBody 27 | public ResponseEntity handleFileUpload( 28 | @RequestParam("name") String name, 29 | @RequestParam("file") MultipartFile file) throws Exception { 30 | 31 | BufferedImage bufferedImage; 32 | InputStream inputStream; 33 | byte[] imageInByte; 34 | String base64String = ""; 35 | 36 | if (!file.isEmpty()) { 37 | inputStream = file.getInputStream(); 38 | bufferedImage = ImageIO.read(inputStream); 39 | 40 | log.debug("Name: " + name); 41 | log.debug("Width: " + bufferedImage.getWidth()); 42 | log.debug("Height: " + bufferedImage.getHeight()); 43 | 44 | ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 45 | ImageIO.write(bufferedImage, "jpg", byteArrayOutputStream); 46 | byteArrayOutputStream.flush(); 47 | imageInByte = byteArrayOutputStream.toByteArray(); 48 | byteArrayOutputStream.close(); 49 | 50 | base64String = Base64.getEncoder().encodeToString(imageInByte); 51 | } 52 | 53 | return ResponseEntity.ok() 54 | .contentType(MediaType.TEXT_PLAIN) 55 | .body(base64String); 56 | } 57 | 58 | } -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /webpack.config.babel.js: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import webpack from 'webpack'; 3 | import HtmlWebpackPlugin from 'html-webpack-plugin'; 4 | import HtmlWebpackTemplate from 'html-webpack-template'; 5 | import MiniCssExtractPlugin from 'mini-css-extract-plugin'; 6 | 7 | // Public path 8 | const publicPath = 'application'; 9 | 10 | export default () => ({ 11 | devServer: { 12 | contentBase: `/${publicPath}/`, 13 | historyApiFallback: { 14 | rewrites: [{from: /./, to: `/index.html`}] 15 | }, 16 | open: true, 17 | port: 9090, 18 | publicPath: `/`, 19 | proxy: [{ 20 | context: ['/api', '/endpoint'], 21 | target: { 22 | host: "localhost", 23 | protocol: 'http:', 24 | port: 8090 25 | } 26 | }] 27 | }, 28 | entry: { 29 | index: path.join(__dirname, 'src/main/js/app/index.jsx') 30 | }, 31 | output: { 32 | filename: 'assets/javascripts/[hash].js', 33 | path: path.join(__dirname, 'src/main/resources/static'), 34 | publicPath: `/` 35 | }, 36 | module: { 37 | rules: [ 38 | { 39 | exclude: /node_modules/, 40 | include: path.join(__dirname, 'src/main/js/'), 41 | test: /\.jsx?$/, 42 | use: 'babel-loader' 43 | }, 44 | { 45 | test: /\.css$/, 46 | use: [MiniCssExtractPlugin.loader, 'css-loader'] 47 | }, 48 | { 49 | test: /\.less$/, 50 | use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader'] 51 | }, 52 | { 53 | test: /\.(ico|png|gif|jpe?g)$/, 54 | use: { 55 | loader: 'file-loader', 56 | options: {name: 'assets/images/[name]/[hash].[ext]'} 57 | } 58 | }, 59 | { 60 | test: /\.(svg|woff|woff2|eot|ttf)$/, 61 | use: { 62 | loader: 'file-loader', 63 | options: {name: 'assets/fonts/[name]/[hash].[ext]'} 64 | } 65 | }, 66 | {test: /\.html$/, use: 'html-loader'}, 67 | ] 68 | }, 69 | resolve: { 70 | extensions: ['.js', '.jsx'], 71 | modules: ['node_modules', 'src/main/js'], 72 | symlinks: false 73 | }, 74 | plugins: [ 75 | new webpack.DefinePlugin({ 76 | 'process.env': {ASSET_PATH: JSON.stringify(publicPath)} 77 | }), 78 | new MiniCssExtractPlugin({ 79 | filename: 'assets/stylesheets/[name]/[hash].css' 80 | }), 81 | new HtmlWebpackPlugin({ 82 | appMountId: 'root', 83 | filename: 'index.html', 84 | inject: false, 85 | template: HtmlWebpackTemplate, 86 | title: 'React-Start' 87 | }) 88 | ] 89 | }); -------------------------------------------------------------------------------- /src/main/js/app/components/pages/webSocket.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import SockJsClient from 'react-stomp'; 3 | import {PulseLoader} from 'react-spinners'; 4 | import { 5 | Alert, 6 | Container, 7 | Row, 8 | Col, 9 | Button, 10 | Input, 11 | InputGroupAddon, 12 | InputGroup, 13 | Jumbotron 14 | } from 'reactstrap'; 15 | import {FormattedMessage, injectIntl, intlShape} from "react-intl"; 16 | 17 | import {baseUrl} from 'app/service/baseUrl' 18 | 19 | const urlWebSocket = baseUrl + '/endpoint'; 20 | const connectionStatusOpen = 'WebSocket connection: open'; 21 | const connectionStatusClose = 'WebSocket connection: close'; 22 | 23 | class WebSocketLayout extends React.Component { 24 | constructor(props) { 25 | super(props); 26 | 27 | this.state = { 28 | getMessage: '', 29 | sendMessage: '', 30 | connectionStatus: 'danger', 31 | connectionMessage: connectionStatusClose 32 | }; 33 | 34 | this.sendMessage = this.sendMessage.bind(this); 35 | } 36 | 37 | sendMessage() { 38 | this.clientRef.sendMessage("/client/message", this.state.sendMessage); 39 | } 40 | 41 | render() { 42 | const {sendMessage, getMessage, connectionStatus, connectionMessage} = this.state; 43 | const {intl} = this.props; 44 | 45 | return ( 46 |
47 | 48 |
49 |
50 | 51 | 52 | 53 | 54 | 55 | 61 | {connectionMessage} 62 | 63 | 64 | 65 | 66 | 67 | 68 | this.setState({sendMessage: value.target.value})}/> 73 | 74 | 81 | 82 | 83 | 84 | 85 | 86 | 87 |
88 | 89 | {getMessage} 90 | 91 | { 95 | this.setState({ 96 | connectionStatus: 'success', 97 | connectionMessage: connectionStatusOpen 98 | }) 99 | }} 100 | onDisconnect={() => { 101 | this.setState({ 102 | connectionStatus: 'danger', 103 | connectionMessage: connectionStatusClose 104 | }) 105 | }} 106 | onMessage={(response) => { 107 | this.setState({getMessage: response.message}) 108 | }} 109 | ref={(client) => { 110 | this.clientRef = client 111 | }}/> 112 | 113 | 114 |
115 | 116 |
117 | 118 |
119 | ); 120 | } 121 | } 122 | 123 | WebSocketLayout.propTypes = { 124 | intl: intlShape.isRequired 125 | }; 126 | 127 | export default injectIntl(WebSocketLayout); -------------------------------------------------------------------------------- /gradle/gradle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/.." >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/lib/gradle-launcher-4.8.1.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.launcher.GradleMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /src/main/js/app/components/pages/rest.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {connect} from 'react-redux'; 3 | import axios from 'axios'; 4 | import *as url from 'app/axios/url'; 5 | import { 6 | Button, 7 | Container, 8 | Row, 9 | Col, 10 | Input, 11 | Modal, 12 | ModalHeader, 13 | ModalBody, 14 | ModalFooter, 15 | Table, 16 | Jumbotron 17 | } from 'reactstrap'; 18 | import {injectIntl, intlShape, FormattedMessage} from 'react-intl'; 19 | 20 | class RestLayout extends React.Component { 21 | constructor(props) { 22 | super(props); 23 | this.state = { 24 | modal: false, 25 | users: [], 26 | userName: '', 27 | userRole: '', 28 | userPassword: '' 29 | }; 30 | 31 | this.toggle = this.toggle.bind(this); 32 | } 33 | 34 | toggle() { 35 | this.setState({ 36 | modal: !this.state.modal 37 | }); 38 | } 39 | 40 | componentDidMount() { 41 | axios.get(url.rest) 42 | .then(res => 43 | this.setState({users: res.data}) 44 | ) 45 | } 46 | 47 | render() { 48 | const {modal, users, userName, userRole, userPassword} = this.state; 49 | const {intl} = this.props; 50 | return ( 51 |
52 | 53 |
54 |
55 |
56 | 57 | 58 | 59 |

60 | 61 | 62 | 71 | 72 | 73 | 74 | 75 | 76 | this.setState({userName: value.target.value})}/> 80 |
81 | this.setState({userRole: value.target.value})}/> 85 |
86 | this.setState({userPassword: value.target.value})}/> 90 |
91 | 92 | {' '} 104 | 105 |
106 | 107 |
108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | {users.map((item, index) => 122 | 123 | 124 | 125 | 126 | 127 | 136 | ) 137 | } 138 | 139 |
{item.id}{item.name}{item.role}{item.password}
140 | 141 |
142 |
143 |
144 | ) 145 | }; 146 | 147 | } 148 | 149 | RestLayout.propTypes = { 150 | intl: intlShape.isRequired 151 | }; 152 | 153 | const mapStateToProps = state => ({ 154 | state: state.state.value 155 | }); 156 | 157 | export default connect(mapStateToProps)(injectIntl(RestLayout)); --------------------------------------------------------------------------------