├── .babelrc
├── .editorconfig
├── .eslintrc
├── .gitignore
├── LICENSE
├── README.md
├── build
├── config.js
├── index.html
├── log-plugin.js
├── server.js
├── utils.js
├── webpack.base.js
├── webpack.dev.js
└── webpack.prod.js
├── client
├── app.js
├── components
│ ├── App
│ │ ├── index.vue
│ │ └── style.scss
│ ├── Dimmer
│ │ └── index.vue
│ ├── Header
│ │ ├── index.vue
│ │ └── style.scss
│ └── Sidebar
│ │ ├── index.vue
│ │ └── style.scss
├── index.js
├── pwa.js
├── router
│ └── index.js
├── store
│ ├── index.js
│ └── ui
│ │ └── index.js
├── styles
│ ├── fonts.scss
│ ├── index.scss
│ ├── mixins.scss
│ └── vars.scss
└── views
│ ├── About
│ └── index.vue
│ ├── Dashboard
│ └── index.vue
│ └── Post
│ └── index.vue
├── package-lock.json
├── package.json
├── static
└── favicon.ico
└── tests
└── index.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": ["lodash",
3 | [
4 | "transform-runtime", {
5 | "helpers": false,
6 | "polyfill": false,
7 | "regenerator": true,
8 | "moduleName": "babel-runtime"
9 | },
10 | ]
11 | ],
12 | "presets": ["es2015", "vue-app", "stage-0"]
13 | }
14 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | indent_size = 4
6 | end_of_line = lf
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 |
11 | [*.md]
12 | trim_trailing_whitespace = false
13 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["vue", "standard"]
3 | }
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | *.log
3 | .DS_Store
4 | /dist
5 | theme
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Vladimir Metnev
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Vue-Element-Starter
2 | #### Demo: https://metnew.github.io/vue-element-starter/
3 |
4 |
5 |
6 |
7 |
8 | [](https://www.bithound.io/github/Metnew/vue-element-starter)
9 | [](https://www.bithound.io/github/Metnew/vue-element-starter/master/dependencies/npm)
10 | [](https://snyk.io/test/github/metnew/vue-element-starter)
11 | ## Includes:
12 |
13 | - [Element](http://element.eleme.io/#/en-US) and normalize.css
14 | - [Vue -v 2.1](https://vuejs.org/) & Vue-router
15 | - [Vuex](https://github.com/vuejs/vuex) & Vuex-router-sync
16 | - [Fetch polyfill](https://www.npmjs.com/package/whatwg-fetch)
17 | - [Webpack](https://webpack.github.io/)
18 | - [TestCafe](https://testcafe.devexpress.com/) for testing
19 | - Eslint, Babel (stage-0)
20 |
21 | ## Out-of-box:
22 | ### (theme color is purple, but you can use your own color, more info below)
23 |
24 | 
25 |
26 | ## Folder structure:
27 |
28 | ```
29 | app
30 | ├── build // webpack config files
31 | ├── client - Your App
32 | │ └── components - your components
33 | │ ├── router - routing
34 | │ ├── store - Vuex store
35 | │ ├── styles - styles folder with scss vars, mixins, etc.
36 | │ ├── views - your pages
37 | │ ├── app.js - import dependencies and App component
38 | │ ├── index.js - main file
39 | │ ├── pwa.js - for PWA apps
40 | ├── dist - build.
41 | ├── static - static assets, etc.
42 | ├── tests - Your tests
43 | ├── theme - Element UI generated theme
44 | ```
45 |
46 | Template built based on [Vuepack bolirplate](https://github.com/egoist/vuepack)
47 |
48 | ## To start:
49 |
50 | ```bash
51 | git clone https://github.com/Metnew/vue-element-starter.git vue-project
52 | cd vue-project && rm -rf .git
53 | npm install
54 | npm run generate_default_styles # run this command to generate default_styles for Element-theme
55 | ```
56 |
57 | [Element-theme](https://www.npmjs.com/package/element-theme) generates default styles. Just **change primary-color** in `./client/element-variables.css` and run:
58 |
59 | ```bash
60 | npm run generate_theme
61 | ```
62 |
63 | Now app is ready and you can run it with:
64 |
65 | ```bash
66 | npm run dev
67 | ```
68 |
69 | Make production build:
70 |
71 | ```bash
72 | npm run build
73 | ```
74 |
75 | ### Also
76 | PRs, issues, questions, \ are always welcome.
77 | Feel free to contact me (or add new issue).
78 |
79 | ### Author
80 | Vladimir Metnew
81 |
82 | ### LICENSE
83 | MIT
84 |
--------------------------------------------------------------------------------
/build/config.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | module.exports = {
4 | port: 4000,
5 | title: 'Vue-Element-Starter',
6 | // when you use electron please set to relative path like ./
7 | // otherwise only set to absolute path when you're using history mode
8 | publicPath: '/',
9 | // add these dependencies to a standalone vendor bundle
10 | vendor: [
11 | 'vue',
12 | 'vuex',
13 | 'vue-router',
14 | 'vuex-router-sync',
15 | 'whatwg-fetch',
16 | 'normalize.css',
17 | 'offline-plugin/runtime',
18 | 'element-ui',
19 | 'material-design-icons'
20 | ]
21 | }
22 |
--------------------------------------------------------------------------------
/build/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | <%= htmlWebpackPlugin.options.title %>
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/build/log-plugin.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const chalk = require('chalk')
3 |
4 | // this plugin if for loggin url after each time the compilation is done.
5 | module.exports = class LogPlugin {
6 | constructor (port) {
7 | this.port = port
8 | }
9 |
10 | apply (compiler) {
11 | compiler.plugin('done', () => {
12 | console.log(
13 | `> App is running at ${chalk.yellow(`http://localhost:${this.port}`)}\n`
14 | )
15 | })
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/build/server.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | // const fs = require('fs')
3 | const path = require('path')
4 | const express = require('express')
5 | const webpack = require('webpack')
6 | const webpackConfig = require('./webpack.dev')
7 | const config = require('./config')
8 | const LogPlugin = require('./log-plugin')
9 |
10 | const app = express()
11 |
12 | const port = config.port
13 | webpackConfig.entry.client = [
14 | `webpack-hot-middleware/client?reload=true`,
15 | webpackConfig.entry.client
16 | ]
17 |
18 | webpackConfig.plugins.push(new LogPlugin(port))
19 |
20 | let compiler
21 |
22 | try {
23 | compiler = webpack(webpackConfig)
24 | } catch (err) {
25 | console.log(err.message)
26 | process.exit(1)
27 | }
28 |
29 | const devMiddleWare = require('webpack-dev-middleware')(compiler, {
30 | publicPath: webpackConfig.output.publicPath,
31 | quiet: false,
32 | hot: true,
33 | inline: true,
34 | headers: {
35 | 'Access-Control-Allow-Origin': '*',
36 | 'Access-Control-Allow-Methods': '*',
37 | 'Access-Control-Allow-Headers': '*'
38 | }
39 | })
40 | app.use(devMiddleWare)
41 | app.use(
42 | require('webpack-hot-middleware')(compiler, {
43 | log: () => {}
44 | })
45 | )
46 |
47 | const mfs = devMiddleWare.fileSystem
48 | const file = path.join(webpackConfig.output.path, 'index.html')
49 |
50 | devMiddleWare.waitUntilValid()
51 |
52 | app.get('*', (req, res) => {
53 | devMiddleWare.waitUntilValid(() => {
54 | const html = mfs.readFileSync(file)
55 | res.end(html)
56 | })
57 | })
58 |
59 | app.listen(port)
60 |
--------------------------------------------------------------------------------
/build/utils.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const _ = (module.exports = {})
4 |
5 | _.cwd = file => {
6 | return path.join(process.cwd(), file || '')
7 | }
8 |
9 | _.outputPath = path.join(__dirname, '../dist')
10 |
11 | _.outputIndexPath = path.join(__dirname, '../dist/index.html')
12 |
13 | _.target = 'web'
14 |
--------------------------------------------------------------------------------
/build/webpack.base.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const webpack = require('webpack')
4 | const HtmlWebpackPlugin = require('html-webpack-plugin')
5 | const CopyWebpackPlugin = require('copy-webpack-plugin')
6 | const config = require('./config')
7 | const _ = require('./utils')
8 |
9 | module.exports = {
10 | entry: {
11 | client: './client/index.js'
12 | },
13 | output: {
14 | path: _.outputPath,
15 | filename: '[name].js',
16 | publicPath: config.publicPath
17 | },
18 | performance: {
19 | hints: process.env.NODE_ENV === 'production' ? 'warning' : false
20 | },
21 | resolve: {
22 | extensions: [
23 | '.js',
24 | '.vue',
25 | '.css',
26 | '.json',
27 | '.scss',
28 | '.eot',
29 | '.svg',
30 | '.ttf',
31 | '.woff'
32 | ],
33 | alias: {
34 | root: path.join(__dirname, '../client'),
35 | components: path.join(__dirname, '../client/components'),
36 | views: path.join(__dirname, '../client/views'),
37 | router: path.join(__dirname, '../client/router'),
38 | theme: path.join(__dirname, '../theme'), // get Element-UI icons
39 | scss_vars: path.resolve(__dirname, '../client/styles/vars.scss'), // get scss vars
40 | styles: path.join(__dirname, '../client/styles') // get scss files
41 | },
42 | modules: [
43 | // places where to search for required modules
44 | _.cwd('node_modules'),
45 | _.cwd('client'),
46 | _.cwd('theme')
47 | ]
48 | },
49 | module: {
50 | rules: [
51 | {
52 | test: /\.vue$/,
53 | use: 'vue-loader'
54 | },
55 | {
56 | test: /\.js$/,
57 | enforce: 'pre',
58 | use: 'eslint-loader?fix=true',
59 | exclude: [/node_modules/]
60 | },
61 | {
62 | test: /\.js$/,
63 | use: 'babel-loader',
64 | exclude: [/node_modules/]
65 | },
66 | {
67 | test: /\.(ico|eot|otf|webp|ttf|woff|woff2)(\?.*)?$/,
68 | use: 'file-loader?limit=100000'
69 | },
70 | {
71 | test: /\.(jpe?g|png|gif|svg)$/i,
72 | use: [
73 | 'file-loader?limit=100000',
74 | {
75 | loader: 'img-loader',
76 | options: {
77 | enabled: true,
78 | optipng: true
79 | }
80 | }
81 | ]
82 | }
83 | ]
84 | },
85 | plugins: [
86 | new HtmlWebpackPlugin({
87 | title: config.title,
88 | template: path.resolve(__dirname, 'index.html'),
89 | filename: _.outputIndexPath
90 | }),
91 | new CopyWebpackPlugin([
92 | {
93 | from: _.cwd('./static'),
94 | // to the root of dist path
95 | to: './'
96 | }
97 | ])
98 | ],
99 | target: _.target
100 | }
101 |
--------------------------------------------------------------------------------
/build/webpack.dev.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | process.env.NODE_ENV = 'development'
3 |
4 | const webpack = require('webpack')
5 | const base = require('./webpack.base')
6 | const FriendlyErrors = require('friendly-errors-webpack-plugin')
7 |
8 | base.devtool = 'eval-source-map'
9 | base.module.rules.push(
10 | {
11 | test: /\.css$/,
12 | loaders: ['style-loader', 'css-loader', 'resolve-url-loader']
13 | },
14 | {
15 | test: /\.scss$/,
16 | loaders: ['style-loader', 'css-loader', 'resolve-url-loader', 'sass-loader']
17 | }
18 | )
19 |
20 | // add dev plugins
21 | base.plugins.push(
22 | new webpack.HotModuleReplacementPlugin(),
23 | new webpack.DefinePlugin({
24 | 'process.env.NODE_ENV': JSON.stringify('development')
25 | }),
26 | new webpack.NoEmitOnErrorsPlugin(),
27 | new FriendlyErrors()
28 | )
29 |
30 | module.exports = base
31 |
--------------------------------------------------------------------------------
/build/webpack.prod.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | process.env.NODE_ENV = 'production'
3 |
4 | const exec = require('child_process').execSync
5 | const webpack = require('webpack')
6 | const ExtractTextPlugin = require('extract-text-webpack-plugin')
7 | const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')
8 | const PreloadWebpackPlugin = require('preload-webpack-plugin')
9 | const ProgressPlugin = require('webpack/lib/ProgressPlugin')
10 | const OfflinePlugin = require('offline-plugin')
11 | const base = require('./webpack.base')
12 | const config = require('./config')
13 |
14 | // remove dist folder
15 | exec('rm -rf dist/')
16 | // use source-map
17 | base.devtool = 'cheap-source-map'
18 | base.module.rules.push(
19 | {
20 | test: /\.css$/,
21 | use: ExtractTextPlugin.extract({
22 | fallback: 'style-loader',
23 | use: 'css-loader'
24 | })
25 | },
26 | {
27 | test: /\.scss$/,
28 | use: ExtractTextPlugin.extract({
29 | fallback: 'style-loader',
30 | use: ['css-loader', 'sass-loader']
31 | })
32 | }
33 | )
34 | // a white list to add dependencies to vendor chunk
35 | base.entry.vendor = config.vendor
36 | // use hash filename to support long-term caching
37 | base.output.filename = '[name].[chunkhash:8].js'
38 | // add webpack plugins
39 | base.plugins.push(
40 | new ProgressPlugin(),
41 | new ExtractTextPlugin('[name].[contenthash:8].css'),
42 | new OptimizeCssAssetsPlugin(),
43 | new webpack.DefinePlugin({
44 | 'process.env.NODE_ENV': JSON.stringify('production')
45 | }),
46 | new webpack.optimize.UglifyJsPlugin({
47 | sourceMap: true,
48 | compress: {
49 | warnings: false
50 | },
51 | output: {
52 | comments: false
53 | }
54 | }),
55 | // extract vendor chunks
56 | new webpack.optimize.CommonsChunkPlugin({
57 | name: 'vendor',
58 | filename: 'vendor.[chunkhash:8].js'
59 | }),
60 | new PreloadWebpackPlugin({ rel: 'preload', as: 'script', include: 'all' }),
61 | // progressive web app
62 | // it uses the publicPath in webpack config
63 | new OfflinePlugin({
64 | relativePaths: false,
65 | AppCache: false,
66 | ServiceWorker: {
67 | events: true
68 | }
69 | })
70 | )
71 |
72 | // minimize webpack output
73 | base.stats = {
74 | // Add children information
75 | children: false,
76 | // Add chunk information (setting this to `false` allows for a less verbose output)
77 | chunks: false,
78 | // Add built modules information to chunk information
79 | chunkModules: false,
80 | chunkOrigins: false,
81 | modules: false
82 | }
83 |
84 | module.exports = base
85 |
--------------------------------------------------------------------------------
/client/app.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import { sync } from 'vuex-router-sync'
3 | import Element from 'element-ui'
4 | import App from 'components/App' // require components using webpack alias
5 | import { router } from './router' // Vue Router
6 | import store from './store' // Vuex store
7 | import locale from 'element-ui/lib/locale/lang/en'
8 | import 'theme/index.css' // generated Element-UI theme
9 | import 'normalize.css' // normalize
10 | import 'whatwg-fetch' // polyfill
11 | import 'material-design-icons' // material icons, because Element-UI icons set is incomplete
12 | import 'styles/index.scss' // require styles using webpack alias
13 |
14 | sync(store, router)
15 | Vue.use(Element, { locale })
16 |
17 | const app = new Vue({
18 | router,
19 | store,
20 | ...App
21 | })
22 |
23 | export { app, router, store }
24 |
--------------------------------------------------------------------------------
/client/components/App/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
53 |
54 |
58 |
--------------------------------------------------------------------------------
/client/components/App/style.scss:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | }
4 |
5 | * {
6 | box-sizing: border-box;
7 | }
8 |
9 | #app {
10 | color: #333;
11 | width: 100%;
12 | height: 100%;
13 | .page-layout {
14 | position: absolute;
15 | width: 100%;
16 | height: 100%;
17 | main {
18 | z-index: 1;
19 | overflow-x: auto;
20 | height: calc(100% - 80px);
21 | padding-top: 80px;
22 | position: absolute;
23 | transform-style: preserve-3d;
24 | will-change: transform;
25 | transition-property: transform;
26 | width: 100%;
27 | transform: translate3d(0, 0, 0)!important;
28 | @include respond-to('lg') {
29 | width: calc(100% - #{$sidebar-size}); //
30 | transform: translate3d($sidebar-size, 0, 0)!important; //
31 | }
32 | .main-content {
33 | width: 100%;
34 | margin: 0;
35 | @include respond-to('sm', 'xs') {
36 | margin: 0 auto;
37 | }
38 | .container {
39 | margin-top: 0;
40 | max-width: 1140px;
41 | padding: 0 20px;
42 | > div:first-child {
43 | width: 100%;
44 | }
45 | }
46 | }
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/client/components/Dimmer/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
12 |
13 |
38 |
--------------------------------------------------------------------------------
/client/components/Header/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
16 |
17 |
18 |
19 |
20 |
26 |
27 |
32 |
--------------------------------------------------------------------------------
/client/components/Header/style.scss:
--------------------------------------------------------------------------------
1 | header {
2 | z-index: 6;
3 | background: #fff;
4 | border-bottom: 1px solid $grey;
5 | box-shadow: inset 0 0 0 0 $grey,0 2px 1px 0 rgba(47,61,73,.05);
6 | color: #2e3d49;
7 | position: fixed;
8 | transform-style: preserve-3d;
9 | will-change: transform;
10 | transition-duration: .2s;
11 | transition-timing-function: cubic-bezier(.4,0,.2,1);
12 | transition-property: transform;
13 | width: 100%;
14 | height: $header-height;
15 |
16 | @include respond-to('sm', 'xs') {
17 | transform: translate3d(0, 0, 0)!important;
18 | }
19 |
20 | @include respond-to('lg') {
21 | width: calc(100% - #{$sidebar-size});
22 | transform: translate3d($sidebar-size, 0, 0)!important;
23 | }
24 |
25 | .el-menu {
26 | border-radius: 0;
27 | }
28 |
29 | &.no_sidebar {
30 | transform: translate3d(0, 0, 0)!important;
31 | width: 100%;
32 | }
33 |
34 | .header-navicon {
35 | display: flex;
36 | align-items: center;
37 | align-content: center;
38 | @include respond-to('lg') {
39 | display: none;
40 | }
41 | i {
42 | color: $white!important;
43 | font-size: 2rem!important;
44 | }
45 | }
46 | .header-menu {
47 | float: right!important;
48 | }
49 |
50 | .header-title {
51 | font-size: 24px;
52 | color: $white;
53 | margin-left: 0;
54 | line-height: 60px;
55 | @include respond-to('lg') {
56 | margin-left: 24px;
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/client/components/Sidebar/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
27 |
28 |
29 |
41 |
42 |
47 |
--------------------------------------------------------------------------------
/client/components/Sidebar/style.scss:
--------------------------------------------------------------------------------
1 | #sidebar {
2 | z-index: 5;
3 | width: $sidebar-size;
4 | border-right: 1px solid $grey;
5 | box-shadow: inset 0 0 0 0 $grey,0 2px 1px 0 rgba(47,61,73,.05);
6 | height: 100%;
7 | visibility: visible!important;
8 | overflow-x: hidden;
9 | will-change: transform;
10 | transition-duration: .2s;
11 | transition-timing-function: cubic-bezier(.4,0,.2,1);
12 | transition-property: transform;
13 | position: fixed;
14 | &.open {
15 | z-index: 11111;
16 | transform: translate3d(0, 0, 0)!important;
17 | }
18 | @include respond-to('sm', 'xs') {
19 | z-index: 10000;
20 | transform: translate3d(-#{$sidebar-size}, 0, 0)!important;
21 | }
22 | @include respond-to('lg') {
23 | transform: translate3d(0, 0, 0)!important;
24 | }
25 |
26 | .el-menu {
27 | height: 100%;
28 | display: flex;
29 | flex-direction: column;
30 | }
31 |
32 | .logo-container {
33 | text-align: center;
34 | width: 100%;
35 | .logo {
36 | width: 215px;
37 | height: 215px;
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/client/index.js:
--------------------------------------------------------------------------------
1 | import { app } from './app'
2 |
3 | // enable progressive web app support (with offline-plugin)
4 | if (process.env.NODE_ENV === 'production') {
5 | require('./pwa')
6 | }
7 |
8 | app.$mount('#app')
9 |
10 | if (module.hot) {
11 | module.hot.accept()
12 | }
13 |
--------------------------------------------------------------------------------
/client/pwa.js:
--------------------------------------------------------------------------------
1 | import runtime from 'offline-plugin/runtime'
2 |
3 | runtime.install({
4 | // When an update is ready, tell ServiceWorker to take control immediately:
5 | onUpdateReady () {
6 | console.log('update ready')
7 | runtime.applyUpdate()
8 | },
9 |
10 | // Reload to get the new version:
11 | onUpdated () {
12 | console.log('updated')
13 | window.location.reload()
14 | }
15 | })
16 |
--------------------------------------------------------------------------------
/client/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Router from 'vue-router'
3 | import Dashboard from 'views/Dashboard'
4 | import Post from 'views/Post'
5 | import About from 'views/About'
6 |
7 | Vue.use(Router)
8 |
9 | export const routes = [
10 | {
11 | path: '/',
12 | component: Dashboard,
13 | meta: {
14 | title: 'Dashboard'
15 | }
16 | }, {
17 | path: '/post/:id',
18 | component: Post,
19 | meta: {
20 | title: 'Post'
21 | }
22 | }, {
23 | path: '/about',
24 | component: About,
25 | meta: {
26 | title: 'About'
27 | }
28 | }
29 | ]
30 | export const router = new Router({ mode: 'history', routes })
31 |
--------------------------------------------------------------------------------
/client/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 | import ui from './ui'
4 |
5 | Vue.use(Vuex)
6 |
7 | const store = new Vuex.Store({
8 | modules: {
9 | ui
10 | }
11 | })
12 |
13 | export default store
14 |
--------------------------------------------------------------------------------
/client/store/ui/index.js:
--------------------------------------------------------------------------------
1 | export const OPEN_SIDEBAR = 'OPEN_SIDEBAR'
2 | export const CLOSE_SIDEBAR = 'CLOSE_SIDEBAR'
3 | export const LOCATION_CHANGE = 'router/ROUTE_CHANGED'
4 | export const WINDOW_RESIZE = 'WINDOW_RESIZE'
5 |
6 | const state = {
7 | sidebarOpened: false,
8 | obfuscatorActive: false,
9 | isMobile: false
10 | }
11 |
12 | const mutations = {
13 | [CLOSE_SIDEBAR] (state) {
14 | state.sidebarOpened = false
15 | state.obfuscatorActive = false
16 | },
17 | [OPEN_SIDEBAR] (state) {
18 | state.sidebarOpened = true
19 | state.obfuscatorActive = true
20 | },
21 | [LOCATION_CHANGE] (state) {
22 | state.sidebarOpened = false
23 | state.obfuscatorActive = false
24 | },
25 | [WINDOW_RESIZE] (state) {
26 | const { innerWidth } = window
27 | const isMobile = innerWidth > 1024
28 | state.isMobile = isMobile
29 | state.sidebarOpened = isMobile
30 | }
31 | }
32 |
33 | const actions = {
34 | openSidebar ({ commit }) {
35 | commit({ type: OPEN_SIDEBAR })
36 | },
37 | closeSidebar ({ commit }) {
38 | commit({ type: CLOSE_SIDEBAR })
39 | },
40 | handleResize ({ commit }) {
41 | commit({ type: WINDOW_RESIZE })
42 | }
43 | }
44 |
45 | export default {
46 | state,
47 | actions,
48 | mutations
49 | }
50 |
--------------------------------------------------------------------------------
/client/styles/fonts.scss:
--------------------------------------------------------------------------------
1 | // Roboto font by default
2 | @import url('https://fonts.googleapis.com/css?family=Roboto');
3 |
4 | body {
5 | font-family: 'Roboto', sans-serif;
6 | }
7 |
8 | // Element-UI icons from /theme folder
9 | @font-face {
10 | font-family: 'element-icons';
11 | src: url('../../theme/fonts/element-icons.woff') format('woff'), /* chrome, firefox */
12 | url('../../theme/fonts/element-icons.ttf') format('truetype'); /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
13 | font-weight: 400;
14 | font-style: normal;
15 | }
16 |
17 | // Add Material icons styles
18 | // cause Element-UI icon set is too small
19 | @font-face {
20 | font-family: 'Material Icons';
21 | font-style: normal;
22 | font-weight: 400;
23 | src: local('Material Icons'), local('MaterialIcons-Regular'), url(https://fonts.gstatic.com/s/materialicons/v17/2fcrYFNaTjcS6g4U3t-Y5ZjZjT5FdEJ140U2DJYC3mY.woff2) format('woff2');
24 | }
25 |
26 | .material-icons, .md-icon, md-icon {
27 | font-family: 'Material Icons';
28 | font-weight: normal;
29 | font-style: normal;
30 | font-size: 24px;
31 | line-height: 1;
32 | letter-spacing: normal;
33 | text-transform: none;
34 | display: inline-block;
35 | white-space: nowrap;
36 | word-wrap: normal;
37 | direction: ltr;
38 | -webkit-font-feature-settings: 'liga';
39 | -webkit-font-smoothing: antialiased;
40 | }
41 |
--------------------------------------------------------------------------------
/client/styles/index.scss:
--------------------------------------------------------------------------------
1 | @import './fonts.scss';
2 |
3 | html, body {
4 | width: 100%;
5 | height: 100%;
6 | }
7 |
--------------------------------------------------------------------------------
/client/styles/mixins.scss:
--------------------------------------------------------------------------------
1 | // MIXIN FOR RESPONSIVE CSS GRID;
2 | // Extra small screen / phone
3 | $xs: 0; // Small screen / phone
4 | $sm: 480px; // Medium screen / tablet
5 | $md: 768px; // Large screen / desktop
6 | $lg: 1024px; // // Extra large screen / wide desktop
7 | // $xl: 1200px;
8 | @mixin respond-to($media...) {
9 | @for $i from 1 through length($media){
10 | @include privat-respond-to(nth($media, $i)) {
11 | @content;
12 | };
13 | }
14 | }
15 | @mixin privat-respond-to($current-media) {
16 | @if $current-media == 'xs' {
17 | @media only screen and (max-width: $sm) {
18 | @content;
19 | }
20 | }
21 |
22 | @else if $current-media == 'sm' {
23 | @media only screen and (min-width: $sm + 1) {
24 | @content;
25 | }
26 | }
27 |
28 | @else if $current-media == 'md' {
29 | @media only screen and (min-width: $md + 1) {
30 | @content;
31 | }
32 | }
33 |
34 | @else if $current-media == 'lg' {
35 | @media only screen and (min-width: $lg + 1) {
36 | @content;
37 | }
38 | }
39 |
40 | @else if $current-media == 'xl' {
41 | @media only screen and (min-width: $xl) {
42 | @content;
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/client/styles/vars.scss:
--------------------------------------------------------------------------------
1 | @import './mixins.scss';
2 | $sidebar-size: 260px;
3 | $grey: #dbe2e8;
4 | $white: #fff;
5 | $header-height: 60px;
6 |
--------------------------------------------------------------------------------
/client/views/About/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
14 |
--------------------------------------------------------------------------------
/client/views/Dashboard/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Hi, I'm a "Vue-Element-Starter".
4 |
7 |
8 |
9 |
10 |
16 |
--------------------------------------------------------------------------------
/client/views/Post/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
24 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Vue-Element-Starter",
3 | "version": "1.0.0",
4 | "description": "Vue-Element-Starter",
5 | "main": "client/index.js",
6 | "scripts": {
7 | "test": "testcafe all tests/index.js --app \"npm run dev\" --app-init-delay 10000",
8 | "build": "webpack --config build/webpack.prod.js",
9 | "dev": "node build/server.js",
10 | "lint": "eslint client/* --ext .js --ext .vue",
11 | "generate_default_styles": "et -i ./client/styles/element-variables.css",
12 | "generate_theme": "et -c ./client/styles/element-variables.css"
13 | },
14 | "author": "Vladimir Metnev ",
15 | "license": "MIT",
16 | "dependencies": {
17 | "babel-runtime": "^6.23.0",
18 | "element-ui": "^1.2.9",
19 | "material-design-icons": "^3.0.1",
20 | "normalize.css": "^6.0.0",
21 | "vue": "^2.3.0",
22 | "vue-router": "^2.5.2",
23 | "vuex": "^2.3.1",
24 | "vuex-router-sync": "^4.1.2",
25 | "whatwg-fetch": "^2.0.3"
26 | },
27 | "devDependencies": {
28 | "autoprefixer": "^6.7.7",
29 | "babel-cli": "^6.24.1",
30 | "babel-core": "^6.24.1",
31 | "babel-eslint": "^7.2.2",
32 | "babel-loader": "^7.0.0",
33 | "babel-plugin-lodash": "^3.2.11",
34 | "babel-plugin-transform-react-jsx": "^6.24.1",
35 | "babel-plugin-transform-regenerator": "^6.24.1",
36 | "babel-plugin-transform-runtime": "^6.23.0",
37 | "babel-polyfill": "^6.23.0",
38 | "babel-preset-es2015": "^6.24.1",
39 | "babel-preset-vue-app": "^1.2.0",
40 | "babel-preset-stage-0": "^6.24.1",
41 | "chalk": "^1.1.3",
42 | "copy-webpack-plugin": "^4.0.1",
43 | "css-loader": "^0.28.0",
44 | "element-theme": "^0.7.1",
45 | "element-theme-default": "^1.3.0-beta.1",
46 | "eslint": "^3.19.0",
47 | "eslint-config-standard": "^10.2.1",
48 | "eslint-config-vue": "^2.0.2",
49 | "eslint-loader": "^1.7.1",
50 | "eslint-plugin-babel": "^4.1.1",
51 | "eslint-plugin-import": "^2.2.0",
52 | "eslint-plugin-node": "^4.2.2",
53 | "eslint-plugin-promise": "^3.5.0",
54 | "eslint-plugin-standard": "^3.0.1",
55 | "eslint-plugin-testcafe": "^0.2.1",
56 | "eslint-plugin-vue": "^2.0.1",
57 | "express": "^4.15.2",
58 | "extract-text-webpack-plugin": "^2.1.0",
59 | "file-loader": "^0.11.1",
60 | "friendly-errors-webpack-plugin": "^1.6.1",
61 | "html-webpack-plugin": "^2.28.0",
62 | "img-loader": "^2.0.0",
63 | "node-sass": "^4.5.2",
64 | "offline-plugin": "^4.7.0",
65 | "optimize-css-assets-webpack-plugin": "^1.3.1",
66 | "preload-webpack-plugin": "^1.2.2",
67 | "resolve-url-loader": "^2.0.2",
68 | "sass-loader": "^6.0.3",
69 | "style-loader": "^0.16.1",
70 | "testcafe": "^0.15.0",
71 | "vue-loader": "^12.0.2",
72 | "vue-template-compiler": "^2.3.0",
73 | "webpack": "2.4.1",
74 | "webpack-dev-middleware": "^1.10.2",
75 | "webpack-hot-middleware": "^2.18.0"
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Metnew/vue-element-starter/aa68364ebdf9f51f4a91c50cdc2feabfa59b0883/static/favicon.ico
--------------------------------------------------------------------------------
/tests/index.js:
--------------------------------------------------------------------------------
1 | // Your tests -> :)
2 |
--------------------------------------------------------------------------------