You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by zh...@apache.org on 2019/09/29 10:38:34 UTC
[incubator-shardingsphere-benchmark] 34/49: feature:add ui-frontend
project
This is an automated email from the ASF dual-hosted git repository.
zhaoyanan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-shardingsphere-benchmark.git
commit e6e1fb4127ac3ae69da6eb74e84970dc76fbf69c
Author: wqzwh <wa...@163.com>
AuthorDate: Thu Sep 26 15:28:22 2019 +0800
feature:add ui-frontend project
---
web/.babelrc | 27 ++
web/.editorconfig | 9 +
web/.eslintignore | 4 +
web/.eslintrc.js | 297 +++++++++++++++++++++
web/.gitignore | 17 ++
web/.postcssrc.js | 27 ++
web/README.md | 17 ++
web/build/build.js | 58 ++++
web/build/check-versions.js | 71 +++++
web/build/utils.js | 125 +++++++++
web/build/vue-loader.conf.js | 22 ++
web/build/webpack.base.conf.js | 119 +++++++++
web/build/webpack.dev.conf.js | 131 +++++++++
web/build/webpack.prod.conf.js | 152 +++++++++++
web/config/dev.env.js | 24 ++
web/config/index.js | 100 +++++++
web/config/prod.env.js | 21 ++
web/favicon.ico | Bin 0 -> 9662 bytes
web/favicon.png | Bin 0 -> 24930 bytes
web/index.html | 32 +++
web/package.json | 87 ++++++
web/src/App.vue | 18 ++
web/src/assets/logo.png | Bin 0 -> 24930 bytes
web/src/assets/logo_top.png | Bin 0 -> 8832 bytes
web/src/components/Container/index.vue | 185 +++++++++++++
web/src/components/Footer/index.vue | 24 ++
web/src/main.js | 15 ++
web/src/router/index.js | 37 +++
web/src/utils/line.js | 50 ++++
web/src/utils/mixin.js | 69 +++++
web/src/utils/utils.js | 11 +
web/src/views/mysql-vs-sharding/index.vue | 64 +++++
.../sharding-proxy-master-slave-sharding/index.vue | 64 +++++
.../views/sharding-proxy-master-slave/index.vue | 64 +++++
.../index.vue | 64 +++++
web/static/.gitkeep | 0
web/static/404.html | 31 +++
37 files changed, 2036 insertions(+)
diff --git a/web/.babelrc b/web/.babelrc
new file mode 100644
index 0000000..f261300
--- /dev/null
+++ b/web/.babelrc
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+{
+ "presets": [
+ "@babel/preset-env"
+ ],
+ "plugins": ["transform-vue-jsx", "@babel/plugin-transform-runtime", "@babel/plugin-syntax-dynamic-import"],
+ "env": {
+ "test": {
+ "plugins": ["istanbul"]
+ }
+ }
+}
diff --git a/web/.editorconfig b/web/.editorconfig
new file mode 100644
index 0000000..9d08a1a
--- /dev/null
+++ b/web/.editorconfig
@@ -0,0 +1,9 @@
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 2
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
diff --git a/web/.eslintignore b/web/.eslintignore
new file mode 100644
index 0000000..e1fcc9c
--- /dev/null
+++ b/web/.eslintignore
@@ -0,0 +1,4 @@
+/build/
+/config/
+/dist/
+/*.js
diff --git a/web/.eslintrc.js b/web/.eslintrc.js
new file mode 100644
index 0000000..a588840
--- /dev/null
+++ b/web/.eslintrc.js
@@ -0,0 +1,297 @@
+module.exports = {
+ root: true,
+ parserOptions: {
+ parser: 'babel-eslint',
+ sourceType: 'module'
+ },
+ env: {
+ browser: true,
+ node: true,
+ es6: true
+ },
+ extends: ['plugin:vue/recommended', 'eslint:recommended'],
+ // add your custom rules here
+ //it is base on https://github.com/vuejs/eslint-config-vue
+ rules: {
+ 'vue/no-parsing-error': [2, { 'x-invalid-end-tag': false }],
+ 'vue/html-indent': [
+ 'off',
+ 2,
+ {
+ attribute: 1,
+ baseIndent: 1,
+ closeBracket: 0,
+ alignAttributesVertically: true,
+ ignores: []
+ }
+ ],
+ 'no-tabs': 'off',
+ 'vue/max-attributes-per-line': [
+ 2,
+ {
+ singleline: 10,
+ multiline: {
+ max: 1,
+ allowFirstLine: false
+ }
+ }
+ ],
+ 'vue/html-self-closing': [
+ 'error',
+ {
+ html: {
+ void: 'any',
+ normal: 'any',
+ component: 'any'
+ },
+ svg: 'any',
+ math: 'any'
+ }
+ ],
+ 'vue/name-property-casing': ['error', 'PascalCase'],
+ 'accessor-pairs': 2,
+ 'arrow-spacing': [
+ 2,
+ {
+ before: true,
+ after: true
+ }
+ ],
+ 'block-spacing': [2, 'always'],
+ 'brace-style': [
+ 2,
+ '1tbs',
+ {
+ allowSingleLine: true
+ }
+ ],
+ camelcase: [
+ 0,
+ {
+ properties: 'always'
+ }
+ ],
+ 'comma-dangle': [2, 'never'],
+ 'comma-spacing': [
+ 2,
+ {
+ before: false,
+ after: true
+ }
+ ],
+ 'comma-style': [2, 'last'],
+ 'constructor-super': 2,
+ curly: [2, 'multi-line'],
+ 'dot-location': [2, 'property'],
+ 'eol-last': 0,
+ eqeqeq: [2, 'allow-null'],
+ 'generator-star-spacing': [
+ 2,
+ {
+ before: true,
+ after: true
+ }
+ ],
+ 'handle-callback-err': [2, '^(err|error)$'],
+ indent: [0, 2],
+ // indent: [
+ // 2,
+ // 2,
+ // {
+ // SwitchCase: 1
+ // }
+ // ],
+ 'jsx-quotes': [2, 'prefer-single'],
+ 'key-spacing': [
+ 2,
+ {
+ beforeColon: false,
+ afterColon: true
+ }
+ ],
+ 'keyword-spacing': [
+ 2,
+ {
+ before: true,
+ after: true
+ }
+ ],
+ 'new-cap': [
+ 2,
+ {
+ newIsCap: true,
+ capIsNew: false
+ }
+ ],
+ 'new-parens': 2,
+ 'no-array-constructor': 2,
+ 'no-caller': 2,
+ 'no-console': 'off',
+ 'no-class-assign': 2,
+ 'no-cond-assign': 2,
+ 'no-const-assign': 2,
+ 'no-control-regex': 2,
+ 'no-delete-var': 2,
+ 'no-dupe-args': 2,
+ 'no-dupe-class-members': 2,
+ 'no-dupe-keys': 2,
+ 'no-duplicate-case': 2,
+ 'no-empty-character-class': 2,
+ 'no-empty-pattern': 2,
+ 'no-eval': 2,
+ 'no-ex-assign': 2,
+ 'no-extend-native': 2,
+ 'no-extra-bind': 2,
+ 'no-extra-boolean-cast': 2,
+ 'no-extra-parens': [2, 'functions'],
+ 'no-fallthrough': 2,
+ 'no-floating-decimal': 2,
+ 'no-func-assign': 2,
+ 'no-implied-eval': 2,
+ 'no-inner-declarations': [2, 'functions'],
+ 'no-invalid-regexp': 2,
+ 'no-irregular-whitespace': 2,
+ 'no-iterator': 2,
+ 'no-label-var': 2,
+ 'no-labels': [
+ 2,
+ {
+ allowLoop: false,
+ allowSwitch: false
+ }
+ ],
+ 'no-lone-blocks': 2,
+ 'no-mixed-spaces-and-tabs': 2,
+ 'no-multi-spaces': 2,
+ 'no-multi-str': 2,
+ 'no-multiple-empty-lines': [
+ 2,
+ {
+ max: 1
+ }
+ ],
+ 'no-native-reassign': 2,
+ 'no-negated-in-lhs': 2,
+ 'no-new-object': 2,
+ 'no-new-require': 2,
+ 'no-new-symbol': 2,
+ 'no-new-wrappers': 2,
+ 'no-obj-calls': 2,
+ 'no-octal': 2,
+ 'no-octal-escape': 2,
+ 'no-path-concat': 2,
+ 'no-proto': 2,
+ 'no-redeclare': 2,
+ 'no-regex-spaces': 2,
+ 'no-return-assign': [2, 'except-parens'],
+ 'no-self-assign': 2,
+ 'no-self-compare': 2,
+ 'no-sequences': 2,
+ 'no-shadow-restricted-names': 2,
+ 'no-spaced-func': 2,
+ 'no-sparse-arrays': 2,
+ 'no-this-before-super': 2,
+ 'no-throw-literal': 2,
+ 'no-trailing-spaces': 2,
+ 'no-undef': 2,
+ 'no-undef-init': 2,
+ 'no-unexpected-multiline': 2,
+ 'no-unmodified-loop-condition': 2,
+ 'no-unneeded-ternary': [
+ 2,
+ {
+ defaultAssignment: false
+ }
+ ],
+ 'no-unreachable': 2,
+ 'no-unsafe-finally': 2,
+ 'no-unused-vars': [
+ 2,
+ {
+ vars: 'all',
+ args: 'none'
+ }
+ ],
+ 'no-useless-call': 2,
+ 'no-useless-computed-key': 2,
+ 'no-useless-constructor': 2,
+ 'no-useless-escape': 0,
+ 'no-whitespace-before-property': 2,
+ 'no-with': 2,
+ 'one-var': [
+ 2,
+ {
+ initialized: 'never'
+ }
+ ],
+ 'operator-linebreak': [
+ 2,
+ 'after',
+ {
+ overrides: {
+ '?': 'before',
+ ':': 'before'
+ }
+ }
+ ],
+ 'padded-blocks': [2, 'never'],
+ quotes: [
+ 2,
+ 'single',
+ {
+ avoidEscape: true,
+ allowTemplateLiterals: true
+ }
+ ],
+ semi: [2, 'never'],
+ 'semi-spacing': [
+ 2,
+ {
+ before: false,
+ after: true
+ }
+ ],
+ 'space-before-blocks': [2, 'always'],
+ 'space-before-function-paren': [2, 'never'],
+ 'space-in-parens': [2, 'never'],
+ 'space-infix-ops': 2,
+ 'space-unary-ops': [
+ 2,
+ {
+ words: true,
+ nonwords: false
+ }
+ ],
+ 'spaced-comment': [
+ 2,
+ 'always',
+ {
+ markers: [
+ 'global',
+ 'globals',
+ 'eslint',
+ 'eslint-disable',
+ '*package',
+ '!',
+ ','
+ ]
+ }
+ ],
+ 'template-curly-spacing': [2, 'never'],
+ 'use-isnan': 2,
+ 'valid-typeof': 2,
+ 'wrap-iife': [2, 'any'],
+ 'yield-star-spacing': [2, 'both'],
+ yoda: [2, 'never'],
+ 'prefer-const': 2,
+ 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
+ 'object-curly-spacing': [
+ 2,
+ 'always',
+ {
+ objectsInObjects: false
+ }
+ ],
+ 'array-bracket-spacing': [2, 'never']
+ }
+}
diff --git a/web/.gitignore b/web/.gitignore
new file mode 100644
index 0000000..6bc0c43
--- /dev/null
+++ b/web/.gitignore
@@ -0,0 +1,17 @@
+.DS_Store
+node_modules/
+node/
+/dist/
+/coverage/
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+package-lock.json
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
diff --git a/web/.postcssrc.js b/web/.postcssrc.js
new file mode 100644
index 0000000..dc9c58f
--- /dev/null
+++ b/web/.postcssrc.js
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// https://github.com/michael-ciniawsky/postcss-load-config
+
+module.exports = {
+ "plugins": {
+ "postcss-import": {},
+ "postcss-url": {},
+ // to edit target browsers: use "browserslist" field in package.json
+ "autoprefixer": {}
+ }
+}
diff --git a/web/README.md b/web/README.md
new file mode 100644
index 0000000..be27161
--- /dev/null
+++ b/web/README.md
@@ -0,0 +1,17 @@
+# incubator-shardingsphere-benchmark-ui-frontend"
+
+## Build Setup
+
+```bash
+# install dependencies
+npm install
+
+# serve with hot reload at localhost:8080
+npm run dev
+
+# build for production with minification
+npm run build
+
+# build for production and view the bundle analyzer report
+npm run build --report
+```
diff --git a/web/build/build.js b/web/build/build.js
new file mode 100644
index 0000000..b6d0ada
--- /dev/null
+++ b/web/build/build.js
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict'
+require('./check-versions')()
+
+process.env.NODE_ENV = 'production'
+
+const ora = require('ora')
+const rm = require('rimraf')
+const path = require('path')
+const chalk = require('chalk')
+const webpack = require('webpack')
+const config = require('../config')
+const webpackConfig = require('./webpack.prod.conf')
+
+const spinner = ora('building for production...')
+spinner.start()
+
+rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
+ if (err) throw err
+ webpack(webpackConfig, (err, stats) => {
+ spinner.stop()
+ if (err) throw err
+ process.stdout.write(stats.toString({
+ colors: true,
+ modules: false,
+ children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
+ chunks: false,
+ chunkModules: false
+ }) + '\n\n')
+
+ if (stats.hasErrors()) {
+ console.log(chalk.red(' Build failed with errors.\n'))
+ process.exit(1)
+ }
+
+ console.log(chalk.cyan(' Build complete.\n'))
+ console.log(chalk.yellow(
+ ' Tip: built files are meant to be served over an HTTP server.\n' +
+ ' Opening index.html over file:// won\'t work.\n'
+ ))
+ })
+})
diff --git a/web/build/check-versions.js b/web/build/check-versions.js
new file mode 100644
index 0000000..b07e6e8
--- /dev/null
+++ b/web/build/check-versions.js
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict'
+const chalk = require('chalk')
+const semver = require('semver')
+const packageConfig = require('../package.json')
+const shell = require('shelljs')
+
+function exec (cmd) {
+ return require('child_process').execSync(cmd).toString().trim()
+}
+
+const versionRequirements = [
+ {
+ name: 'node',
+ currentVersion: semver.clean(process.version),
+ versionRequirement: packageConfig.engines.node
+ }
+]
+
+if (shell.which('npm')) {
+ versionRequirements.push({
+ name: 'npm',
+ currentVersion: exec('npm --version'),
+ versionRequirement: packageConfig.engines.npm
+ })
+}
+
+module.exports = function () {
+ const warnings = []
+
+ for (let i = 0; i < versionRequirements.length; i++) {
+ const mod = versionRequirements[i]
+
+ if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
+ warnings.push(mod.name + ': ' +
+ chalk.red(mod.currentVersion) + ' should be ' +
+ chalk.green(mod.versionRequirement)
+ )
+ }
+ }
+
+ if (warnings.length) {
+ console.log('')
+ console.log(chalk.yellow('To use this template, you must update following to modules:'))
+ console.log()
+
+ for (let i = 0; i < warnings.length; i++) {
+ const warning = warnings[i]
+ console.log(' ' + warning)
+ }
+
+ console.log()
+ process.exit(1)
+ }
+}
diff --git a/web/build/utils.js b/web/build/utils.js
new file mode 100644
index 0000000..5c6cf79
--- /dev/null
+++ b/web/build/utils.js
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict'
+const path = require('path')
+const config = require('../config')
+const MiniCssExtractPlugin = require('mini-css-extract-plugin')
+const packageConfig = require('../package.json')
+
+exports.assetsPath = function(_path) {
+ const assetsSubDirectory =
+ process.env.NODE_ENV === 'production'
+ ? config.build.assetsSubDirectory
+ : config.dev.assetsSubDirectory
+
+ return path.posix.join(assetsSubDirectory, _path)
+}
+
+exports.cssLoaders = function(options) {
+ options = options || {}
+
+ const cssLoader = {
+ loader: 'css-loader',
+ options: {
+ sourceMap: options.sourceMap
+ }
+ }
+
+ const postcssLoader = {
+ loader: 'postcss-loader',
+ options: {
+ sourceMap: options.sourceMap
+ }
+ }
+
+ // generate loader string to be used with extract text plugin
+ function generateLoaders(loader, loaderOptions) {
+ const loaders = options.usePostCSS
+ ? [cssLoader, postcssLoader]
+ : [cssLoader]
+
+ if (loader) {
+ loaders.push({
+ loader: loader + '-loader',
+ options: Object.assign({}, loaderOptions, {
+ sourceMap: options.sourceMap
+ })
+ })
+ }
+
+ // Extract CSS when that option is specified
+ // (which is the case during production build)
+ if (options.extract) {
+ return [
+ {
+ loader: MiniCssExtractPlugin.loader,
+ options: {
+ publicPath: '../../'
+ }
+ }
+ ].concat(loaders)
+ } else {
+ return ['vue-style-loader'].concat(loaders)
+ }
+ }
+
+ // https://vue-loader.vuejs.org/en/configurations/extract-css.html
+ return {
+ css: generateLoaders(),
+ postcss: generateLoaders(),
+ less: generateLoaders('less'),
+ sass: generateLoaders('sass', { indentedSyntax: true }),
+ scss: generateLoaders('sass'),
+ stylus: generateLoaders('stylus'),
+ styl: generateLoaders('stylus')
+ }
+}
+
+// Generate loaders for standalone style files (outside of .vue)
+exports.styleLoaders = function(options) {
+ const output = []
+ const loaders = exports.cssLoaders(options)
+
+ for (const extension in loaders) {
+ const loader = loaders[extension]
+ output.push({
+ test: new RegExp('\\.' + extension + '$'),
+ use: loader
+ })
+ }
+
+ return output
+}
+
+exports.createNotifierCallback = () => {
+ const notifier = require('node-notifier')
+
+ return (severity, errors) => {
+ if (severity !== 'error') return
+
+ const error = errors[0]
+ const filename = error.file && error.file.split('!').pop()
+
+ notifier.notify({
+ title: packageConfig.name,
+ message: severity + ': ' + error.name,
+ subtitle: filename || '',
+ icon: path.join(__dirname, 'logo.png')
+ })
+ }
+}
diff --git a/web/build/vue-loader.conf.js b/web/build/vue-loader.conf.js
new file mode 100644
index 0000000..9c30005
--- /dev/null
+++ b/web/build/vue-loader.conf.js
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict'
+
+module.exports = {
+
+}
diff --git a/web/build/webpack.base.conf.js b/web/build/webpack.base.conf.js
new file mode 100644
index 0000000..76b5575
--- /dev/null
+++ b/web/build/webpack.base.conf.js
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict'
+const path = require('path')
+const utils = require('./utils')
+const config = require('../config')
+const vueLoaderConfig = require('./vue-loader.conf')
+
+function resolve(dir) {
+ return path.join(__dirname, '..', dir)
+}
+
+const createLintingRule = () => ({
+ test: /\.(js|vue)$/,
+ loader: 'eslint-loader',
+ enforce: 'pre',
+ include: [resolve('src'), resolve('test')],
+ options: {
+ formatter: require('eslint-friendly-formatter'),
+ emitWarning: !config.dev.showEslintErrorsInOverlay
+ }
+})
+
+module.exports = {
+ context: path.resolve(__dirname, '../'),
+ entry: {
+ app: './src/main.js'
+ },
+ output: {
+ path: config.build.assetsRoot,
+ filename: '[name].js',
+ publicPath:
+ process.env.NODE_ENV === 'production'
+ ? config.build.assetsPublicPath
+ : config.dev.assetsPublicPath
+ },
+ resolve: {
+ extensions: ['.js', '.vue', '.json'],
+ alias: {
+ vue$: 'vue/dist/vue.esm.js',
+ '@': resolve('src')
+ }
+ },
+ module: {
+ rules: [
+ ...(config.dev.useEslint ? [createLintingRule()] : []),
+ {
+ test: /\.vue$/,
+ loader: 'vue-loader',
+ options: vueLoaderConfig
+ },
+ {
+ test: /\.js$/,
+ loader: 'babel-loader',
+ include: [resolve('src'), resolve('test')]
+ },
+ {
+ test: /\.svg$/,
+ loader: 'svg-sprite-loader',
+ include: [resolve('src/icons')],
+ options: {
+ symbolId: 'icon-[name]'
+ }
+ },
+ {
+ test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
+ loader: 'url-loader',
+ exclude: [resolve('src/icons')],
+ options: {
+ limit: 10000,
+ name: utils.assetsPath('img/[name].[hash:7].[ext]')
+ }
+ },
+ {
+ test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
+ loader: 'url-loader',
+ options: {
+ limit: 10000,
+ name: utils.assetsPath('media/[name].[hash:7].[ext]')
+ }
+ },
+ {
+ test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
+ loader: 'url-loader',
+ options: {
+ limit: 10000,
+ name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
+ }
+ }
+ ]
+ },
+ node: {
+ // prevent webpack from injecting useless setImmediate polyfill because Vue
+ // source contains it (although only uses it if it's native).
+ setImmediate: false,
+ // prevent webpack from injecting mocks to Node native modules
+ // that does not make sense for the client
+ dgram: 'empty',
+ fs: 'empty',
+ net: 'empty',
+ tls: 'empty',
+ child_process: 'empty'
+ }
+}
diff --git a/web/build/webpack.dev.conf.js b/web/build/webpack.dev.conf.js
new file mode 100644
index 0000000..3dd767e
--- /dev/null
+++ b/web/build/webpack.dev.conf.js
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict'
+const utils = require('./utils')
+const webpack = require('webpack')
+const config = require('../config')
+const merge = require('webpack-merge')
+const path = require('path')
+const baseWebpackConfig = require('./webpack.base.conf')
+const CopyWebpackPlugin = require('copy-webpack-plugin')
+const HtmlWebpackPlugin = require('html-webpack-plugin')
+const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
+const portfinder = require('portfinder')
+const { VueLoaderPlugin } = require('vue-loader')
+
+function resolve(dir) {
+ return path.join(__dirname, '..', dir)
+}
+
+const HOST = process.env.HOST
+const PORT = process.env.PORT && Number(process.env.PORT)
+
+const devWebpackConfig = merge(baseWebpackConfig, {
+ mode: 'development',
+ module: {
+ rules: utils.styleLoaders({
+ sourceMap: config.dev.cssSourceMap,
+ usePostCSS: true
+ })
+ },
+ // cheap-module-eval-source-map is faster for development
+ devtool: config.dev.devtool,
+
+ // these devServer options should be customized in /config/index.js
+ devServer: {
+ clientLogLevel: 'warning',
+ historyApiFallback: {
+ rewrites: [
+ {
+ from: /.*/,
+ to: path.posix.join(config.dev.assetsPublicPath, 'index.html')
+ }
+ ]
+ },
+ hot: true,
+ contentBase: false, // since we use CopyWebpackPlugin.
+ compress: true,
+ host: HOST || config.dev.host,
+ port: PORT || config.dev.port,
+ open: config.dev.autoOpenBrowser,
+ overlay: config.dev.errorOverlay
+ ? { warnings: false, errors: true }
+ : false,
+ publicPath: config.dev.assetsPublicPath,
+ proxy: config.dev.proxyTable,
+ quiet: true, // necessary for FriendlyErrorsPlugin
+ watchOptions: {
+ poll: config.dev.poll
+ }
+ },
+ plugins: [
+ new webpack.DefinePlugin({
+ 'process.env': require('../config/dev.env')
+ }),
+ new VueLoaderPlugin(),
+ new webpack.HotModuleReplacementPlugin(),
+ // https://github.com/ampedandwired/html-webpack-plugin
+ new HtmlWebpackPlugin({
+ filename: 'index.html',
+ template: 'index.html',
+ inject: true,
+ favicon: resolve('favicon.png'),
+ title: 'sharding-ui'
+ }),
+ // copy custom static assets
+ new CopyWebpackPlugin([
+ {
+ from: path.resolve(__dirname, '../static'),
+ to: config.dev.assetsSubDirectory,
+ ignore: ['.*']
+ }
+ ])
+ ]
+})
+
+module.exports = new Promise((resolve, reject) => {
+ portfinder.basePort = process.env.PORT || config.dev.port
+ portfinder.getPort((err, port) => {
+ if (err) {
+ reject(err)
+ } else {
+ // publish the new Port, necessary for e2e tests
+ process.env.PORT = port
+ // add port to devServer config
+ devWebpackConfig.devServer.port = port
+
+ // Add FriendlyErrorsPlugin
+ devWebpackConfig.plugins.push(
+ new FriendlyErrorsPlugin({
+ compilationSuccessInfo: {
+ messages: [
+ `Your application is running here: http://${
+ devWebpackConfig.devServer.host
+ }:${port}`
+ ]
+ },
+ onErrors: config.dev.notifyOnErrors
+ ? utils.createNotifierCallback()
+ : undefined
+ })
+ )
+
+ resolve(devWebpackConfig)
+ }
+ })
+})
diff --git a/web/build/webpack.prod.conf.js b/web/build/webpack.prod.conf.js
new file mode 100644
index 0000000..58b5373
--- /dev/null
+++ b/web/build/webpack.prod.conf.js
@@ -0,0 +1,152 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict'
+const path = require('path')
+const utils = require('./utils')
+const webpack = require('webpack')
+const config = require('../config')
+const merge = require('webpack-merge')
+const baseWebpackConfig = require('./webpack.base.conf')
+const CopyWebpackPlugin = require('copy-webpack-plugin')
+const HtmlWebpackPlugin = require('html-webpack-plugin')
+const MiniCssExtractPlugin = require('mini-css-extract-plugin')
+const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
+const { VueLoaderPlugin } = require('vue-loader')
+
+function resolve(dir) {
+ return path.join(__dirname, '..', dir)
+}
+
+const env = require('../config/prod.env')
+
+const webpackConfig = merge(baseWebpackConfig, {
+ mode: 'production',
+ module: {
+ rules: utils.styleLoaders({
+ sourceMap: config.build.productionSourceMap,
+ extract: true,
+ usePostCSS: true
+ })
+ },
+ devtool: config.build.productionSourceMap ? config.build.devtool : false,
+ output: {
+ path: config.build.assetsRoot,
+ filename: utils.assetsPath('js/[name].[chunkhash].js'),
+ chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
+ },
+ optimization: {
+ providedExports: true,
+ usedExports: true, // tree shaking
+ sideEffects: true,
+ concatenateModules: true,
+ noEmitOnErrors: true,
+ splitChunks: {
+ chunks: 'all',
+ minSize: 30000,
+ maxSize: 0,
+ minChunks: 1,
+ maxAsyncRequests: 5,
+ maxInitialRequests: 3,
+ automaticNameDelimiter: '~',
+ name: true,
+ cacheGroups: {
+ vendors: {
+ test: /[\\/]node_modules[\\/]/,
+ priority: -10
+ },
+ default: {
+ priority: -20,
+ reuseExistingChunk: true
+ }
+ }
+ },
+ runtimeChunk: {
+ name: 'manifest'
+ }
+ },
+ plugins: [
+ // http://vuejs.github.io/vue-loader/en/workflow/production.html
+ new webpack.DefinePlugin({
+ 'process.env': env
+ }),
+ new VueLoaderPlugin(),
+ new MiniCssExtractPlugin({
+ filename: utils.assetsPath('css/[name].[contenthash].css')
+ }),
+ // Compress extracted CSS. We are using this plugin so that possible
+ // duplicated CSS from different components can be deduped.
+ new OptimizeCSSPlugin({
+ cssProcessorOptions: config.build.productionSourceMap
+ ? { safe: true, map: { inline: false }}
+ : { safe: true }
+ }),
+ // generate dist index.html with correct asset hash for caching.
+ // you can customize output by editing /index.html
+ // see https://github.com/ampedandwired/html-webpack-plugin
+ new HtmlWebpackPlugin({
+ filename: config.build.index,
+ template: 'index.html',
+ inject: true,
+ favicon: resolve('favicon.png'),
+ title: 'sharding-ui',
+ minify: {
+ removeComments: true,
+ collapseWhitespace: true,
+ removeAttributeQuotes: true
+ // more options:
+ // https://github.com/kangax/html-minifier#options-quick-reference
+ },
+ // necessary to consistently work with multiple chunks via CommonsChunkPlugin
+ chunksSortMode: 'dependency'
+ }),
+ // keep module.id stable when vendor modules does not change
+ new webpack.HashedModuleIdsPlugin(),
+ // copy custom static assets
+ new CopyWebpackPlugin([
+ {
+ from: path.resolve(__dirname, '../static'),
+ to: config.build.assetsSubDirectory,
+ ignore: ['.*']
+ }
+ ])
+ ]
+})
+
+if (config.build.productionGzip) {
+ const CompressionWebpackPlugin = require('compression-webpack-plugin')
+
+ webpackConfig.plugins.push(
+ new CompressionWebpackPlugin({
+ asset: '[path].gz[query]',
+ algorithm: 'gzip',
+ test: new RegExp(
+ '\\.(' + config.build.productionGzipExtensions.join('|') + ')$'
+ ),
+ threshold: 10240,
+ minRatio: 0.8
+ })
+ )
+}
+
+if (config.build.bundleAnalyzerReport) {
+ const BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
+ .BundleAnalyzerPlugin
+ webpackConfig.plugins.push(new BundleAnalyzerPlugin())
+}
+
+module.exports = webpackConfig
diff --git a/web/config/dev.env.js b/web/config/dev.env.js
new file mode 100644
index 0000000..58340ed
--- /dev/null
+++ b/web/config/dev.env.js
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict'
+const merge = require('webpack-merge')
+const prodEnv = require('./prod.env')
+
+module.exports = merge(prodEnv, {
+ NODE_ENV: process.env.NODE_ENV !== 'mock' ? '"development"' : '"mock"'
+})
diff --git a/web/config/index.js b/web/config/index.js
new file mode 100644
index 0000000..ceb6f12
--- /dev/null
+++ b/web/config/index.js
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict'
+// Template version: 1.3.1
+// see http://vuejs-templates.github.io/webpack for documentation.
+
+const path = require('path')
+
+module.exports = {
+ dev: {
+ // Paths
+ assetsSubDirectory: 'static',
+ assetsPublicPath: '/',
+ proxyTable: {
+ '/api': {
+ target: 'http://localhost:8088',
+ changeOrigin: true,
+ pathRewrite: {
+ '^/api': '/api'
+ }
+ }
+ },
+
+ // Various Dev Server settings
+ host: 'localhost', // can be overwritten by process.env.HOST
+ port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
+ autoOpenBrowser: false,
+ errorOverlay: true,
+ notifyOnErrors: true,
+ poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
+
+ // Use Eslint Loader?
+ // If true, your code will be linted during bundling and
+ // linting errors and warnings will be shown in the console.
+ useEslint: true,
+ // If true, eslint errors and warnings will also be shown in the error overlay
+ // in the browser.
+ showEslintErrorsInOverlay: false,
+
+ /**
+ * Source Maps
+ */
+
+ // https://webpack.js.org/configuration/devtool/#development
+ devtool: 'cheap-module-eval-source-map',
+
+ // If you have problems debugging vue-files in devtools,
+ // set this to false - it *may* help
+ // https://vue-loader.vuejs.org/en/options.html#cachebusting
+ cacheBusting: true,
+
+ cssSourceMap: false
+ },
+
+ build: {
+ // Template for index.html
+ index: path.resolve(__dirname, '../dist/index.html'),
+
+ // Paths
+ assetsRoot: path.resolve(__dirname, '../dist'),
+ assetsSubDirectory: 'static',
+ assetsPublicPath: '/',
+
+ /**
+ * Source Maps
+ */
+
+ productionSourceMap: true,
+ // https://webpack.js.org/configuration/devtool/#production
+ devtool: '#source-map',
+
+ // Gzip off by default as many popular static hosts such as
+ // Surge or Netlify already gzip all static assets for you.
+ // Before setting to `true`, make sure to:
+ // npm install --save-dev compression-webpack-plugin
+ productionGzip: false,
+ productionGzipExtensions: ['js', 'css'],
+
+ // Run the build command with an extra argument to
+ // View the bundle analyzer report after build finishes:
+ // `npm run build --report`
+ // Set to `true` or `false` to always turn it on or off
+ bundleAnalyzerReport: process.env.npm_config_report
+ }
+}
diff --git a/web/config/prod.env.js b/web/config/prod.env.js
new file mode 100644
index 0000000..00279d4
--- /dev/null
+++ b/web/config/prod.env.js
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+'use strict'
+module.exports = {
+ NODE_ENV: '"production"'
+}
diff --git a/web/favicon.ico b/web/favicon.ico
new file mode 100644
index 0000000..83655b2
Binary files /dev/null and b/web/favicon.ico differ
diff --git a/web/favicon.png b/web/favicon.png
new file mode 100644
index 0000000..209bb49
Binary files /dev/null and b/web/favicon.png differ
diff --git a/web/index.html b/web/index.html
new file mode 100644
index 0000000..364ecc1
--- /dev/null
+++ b/web/index.html
@@ -0,0 +1,32 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ he License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<!DOCTYPE html>
+<html>
+
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width,initial-scale=1.0">
+ <title>Sharding Performance monitoring</title>
+</head>
+
+<body>
+ <div id="app"></div>
+ <!-- built files will be auto injected -->
+</body>
+
+</html>
diff --git a/web/package.json b/web/package.json
new file mode 100644
index 0000000..c237062
--- /dev/null
+++ b/web/package.json
@@ -0,0 +1,87 @@
+{
+ "name": "incubator-shardingsphere-benchmark-ui-frontend",
+ "version": "1.0.0",
+ "description": "A Vue.js project",
+ "author": "ShardingSphere",
+ "private": true,
+ "scripts": {
+ "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
+ "start": "npm run dev",
+ "lint": "eslint --ext .js,.vue src",
+ "build": "node build/build.js"
+ },
+ "dependencies": {
+ "echarts": "^4.3.0",
+ "vue-echarts": "^4.0.4",
+ "iview": "^3.5.1",
+ "vue": "^2.5.2",
+ "vue-i18n": "^8.4.0",
+ "vue-router": "^3.0.1",
+ "vuex": "^3.0.1"
+ },
+ "devDependencies": {
+ "@babel/core": "^7.6.0",
+ "@babel/plugin-syntax-dynamic-import": "^7.2.0",
+ "@babel/plugin-transform-runtime": "^7.6.0",
+ "@babel/preset-env": "^7.6.0",
+ "@babel/runtime": "^7.6.0",
+ "autoprefixer": "^7.1.2",
+ "babel-core": "^7.0.0-bridge.0",
+ "babel-eslint": "^8.2.1",
+ "babel-helper-vue-jsx-merge-props": "^2.0.3",
+ "babel-loader": "^7.1.1",
+ "babel-plugin-dynamic-import-webpack": "^1.1.0",
+ "babel-plugin-istanbul": "^5.2.0",
+ "babel-plugin-syntax-jsx": "^6.18.0",
+ "babel-plugin-transform-runtime": "^6.22.0",
+ "babel-plugin-transform-vue-jsx": "^3.7.0",
+ "chalk": "^2.0.1",
+ "copy-webpack-plugin": "^5.0.3",
+ "cross-env": "^5.2.1",
+ "css-loader": "^2.1.1",
+ "eslint": "^4.15.0",
+ "eslint-config-standard": "^10.2.1",
+ "eslint-friendly-formatter": "^3.0.0",
+ "eslint-loader": "^2.1.2",
+ "eslint-plugin-import": "^2.7.0",
+ "eslint-plugin-node": "^5.2.0",
+ "eslint-plugin-promise": "^3.4.0",
+ "eslint-plugin-standard": "^3.0.1",
+ "eslint-plugin-vue": "^4.0.0",
+ "file-loader": "^3.0.1",
+ "friendly-errors-webpack-plugin": "^1.7.0",
+ "html-webpack-plugin": "^3.2.0",
+ "mini-css-extract-plugin": "^0.6.0",
+ "node-notifier": "^5.1.2",
+ "node-sass": "^4.10.0",
+ "optimize-css-assets-webpack-plugin": "^5.0.1",
+ "ora": "^1.2.0",
+ "portfinder": "^1.0.13",
+ "postcss-import": "^11.0.0",
+ "postcss-loader": "^2.0.8",
+ "postcss-url": "^7.2.1",
+ "rimraf": "^2.6.0",
+ "sass-loader": "^7.1.0",
+ "semver": "^5.3.0",
+ "shelljs": "^0.7.6",
+ "svg-sprite-loader": "^4.1.3",
+ "url-loader": "^1.1.2",
+ "vue-loader": "^15.7.0",
+ "vue-style-loader": "^3.0.1",
+ "vue-template-compiler": "^2.5.2",
+ "webpack": "^4.31.0",
+ "webpack-bundle-analyzer": "^2.9.0",
+ "webpack-cli": "^3.3.2",
+ "webpack-dev-server": "^3.4.1",
+ "webpack-merge": "^4.1.0"
+ },
+ "engines": {
+ "node": ">= 6.0.0",
+ "npm": ">= 3.0.0"
+ },
+ "browserslist": [
+ "> 1%",
+ "last 2 versions",
+ "not ie <= 8"
+ ]
+}
diff --git a/web/src/App.vue b/web/src/App.vue
new file mode 100644
index 0000000..28de323
--- /dev/null
+++ b/web/src/App.vue
@@ -0,0 +1,18 @@
+<template>
+ <div id="app">
+ <Container>
+ <router-view />
+ </Container>
+ </div>
+</template>
+
+<script>
+import Container from '@/components/Container'
+
+export default {
+ name: 'App',
+ components: {
+ Container
+ }
+}
+</script>
diff --git a/web/src/assets/logo.png b/web/src/assets/logo.png
new file mode 100644
index 0000000..209bb49
Binary files /dev/null and b/web/src/assets/logo.png differ
diff --git a/web/src/assets/logo_top.png b/web/src/assets/logo_top.png
new file mode 100644
index 0000000..ff22614
Binary files /dev/null and b/web/src/assets/logo_top.png differ
diff --git a/web/src/components/Container/index.vue b/web/src/components/Container/index.vue
new file mode 100644
index 0000000..1b2e15a
--- /dev/null
+++ b/web/src/components/Container/index.vue
@@ -0,0 +1,185 @@
+<template>
+ <div class="layout">
+ <Layout>
+ <Sider
+ ref="side1"
+ v-model="isCollapsed"
+ :collapsed-width="78"
+ class="layout-sider"
+ hide-trigger
+ collapsible
+ >
+ <div class="i-layout-sider-logo i-layout-sider-logo-dark">
+ <a href="/" target="_self" class="i-link i-link-color">
+ <img class="logo" src="../../assets/logo_top.png" />
+ <img class="collapse-logo" src="../../assets/logo.png" alt="logo" />
+ </a>
+ </div>
+ <Menu :class="menuitemClasses" active-name="1-2" theme="dark" width="auto">
+ <router-link to="mysql-vs-sharding">
+ <MenuItem name="1-2">
+ <Tooltip content="mysqlVsSharding" placement="right">
+ <span>mysqlVsSharding</span>
+ </Tooltip>
+ </MenuItem>
+ </router-link>
+ <router-link to="sharding-proxy-master-slave">
+ <MenuItem name="1-3">
+ <Tooltip content="shardingProxyMasterSlave" placement="right">
+ <span>shardingProxyMasterSlave</span>
+ </Tooltip>
+ </MenuItem>
+ </router-link>
+ <router-link to="sharding-proxy-master-slave-sharding">
+ <MenuItem name="1-4">
+ <Tooltip content="shardingProxyMasterSlaveSharding" placement="right">
+ <span>shardingProxyMasterSlaveSharding</span>
+ </Tooltip>
+ </MenuItem>
+ </router-link>
+ <router-link to="sharding-proxy-single-database-single-table">
+ <MenuItem name="1-5">
+ <Tooltip content="shardingProxySingleDatabaseSingleTable" placement="right">
+ <span>shardingProxySingleDatabaseSingleTable</span>
+ </Tooltip>
+ </MenuItem>
+ </router-link>
+ </Menu>
+ </Sider>
+ <Layout style="margin-left: 200px;">
+ <Header :style="{padding: 0}" class="layout-header-bar">
+ <!-- <Icon
+ :class="rotateIcon"
+ :style="{margin: '0 20px', color: '#f6ca9d', cursor: 'pointer'}"
+ size="24"
+ type="md-menu"
+ @click.native="collapsedSider"
+ />-->
+ </Header>
+ <Content>
+ <slot />
+ </Content>
+ <v-footer />
+ </Layout>
+ </Layout>
+ </div>
+</template>
+<script>
+import Footer from '../Footer/index.vue'
+export default {
+ name: 'Container',
+ components: {
+ 'v-footer': Footer
+ },
+ data() {
+ return {
+ isCollapsed: false
+ }
+ },
+ computed: {
+ rotateIcon() {
+ return ['menu-icon', this.isCollapsed ? 'rotate-icon' : '']
+ },
+ menuitemClasses() {
+ return ['menu-item', this.isCollapsed ? 'collapsed-menu' : '']
+ }
+ },
+ methods: {
+ collapsedSider() {
+ // this.$refs.side1.toggleCollapse()
+ }
+ }
+}
+</script>
+<style scoped>
+.layout {
+ background: #f5f7f9;
+ position: relative;
+ overflow: hidden;
+}
+a {
+ color: #fff;
+}
+.layout-header-bar {
+ background: #fff;
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
+}
+.layout-logo-left {
+ width: 90%;
+ height: 30px;
+ background: #5b6270;
+ border-radius: 3px;
+ margin: 15px auto;
+}
+.menu-icon {
+ transition: all 0.3s;
+}
+.rotate-icon {
+ transform: rotate(-90deg);
+}
+.menu-item {
+ background: #1d1e23;
+}
+.menu-item span {
+ display: inline-block;
+ width: 130px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ vertical-align: bottom;
+ transition: width 0.2s ease 0.2s;
+}
+.menu-item i {
+ transform: translateX(0px);
+ transition: font-size 0.2s ease, transform 0.2s ease;
+ vertical-align: middle;
+ font-size: 16px;
+}
+.collapsed-menu span {
+ width: 0px;
+ transition: width 0.2s ease;
+}
+.collapsed-menu i {
+ transform: translateX(5px);
+ transition: font-size 0.2s ease 0.2s, transform 0.2s ease 0.2s;
+ vertical-align: middle;
+ font-size: 22px;
+}
+.i-layout-sider-logo {
+ height: 63px;
+ line-height: 63px;
+ text-align: center;
+ border-bottom: 1px solid #f8f8f9;
+}
+.i-layout-sider-logo-dark {
+ border-bottom: 1px solid #101117;
+ background: #1d1e23;
+}
+.i-layout-sider-logo img {
+ height: 54%;
+ vertical-align: middle;
+}
+.layout-header-bar {
+ background: #1d1e23;
+ background: linear-gradient(90deg, #1d1e23, #3f4045);
+}
+.layout-sider {
+ background: #1d1e23;
+ z-index: 99;
+ position: fixed;
+ left: 0;
+ height: 100%;
+}
+.layout-sider .ivu-layout-sider-children {
+ background: #1d1e23 !important;
+}
+.ivu-layout-sider-collapsed .logo {
+ display: none;
+}
+.ivu-layout-sider-collapsed .collapse-logo {
+ display: inline-block;
+}
+.collapse-logo {
+ display: none;
+}
+</style>
\ No newline at end of file
diff --git a/web/src/components/Footer/index.vue b/web/src/components/Footer/index.vue
new file mode 100644
index 0000000..0c4b903
--- /dev/null
+++ b/web/src/components/Footer/index.vue
@@ -0,0 +1,24 @@
+<template>
+ <div class="footer-wrapper">
+ Copyright
+ <i class="icon-copyright iconfont" /> 2016 - 2018 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.
+ </div>
+</template>
+<script>
+export default {
+ name: 'Footer'
+}
+</script>
+<style rel="stylesheet/scss" lang="scss" scoped>
+$bg: #2d3a4b;
+$dark_gray: #889aa4;
+$light_gray: #eee;
+
+.footer-wrapper {
+ color: $dark_gray;
+ width: 100%;
+ font-size: 14px;
+ line-height: 60px;
+ text-align: center;
+}
+</style>
diff --git a/web/src/main.js b/web/src/main.js
new file mode 100644
index 0000000..f6104a4
--- /dev/null
+++ b/web/src/main.js
@@ -0,0 +1,15 @@
+import Vue from 'vue'
+import App from './App'
+import router from './router'
+
+import iView from 'iview'
+import 'iview/dist/styles/iview.css'
+
+Vue.config.productionTip = false
+
+Vue.use(iView)
+
+new Vue({
+ router,
+ render: h => h(App)
+}).$mount('#app')
diff --git a/web/src/router/index.js b/web/src/router/index.js
new file mode 100644
index 0000000..7441fce
--- /dev/null
+++ b/web/src/router/index.js
@@ -0,0 +1,37 @@
+import Vue from 'vue'
+import Router from 'vue-router'
+Vue.use(Router)
+
+export const constantRouterMap = [
+ {
+ path: '*',
+ redirect: '/mysql-vs-sharding'
+ },
+ {
+ path: '/mysql-vs-sharding',
+ component: () => import('@/views/mysql-vs-sharding/index'),
+ hidden: true
+ },
+ {
+ path: '/sharding-proxy-master-slave',
+ component: () => import('@/views/sharding-proxy-master-slave/index'),
+ hidden: true
+ },
+ {
+ path: '/sharding-proxy-master-slave-sharding',
+ component: () =>
+ import('@/views/sharding-proxy-master-slave-sharding/index'),
+ hidden: true
+ },
+ {
+ path: '/sharding-proxy-single-database-single-table',
+ component: () =>
+ import('@/views/sharding-proxy-single-database-single-table/index'),
+ hidden: true
+ }
+]
+
+export default new Router({
+ scrollBehavior: () => ({ y: 0 }),
+ routes: constantRouterMap
+})
diff --git a/web/src/utils/line.js b/web/src/utils/line.js
new file mode 100644
index 0000000..bf30a09
--- /dev/null
+++ b/web/src/utils/line.js
@@ -0,0 +1,50 @@
+const color = ['#2D8CF0', '#9A66E4', '#19BE6B', '#FF9900', '#E46CBB']
+const getLineOptions = (name, xAxis, legend, series) => {
+ return {
+ color,
+ grid: {
+ left: '2%',
+ right: '2%',
+ bottom: '6%',
+ containLabel: true
+ },
+ tooltip: {
+ trigger: 'axis',
+ formatter(d) {
+ let html = ``
+ for (const v of d) {
+ html += `<div style="display:inline-block;margin: 10px;font-size: 14px;">
+ <p><span style="display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:${
+ v.color
+ };"></span>${v.seriesName}</p>
+ <p>Throughtput: ${v.data.Throughout}</p>
+ <p>Samples: ${v.data.Samples}</p>
+ <p>Err: ${v.data.Err}</p>
+ <p>Max: ${v.data.Max}</p>
+ <p>Min: ${v.data.Min}</p>
+ </div>`
+ }
+ return html
+ }
+ },
+ xAxis: {
+ name: '(TEST TIMES)/DAY',
+ nameLocation: 'middle',
+ nameGap: 30,
+ type: 'category',
+ boundaryGap: false,
+ data: xAxis[name]
+ },
+ yAxis: {
+ name: 'TPS',
+ type: 'value'
+ },
+ legend: {
+ data: legend[name],
+ right: '2%'
+ },
+ series: series[name]
+ }
+}
+
+export { getLineOptions }
diff --git a/web/src/utils/mixin.js b/web/src/utils/mixin.js
new file mode 100644
index 0000000..1100e77
--- /dev/null
+++ b/web/src/utils/mixin.js
@@ -0,0 +1,69 @@
+const mountedMixin = {
+ data() {
+ return {
+ legend: {},
+ series: {},
+ desc: {},
+ xAxis: {}
+ }
+ },
+ mounted() {
+ const map = []
+ const legend = {}
+ const series = {}
+ const desc = {}
+ const xAxis = {}
+ for (const v in this.data) {
+ map.push(v)
+ if (v !== 'DESC') {
+ legend[v] = []
+ series[v] = []
+ xAxis[v] = []
+ }
+ }
+ for (const m of map) {
+ if (Object.prototype.toString.call(this.data[m]) === '[object Array]') {
+ for (const mm of this.data[m]) {
+ legend[m].push(mm.type)
+ const data = []
+ for (const mmm of Object.keys(mm.data)) {
+ if (xAxis[m].length !== mm.data.length) {
+ xAxis[m].push(mmm)
+ }
+ data.push({
+ ...mm.data[mmm],
+ value: mm.data[mmm].Throughout
+ })
+ }
+ series[m].push({
+ name: mm.type,
+ type: 'line',
+ data
+ })
+ }
+ } else {
+ for (const k of map) {
+ if (k !== m) {
+ desc[k] = {
+ mysqlVerison: this.data[m]['mysqlVerison'],
+ // 'ShardingSphere-proxy': this.data[m]['ShardingSphere-proxy'],
+ tableNumber: this.data[m]['tableNumber'],
+ // DataVolume: this.data[m]['DataVolume'],
+ // X: this.data[m]['X'],
+ // Y: this.data[m]['Y'],
+ sceneDescription: this.data[m]['sceneDescription'],
+ sqlExample: this.data[m][k].SqlExample
+ // ComparativeType: this.data[m][k].ComparativeType
+ }
+ }
+ }
+ }
+ }
+ this.legend = legend
+ this.series = series
+ this.desc = desc
+ this.xAxis = xAxis
+ }
+}
+
+export { mountedMixin }
diff --git a/web/src/utils/utils.js b/web/src/utils/utils.js
new file mode 100644
index 0000000..1f7851a
--- /dev/null
+++ b/web/src/utils/utils.js
@@ -0,0 +1,11 @@
+import mysqlVsShardingproxy from '../../../report/data_json/mysql_vs_shardingproxy.json'
+import shardingProxyMasterSlaveSharding from '../../../report/data_json/sharding_proxy_master_slave_sharding.json'
+import shardingProxyMasterSlave from '../../../report/data_json/sharding_proxy_master_slave.json'
+import shardingProxySingleDatabaseSingleTable from '../../../report/data_json/sharding_proxy_single_database_single_table.json'
+
+export {
+ mysqlVsShardingproxy,
+ shardingProxyMasterSlaveSharding,
+ shardingProxyMasterSlave,
+ shardingProxySingleDatabaseSingleTable
+}
diff --git a/web/src/views/mysql-vs-sharding/index.vue b/web/src/views/mysql-vs-sharding/index.vue
new file mode 100644
index 0000000..5125c39
--- /dev/null
+++ b/web/src/views/mysql-vs-sharding/index.vue
@@ -0,0 +1,64 @@
+<template>
+ <Row :gutter="16" style="background:#eee; padding:20px">
+ <Col v-for="(value, name, index) in series" :key="index" class="col-item" span="24">
+ <Card :bordered="false">
+ <p slot="title" style="font-size: 18px">{{ name.toLowerCase() }} throughtout compare</p>
+ <v-chart :options="getOptions(name)" />
+ <Form :label-width="140">
+ <FormItem
+ v-for="(value, name,indx) in desc[name]"
+ :label="`${name}:`"
+ :key="indx"
+ >{{ value }}</FormItem>
+ </Form>
+ </Card>
+ </Col>
+ </Row>
+</template>
+
+<script>
+import ECharts from 'vue-echarts'
+import 'echarts/lib/chart/line'
+import 'echarts/lib/component/tooltip'
+import 'echarts/lib/component/legend'
+import 'echarts/lib/component/title'
+import { mysqlVsShardingproxy } from '../../utils/utils'
+import { mountedMixin } from '../../utils/mixin'
+import { getLineOptions } from '../../utils/line'
+
+export default {
+ name: 'Home',
+ components: {
+ 'v-chart': ECharts
+ },
+ mixins: [mountedMixin],
+ data() {
+ return {
+ data: mysqlVsShardingproxy
+ }
+ },
+ methods: {
+ getOptions(name) {
+ return getLineOptions(name, this.xAxis, this.legend, this.series)
+ }
+ }
+}
+</script>
+<style>
+.echarts {
+ width: 100%;
+ height: 400px;
+}
+.col-item {
+ margin-bottom: 16px;
+}
+.ivu-form-item {
+ margin-bottom: 10px !important;
+}
+.ivu-form-item-label {
+ font-size: 15px !important;
+}
+.ivu-form-item-content {
+ font-size: 14px !important;
+}
+</style>
\ No newline at end of file
diff --git a/web/src/views/sharding-proxy-master-slave-sharding/index.vue b/web/src/views/sharding-proxy-master-slave-sharding/index.vue
new file mode 100644
index 0000000..19cbef9
--- /dev/null
+++ b/web/src/views/sharding-proxy-master-slave-sharding/index.vue
@@ -0,0 +1,64 @@
+<template>
+ <Row :gutter="16" style="background:#eee; padding:20px">
+ <Col v-for="(value, name, index) in series" :key="index" class="col-item" span="24">
+ <Card :bordered="false">
+ <p slot="title" style="font-size: 18px">{{ name.toLowerCase() }} throughtout compare</p>
+ <v-chart :options="getOptions(name)" />
+ <Form :label-width="140">
+ <FormItem
+ v-for="(value, name,indx) in desc[name]"
+ :label="`${name}:`"
+ :key="indx"
+ >{{ value }}</FormItem>
+ </Form>
+ </Card>
+ </Col>
+ </Row>
+</template>
+
+<script>
+import ECharts from 'vue-echarts'
+import 'echarts/lib/chart/line'
+import 'echarts/lib/component/tooltip'
+import 'echarts/lib/component/legend'
+import 'echarts/lib/component/title'
+import { shardingProxyMasterSlaveSharding } from '../../utils/utils'
+import { mountedMixin } from '../../utils/mixin'
+import { getLineOptions } from '../../utils/line'
+
+export default {
+ name: 'Home',
+ components: {
+ 'v-chart': ECharts
+ },
+ mixins: [mountedMixin],
+ data() {
+ return {
+ data: shardingProxyMasterSlaveSharding
+ }
+ },
+ methods: {
+ getOptions(name) {
+ return getLineOptions(name, this.xAxis, this.legend, this.series)
+ }
+ }
+}
+</script>
+<style>
+.echarts {
+ width: 100%;
+ height: 400px;
+}
+.col-item {
+ margin-bottom: 16px;
+}
+.ivu-form-item {
+ margin-bottom: 10px !important;
+}
+.ivu-form-item-label {
+ font-size: 15px !important;
+}
+.ivu-form-item-content {
+ font-size: 14px !important;
+}
+</style>
\ No newline at end of file
diff --git a/web/src/views/sharding-proxy-master-slave/index.vue b/web/src/views/sharding-proxy-master-slave/index.vue
new file mode 100644
index 0000000..1be9b47
--- /dev/null
+++ b/web/src/views/sharding-proxy-master-slave/index.vue
@@ -0,0 +1,64 @@
+<template>
+ <Row :gutter="16" style="background:#eee; padding:20px">
+ <Col v-for="(value, name, index) in series" :key="index" class="col-item" span="24">
+ <Card :bordered="false">
+ <p slot="title" style="font-size: 18px">{{ name.toLowerCase() }} throughtout compare</p>
+ <v-chart :options="getOptions(name)" />
+ <Form :label-width="140">
+ <FormItem
+ v-for="(value, name,indx) in desc[name]"
+ :label="`${name}:`"
+ :key="indx"
+ >{{ value }}</FormItem>
+ </Form>
+ </Card>
+ </Col>
+ </Row>
+</template>
+
+<script>
+import ECharts from 'vue-echarts'
+import 'echarts/lib/chart/line'
+import 'echarts/lib/component/tooltip'
+import 'echarts/lib/component/legend'
+import 'echarts/lib/component/title'
+import { shardingProxyMasterSlave } from '../../utils/utils'
+import { mountedMixin } from '../../utils/mixin'
+import { getLineOptions } from '../../utils/line'
+
+export default {
+ name: 'Home',
+ components: {
+ 'v-chart': ECharts
+ },
+ mixins: [mountedMixin],
+ data() {
+ return {
+ data: shardingProxyMasterSlave
+ }
+ },
+ methods: {
+ getOptions(name) {
+ return getLineOptions(name, this.xAxis, this.legend, this.series)
+ }
+ }
+}
+</script>
+<style>
+.echarts {
+ width: 100%;
+ height: 400px;
+}
+.col-item {
+ margin-bottom: 16px;
+}
+.ivu-form-item {
+ margin-bottom: 10px !important;
+}
+.ivu-form-item-label {
+ font-size: 15px !important;
+}
+.ivu-form-item-content {
+ font-size: 14px !important;
+}
+</style>
\ No newline at end of file
diff --git a/web/src/views/sharding-proxy-single-database-single-table/index.vue b/web/src/views/sharding-proxy-single-database-single-table/index.vue
new file mode 100644
index 0000000..ae7b588
--- /dev/null
+++ b/web/src/views/sharding-proxy-single-database-single-table/index.vue
@@ -0,0 +1,64 @@
+<template>
+ <Row :gutter="16" style="background:#eee; padding:20px">
+ <Col v-for="(value, name, index) in series" :key="index" class="col-item" span="24">
+ <Card :bordered="false">
+ <p slot="title" style="font-size: 18px">{{ name.toLowerCase() }} throughtout compare</p>
+ <v-chart :options="getOptions(name)" />
+ <Form :label-width="140">
+ <FormItem
+ v-for="(value, name,indx) in desc[name]"
+ :label="`${name}:`"
+ :key="indx"
+ >{{ value }}</FormItem>
+ </Form>
+ </Card>
+ </Col>
+ </Row>
+</template>
+
+<script>
+import ECharts from 'vue-echarts'
+import 'echarts/lib/chart/line'
+import 'echarts/lib/component/tooltip'
+import 'echarts/lib/component/legend'
+import 'echarts/lib/component/title'
+import { shardingProxySingleDatabaseSingleTable } from '../../utils/utils'
+import { mountedMixin } from '../../utils/mixin'
+import { getLineOptions } from '../../utils/line'
+
+export default {
+ name: 'Home',
+ components: {
+ 'v-chart': ECharts
+ },
+ mixins: [mountedMixin],
+ data() {
+ return {
+ data: shardingProxySingleDatabaseSingleTable
+ }
+ },
+ methods: {
+ getOptions(name) {
+ return getLineOptions(name, this.xAxis, this.legend, this.series)
+ }
+ }
+}
+</script>
+<style>
+.echarts {
+ width: 100%;
+ height: 400px;
+}
+.col-item {
+ margin-bottom: 16px;
+}
+.ivu-form-item {
+ margin-bottom: 10px !important;
+}
+.ivu-form-item-label {
+ font-size: 15px !important;
+}
+.ivu-form-item-content {
+ font-size: 14px !important;
+}
+</style>
\ No newline at end of file
diff --git a/web/static/.gitkeep b/web/static/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/web/static/404.html b/web/static/404.html
new file mode 100644
index 0000000..5a0ea23
--- /dev/null
+++ b/web/static/404.html
@@ -0,0 +1,31 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ he License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<!DOCTYPE html>
+<html>
+
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width,initial-scale=1.0">
+ <title>sharding-ui</title>
+</head>
+
+<body>
+ <div>404</div>
+</body>
+
+</html>