├── .babelrc ├── .editorconfig ├── .eslintrc ├── .gitignore ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── CHANGELOG.md ├── README.md ├── build ├── index.template.html ├── karma.conf.js ├── webpack.base.conf.js ├── webpack.dev.conf.js └── webpack.prod.conf.js ├── mvnw ├── mvnw.cmd ├── npm ├── npm.cmd ├── package.json ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── shardis │ │ ├── ShardisFrameworkApplication.java │ │ ├── cons │ │ └── Profiles.java │ │ ├── controllers │ │ ├── error │ │ │ └── ErrorHandlerController.java │ │ ├── rest │ │ │ ├── ChatController.java │ │ │ └── SampleRestController.java │ │ └── web │ │ │ └── MainPageController.java │ │ ├── dto │ │ ├── chat │ │ │ └── ChatMessage.java │ │ ├── error │ │ │ └── ServerErrorDTO.java │ │ └── user │ │ │ └── UserPost.java │ │ └── utils │ │ └── EnvironmentProvider.java ├── resources │ ├── application.properties │ ├── static │ │ ├── css │ │ │ └── dev.css │ │ ├── images │ │ │ └── development_ribbon.png │ │ └── index.html │ └── templates │ │ └── error.html └── vuejs │ ├── app.vue │ ├── assets │ ├── images │ │ └── logo.png │ └── scss │ │ ├── _animations.scss │ │ ├── _bootstrap.scss │ │ ├── _fonts.scss │ │ ├── _layout.scss │ │ ├── _variables.scss │ │ ├── _vue.scss │ │ └── main.scss │ ├── components │ ├── about.vue │ ├── chat.vue │ ├── hello.vue │ ├── home.vue │ ├── layout │ │ ├── page-footer.vue │ │ └── page-header.vue │ ├── not-found.vue │ ├── survey │ │ ├── data.js │ │ ├── question.vue │ │ └── survey.vue │ └── user │ │ ├── index.vue │ │ ├── posts.vue │ │ ├── profile.vue │ │ └── settings.vue │ ├── config │ └── routes.js │ ├── main.js │ └── stores │ └── store.js └── test ├── java └── com │ └── shardis │ └── ShardisFrameworkApplicationTests.java └── vuejs └── unit ├── Hello.spec.js └── index.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-2"], 3 | "plugins": ["transform-runtime"], 4 | "comments": false 5 | } 6 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | 11 | # Set default charset 12 | [*.{js,java,vue}] 13 | charset = utf-8 14 | 15 | # 4 space indentation 16 | [*.java] 17 | indent_style = space 18 | indent_size = 4 19 | 20 | # 2 space indentation 21 | [*.{js,vue}] 22 | indent_style = space 23 | indent_size = 2 24 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "node": true 5 | }, 6 | 7 | "ecmaFeatures": { 8 | "arrowFunctions": true, 9 | "destructuring": true, 10 | "classes": true, 11 | "defaultParams": true, 12 | "blockBindings": true, 13 | "modules": true, 14 | "objectLiteralComputedProperties": true, 15 | "objectLiteralShorthandMethods": true, 16 | "objectLiteralShorthandProperties": true, 17 | "restParams": true, 18 | "spread": true, 19 | "forOf": true, 20 | "generators": true, 21 | "templateStrings": true, 22 | "superInFunctions": true, 23 | "experimentalObjectRestSpread": true 24 | }, 25 | 26 | "globals": { 27 | "$": true, 28 | "jQuery": true, 29 | "window.jQuery": true, 30 | "Tether": true, 31 | "window.Tether": true 32 | }, 33 | 34 | "rules": { 35 | "accessor-pairs": 2, 36 | "array-bracket-spacing": 0, 37 | "block-scoped-var": 0, 38 | "brace-style": [2, "1tbs", { "allowSingleLine": true }], 39 | "camelcase": 0, 40 | "comma-dangle": [2, "never"], 41 | "comma-spacing": [2, { "before": false, "after": true }], 42 | "comma-style": [2, "last"], 43 | "complexity": 0, 44 | "computed-property-spacing": 0, 45 | "consistent-return": 0, 46 | "consistent-this": 0, 47 | "constructor-super": 2, 48 | "curly": [2, "multi-line"], 49 | "default-case": 0, 50 | "dot-location": [2, "property"], 51 | "dot-notation": 0, 52 | "eol-last": 2, 53 | "eqeqeq": [2, "allow-null"], 54 | "func-names": 0, 55 | "func-style": 0, 56 | "generator-star-spacing": [2, { "before": true, "after": true }], 57 | "guard-for-in": 0, 58 | "handle-callback-err": [2, "^(err|error)$" ], 59 | "indent": [2, 2, { "SwitchCase": 1 }], 60 | "key-spacing": [2, { "beforeColon": false, "afterColon": true }], 61 | "linebreak-style": 0, 62 | "lines-around-comment": 0, 63 | "max-nested-callbacks": 0, 64 | "new-cap": [2, { "newIsCap": true, "capIsNew": false }], 65 | "new-parens": 2, 66 | "newline-after-var": 0, 67 | "no-alert": 0, 68 | "no-array-constructor": 2, 69 | "no-caller": 2, 70 | "no-catch-shadow": 0, 71 | "no-cond-assign": 2, 72 | "no-console": 0, 73 | "no-constant-condition": 0, 74 | "no-continue": 0, 75 | "no-control-regex": 2, 76 | "no-debugger": 2, 77 | "no-delete-var": 2, 78 | "no-div-regex": 0, 79 | "no-dupe-args": 2, 80 | "no-dupe-keys": 2, 81 | "no-duplicate-case": 2, 82 | "no-else-return": 0, 83 | "no-empty": 0, 84 | "no-empty-character-class": 2, 85 | "no-empty-label": 2, 86 | "no-eq-null": 0, 87 | "no-eval": 2, 88 | "no-ex-assign": 2, 89 | "no-extend-native": 2, 90 | "no-extra-bind": 2, 91 | "no-extra-boolean-cast": 2, 92 | "no-extra-parens": 0, 93 | "no-extra-semi": 0, 94 | "no-fallthrough": 2, 95 | "no-floating-decimal": 2, 96 | "no-func-assign": 2, 97 | "no-implied-eval": 2, 98 | "no-inline-comments": 0, 99 | "no-inner-declarations": [2, "functions"], 100 | "no-invalid-regexp": 2, 101 | "no-irregular-whitespace": 2, 102 | "no-iterator": 2, 103 | "no-label-var": 2, 104 | "no-labels": 2, 105 | "no-lone-blocks": 2, 106 | "no-lonely-if": 0, 107 | "no-loop-func": 0, 108 | "no-mixed-requires": 0, 109 | "no-mixed-spaces-and-tabs": 2, 110 | "no-multi-spaces": 2, 111 | "no-multi-str": 2, 112 | "no-multiple-empty-lines": [2, { "max": 1 }], 113 | "no-native-reassign": 2, 114 | "no-negated-in-lhs": 2, 115 | "no-nested-ternary": 0, 116 | "no-new": 2, 117 | "no-new-func": 0, 118 | "no-new-object": 2, 119 | "no-new-require": 2, 120 | "no-new-wrappers": 2, 121 | "no-obj-calls": 2, 122 | "no-octal": 2, 123 | "no-octal-escape": 2, 124 | "no-param-reassign": 0, 125 | "no-path-concat": 0, 126 | "no-process-env": 0, 127 | "no-process-exit": 0, 128 | "no-proto": 0, 129 | "no-redeclare": 2, 130 | "no-regex-spaces": 2, 131 | "no-restricted-modules": 0, 132 | "no-return-assign": 2, 133 | "no-script-url": 0, 134 | "no-self-compare": 2, 135 | "no-sequences": 2, 136 | "no-shadow": 0, 137 | "no-shadow-restricted-names": 2, 138 | "no-spaced-func": 2, 139 | "no-sparse-arrays": 2, 140 | "no-sync": 0, 141 | "no-ternary": 0, 142 | "no-this-before-super": 2, 143 | "no-throw-literal": 2, 144 | "no-trailing-spaces": 2, 145 | "no-undef": 2, 146 | "no-undef-init": 2, 147 | "no-undefined": 0, 148 | "no-underscore-dangle": 0, 149 | "no-unexpected-multiline": 2, 150 | "no-unneeded-ternary": 2, 151 | "no-unreachable": 2, 152 | "no-unused-expressions": 0, 153 | "no-unused-vars": [2, { "vars": "all", "args": "none" }], 154 | "no-use-before-define": 0, 155 | "no-var": 0, 156 | "no-void": 0, 157 | "no-warning-comments": 0, 158 | "no-with": 2, 159 | "object-curly-spacing": 0, 160 | "object-shorthand": 0, 161 | "one-var": [2, { "initialized": "never" }], 162 | "operator-assignment": 0, 163 | "operator-linebreak": [2, "after", { "overrides": { "?": "before", ":": "before" } }], 164 | "padded-blocks": 0, 165 | "prefer-const": 0, 166 | "quote-props": 0, 167 | "quotes": [2, "single", "avoid-escape"], 168 | "radix": 2, 169 | "semi": [1, "always"], 170 | "semi-spacing": 0, 171 | "sort-vars": 0, 172 | "space-after-keywords": [2, "always"], 173 | "space-before-blocks": [2, "always"], 174 | "space-before-function-paren": [2, "always"], 175 | "space-in-parens": [2, "never"], 176 | "space-infix-ops": 2, 177 | "space-return-throw-case": 2, 178 | "space-unary-ops": [2, { "words": true, "nonwords": false }], 179 | "spaced-comment": [2, "always", { "markers": ["global", "globals", "eslint", "eslint-disable", "*package", "!"] }], 180 | "strict": 0, 181 | "use-isnan": 2, 182 | "valid-jsdoc": 0, 183 | "valid-typeof": 2, 184 | "vars-on-top": 0, 185 | "wrap-iife": [2, "any"], 186 | "wrap-regex": 0, 187 | "yoda": [2, "never"] 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### idea 2 | .idea/ 3 | *.iml 4 | ### dist 5 | src/main/resources/static/dist/ 6 | ### maven 7 | target/ 8 | ### node 9 | etc/ 10 | node/ 11 | node_modules/ 12 | npm-debug.log 13 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kucharzyk/vuejs-java-starter/e55e5fd4a968494a2436ce70906491858db289d0/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.3/apache-maven-3.3.3-bin.zip -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.1.1 (2016-01-17) 2 | 3 | * added Simple survey as Vue.js example 4 | 5 | ## 0.1.0 (2016-01-15) 6 | 7 | * added Vuex (It's like flux) 8 | * refactor counter example to Vuex 9 | * some other refactorings 10 | 11 | ## 0.0.9 (2016-01-14) 12 | 13 | * added realtime chat example (SSE) 14 | 15 | ## 0.0.8 (2016-01-13) 16 | 17 | * added active class to menu links 18 | * added dropdown to menu 19 | * added two-way binding example 20 | * added font-awesome and some icons 21 | 22 | ## 0.0.7 (2016-01-13) 23 | 24 | * switched from semantic-ui to bootstrap 4 25 | * semantic-ui was too big 26 | * switched from less to sass 27 | * style app with bootstrap 28 | 29 | ## 0.0.6 (2016-01-12) 30 | 31 | * styled application with semantic-ui 32 | * updated npm packages 33 | * configured autoprefixer 34 | 35 | ## 0.0.5 (2016-01-12) 36 | 37 | * styled application with semantic-ui 38 | * refactor webpack configuration 39 | * refactor styles configuration 40 | * add less-css support 41 | 42 | ## 0.0.4 (2016-01-11) 43 | 44 | * fixed 404 status code in routing 45 | * fixed hot reload issues with images and fonts 46 | * Added jquery and semantic-ui 47 | * Added file loader for fonts 48 | 49 | ## 0.0.3 (2016-01-11) 50 | 51 | * Added basic vue-resource example 52 | * Configured proxy from webpack-dev-server to backend 53 | * Added .editorconfig 54 | 55 | ## 0.0.2 (2016-01-10) 56 | 57 | * Added vue-router example 58 | * Handle html5 history router from java 59 | * Added json error handler 60 | 61 | ## 0.0.1 (2016-01-09) 62 | 63 | * Initial version 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vuejs-java-starter 2 | 3 | > Vue.js spring boot starter project 4 | 5 | ## Features: 6 | * Spring Boot 7 | * Vue.js 8 | * Hot module replacement (from webpack dev server and from java) 9 | * vue-router for routing (working well with spring router) 10 | * vue-resources for data fetching 11 | * development and production profiles 12 | * fully automated maven workflow 13 | * bootstrap 4 integration 14 | * font-awesome 15 | * less-css support 16 | * sass support 17 | * and will be more... 18 | 19 | ## Changelog 20 | 21 | ## 0.1.1 (2016-01-17) 22 | 23 | * added Simple survey as Vue.js example 24 | 25 | ## 0.1.0 (2016-01-15) 26 | 27 | * added Vuex (It's like flux) 28 | * refactor counter example to Vuex 29 | * some other refactorings 30 | 31 | ## 0.0.9 (2016-01-14) 32 | 33 | * added realtime chat example (SSE) 34 | 35 | [show full changelog](CHANGELOG.md) 36 | 37 | ## Run in production mode 38 | 39 | ``` bash 40 | # compile and start in production mode 41 | mvn spring-boot:run 42 | ``` 43 | 44 | server will start on [http://localhost:8080/](http://localhost:8080/) 45 | 46 | ## Run in development mode 47 | 48 | ``` bash 49 | # compile and start in development mode 50 | mvn spring-boot:run -Dspring.profiles.active=dev 51 | 52 | # start webpack development server for HMR 53 | npm run dev 54 | ``` 55 | 56 | java server will start on [http://localhost:8080/](http://localhost:8080/) 57 | webpack server will start on [http://localhost:3000/](http://localhost:3000/) 58 | 59 | Hot module replacement will be available from both servers 60 | 61 | ##Running tests 62 | 63 | ``` bash 64 | # run karma tests 65 | npm run tests 66 | 67 | # run java and karma 68 | mvn test 69 | ``` 70 | 71 | ## Directory structure 72 | 73 | ``` 74 | . 75 | ├ build # webpack build configuration 76 | ├ .mvn # maven wrapper directory 77 | ├ node # maven will install node here 78 | ├ node_modules # node modules 79 | ├ target # compiled java sources 80 | ├ src # sources 81 | │ ├ main 82 | │ │ ├ java # java sources 83 | │ │ ├ vuejs # javascript sources 84 | │ │ └ resources # resources 85 | │ │ ├ static # static resources 86 | │ │ │ ├ css # styles 87 | │ │ │ ├ images # images 88 | │ │ │ ├ dist # generated javascript goes here 89 | │ │ │ └ index.html # development index.html 90 | │ │ └ application.properties # spring boot configuration properties 91 | │ └ test # test sources 92 | │ ├ java # java tests 93 | │ └ vuejs # vue.js tests 94 | ├ .babelrc # babel configuration 95 | ├ .eslintrc # eslint configuration 96 | ├ .gitignore # gitignore 97 | ├ package.json # node configuration 98 | ├ pom.xml # maven configuration 99 | ├ mvnw # maven linux wrapper 100 | ├ mvnw.cmd # maven windows wrapper 101 | ├ npm # local npm linux wrapper 102 | ├ npm.cmd # local npm windows wrapper 103 | └ README.md # this file 104 | ``` 105 | -------------------------------------------------------------------------------- /build/index.template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | vuejs-java-starter 7 | {% for (var css in o.htmlWebpackPlugin.files.css) { %} 8 | 9 | {% } %} 10 | 11 | 12 | 13 | {% for (var chunk in o.htmlWebpackPlugin.files.chunks) { %} 14 | 15 | {% } %} 16 | 17 | 18 | -------------------------------------------------------------------------------- /build/karma.conf.js: -------------------------------------------------------------------------------- 1 | var webpackConf = require('./webpack.base.conf'); 2 | delete webpackConf.entry; 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | browsers: ['PhantomJS'], 7 | frameworks: ['jasmine'], 8 | reporters: ['spec'], 9 | files: ['../src/test/vuejs/unit/index.js'], 10 | preprocessors: { 11 | '../src/test/vuejs/unit/index.js': ['webpack'] 12 | }, 13 | webpack: webpackConf, 14 | webpackMiddleware: { 15 | noInfo: true 16 | } 17 | }); 18 | }; 19 | -------------------------------------------------------------------------------- /build/webpack.base.conf.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | var path = require('path'); 3 | 4 | module.exports = { 5 | entry: { 6 | app: './src/main/vuejs/main.js' 7 | }, 8 | output: { 9 | path: path.resolve(__dirname, '../src/main/resources/static/dist/'), 10 | filename: '[name].js' 11 | }, 12 | resolve: { 13 | extensions: ['', '.js', '.vue'], 14 | alias: { 15 | 'src': path.resolve(__dirname, '../src') 16 | } 17 | }, 18 | module: { 19 | loaders: [ 20 | { 21 | test: /\.vue$/, 22 | loader: 'vue' 23 | }, 24 | { 25 | test: /\.js$/, 26 | loader: 'babel!eslint', 27 | exclude: /node_modules/ 28 | }, 29 | { 30 | test: /\.json$/, 31 | loader: 'json' 32 | }, 33 | { 34 | test: /\.(png|jpg|gif|svg)/, 35 | loader: 'url', 36 | query: { 37 | limit: 10000, 38 | name: '[name].[ext]?[hash]' 39 | } 40 | }, 41 | { 42 | test: /\.(woff|eot|ttf|woff(2)?|otf)/i, 43 | loader: 'file-loader?[name].[ext]?[hash]' 44 | } 45 | ] 46 | }, 47 | vue: { 48 | loaders: { 49 | js: 'babel!eslint' 50 | }, 51 | autoprefixer: { 52 | browsers: ['last 2 versions'] 53 | } 54 | }, 55 | eslint: { 56 | formatter: require('eslint-friendly-formatter') 57 | }, 58 | plugins: [ 59 | new webpack.ProvidePlugin({ 60 | $: 'jquery', 61 | jQuery: 'jquery', 62 | 'window.jQuery': 'jquery', 63 | 'Tether': 'tether', 64 | 'window.Tether': 'tether' 65 | }) 66 | ] 67 | }; 68 | -------------------------------------------------------------------------------- /build/webpack.dev.conf.js: -------------------------------------------------------------------------------- 1 | var config = require('./webpack.base.conf'); 2 | 3 | config.devtool = 'eval-source-map'; 4 | 5 | // set output path for development 6 | config.output.publicPath = 'http://localhost:3000/dist/'; 7 | 8 | config.devServer = { 9 | host: '0.0.0.0', 10 | port: 3000, 11 | historyApiFallback: true, 12 | noInfo: true, 13 | contentBase: 'src/main/resources/static/', 14 | proxy: { 15 | '/rest/*': 'http://localhost:8080' 16 | } 17 | }; 18 | 19 | module.exports = config; 20 | -------------------------------------------------------------------------------- /build/webpack.prod.conf.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | var config = require('./webpack.base.conf'); 3 | var ExtractTextPlugin = require('extract-text-webpack-plugin'); 4 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 5 | 6 | // naming output files with hashes for better caching. 7 | // dist/index.html will be auto-generated with correct URLs. 8 | config.output.filename = '[name].[chunkhash].js'; 9 | config.output.chunkFilename = '[id].[chunkhash].js'; 10 | 11 | // set output path for production 12 | config.output.publicPath = '/dist/'; 13 | 14 | // whether to generate source map for production files. 15 | // disabling this can speed up the build. 16 | var SOURCE_MAP = true; 17 | 18 | config.devtool = SOURCE_MAP ? 'source-map' : false; 19 | 20 | // generate loader string to be used with extract text plugin 21 | function generateExtractLoaders (loaders) { 22 | return loaders.map(function (loader) { 23 | return loader + '-loader' + (SOURCE_MAP ? '?sourceMap' : ''); 24 | }).join('!'); 25 | } 26 | 27 | config.vue.loaders = { 28 | js: 'babel!eslint', 29 | // http://vuejs.github.io/vue-loader/configurations/extract-css.html 30 | css: ExtractTextPlugin.extract('vue-style-loader', generateExtractLoaders(['css'])), 31 | less: ExtractTextPlugin.extract('vue-style-loader', generateExtractLoaders(['css', 'less'])), 32 | sass: ExtractTextPlugin.extract('vue-style-loader', generateExtractLoaders(['css', 'sass'])), 33 | stylus: ExtractTextPlugin.extract('vue-style-loader', generateExtractLoaders(['css', 'stylus'])) 34 | }; 35 | 36 | config.plugins = (config.plugins || []).concat([ 37 | // http://vuejs.github.io/vue-loader/workflow/production.html 38 | new webpack.DefinePlugin({ 39 | 'process.env': { 40 | NODE_ENV: '"production"' 41 | } 42 | }), 43 | new webpack.optimize.UglifyJsPlugin({ 44 | compress: { 45 | warnings: false 46 | } 47 | }), 48 | new webpack.optimize.OccurenceOrderPlugin(), 49 | // extract css into its own file 50 | new ExtractTextPlugin('[name].[contenthash].css'), 51 | // generate dist index.html with correct asset hash for caching. 52 | // you can customize output by editing /build/index.template.html 53 | // see https://github.com/ampedandwired/html-webpack-plugin 54 | new HtmlWebpackPlugin({ 55 | filename: 'index.html', 56 | template: 'build/index.template.html' 57 | }) 58 | ]); 59 | 60 | module.exports = config; 61 | -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # 58 | # Look for the Apple JDKs first to preserve the existing behaviour, and then look 59 | # for the new JDKs provided by Oracle. 60 | # 61 | if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK ] ; then 62 | # 63 | # Apple JDKs 64 | # 65 | export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home 66 | fi 67 | 68 | if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Java/JavaVirtualMachines/CurrentJDK ] ; then 69 | # 70 | # Apple JDKs 71 | # 72 | export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home 73 | fi 74 | 75 | if [ -z "$JAVA_HOME" ] && [ -L "/Library/Java/JavaVirtualMachines/CurrentJDK" ] ; then 76 | # 77 | # Oracle JDKs 78 | # 79 | export JAVA_HOME=/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home 80 | fi 81 | 82 | if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then 83 | # 84 | # Apple JDKs 85 | # 86 | export JAVA_HOME=`/usr/libexec/java_home` 87 | fi 88 | ;; 89 | esac 90 | 91 | if [ -z "$JAVA_HOME" ] ; then 92 | if [ -r /etc/gentoo-release ] ; then 93 | JAVA_HOME=`java-config --jre-home` 94 | fi 95 | fi 96 | 97 | if [ -z "$M2_HOME" ] ; then 98 | ## resolve links - $0 may be a link to maven's home 99 | PRG="$0" 100 | 101 | # need this for relative symlinks 102 | while [ -h "$PRG" ] ; do 103 | ls=`ls -ld "$PRG"` 104 | link=`expr "$ls" : '.*-> \(.*\)$'` 105 | if expr "$link" : '/.*' > /dev/null; then 106 | PRG="$link" 107 | else 108 | PRG="`dirname "$PRG"`/$link" 109 | fi 110 | done 111 | 112 | saveddir=`pwd` 113 | 114 | M2_HOME=`dirname "$PRG"`/.. 115 | 116 | # make it fully qualified 117 | M2_HOME=`cd "$M2_HOME" && pwd` 118 | 119 | cd "$saveddir" 120 | # echo Using m2 at $M2_HOME 121 | fi 122 | 123 | # For Cygwin, ensure paths are in UNIX format before anything is touched 124 | if $cygwin ; then 125 | [ -n "$M2_HOME" ] && 126 | M2_HOME=`cygpath --unix "$M2_HOME"` 127 | [ -n "$JAVA_HOME" ] && 128 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 129 | [ -n "$CLASSPATH" ] && 130 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 131 | fi 132 | 133 | # For Migwn, ensure paths are in UNIX format before anything is touched 134 | if $mingw ; then 135 | [ -n "$M2_HOME" ] && 136 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 137 | [ -n "$JAVA_HOME" ] && 138 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 139 | # TODO classpath? 140 | fi 141 | 142 | if [ -z "$JAVA_HOME" ]; then 143 | javaExecutable="`which javac`" 144 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 145 | # readlink(1) is not available as standard on Solaris 10. 146 | readLink=`which readlink` 147 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 148 | if $darwin ; then 149 | javaHome="`dirname \"$javaExecutable\"`" 150 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 151 | else 152 | javaExecutable="`readlink -f \"$javaExecutable\"`" 153 | fi 154 | javaHome="`dirname \"$javaExecutable\"`" 155 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 156 | JAVA_HOME="$javaHome" 157 | export JAVA_HOME 158 | fi 159 | fi 160 | fi 161 | 162 | if [ -z "$JAVACMD" ] ; then 163 | if [ -n "$JAVA_HOME" ] ; then 164 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 165 | # IBM's JDK on AIX uses strange locations for the executables 166 | JAVACMD="$JAVA_HOME/jre/sh/java" 167 | else 168 | JAVACMD="$JAVA_HOME/bin/java" 169 | fi 170 | else 171 | JAVACMD="`which java`" 172 | fi 173 | fi 174 | 175 | if [ ! -x "$JAVACMD" ] ; then 176 | echo "Error: JAVA_HOME is not defined correctly." >&2 177 | echo " We cannot execute $JAVACMD" >&2 178 | exit 1 179 | fi 180 | 181 | if [ -z "$JAVA_HOME" ] ; then 182 | echo "Warning: JAVA_HOME environment variable is not set." 183 | fi 184 | 185 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 186 | 187 | # For Cygwin, switch paths to Windows format before running java 188 | if $cygwin; then 189 | [ -n "$M2_HOME" ] && 190 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 191 | [ -n "$JAVA_HOME" ] && 192 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 193 | [ -n "$CLASSPATH" ] && 194 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 195 | fi 196 | 197 | # traverses directory structure from process work directory to filesystem root 198 | # first directory with .mvn subdirectory is considered project base directory 199 | find_maven_basedir() { 200 | local basedir=$(pwd) 201 | local wdir=$(pwd) 202 | while [ "$wdir" != '/' ] ; do 203 | if [ -d "$wdir"/.mvn ] ; then 204 | basedir=$wdir 205 | break 206 | fi 207 | wdir=$(cd "$wdir/.."; pwd) 208 | done 209 | echo "${basedir}" 210 | } 211 | 212 | # concatenates all lines of a file 213 | concat_lines() { 214 | if [ -f "$1" ]; then 215 | echo "$(tr -s '\n' ' ' < "$1")" 216 | fi 217 | } 218 | 219 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-$(find_maven_basedir)} 220 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 221 | 222 | # Provide a "standardized" way to retrieve the CLI args that will 223 | # work with both Windows and non-Windows executions. 224 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" 225 | export MAVEN_CMD_LINE_ARGS 226 | 227 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 228 | 229 | exec "$JAVACMD" \ 230 | $MAVEN_OPTS \ 231 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 232 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 233 | ${WRAPPER_LAUNCHER} "$@" 234 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | set MAVEN_CMD_LINE_ARGS=%* 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | 121 | set WRAPPER_JAR="".\.mvn\wrapper\maven-wrapper.jar"" 122 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 123 | 124 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS% 125 | if ERRORLEVEL 1 goto error 126 | goto end 127 | 128 | :error 129 | set ERROR_CODE=1 130 | 131 | :end 132 | @endlocal & set ERROR_CODE=%ERROR_CODE% 133 | 134 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 135 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 136 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 137 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 138 | :skipRcPost 139 | 140 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 141 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 142 | 143 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 144 | 145 | exit /B %ERROR_CODE% -------------------------------------------------------------------------------- /npm: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | "node/node" "node/node_modules/npm/bin/npm-cli.js" "$@" 3 | -------------------------------------------------------------------------------- /npm.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | %~dp0node/node node/node_modules/npm/bin/npm-cli.js %* 3 | @echo on -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vuejs-java-starter", 3 | "description": "vue.js java starter", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/kucharzyk/vuejs-java-starter.git" 7 | }, 8 | "author": "Tomasz Kucharzyk", 9 | "license": "MIT", 10 | "bugs": { 11 | "url": "https://github.com/kucharzyk/vuejs-java-starter/issues" 12 | }, 13 | "private": true, 14 | "scripts": { 15 | "dev": "webpack-dev-server --inline --hot --config build/webpack.dev.conf.js", 16 | "build": "rimraf src/main/resources/static/dist && webpack --progress --hide-modules --config build/webpack.prod.conf.js", 17 | "test": "karma start build/karma.conf.js --single-run" 18 | }, 19 | "dependencies": { 20 | "bootstrap": "4.0.0-alpha.2", 21 | "es6-promise": "3.0.2", 22 | "font-awesome": "4.5.0", 23 | "jquery": "2.2.0", 24 | "tether": "1.1.1", 25 | "vue": "1.0.14", 26 | "vue-resource": "0.6.1", 27 | "vue-router": "0.7.8", 28 | "vuex": "0.2.0" 29 | }, 30 | "devDependencies": { 31 | "autoprefixer": "6.3.1", 32 | "babel-core": "6.3.13", 33 | "babel-loader": "6.2.0", 34 | "babel-plugin-transform-runtime": "6.4.3", 35 | "babel-preset-es2015": "6.1.2", 36 | "babel-preset-stage-2": "6.1.2", 37 | "babel-runtime": "6.1.18", 38 | "css-loader": "0.23.0", 39 | "eslint": "1.10.3", 40 | "eslint-friendly-formatter": "1.2.2", 41 | "eslint-loader": "1.3.0", 42 | "extract-text-webpack-plugin": "0.9.1", 43 | "file-loader": "0.8.4", 44 | "function-bind": "1.0.2", 45 | "html-webpack-plugin": "1.7.0", 46 | "inject-loader": "2.0.1", 47 | "jasmine-core": "2.4.1", 48 | "json-loader": "0.5.4", 49 | "karma": "0.13.19", 50 | "karma-jasmine": "0.3.6", 51 | "karma-phantomjs-launcher": "0.2.1", 52 | "karma-spec-reporter": "0.0.23", 53 | "karma-webpack": "1.7.0", 54 | "less": "2.5.3", 55 | "less-loader": "2.2.2", 56 | "node-sass": "3.4.2", 57 | "phantomjs": "2.1.7", 58 | "rimraf": "2.5.0", 59 | "sass-loader": "3.1.2", 60 | "style-loader": "0.13.0", 61 | "url-loader": "0.5.7", 62 | "vue-hot-reload-api": "1.2.0", 63 | "vue-html-loader": "1.0.0", 64 | "vue-loader": "8.0.0", 65 | "vue-style-loader": "1.0.0", 66 | "webpack": "1.12.11", 67 | "webpack-dev-server": "1.14.1" 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.shardis 7 | vuejs-java-starter 8 | 0.1.1 9 | jar 10 | 11 | vuejs-java-starter 12 | vuejs-java-starter 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 1.3.1.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | 1.8 24 | 0.0.27 25 | 1.16.6 26 | 9.4-1201-jdbc41 27 | v4.2.4 28 | 3.5.3 29 | 30 | 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-starter-cache 35 | 36 | 37 | org.springframework.boot 38 | spring-boot-starter-data-jpa 39 | 40 | 41 | org.springframework.boot 42 | spring-boot-starter-data-rest 43 | 44 | 45 | org.springframework.boot 46 | spring-boot-devtools 47 | 48 | 49 | org.springframework.boot 50 | spring-boot-starter-hateoas 51 | 52 | 53 | org.springframework.boot 54 | spring-boot-starter-mail 55 | 56 | 57 | org.springframework.boot 58 | spring-boot-starter-web 59 | 60 | 61 | org.springframework.boot 62 | spring-boot-starter-websocket 63 | 64 | 65 | org.springframework.boot 66 | spring-boot-starter-thymeleaf 67 | 68 | 69 | 70 | org.projectlombok 71 | lombok 72 | ${lombok.version} 73 | 74 | 75 | org.postgresql 76 | postgresql 77 | ${postgresql.version} 78 | runtime 79 | 80 | 81 | 82 | com.h2database 83 | h2 84 | runtime 85 | 86 | 87 | org.springframework.boot 88 | spring-boot-starter-test 89 | test 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | org.springframework.boot 98 | spring-boot-maven-plugin 99 | 100 | 101 | com.github.eirslett 102 | frontend-maven-plugin 103 | ${frontend-maven-plugin.version} 104 | 105 | 106 | install node and npm 107 | 108 | install-node-and-npm 109 | 110 | 111 | ${frontend-maven-plugin.nodeVersion} 112 | ${frontend-maven-plugin.npmVersion} 113 | 114 | 115 | 116 | npm install 117 | 118 | npm 119 | 120 | 121 | install 122 | 123 | 124 | 125 | npm build 126 | 127 | npm 128 | 129 | 130 | run build 131 | 132 | 133 | 134 | npm test 135 | test 136 | 137 | npm 138 | 139 | 140 | run test 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | -------------------------------------------------------------------------------- /src/main/java/com/shardis/ShardisFrameworkApplication.java: -------------------------------------------------------------------------------- 1 | package com.shardis; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer; 6 | import org.springframework.boot.context.embedded.ErrorPage; 7 | import org.springframework.cache.annotation.EnableCaching; 8 | import org.springframework.context.annotation.Bean; 9 | import org.springframework.http.HttpStatus; 10 | 11 | /** 12 | * Created by Tomasz Kucharzyk 13 | */ 14 | @SpringBootApplication 15 | @EnableCaching 16 | public class ShardisFrameworkApplication { 17 | 18 | @Bean 19 | public EmbeddedServletContainerCustomizer containerCustomizer() { 20 | 21 | return (container -> { 22 | ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/"); 23 | container.addErrorPages(error404Page); 24 | }); 25 | } 26 | 27 | public static void main(String[] args) { 28 | SpringApplication.run(ShardisFrameworkApplication.class, args); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/shardis/cons/Profiles.java: -------------------------------------------------------------------------------- 1 | package com.shardis.cons; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | /** 7 | * Created by Tomasz Kucharzyk 8 | */ 9 | 10 | @Getter 11 | @AllArgsConstructor 12 | public enum Profiles { 13 | 14 | DEV("dev"), 15 | PROD("prod"); 16 | 17 | private String profileName; 18 | 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/shardis/controllers/error/ErrorHandlerController.java: -------------------------------------------------------------------------------- 1 | package com.shardis.controllers.error; 2 | 3 | import com.google.common.collect.Lists; 4 | import com.shardis.dto.error.ServerErrorDTO; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.apache.catalina.connector.ClientAbortException; 7 | import org.springframework.http.HttpStatus; 8 | import org.springframework.http.ResponseEntity; 9 | import org.springframework.web.HttpMediaTypeNotAcceptableException; 10 | import org.springframework.web.bind.annotation.ControllerAdvice; 11 | import org.springframework.web.bind.annotation.ExceptionHandler; 12 | import org.springframework.web.bind.annotation.ResponseBody; 13 | import org.springframework.web.bind.annotation.ResponseStatus; 14 | 15 | import javax.servlet.http.HttpServletRequest; 16 | 17 | /** 18 | * Created by Tomasz Kucharzyk 19 | */ 20 | 21 | @Slf4j 22 | @ControllerAdvice 23 | public class ErrorHandlerController { 24 | 25 | @ExceptionHandler(HttpMediaTypeNotAcceptableException.class) 26 | public void procesHttpMediaTypeNotAcceptableException(HttpMediaTypeNotAcceptableException ex) { 27 | log.debug(ex.getMessage(),ex); 28 | } 29 | 30 | @ExceptionHandler(ClientAbortException.class) 31 | public void processClientAbortException(ClientAbortException ex) { 32 | log.debug(ex.getMessage(),ex); 33 | log.debug("client disconected"); 34 | } 35 | 36 | @ExceptionHandler(Exception.class) 37 | @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) 38 | @ResponseBody 39 | public ServerErrorDTO processException(Exception ex) { 40 | log.error(ex.getMessage(),ex); 41 | return new ServerErrorDTO(ex.getClass().getCanonicalName(), ex.getMessage(), Lists.newArrayList()); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/shardis/controllers/rest/ChatController.java: -------------------------------------------------------------------------------- 1 | package com.shardis.controllers.rest; 2 | 3 | 4 | import com.shardis.dto.chat.ChatMessage; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.http.MediaType; 7 | import org.springframework.web.bind.annotation.*; 8 | import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; 9 | 10 | import java.io.IOException; 11 | import java.util.ArrayList; 12 | import java.util.Collections; 13 | import java.util.List; 14 | import java.util.concurrent.TimeUnit; 15 | 16 | /** 17 | * Created by Tomasz Kucharzyk 18 | */ 19 | 20 | @Slf4j 21 | @RestController 22 | @RequestMapping("/rest/chat") 23 | public class ChatController { 24 | 25 | private final List sseEmitters = Collections.synchronizedList(new ArrayList<>()); 26 | 27 | @RequestMapping(path = "/post", method = RequestMethod.POST, produces = "application/json") 28 | @ResponseBody 29 | ChatMessage jsonCreate(@RequestBody ChatMessage chatMessage) throws IOException { 30 | log.info("Message received -> resending to " + sseEmitters.size() + " client(s)"); 31 | synchronized (sseEmitters) { 32 | for (SseEmitter sseEmitter : sseEmitters) { 33 | sseEmitter.send(chatMessage, MediaType.APPLICATION_JSON); 34 | } 35 | } 36 | return chatMessage; 37 | } 38 | 39 | @RequestMapping("/sse/updates") 40 | SseEmitter subscribeUpdates() { 41 | SseEmitter sseEmitter = new SseEmitter(TimeUnit.MINUTES.toMillis(1)); 42 | synchronized (sseEmitters) { 43 | this.sseEmitters.add(sseEmitter); 44 | log.info("Client connected"); 45 | sseEmitter.onCompletion(() -> { 46 | synchronized (sseEmitters) { 47 | sseEmitters.remove(sseEmitter); 48 | log.info("Client disconnected"); 49 | } 50 | }); 51 | } 52 | return sseEmitter; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/shardis/controllers/rest/SampleRestController.java: -------------------------------------------------------------------------------- 1 | package com.shardis.controllers.rest; 2 | 3 | 4 | import com.google.common.collect.Lists; 5 | import com.shardis.dto.user.UserPost; 6 | import org.springframework.web.bind.annotation.PathVariable; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | import java.time.LocalDateTime; 11 | import java.util.List; 12 | 13 | /** 14 | * Created by Tomasz Kucharzyk 15 | */ 16 | 17 | @RestController 18 | @RequestMapping("/rest") 19 | public class SampleRestController { 20 | 21 | @RequestMapping("/test") 22 | public List test() { 23 | return Lists.newArrayList("Vue.js", "is", "great"); 24 | } 25 | 26 | @RequestMapping("/fail") 27 | public List fail() { 28 | throw new RuntimeException("method failed"); 29 | } 30 | 31 | @RequestMapping("/user/{userId}/posts") 32 | public List userPosts(@PathVariable("userId") Long userId) { 33 | List posts = Lists.newArrayList(); 34 | for (long i = 1; i <= 8; i++) { 35 | posts.add(new UserPost(i, "Post #" + i + " of user " + userId, "sample content #" + i, LocalDateTime.now())); 36 | } 37 | return posts; 38 | } 39 | 40 | @RequestMapping("/user/{userId}/settings") 41 | public List userSettings(@PathVariable("userId") Long userId) throws InterruptedException { 42 | //Don't do that at home 43 | Thread.currentThread().sleep(1000); 44 | 45 | List settings = Lists.newArrayList(); 46 | for (int i = 0; i < 10; i++) { 47 | settings.add("Setting #" + i+" of user "+userId); 48 | } 49 | return settings; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/shardis/controllers/web/MainPageController.java: -------------------------------------------------------------------------------- 1 | package com.shardis.controllers.web; 2 | 3 | import com.shardis.utils.EnvironmentProvider; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.http.HttpStatus; 6 | import org.springframework.stereotype.Controller; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.ResponseStatus; 9 | import org.springframework.web.servlet.ModelAndView; 10 | 11 | /** 12 | * Created by Tomasz Kucharzyk 13 | */ 14 | 15 | @Controller 16 | @RequestMapping("/") 17 | public class MainPageController { 18 | 19 | @Autowired 20 | EnvironmentProvider environmentProvider; 21 | 22 | @ResponseStatus(HttpStatus.OK) 23 | @RequestMapping("/") 24 | public ModelAndView mainPage() { 25 | if (environmentProvider.isProduction()) { 26 | return new ModelAndView("forward://dist/index.html"); 27 | } else { 28 | return new ModelAndView("forward://index.html"); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/shardis/dto/chat/ChatMessage.java: -------------------------------------------------------------------------------- 1 | package com.shardis.dto.chat; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * Created by tomasz on 14.01.16. 10 | * All rights reserved Bazus 2016 11 | */ 12 | @Data 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | @EqualsAndHashCode 16 | public class ChatMessage { 17 | private String message; 18 | private String author; 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/shardis/dto/error/ServerErrorDTO.java: -------------------------------------------------------------------------------- 1 | package com.shardis.dto.error; 2 | 3 | import com.google.common.collect.Lists; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * Created by Tomasz Kucharzyk 12 | */ 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | @Data 16 | public class ServerErrorDTO { 17 | private String error; 18 | private String description; 19 | private List details = Lists.newArrayList(); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/shardis/dto/user/UserPost.java: -------------------------------------------------------------------------------- 1 | package com.shardis.dto.user; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.time.LocalDateTime; 8 | 9 | /** 10 | * Created by Tomasz Kucharzyk 11 | */ 12 | @Data 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class UserPost { 16 | private Long id; 17 | private String title; 18 | private String content; 19 | private LocalDateTime creationDate; 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/shardis/utils/EnvironmentProvider.java: -------------------------------------------------------------------------------- 1 | package com.shardis.utils; 2 | 3 | import com.shardis.cons.Profiles; 4 | import org.springframework.cache.annotation.Cacheable; 5 | import org.springframework.context.EnvironmentAware; 6 | import org.springframework.core.env.Environment; 7 | import org.springframework.stereotype.Component; 8 | 9 | /** 10 | * Created by Tomasz Kucharzyk 11 | */ 12 | @Component 13 | public class EnvironmentProvider implements EnvironmentAware { 14 | 15 | private static Environment environment; 16 | 17 | @Cacheable("EnvironmentProvider.isProduction") 18 | public Boolean isProduction() { 19 | return environment.acceptsProfiles(Profiles.PROD.getProfileName()); 20 | } 21 | 22 | @Cacheable("EnvironmentProvider.isDevelopment") 23 | public Boolean isDevelopment() { 24 | return environment.acceptsProfiles(Profiles.DEV.getProfileName()); 25 | } 26 | 27 | @Override 28 | public void setEnvironment(Environment environment) { 29 | EnvironmentProvider.environment = environment; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # EMBEDDED SERVER CONFIGURATION 2 | server.port=${port:8080} 3 | server.error.whitelabel.enabled=false 4 | # PROFILES 5 | spring.profiles.active=prod 6 | -------------------------------------------------------------------------------- /src/main/resources/static/css/dev.css: -------------------------------------------------------------------------------- 1 | /* ========================================================================== 2 | Developement Ribbon 3 | ========================================================================== */ 4 | .development { 5 | position: absolute; 6 | width: 149px; 7 | height: 149px; 8 | top: 0; 9 | left: 0; 10 | border: 0; 11 | z-index: 2000; 12 | background-image: url("../images/development_ribbon.png"); 13 | background-position: center center; 14 | background-repeat: no-repeat; 15 | } 16 | -------------------------------------------------------------------------------- /src/main/resources/static/images/development_ribbon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kucharzyk/vuejs-java-starter/e55e5fd4a968494a2436ce70906491858db289d0/src/main/resources/static/images/development_ribbon.png -------------------------------------------------------------------------------- /src/main/resources/static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | vuejs-java-starter 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/main/resources/templates/error.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Your request cannot be processed 5 | 6 |
Your request cannot be processed
7 | 8 | -------------------------------------------------------------------------------- /src/main/vuejs/app.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | 17 | 37 | -------------------------------------------------------------------------------- /src/main/vuejs/assets/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kucharzyk/vuejs-java-starter/e55e5fd4a968494a2436ce70906491858db289d0/src/main/vuejs/assets/images/logo.png -------------------------------------------------------------------------------- /src/main/vuejs/assets/scss/_animations.scss: -------------------------------------------------------------------------------- 1 | .view { 2 | transition: all .5s ease; 3 | } 4 | 5 | .test-enter, .test-leave { 6 | opacity: 0; 7 | transform: translate3d(10px, 0, 0); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/vuejs/assets/scss/_bootstrap.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v4.0.0-alpha.2 (http://getbootstrap.com) 3 | * Copyright 2011-2015 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */ 6 | 7 | // Customisation 8 | @import "variables"; 9 | 10 | // Core variables and mixins 11 | @import "~bootstrap/scss/variables"; 12 | @import "~bootstrap/scss/mixins"; 13 | 14 | // Reset and dependencies 15 | @import "~bootstrap/scss/normalize"; 16 | @import "~bootstrap/scss/print"; 17 | 18 | // Core CSS 19 | @import "~bootstrap/scss/reboot"; 20 | @import "~bootstrap/scss/type"; 21 | @import "~bootstrap/scss/images"; 22 | @import "~bootstrap/scss/code"; 23 | @import "~bootstrap/scss/grid"; 24 | @import "~bootstrap/scss/tables"; 25 | @import "~bootstrap/scss/forms"; 26 | @import "~bootstrap/scss/buttons"; 27 | 28 | // Components 29 | @import "~bootstrap/scss/animation"; 30 | @import "~bootstrap/scss/dropdown"; 31 | @import "~bootstrap/scss/button-group"; 32 | @import "~bootstrap/scss/input-group"; 33 | @import "~bootstrap/scss/custom-forms"; 34 | @import "~bootstrap/scss/nav"; 35 | @import "~bootstrap/scss/navbar"; 36 | @import "~bootstrap/scss/card"; 37 | @import "~bootstrap/scss/breadcrumb"; 38 | @import "~bootstrap/scss/pagination"; 39 | @import "~bootstrap/scss/pager"; 40 | @import "~bootstrap/scss/labels"; 41 | @import "~bootstrap/scss/jumbotron"; 42 | @import "~bootstrap/scss/alert"; 43 | @import "~bootstrap/scss/progress"; 44 | @import "~bootstrap/scss/media"; 45 | @import "~bootstrap/scss/list-group"; 46 | @import "~bootstrap/scss/responsive-embed"; 47 | @import "~bootstrap/scss/close"; 48 | 49 | // Components w/ JavaScript 50 | @import "~bootstrap/scss/modal"; 51 | @import "~bootstrap/scss/tooltip"; 52 | @import "~bootstrap/scss/popover"; 53 | @import "~bootstrap/scss/carousel"; 54 | 55 | // Utility classes 56 | @import "~bootstrap/scss/utilities"; 57 | @import "~bootstrap/scss/utilities-background"; 58 | @import "~bootstrap/scss/utilities-spacing"; 59 | @import "~bootstrap/scss/utilities-responsive"; 60 | -------------------------------------------------------------------------------- /src/main/vuejs/assets/scss/_fonts.scss: -------------------------------------------------------------------------------- 1 | $fa-font-path: '~font-awesome/fonts/'; 2 | @import "~font-awesome/scss/font-awesome"; 3 | -------------------------------------------------------------------------------- /src/main/vuejs/assets/scss/_layout.scss: -------------------------------------------------------------------------------- 1 | /* Sticky footer styles 2 | -------------------------------------------------- */ 3 | html { 4 | position: relative; 5 | min-height: 100%; 6 | } 7 | 8 | body { 9 | /* Margin bottom by footer height */ 10 | margin-bottom: 60px; 11 | } 12 | 13 | .footer { 14 | position: absolute; 15 | bottom: 0; 16 | width: 100%; 17 | /* Set the fixed height of the footer here */ 18 | height: 60px; 19 | line-height: 60px; /* Vertically center the text there */ 20 | background-color: #f5f5f5; 21 | } 22 | 23 | /* Custom page CSS 24 | -------------------------------------------------- */ 25 | /* Not required for template or sticky footer method. */ 26 | 27 | body > .container { 28 | padding: 60px 15px 0; 29 | } 30 | 31 | .footer > .container { 32 | padding-right: 15px; 33 | padding-left: 15px; 34 | } 35 | 36 | code { 37 | font-size: 80%; 38 | } 39 | 40 | .header-logo{ 41 | width: 32px; 42 | } 43 | 44 | .application.main.container { 45 | padding-top: 10rem; 46 | padding-bottom: 5rem; 47 | } 48 | -------------------------------------------------------------------------------- /src/main/vuejs/assets/scss/_variables.scss: -------------------------------------------------------------------------------- 1 | // Variables 2 | // 3 | // Copy settings from this file into the provided `_custom.scss` to override 4 | // the Bootstrap defaults without modifying key, versioned files. 5 | 6 | 7 | // Table of Contents 8 | // 9 | // Colors 10 | // Options 11 | // Spacing 12 | // Body 13 | // Links 14 | // Grid breakpoints 15 | // Grid containers 16 | // Grid columns 17 | // Fonts 18 | // Components 19 | 20 | // General variable structure 21 | // 22 | // Variable format should follow the `$component-modifier-state-property` order. 23 | 24 | 25 | // Colors 26 | // 27 | // Grayscale and brand colors for use across Bootstrap. 28 | 29 | $gray-dark: #373a3c !default; 30 | $gray: #55595c !default; 31 | $gray-light: #818a91 !default; 32 | $gray-lighter: #eceeef !default; 33 | $gray-lightest: #f7f7f9 !default; 34 | 35 | $brand-primary: #0275d8 !default; 36 | $brand-success: #5cb85c !default; 37 | $brand-info: #5bc0de !default; 38 | $brand-warning: #f0ad4e !default; 39 | $brand-danger: #d9534f !default; 40 | 41 | 42 | 43 | // Options 44 | // 45 | // Quickly modify global styling by enabling or disabling optional features. 46 | 47 | $enable-flex: false !default; 48 | $enable-rounded: true !default; 49 | $enable-shadows: false !default; 50 | $enable-gradients: false !default; 51 | $enable-transitions: false !default; 52 | $enable-hover-media-query: false !default; 53 | $enable-grid-classes: true !default; 54 | 55 | 56 | // Spacing 57 | // 58 | // Control the default styling of most Bootstrap elements by modifying these 59 | // variables. Mostly focused on spacing. 60 | 61 | $spacer: 1rem !default; 62 | $spacer-x: $spacer !default; 63 | $spacer-y: $spacer !default; 64 | $spacers: ( 65 | 0: ( 66 | x: 0, 67 | y: 0 68 | ), 69 | 1: ( 70 | x: $spacer-x, 71 | y: $spacer-y 72 | ), 73 | 2: ( 74 | x: ($spacer-x * 1.5), 75 | y: ($spacer-y * 1.5) 76 | ), 77 | 3: ( 78 | x: ($spacer-x * 3), 79 | y: ($spacer-y * 3) 80 | ) 81 | ) !default; 82 | $border-width: 1px !default; 83 | 84 | 85 | // Body 86 | // 87 | // Settings for the `` element. 88 | 89 | $body-bg: #fff !default; 90 | $body-color: $gray-dark !default; 91 | 92 | 93 | // Links 94 | // 95 | // Style anchor elements. 96 | 97 | $link-color: $brand-primary !default; 98 | $link-decoration: none !default; 99 | $link-hover-color: darken($link-color, 15%) !default; 100 | $link-hover-decoration: underline !default; 101 | 102 | 103 | // Grid breakpoints 104 | // 105 | // Define the minimum and maximum dimensions at which your layout will change, 106 | // adapting to different screen sizes, for use in media queries. 107 | 108 | $grid-breakpoints: ( 109 | // Extra small screen / phone 110 | xs: 0, 111 | // Small screen / phone 112 | sm: 544px, 113 | // Medium screen / tablet 114 | md: 768px, 115 | // Large screen / desktop 116 | lg: 992px, 117 | // Extra large screen / wide desktop 118 | xl: 1200px 119 | ) !default; 120 | 121 | 122 | // Grid containers 123 | // 124 | // Define the maximum width of `.container` for different screen sizes. 125 | 126 | $container-max-widths: ( 127 | sm: 576px, 128 | md: 720px, 129 | lg: 940px, 130 | xl: 1140px 131 | ) !default; 132 | 133 | 134 | // Grid columns 135 | // 136 | // Set the number of columns and specify the width of the gutters. 137 | 138 | $grid-columns: 12 !default; 139 | $grid-gutter-width: 1.875rem !default; // 30px 140 | 141 | 142 | // Typography 143 | // 144 | // Font, line-height, and color for body text, headings, and more. 145 | 146 | $font-family-sans-serif: "Helvetica Neue", Helvetica, Arial, sans-serif !default; 147 | $font-family-serif: Georgia, "Times New Roman", Times, serif !default; 148 | $font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace !default; 149 | $font-family-base: $font-family-sans-serif !default; 150 | 151 | // Pixel value used to responsively scale all typography. Applied to the `` element. 152 | $font-size-root: 16px !default; 153 | 154 | $font-size-base: 1rem !default; 155 | $font-size-lg: 1.25rem !default; 156 | $font-size-sm: .875rem !default; 157 | $font-size-xs: .75rem !default; 158 | 159 | $font-size-h1: 2.5rem !default; 160 | $font-size-h2: 2rem !default; 161 | $font-size-h3: 1.75rem !default; 162 | $font-size-h4: 1.5rem !default; 163 | $font-size-h5: 1.25rem !default; 164 | $font-size-h6: 1rem !default; 165 | 166 | $display1-size: 6rem !default; 167 | $display2-size: 5.5rem !default; 168 | $display3-size: 4.5rem !default; 169 | $display4-size: 3.5rem !default; 170 | 171 | $display1-weight: 300 !default; 172 | $display2-weight: 300 !default; 173 | $display3-weight: 300 !default; 174 | $display4-weight: 300 !default; 175 | 176 | $line-height: 1.5 !default; 177 | 178 | $headings-margin-bottom: ($spacer / 2) !default; 179 | $headings-font-family: inherit !default; 180 | $headings-font-weight: 500 !default; 181 | $headings-line-height: 1.1 !default; 182 | $headings-color: inherit !default; 183 | 184 | $lead-font-size: 1.25rem !default; 185 | $lead-font-weight: 300 !default; 186 | 187 | $text-muted: $gray-light !default; 188 | 189 | $abbr-border-color: $gray-light !default; 190 | 191 | $blockquote-small-color: $gray-light !default; 192 | $blockquote-font-size: ($font-size-base * 1.25) !default; 193 | $blockquote-border-color: $gray-lighter !default; 194 | 195 | $hr-border-color: rgba(0,0,0,.1) !default; 196 | $hr-border-width: $border-width !default; 197 | 198 | $dt-font-weight: bold !default; 199 | 200 | $nested-kbd-font-weight: bold !default; 201 | 202 | $list-inline-padding: 5px !default; 203 | 204 | 205 | // Components 206 | // 207 | // Define common padding and border radius sizes and more. 208 | 209 | $line-height-lg: (4 / 3) !default; 210 | $line-height-sm: 1.5 !default; 211 | 212 | $border-radius: .25rem !default; 213 | $border-radius-lg: .3rem !default; 214 | $border-radius-sm: .2rem !default; 215 | 216 | $component-active-color: #fff !default; 217 | $component-active-bg: $brand-primary !default; 218 | 219 | $caret-width: .3em !default; 220 | $caret-width-lg: $caret-width !default; 221 | 222 | 223 | // Tables 224 | // 225 | // Customizes the `.table` component with basic values, each used across all table variations. 226 | 227 | $table-cell-padding: .75rem !default; 228 | $table-sm-cell-padding: .3rem !default; 229 | 230 | $table-bg: transparent !default; 231 | $table-bg-accent: #f9f9f9 !default; 232 | $table-bg-hover: #f5f5f5 !default; 233 | $table-bg-active: $table-bg-hover !default; 234 | 235 | $table-border-width: $border-width !default; 236 | $table-border-color: $gray-lighter !default; 237 | 238 | 239 | // Buttons 240 | // 241 | // For each of Bootstrap's buttons, define text, background and border color. 242 | 243 | $btn-padding-x: 1rem !default; 244 | $btn-padding-y: .375rem !default; 245 | $btn-font-weight: normal !default; 246 | 247 | $btn-primary-color: #fff !default; 248 | $btn-primary-bg: $brand-primary !default; 249 | $btn-primary-border: $btn-primary-bg !default; 250 | 251 | $btn-secondary-color: $gray-dark !default; 252 | $btn-secondary-bg: #fff !default; 253 | $btn-secondary-border: #ccc !default; 254 | 255 | $btn-info-color: #fff !default; 256 | $btn-info-bg: $brand-info !default; 257 | $btn-info-border: $btn-info-bg !default; 258 | 259 | $btn-success-color: #fff !default; 260 | $btn-success-bg: $brand-success !default; 261 | $btn-success-border: $btn-success-bg !default; 262 | 263 | $btn-warning-color: #fff !default; 264 | $btn-warning-bg: $brand-warning !default; 265 | $btn-warning-border: $btn-warning-bg !default; 266 | 267 | $btn-danger-color: #fff !default; 268 | $btn-danger-bg: $brand-danger !default; 269 | $btn-danger-border: $btn-danger-bg !default; 270 | 271 | $btn-link-disabled-color: $gray-light !default; 272 | 273 | $btn-padding-x-sm: .75rem !default; 274 | $btn-padding-y-sm: .25rem !default; 275 | 276 | $btn-padding-x-lg: 1.25rem !default; 277 | $btn-padding-y-lg: .75rem !default; 278 | 279 | // Allows for customizing button radius independently from global border radius 280 | $btn-border-radius: $border-radius !default; 281 | $btn-border-radius-lg: $border-radius-lg !default; 282 | $btn-border-radius-sm: $border-radius-sm !default; 283 | 284 | 285 | // Forms 286 | 287 | $input-padding-x: .75rem !default; 288 | $input-padding-y: .375rem !default; 289 | 290 | $input-bg: #fff !default; 291 | $input-bg-disabled: $gray-lighter !default; 292 | 293 | $input-color: $gray !default; 294 | $input-border-color: #ccc !default; 295 | $input-btn-border-width: $border-width !default; // For form controls and buttons 296 | $input-box-shadow: inset 0 1px 1px rgba(0,0,0,.075) !default; 297 | 298 | $input-border-radius: $border-radius !default; 299 | $input-border-radius-lg: $border-radius-lg !default; 300 | $input-border-radius-sm: $border-radius-sm !default; 301 | 302 | $input-border-focus: #66afe9 !default; 303 | $input-box-shadow-focus: rgba(102,175,233,.6) !default; 304 | 305 | $input-color-placeholder: #999 !default; 306 | 307 | $input-padding-x-sm: .75rem !default; 308 | $input-padding-y-sm: .275rem !default; 309 | 310 | $input-padding-x-lg: 1.25rem !default; 311 | $input-padding-y-lg: .75rem !default; 312 | 313 | $input-height: (($font-size-base * $line-height) + ($input-padding-y * 2)) !default; 314 | $input-height-lg: (($font-size-lg * $line-height-lg) + ($input-padding-y-lg * 2)) !default; 315 | $input-height-sm: (($font-size-sm * $line-height-sm) + ($input-padding-y-sm * 2)) !default; 316 | 317 | $form-group-margin-bottom: $spacer-y !default; 318 | 319 | $input-group-addon-bg: $gray-lighter !default; 320 | $input-group-addon-border-color: $input-border-color !default; 321 | 322 | $cursor-disabled: not-allowed !default; 323 | 324 | // Form validation icons 325 | $form-icon-success: "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2MTIgNzkyIj48cGF0aCBmaWxsPSIjNWNiODVjIiBkPSJNMjMzLjggNjEwYy0xMy4zIDAtMjYtNi0zNC0xNi44TDkwLjUgNDQ4LjhDNzYuMyA0MzAgODAgNDAzLjMgOTguOCAzODljMTguOC0xNC4yIDQ1LjUtMTAuNCA1OS44IDguNGw3MiA5NUw0NTEuMyAyNDJjMTIuNS0yMCAzOC44LTI2LjIgNTguOC0xMy43IDIwIDEyLjQgMjYgMzguNyAxMy43IDU4LjhMMjcwIDU5MGMtNy40IDEyLTIwLjIgMTkuNC0zNC4zIDIwaC0yeiIvPjwvc3ZnPg==" !default; 326 | $form-icon-warning: "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2MTIgNzkyIj48cGF0aCBmaWxsPSIjZjBhZDRlIiBkPSJNNjAzIDY0MC4ybC0yNzguNS01MDljLTMuOC02LjYtMTAuOC0xMC42LTE4LjUtMTAuNnMtMTQuNyA0LTE4LjUgMTAuNkw5IDY0MC4yYy0zLjcgNi41LTMuNiAxNC40LjIgMjAuOCAzLjggNi41IDEwLjggMTAuNCAxOC4zIDEwLjRoNTU3YzcuNiAwIDE0LjYtNCAxOC40LTEwLjQgMy41LTYuNCAzLjYtMTQuNCAwLTIwLjh6bS0yNjYuNC0zMGgtNjEuMlY1NDloNjEuMnY2MS4yem0wLTEwN2gtNjEuMlYzMDRoNjEuMnYxOTl6Ii8+PC9zdmc+" !default; 327 | $form-icon-danger: "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2MTIgNzkyIj48cGF0aCBmaWxsPSIjZDk1MzRmIiBkPSJNNDQ3IDU0NC40Yy0xNC40IDE0LjQtMzcuNiAxNC40LTUyIDBsLTg5LTkyLjctODkgOTIuN2MtMTQuNSAxNC40LTM3LjcgMTQuNC01MiAwLTE0LjQtMTQuNC0xNC40LTM3LjYgMC01Mmw5Mi40LTk2LjMtOTIuNC05Ni4zYy0xNC40LTE0LjQtMTQuNC0zNy42IDAtNTJzMzcuNi0xNC4zIDUyIDBsODkgOTIuOCA4OS4yLTkyLjdjMTQuNC0xNC40IDM3LjYtMTQuNCA1MiAwIDE0LjMgMTQuNCAxNC4zIDM3LjYgMCA1MkwzNTQuNiAzOTZsOTIuNCA5Ni40YzE0LjQgMTQuNCAxNC40IDM3LjYgMCA1MnoiLz48L3N2Zz4=" !default; 328 | 329 | 330 | // Dropdowns 331 | // 332 | // Dropdown menu container and contents. 333 | 334 | $dropdown-bg: #fff !default; 335 | $dropdown-border-color: rgba(0,0,0,.15) !default; 336 | $dropdown-border-width: $border-width !default; 337 | $dropdown-divider-bg: #e5e5e5 !default; 338 | 339 | $dropdown-link-color: $gray-dark !default; 340 | $dropdown-link-hover-color: darken($gray-dark, 5%) !default; 341 | $dropdown-link-hover-bg: #f5f5f5 !default; 342 | 343 | $dropdown-link-active-color: $component-active-color !default; 344 | $dropdown-link-active-bg: $component-active-bg !default; 345 | 346 | $dropdown-link-disabled-color: $gray-light !default; 347 | 348 | $dropdown-header-color: $gray-light !default; 349 | 350 | 351 | // Z-index master list 352 | // 353 | // Warning: Avoid customizing these values. They're used for a bird's eye view 354 | // of components dependent on the z-axis and are designed to all work together. 355 | 356 | $zindex-navbar: 1000 !default; 357 | $zindex-dropdown: 1000 !default; 358 | $zindex-popover: 1060 !default; 359 | $zindex-tooltip: 1070 !default; 360 | $zindex-navbar-fixed: 1030 !default; 361 | $zindex-navbar-sticky: 1030 !default; 362 | $zindex-modal-bg: 1040 !default; 363 | $zindex-modal: 1050 !default; 364 | 365 | 366 | // Navbar 367 | 368 | $navbar-border-radius: $border-radius !default; 369 | $navbar-padding-horizontal: $spacer !default; 370 | $navbar-padding-vertical: ($spacer / 2) !default; 371 | 372 | $navbar-dark-color: rgba(255,255,255,.5) !default; 373 | $navbar-dark-hover-color: rgba(255,255,255,.75) !default; 374 | $navbar-dark-active-color: rgba(255,255,255,1) !default; 375 | $navbar-dark-disabled-color: rgba(255,255,255,.25) !default; 376 | 377 | $navbar-light-color: rgba(0,0,0,.3) !default; 378 | $navbar-light-hover-color: rgba(0,0,0,.6) !default; 379 | $navbar-light-active-color: rgba(0,0,0,.8) !default; 380 | $navbar-light-disabled-color: rgba(0,0,0,.15) !default; 381 | 382 | 383 | // Navs 384 | 385 | $nav-link-padding: .5em 1em !default; 386 | $nav-link-hover-bg: $gray-lighter !default; 387 | 388 | $nav-disabled-link-color: $gray-light !default; 389 | $nav-disabled-link-hover-color: $gray-light !default; 390 | 391 | $nav-tabs-border-color: #ddd !default; 392 | 393 | $nav-tabs-link-border-width: $border-width !default; 394 | $nav-tabs-link-hover-border-color: $gray-lighter !default; 395 | 396 | $nav-tabs-active-link-hover-bg: $body-bg !default; 397 | $nav-tabs-active-link-hover-color: $gray !default; 398 | $nav-tabs-active-link-hover-border-color: #ddd !default; 399 | 400 | $nav-tabs-justified-link-border-color: #ddd !default; 401 | $nav-tabs-justified-active-link-border-color: $body-bg !default; 402 | 403 | $nav-pills-border-radius: $border-radius !default; 404 | $nav-pills-active-link-hover-bg: $component-active-bg !default; 405 | $nav-pills-active-link-hover-color: $component-active-color !default; 406 | 407 | 408 | // Pagination 409 | 410 | $pagination-padding-x: .75rem !default; 411 | $pagination-padding-y: .5rem !default; 412 | $pagination-padding-x-sm: .75rem !default; 413 | $pagination-padding-y-sm: .275rem !default; 414 | $pagination-padding-x-lg: 1.5rem !default; 415 | $pagination-padding-y-lg: .75rem !default; 416 | 417 | 418 | $pagination-color: $link-color !default; 419 | $pagination-bg: #fff !default; 420 | $pagination-border-width: $border-width !default; 421 | $pagination-border-color: #ddd !default; 422 | 423 | $pagination-hover-color: $link-hover-color !default; 424 | $pagination-hover-bg: $gray-lighter !default; 425 | $pagination-hover-border: #ddd !default; 426 | 427 | $pagination-active-color: #fff !default; 428 | $pagination-active-bg: $brand-primary !default; 429 | $pagination-active-border: $brand-primary !default; 430 | 431 | $pagination-disabled-color: $gray-light !default; 432 | $pagination-disabled-bg: #fff !default; 433 | $pagination-disabled-border: #ddd !default; 434 | 435 | 436 | // Pager 437 | 438 | $pager-bg: $pagination-bg !default; 439 | $pager-border-width: $border-width !default; 440 | $pager-border-color: $pagination-border-color !default; 441 | $pager-border-radius: 15px !default; 442 | 443 | $pager-hover-bg: $pagination-hover-bg !default; 444 | 445 | $pager-active-bg: $pagination-active-bg !default; 446 | $pager-active-color: $pagination-active-color !default; 447 | 448 | $pager-disabled-color: $pagination-disabled-color !default; 449 | 450 | 451 | // Jumbotron 452 | 453 | $jumbotron-padding: 2rem !default; 454 | $jumbotron-bg: $gray-lighter !default; 455 | 456 | 457 | // Form states and alerts 458 | // 459 | // Define colors for form feedback states and, by default, alerts. 460 | 461 | $state-success-text: #3c763d !default; 462 | $state-success-bg: #dff0d8 !default; 463 | $state-success-border: darken($state-success-bg, 5%) !default; 464 | 465 | $state-info-text: #31708f !default; 466 | $state-info-bg: #d9edf7 !default; 467 | $state-info-border: darken($state-info-bg, 7%) !default; 468 | 469 | $state-warning-text: #8a6d3b !default; 470 | $state-warning-bg: #fcf8e3 !default; 471 | $state-warning-border: darken($state-warning-bg, 5%) !default; 472 | 473 | $state-danger-text: #a94442 !default; 474 | $state-danger-bg: #f2dede !default; 475 | $state-danger-border: darken($state-danger-bg, 5%) !default; 476 | 477 | 478 | // Cards 479 | $card-spacer-x: 1.25rem !default; 480 | $card-spacer-y: .75rem !default; 481 | $card-border-width: 1px !default; 482 | $card-border-radius: $border-radius !default; 483 | $card-border-color: #e5e5e5 !default; 484 | $card-border-radius-inner: $card-border-radius !default; 485 | $card-cap-bg: #f5f5f5 !default; 486 | $card-bg: #fff !default; 487 | 488 | $card-link-hover-color: #fff !default; 489 | 490 | 491 | // Tooltips 492 | 493 | $tooltip-max-width: 200px !default; 494 | $tooltip-color: #fff !default; 495 | $tooltip-bg: #000 !default; 496 | $tooltip-opacity: .9 !default; 497 | 498 | $tooltip-arrow-width: 5px !default; 499 | $tooltip-arrow-color: $tooltip-bg !default; 500 | 501 | 502 | // Popovers 503 | 504 | $popover-bg: #fff !default; 505 | $popover-max-width: 276px !default; 506 | $popover-border-width: $border-width !default; 507 | $popover-border-color: rgba(0,0,0,.2) !default; 508 | 509 | $popover-title-bg: darken($popover-bg, 3%) !default; 510 | 511 | $popover-arrow-width: 10px !default; 512 | $popover-arrow-color: $popover-bg !default; 513 | 514 | $popover-arrow-outer-width: ($popover-arrow-width + 1) !default; 515 | $popover-arrow-outer-color: fade-in($popover-border-color, 0.05) !default; 516 | 517 | 518 | // Labels 519 | 520 | $label-default-bg: $gray-light !default; 521 | $label-primary-bg: $brand-primary !default; 522 | $label-success-bg: $brand-success !default; 523 | $label-info-bg: $brand-info !default; 524 | $label-warning-bg: $brand-warning !default; 525 | $label-danger-bg: $brand-danger !default; 526 | 527 | $label-color: #fff !default; 528 | $label-link-hover-color: #fff !default; 529 | $label-font-weight: bold !default; 530 | 531 | 532 | // Modals 533 | 534 | // Padding applied to the modal body 535 | $modal-inner-padding: 15px !default; 536 | 537 | $modal-title-padding: 15px !default; 538 | $modal-title-line-height: $line-height !default; 539 | 540 | $modal-content-bg: #fff !default; 541 | $modal-content-border-color: rgba(0,0,0,.2) !default; 542 | 543 | $modal-backdrop-bg: #000 !default; 544 | $modal-backdrop-opacity: .5 !default; 545 | $modal-header-border-color: #e5e5e5 !default; 546 | $modal-footer-border-color: $modal-header-border-color !default; 547 | 548 | $modal-lg: 900px !default; 549 | $modal-md: 600px !default; 550 | $modal-sm: 300px !default; 551 | 552 | 553 | // Alerts 554 | // 555 | // Define alert colors, border radius, and padding. 556 | 557 | $alert-padding: 15px !default; 558 | $alert-border-radius: $border-radius !default; 559 | $alert-link-font-weight: bold !default; 560 | $alert-border-width: $border-width !default; 561 | 562 | $alert-success-bg: $state-success-bg !default; 563 | $alert-success-text: $state-success-text !default; 564 | $alert-success-border: $state-success-border !default; 565 | 566 | $alert-info-bg: $state-info-bg !default; 567 | $alert-info-text: $state-info-text !default; 568 | $alert-info-border: $state-info-border !default; 569 | 570 | $alert-warning-bg: $state-warning-bg !default; 571 | $alert-warning-text: $state-warning-text !default; 572 | $alert-warning-border: $state-warning-border !default; 573 | 574 | $alert-danger-bg: $state-danger-bg !default; 575 | $alert-danger-text: $state-danger-text !default; 576 | $alert-danger-border: $state-danger-border !default; 577 | 578 | 579 | // Progress bars 580 | 581 | $progress-bg: #f5f5f5 !default; 582 | $progress-bar-color: #fff !default; 583 | $progress-border-radius: $border-radius !default; 584 | 585 | $progress-bar-bg: $brand-primary !default; 586 | $progress-bar-success-bg: $brand-success !default; 587 | $progress-bar-warning-bg: $brand-warning !default; 588 | $progress-bar-danger-bg: $brand-danger !default; 589 | $progress-bar-info-bg: $brand-info !default; 590 | 591 | 592 | // List group 593 | 594 | $list-group-bg: #fff !default; 595 | $list-group-border-color: #ddd !default; 596 | $list-group-border-width: $border-width !default; 597 | $list-group-border-radius: $border-radius !default; 598 | 599 | $list-group-hover-bg: #f5f5f5 !default; 600 | $list-group-active-color: $component-active-color !default; 601 | $list-group-active-bg: $component-active-bg !default; 602 | $list-group-active-border: $list-group-active-bg !default; 603 | $list-group-active-text-color: lighten($list-group-active-bg, 40%) !default; 604 | 605 | $list-group-disabled-color: $gray-light !default; 606 | $list-group-disabled-bg: $gray-lighter !default; 607 | $list-group-disabled-text-color: $list-group-disabled-color !default; 608 | 609 | $list-group-link-color: #555 !default; 610 | $list-group-link-hover-color: $list-group-link-color !default; 611 | $list-group-link-heading-color: #333 !default; 612 | 613 | 614 | // Image thumbnails 615 | 616 | $thumbnail-padding: .25rem !default; 617 | $thumbnail-bg: $body-bg !default; 618 | $thumbnail-border-width: $border-width !default; 619 | $thumbnail-border-color: #ddd !default; 620 | $thumbnail-border-radius: $border-radius !default; 621 | 622 | 623 | // Breadcrumbs 624 | 625 | $breadcrumb-padding-vertical: .75rem !default; 626 | $breadcrumb-padding-horizontal: 1rem !default; 627 | 628 | $breadcrumb-bg: $gray-lighter !default; 629 | $breadcrumb-divider-color: $gray-light !default; 630 | $breadcrumb-active-color: $gray-light !default; 631 | $breadcrumb-divider: "/" !default; 632 | 633 | 634 | // Carousel 635 | 636 | $carousel-text-shadow: 0 1px 2px rgba(0,0,0,.6) !default; 637 | 638 | $carousel-control-color: #fff !default; 639 | $carousel-control-width: 15% !default; 640 | $carousel-control-opacity: .5 !default; 641 | $carousel-control-font-size: 20px !default; 642 | 643 | $carousel-indicator-active-bg: #fff !default; 644 | $carousel-indicator-border-color: #fff !default; 645 | 646 | $carousel-caption-color: #fff !default; 647 | 648 | 649 | // Close 650 | 651 | $close-font-weight: bold !default; 652 | $close-color: #000 !default; 653 | $close-text-shadow: 0 1px 0 #fff !default; 654 | 655 | 656 | // Code 657 | 658 | $code-color: #bd4147 !default; 659 | $code-bg: #f7f7f9 !default; 660 | 661 | $kbd-color: #fff !default; 662 | $kbd-bg: #333 !default; 663 | 664 | $pre-bg: #f7f7f9 !default; 665 | $pre-color: $gray-dark !default; 666 | $pre-border-color: #ccc !default; 667 | $pre-scrollable-max-height: 340px !default; 668 | 669 | -------------------------------------------------------------------------------- /src/main/vuejs/assets/scss/_vue.scss: -------------------------------------------------------------------------------- 1 | [v-cloak] { 2 | display: none; 3 | } 4 | -------------------------------------------------------------------------------- /src/main/vuejs/assets/scss/main.scss: -------------------------------------------------------------------------------- 1 | @import "bootstrap"; 2 | @import "vue"; 3 | @import "animations"; 4 | @import "layout"; 5 | @import "fonts"; 6 | 7 | -------------------------------------------------------------------------------- /src/main/vuejs/components/about.vue: -------------------------------------------------------------------------------- 1 | 42 | 57 | -------------------------------------------------------------------------------- /src/main/vuejs/components/chat.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 63 | -------------------------------------------------------------------------------- /src/main/vuejs/components/hello.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 46 | -------------------------------------------------------------------------------- /src/main/vuejs/components/home.vue: -------------------------------------------------------------------------------- 1 | 41 | 46 | -------------------------------------------------------------------------------- /src/main/vuejs/components/layout/page-footer.vue: -------------------------------------------------------------------------------- 1 | 9 | 14 | -------------------------------------------------------------------------------- /src/main/vuejs/components/layout/page-header.vue: -------------------------------------------------------------------------------- 1 | 61 | 66 | -------------------------------------------------------------------------------- /src/main/vuejs/components/not-found.vue: -------------------------------------------------------------------------------- 1 | 7 | 15 | 20 | -------------------------------------------------------------------------------- /src/main/vuejs/components/survey/data.js: -------------------------------------------------------------------------------- 1 | var survey = { 2 | title: 'Simple survey', 3 | numbered: true, 4 | questions: [ 5 | { 6 | id: 1, 7 | name: 'What\'s answer #1?', 8 | type: 'TEXT', 9 | answer: null 10 | }, 11 | { 12 | id: 2, 13 | name: 'What\'s answer #2?', 14 | type: 'COMBO', 15 | options: [ 16 | { 17 | name: 'Option A', 18 | value: 'A' 19 | }, 20 | { 21 | name: 'Option B', 22 | value: 'B' 23 | }, 24 | { 25 | name: 'Option C', 26 | value: 'C' 27 | } 28 | ], 29 | answer: null 30 | }, 31 | { 32 | id: 3, 33 | type: 'BREAK_PAGE', 34 | answer: null 35 | }, 36 | { 37 | id: 4, 38 | name: 'What\'s answer #4?', 39 | type: 'RADIO', 40 | options: [ 41 | { 42 | name: 'Option A', 43 | value: 'A' 44 | }, 45 | { 46 | name: 'Option B', 47 | value: 'B' 48 | }, 49 | { 50 | name: 'Option C', 51 | value: 'C' 52 | } 53 | ], 54 | answer: null 55 | }, 56 | { 57 | id: 5, 58 | name: 'What\'s answer #5?', 59 | type: 'NONE', 60 | answer: null 61 | }, 62 | { 63 | id: 6, 64 | name: 'What\'s answer #6?', 65 | type: 'COMBO', 66 | options: [ 67 | { 68 | name: 'Option A', 69 | value: 'A' 70 | }, 71 | { 72 | name: 'Option B', 73 | value: 'B' 74 | }, 75 | { 76 | name: 'Option C', 77 | value: 'C' 78 | } 79 | ], 80 | answer: null 81 | }, 82 | { 83 | id: 7, 84 | type: 'BREAK_PAGE', 85 | answer: null 86 | }, 87 | { 88 | id: 8, 89 | name: 'What\'s answer #8?', 90 | type: 'RADIO', 91 | options: [ 92 | { 93 | name: 'Option A', 94 | value: 'A' 95 | }, 96 | { 97 | name: 'Option B', 98 | value: 'B' 99 | }, 100 | { 101 | name: 'Option C', 102 | value: 'C' 103 | } 104 | ], 105 | answer: null 106 | } 107 | ] 108 | }; 109 | 110 | export default survey; 111 | -------------------------------------------------------------------------------- /src/main/vuejs/components/survey/question.vue: -------------------------------------------------------------------------------- 1 | 20 | 43 | -------------------------------------------------------------------------------- /src/main/vuejs/components/survey/survey.vue: -------------------------------------------------------------------------------- 1 | 34 | 124 | -------------------------------------------------------------------------------- /src/main/vuejs/components/user/index.vue: -------------------------------------------------------------------------------- 1 | 9 | 14 | -------------------------------------------------------------------------------- /src/main/vuejs/components/user/posts.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 30 | -------------------------------------------------------------------------------- /src/main/vuejs/components/user/profile.vue: -------------------------------------------------------------------------------- 1 | 7 | 12 | -------------------------------------------------------------------------------- /src/main/vuejs/components/user/settings.vue: -------------------------------------------------------------------------------- 1 | 17 | 37 | -------------------------------------------------------------------------------- /src/main/vuejs/config/routes.js: -------------------------------------------------------------------------------- 1 | export function configRouter (router) { 2 | 3 | // normal routes 4 | router.map({ 5 | '/home': { 6 | component: require('./../components/home.vue') 7 | }, 8 | // nested example 9 | '/user/:userId': { 10 | component: require('./../components/user/index.vue'), 11 | subRoutes: { 12 | // matches "/user/:userId/profile/:something" 13 | 'profile/:something': { 14 | component: require('./../components/user/profile.vue') 15 | }, 16 | // matches "/user/:userId/posts" 17 | 'posts': { 18 | component: require('./../components/user/posts.vue') 19 | }, 20 | // matches "/user/:userId/settings" 21 | 'settings': { 22 | component: require('./../components/user/settings.vue') 23 | } 24 | } 25 | }, 26 | // basic example 27 | '/about': { 28 | component: require('./../components/about.vue') 29 | }, 30 | '/survey': { 31 | component: require('./../components/survey/survey.vue') 32 | }, 33 | '/chat': { 34 | component: require('./../components/chat.vue') 35 | }, 36 | '/hello': { 37 | component: require('./../components/hello.vue') 38 | }, 39 | // not found handler 40 | '*': { 41 | component: require('./../components/not-found.vue') 42 | } 43 | }); 44 | 45 | // redirect 46 | router.redirect({ 47 | '/info': '/about', 48 | '/': '/home', 49 | '/hello/:userId': '/user/:userId' 50 | }); 51 | 52 | // global before 53 | // 3 options: 54 | // 1. return a boolean 55 | // 2. return a Promise that resolves to a boolean 56 | // 3. call transition.next() or transition.abort() 57 | router.beforeEach((transition) => { 58 | if (transition.to.path === '/forbidden') { 59 | router.app.authenticating = true; 60 | setTimeout(() => { 61 | router.app.authenticating = false; 62 | alert('this route is forbidden by a global before hook'); 63 | transition.abort(); 64 | }, 3000); 65 | } else { 66 | transition.next(); 67 | } 68 | }); 69 | } 70 | -------------------------------------------------------------------------------- /src/main/vuejs/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import VueRouter from 'vue-router'; 3 | import VueResource from 'vue-resource'; 4 | 5 | require('es6-promise').polyfill(); 6 | import { configRouter } from './config/routes'; 7 | 8 | // Bootstrap 4 9 | require('bootstrap'); 10 | 11 | // debug mode 12 | Vue.config.debug = false; 13 | 14 | // install vue-resource 15 | Vue.use(VueResource); 16 | 17 | // install router 18 | Vue.use(VueRouter); 19 | 20 | // create router 21 | const router = new VueRouter({ 22 | history: true, 23 | saveScrollPosition: true 24 | }); 25 | 26 | // configure router 27 | configRouter(router); 28 | 29 | // boostrap the app 30 | router.start(require('./app'), 'app'); 31 | 32 | -------------------------------------------------------------------------------- /src/main/vuejs/stores/store.js: -------------------------------------------------------------------------------- 1 | import Vuex from 'vuex'; 2 | import Vue from 'vue'; 3 | 4 | Vue.use(Vuex); 5 | 6 | var store = new Vuex.Store({ 7 | state: { 8 | count: 0 9 | }, 10 | mutations: { 11 | INCREMENT: function (state) { 12 | state.count++; 13 | if (state.count > 100) { 14 | state.count = state.count - 100; 15 | } 16 | }, 17 | DECREMENT: function (state) { 18 | state.count--; 19 | if (state.count < 0) { 20 | state.count = state.count + 100; 21 | } 22 | }, 23 | SET_PROGRESS: function (state, number) { 24 | state.count = number; 25 | } 26 | } 27 | }); 28 | 29 | export default store; 30 | -------------------------------------------------------------------------------- /src/test/java/com/shardis/ShardisFrameworkApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.shardis; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.test.context.web.WebAppConfiguration; 6 | import org.springframework.boot.test.SpringApplicationConfiguration; 7 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 8 | 9 | @RunWith(SpringJUnit4ClassRunner.class) 10 | @SpringApplicationConfiguration(classes = ShardisFrameworkApplication.class) 11 | @WebAppConfiguration 12 | public class ShardisFrameworkApplicationTests { 13 | 14 | @Test 15 | public void contextLoads() { 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/test/vuejs/unit/Hello.spec.js: -------------------------------------------------------------------------------- 1 | /* global describe, it, expect */ 2 | 3 | import Vue from 'vue'; 4 | import Hello from '../../../main/vuejs/components/hello.vue'; 5 | 6 | describe('Hello.vue', () => { 7 | it('should render correct contents', () => { 8 | const vm = new Vue({ 9 | template: '
', 10 | components: { Hello } 11 | }).$mount(); 12 | expect(vm.$el.querySelector('.hello h1').textContent).toBe('Hello Vue.js!!!'); 13 | }); 14 | }); 15 | 16 | // also see example testing a component with mocks at 17 | // https://github.com/vuejs/vue-loader-example/blob/master/test/unit/a.spec.js#L24-L49 18 | -------------------------------------------------------------------------------- /src/test/vuejs/unit/index.js: -------------------------------------------------------------------------------- 1 | // Polyfill fn.bind() for PhantomJS 2 | /* eslint-disable no-extend-native */ 3 | Function.prototype.bind = require('function-bind'); 4 | 5 | // require all test files (files that ends with .spec.js) 6 | var testsContext = require.context('.', true, /\.spec$/); 7 | testsContext.keys().forEach(testsContext); 8 | --------------------------------------------------------------------------------