You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by ju...@apache.org on 2020/06/17 02:56:09 UTC

[incubator-apisix-dashboard] 01/02: remove outdated codes

This is an automated email from the ASF dual-hosted git repository.

juzhiyuan pushed a commit to branch feat-master
in repository https://gitbox.apache.org/repos/asf/incubator-apisix-dashboard.git

commit 0cc70e3170db2b9e6a6de78e152d56d414967e98
Author: juzhiyuan <jj...@gmail.com>
AuthorDate: Wed Jun 17 10:52:47 2020 +0800

    remove outdated codes
---
 .DS_Store                                         |  Bin 0 -> 6148 bytes
 .browserslistrc                                   |    2 -
 .editorconfig                                     |   35 -
 .env.development                                  |   11 -
 .env.production                                   |    5 -
 .eslintignore                                     |    3 -
 .eslintrc.js                                      |   37 -
 .gitignore                                        |   21 -
 CHANGELOG.md                                      |   36 -
 DISCLAIMER                                        |    5 -
 LICENSE                                           |  206 -
 NOTICE                                            |    5 -
 README.md                                         |  110 -
 babel.config.js                                   |   22 -
 licenses/LICENSE.ALv2                             |  201 -
 licenses/LICENSE.vue-typescript-admin-template    |   21 -
 package.json                                      |   82 -
 postcss.config.js                                 |   22 -
 public/favicon.ico                                |  Bin 9662 -> 0 bytes
 public/img/icons/favicon-16x16.png                |  Bin 9662 -> 0 bytes
 public/img/icons/favicon-32x32.png                |  Bin 9662 -> 0 bytes
 public/index.html                                 |   43 -
 public/robots.txt                                 |    2 -
 src/App.vue                                       |   33 -
 src/api/schema/consumers.ts                       |   50 -
 src/api/schema/plugins.ts                         |   24 -
 src/api/schema/routes.ts                          |   51 -
 src/api/schema/schema.ts                          |   24 -
 src/api/schema/services.ts                        |   51 -
 src/api/schema/ssl.ts                             |   52 -
 src/api/schema/upstream.ts                        |   50 -
 src/api/types.d.ts                                |   78 -
 src/api/users.ts                                  |   38 -
 src/components/Breadcrumb/index.vue               |  125 -
 src/components/Hamburger/index.vue                |   75 -
 src/components/HeaderSearch/index.vue             |  244 -
 src/components/LangSelect/index.vue               |   77 -
 src/components/Pagination/index.vue               |  104 -
 src/components/PluginDialog/index.vue             |  523 --
 src/components/Screenfull/index.vue               |   79 -
 src/components/VarArgs/index.vue                  |  128 -
 src/lang/en.ts                                    |   94 -
 src/lang/index.ts                                 |   67 -
 src/lang/zh.ts                                    |  102 -
 src/layout/components/AppMain.vue                 |   83 -
 src/layout/components/Navbar/index.vue            |  195 -
 src/layout/components/Sidebar/SidebarItem.vue     |  209 -
 src/layout/components/Sidebar/SidebarItemLink.vue |   56 -
 src/layout/components/Sidebar/SidebarLogo.vue     |  123 -
 src/layout/components/Sidebar/index.vue           |  156 -
 src/layout/components/TagsView/ScrollPane.vue     |  113 -
 src/layout/components/TagsView/index.vue          |  359 -
 src/layout/components/index.ts                    |   28 -
 src/layout/index.vue                              |  192 -
 src/layout/mixin/resize.ts                        |   79 -
 src/main.ts                                       |   57 -
 src/permission.ts                                 |  102 -
 src/router/index.ts                               |   82 -
 src/router/modules/schema/consumers.ts            |   56 -
 src/router/modules/schema/routes.ts               |   56 -
 src/router/modules/schema/services.ts             |   56 -
 src/router/modules/schema/ssl.ts                  |   56 -
 src/router/modules/schema/upstream.ts             |   56 -
 src/settings.ts                                   |   48 -
 src/shims.d.ts                                    |   36 -
 src/store/index.ts                                |   37 -
 src/store/modules/app.ts                          |  116 -
 src/store/modules/permission.ts                   |   80 -
 src/store/modules/settings.ts                     |   62 -
 src/store/modules/tags-view.ts                    |  165 -
 src/store/modules/user.ts                         |  169 -
 src/styles/_mixins.scss                           |   31 -
 src/styles/_svgicon.scss                          |   56 -
 src/styles/_transition.scss                       |   73 -
 src/styles/_variables.scss                        |   56 -
 src/styles/_variables.scss.d.ts                   |   33 -
 src/styles/element-variables.scss                 |   47 -
 src/styles/element-variables.scss.d.ts            |   31 -
 src/styles/index.scss                             |  183 -
 src/utils/cookies.ts                              |   44 -
 src/utils/index.ts                                |  112 -
 src/utils/permission.ts                           |   39 -
 src/utils/request.ts                              |   59 -
 src/utils/scroll-to.ts                            |   74 -
 src/utils/validate.ts                             |   39 -
 src/views/login/index.vue                         |  228 -
 src/views/schema/consumers/edit.vue               |  266 -
 src/views/schema/consumers/list.vue               |  222 -
 src/views/schema/routes/edit.vue                  |  549 --
 src/views/schema/routes/list.vue                  |  252 -
 src/views/schema/service/edit.vue                 |  300 -
 src/views/schema/service/list.vue                 |  215 -
 src/views/schema/ssl/edit.vue                     |  191 -
 src/views/schema/ssl/list.vue                     |  206 -
 src/views/schema/upstream/edit.vue                |  434 -
 src/views/schema/upstream/list.vue                |  289 -
 tsconfig.json                                     |   41 -
 vue.config.js                                     |   84 -
 yarn.lock                                         | 9432 ---------------------
 99 files changed, 19351 deletions(-)

diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..5008ddf
Binary files /dev/null and b/.DS_Store differ
diff --git a/.browserslistrc b/.browserslistrc
deleted file mode 100644
index 3a455dd..0000000
--- a/.browserslistrc
+++ /dev/null
@@ -1,2 +0,0 @@
-> 1%
-last 2 versions
\ No newline at end of file
diff --git a/.editorconfig b/.editorconfig
deleted file mode 100644
index 9b38463..0000000
--- a/.editorconfig
+++ /dev/null
@@ -1,35 +0,0 @@
-# http://editorconfig.org
-
-# top-most EditorConfig file
-root = true
-
-# Unix-style newlines with a newline ending every file
-[*]
-charset = utf-8
-end_of_line = lf
-insert_final_newline = true
-trim_trailing_whitespace = true
-
-# Indentation override for js(x), ts(x) and vue files
-[*.{js,jsx,ts,tsx,vue}]
-indent_size = 2
-indent_style = space
-
-# Indentation override for css related files
-[*.{css,styl,scss,less,sass}]
-indent_size = 2
-indent_style = space
-
-# Indentation override for html files
-[*.html]
-indent_size = 2
-indent_style = space
-
-# Trailing space override for markdown file
-[*.md]
-trim_trailing_whitespace = false
-
-# Indentation override for config files
-[*.{json,yml}]
-indent_size = 2
-indent_style = space
\ No newline at end of file
diff --git a/.env.development b/.env.development
deleted file mode 100644
index 1e3d951..0000000
--- a/.env.development
+++ /dev/null
@@ -1,11 +0,0 @@
-# Base api
-VUE_APP_BASE_API = ''
-
-# vue-cli uses the VUE_CLI_BABEL_TRANSPILE_MODULES environment variable,
-# to control whether the babel-plugin-dynamic-import-node plugin is enabled.
-# It only does one thing by converting all import() to require().
-# This configuration can significantly increase the speed of hot updates,
-# when you have a large number of pages.
-# Detail:  https://github.com/vuejs/vue-cli/blob/dev/packages/@vue/babel-preset-app/index.js
-
-VUE_CLI_BABEL_TRANSPILE_MODULES = true
\ No newline at end of file
diff --git a/.env.production b/.env.production
deleted file mode 100644
index edd19d0..0000000
--- a/.env.production
+++ /dev/null
@@ -1,5 +0,0 @@
-
-# Base api
-# Remeber to change this to your production server address
-# Here I used my mock server for this project
-VUE_APP_BASE_API = '/apisix/admin/'
\ No newline at end of file
diff --git a/.eslintignore b/.eslintignore
deleted file mode 100644
index 4bcf40f..0000000
--- a/.eslintignore
+++ /dev/null
@@ -1,3 +0,0 @@
-
-dist/*.js
-tests/unit/coverage
\ No newline at end of file
diff --git a/.eslintrc.js b/.eslintrc.js
deleted file mode 100644
index 4f0b93f..0000000
--- a/.eslintrc.js
+++ /dev/null
@@ -1,37 +0,0 @@
-module.exports = {
-    root: true,
-    env: {
-      browser: true,
-      node: true,
-      es6: true
-    },
-    parserOptions: {
-      parser: '@typescript-eslint/parser',
-      sourceType: 'module'
-    },
-    plugins: [
-      'vue'
-    ],
-    rules: {
-      'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
-      'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
-      'space-before-function-paren': [2, 'never'],
-      'vue/array-bracket-spacing': 'error',
-      'vue/arrow-spacing': 'error',
-      'vue/block-spacing': 'error',
-      'vue/brace-style': 'error',
-      'vue/comma-dangle': 'error',
-      'vue/component-name-in-template-casing': 'error',
-      'vue/eqeqeq': 'error',
-      'vue/key-spacing': 'error',
-      'vue/match-component-file-name': 'error',
-      'vue/object-curly-spacing': 'error',
-      "camelcase": 'off'
-    },
-    'extends': [
-      'eslint:recommended',
-      'plugin:vue/recommended',
-      '@vue/standard',
-      '@vue/typescript'
-    ]
-  }
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 2b33ebe..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,21 +0,0 @@
-.DS_Store
-node_modules
-/dist
-
-# local env files
-.env.local
-.env.*.local
-
-# Log files
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-
-# Editor directories and files
-.idea
-.vscode
-*.suo
-*.ntvs*
-*.njsproj
-*.sln
-*.sw*
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
deleted file mode 100644
index f2eb346..0000000
--- a/CHANGELOG.md
+++ /dev/null
@@ -1,36 +0,0 @@
-
-<!--
-#
-# 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.
-#
--->
-
-# Table of Contents
-
-- [1.0.0](#100)
-
-## 1.0.0
-
-This release is mainly to build some basic panels and resolve License issue.
-
-### Core
-- Dashboard initial. [#1](https://github.com/apache/incubator-apisix-dashboard/pull/1)
-- Resolve licence issues.
-- Remove unused files from the Dashboard boilerplate.
-- Support panel to list, create and modify Route, Consumer, Service, SSL and Upstream.
-- Support custom configuration for Plugin dialog.
-
-[Back to TOC](#table-of-contents)
diff --git a/DISCLAIMER b/DISCLAIMER
deleted file mode 100644
index 70fc20c..0000000
--- a/DISCLAIMER
+++ /dev/null
@@ -1,5 +0,0 @@
-Apache APISIX Dashboard (incubating) is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Apache Incubator PMC.
-Incubation is required of all newly accepted projects until a further review indicates that the infrastructure,
-communications, and decision making process have stabilized in a manner consistent with other successful ASF projects.
-While incubation status is not necessarily a reflection of the completeness or stability of the code,
-it does indicate that the project has yet to be fully endorsed by the ASF.
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 6da9712..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,206 +0,0 @@
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright [yyyy] [name of copyright owner]
-
-   Licensed 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.
-
-=======================================================================
-
-The Apache APISIX project bundles vue-typescript-admin-template under the MIT license.
-For details, see licenses/LICENSE.vue-typescript-admin-template.
diff --git a/NOTICE b/NOTICE
deleted file mode 100644
index f0a4483..0000000
--- a/NOTICE
+++ /dev/null
@@ -1,5 +0,0 @@
-Apache APISIX Dashboard (incubating)
-Copyright 2020 The Apache Software Foundation
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
diff --git a/README.md b/README.md
deleted file mode 100644
index 438999c..0000000
--- a/README.md
+++ /dev/null
@@ -1,110 +0,0 @@
-<!--
-#
-# 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.
-#
--->
-
-# apisix_dashboard
-
-## Overview
-
-Dashboard for APISIX & based on ElementUI.
-
-## Documentation
-
-[Docs](https://armour.github.io/vue-typescript-admin-docs)
-
-[Vue Config Docs](https://cli.vuejs.org/zh/config/#publicpath)
-
-## Project Structure
-
-```bash
-├── public                     # public static assets
-│   │── img/                   # static image files
-│   │── favicon.ico            # favicon
-│   │── index.html             # index.html template
-│   └── robots.txt             # robots file
-├── src                        # main source code
-│   ├── api/                   # api service
-│   ├── components/            # global components
-│   ├── lang/                  # i18n language
-│   ├── layout/                # global layout
-│   ├── router/                # router
-│   ├── store/                 # store
-│   ├── styles/                # global css
-│   ├── utils/                 # global utils
-│   ├── views/                 # views
-│   ├── App.vue                # main app component
-│   ├── main.ts                # app entry file
-│   ├── permission.ts          # permission authentication
-│   ├── settings.ts            # setting file
-│   └── shims.d.ts             # type definition shims
-├── licenses                   # license files for ALv2 and boilerplate
-├── .browserslistrc            # browserslist config file (to support Autoprefixer)
-├── .editorconfig              # editor code format consistency config
-├── .env.xxx                   # env variable configuration
-├── .eslintrc.js               # eslint config
-├── .eslintignore              # eslint ignore config
-├── .gitignore                 # git ignore config
-├── babel.config.js            # babel config
-├── LICENSE                    # license file
-├── NOTICE                     # notice file
-├── package.json               # package.json
-├── postcss.config.js          # postcss config
-├── README.md                  # some information about APISIX
-├── tsconfig.json              # typescript config
-├── vue.config.js              # vue-cli config
-└── yarn.lock                  # keep exact versions of each dependency
-```
-
-## Project setup
-> Make sure Node.js 8.12.0 or higher, and Yarn are installed on your machine: https://yarnpkg.com/en/docs/install
-
-### Install dependencies
-
-```bash
-yarn install
-```
-
-### Compiles and hot-reloads for development
-
-```bash
-yarn run serve
-```
-
-### Compiles and minifies for production
-
-```bash
-yarn run build:prod
-```
-
-### Lints and fixes files
-
-```bash
-yarn run lint
-```
-
-### Customize Vue configuration
-
-See [Configuration Reference](https://cli.vuejs.org/config/).
-
-## Browsers support
-
-Modern browsers and Internet Explorer 10+.
-
-| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/mas [...]
-| --------- | --------- | --------- | --------- |
-| IE10, IE11, Edge| last 2 versions| last 2 versions| last 2 versions
diff --git a/babel.config.js b/babel.config.js
deleted file mode 100644
index e7708a0..0000000
--- a/babel.config.js
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * 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.
- */
-
-module.exports = {
-  presets: [
-    '@vue/app'
-  ]
-}
diff --git a/licenses/LICENSE.ALv2 b/licenses/LICENSE.ALv2
deleted file mode 100644
index 261eeb9..0000000
--- a/licenses/LICENSE.ALv2
+++ /dev/null
@@ -1,201 +0,0 @@
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright [yyyy] [name of copyright owner]
-
-   Licensed 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.
diff --git a/licenses/LICENSE.vue-typescript-admin-template b/licenses/LICENSE.vue-typescript-admin-template
deleted file mode 100644
index 7c3565d..0000000
--- a/licenses/LICENSE.vue-typescript-admin-template
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2018 Chong Guo
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/package.json b/package.json
deleted file mode 100644
index b769c33..0000000
--- a/package.json
+++ /dev/null
@@ -1,82 +0,0 @@
-{
-  "name": "incubator-apisix-dashboard",
-  "version": "0.1.0",
-  "private": true,
-  "scripts": {
-    "serve": "concurrently \"vue-cli-service serve\"",
-    "lint": "vue-cli-service lint",
-    "build:prod": "vue-cli-service build"
-  },
-  "dependencies": {
-    "axios": "^0.19.0",
-    "echarts": "^4.2.1",
-    "element-ui": "^2.9.2",
-    "fuse.js": "^3.4.5",
-    "js-cookie": "^2.2.0",
-    "normalize.css": "^8.0.1",
-    "nprogress": "^0.2.0",
-    "path-to-regexp": "^3.0.0",
-    "screenfull": "^4.2.0",
-    "uuid": "^3.3.2",
-    "vue": "^2.6.10",
-    "vue-class-component": "^7.1.0",
-    "vue-i18n": "^8.11.2",
-    "vue-property-decorator": "^8.2.1",
-    "vue-router": "^3.0.6",
-    "vue-svgicon": "^3.2.6",
-    "vuex": "^3.1.1",
-    "vuex-class": "^0.3.2",
-    "vuex-module-decorators": "^0.9.9"
-  },
-  "devDependencies": {
-    "@types/compression": "^0.0.36",
-    "@types/echarts": "^4.1.9",
-    "@types/js-cookie": "^2.2.2",
-    "@types/nprogress": "^0.2.0",
-    "@types/webpack-env": "^1.13.9",
-    "@vue/cli-plugin-babel": "^3.8.0",
-    "@vue/cli-plugin-eslint": "^3.8.0",
-    "@vue/cli-plugin-typescript": "^3.8.1",
-    "@vue/cli-service": "^3.8.4",
-    "@vue/eslint-config-standard": "^4.0.0",
-    "@vue/eslint-config-typescript": "^4.0.0",
-    "babel-core": "^7.0.0-bridge.0",
-    "babel-eslint": "^10.0.2",
-    "concurrently": "^4.1.0",
-    "eslint": "^5.16.0",
-    "eslint-plugin-vue": "^5.2.2",
-    "fibers": "^4.0.1",
-    "lint-staged": "^8.2.1",
-    "sass": "^1.21.0",
-    "sass-loader": "^7.1.0",
-    "style-resources-loader": "^1.2.1",
-    "typescript": "3.5.2",
-    "vue-cli-plugin-element": "^1.0.1",
-    "vue-cli-plugin-style-resources-loader": "^0.1.3",
-    "vue-template-compiler": "^2.6.10",
-    "webpack": "^4.35.0"
-  },
-  "bugs": {
-    "url": "https://github.com/apache/incubator-apisix-dashboard/issues"
-  },
-  "gitHooks": {
-    "pre-commit": "lint-staged"
-  },
-  "keywords": [
-    "vue",
-    "typescript",
-    "admin",
-    "template",
-    "element-ui"
-  ],
-  "lint-staged": {
-    "*.{js,vue}": [
-      "vue-cli-service lint",
-      "git add"
-    ]
-  },
-  "repository": {
-    "type": "git",
-    "url": "git+https://github.com/apache/incubator-apisix-dashboard.git"
-  }
-}
diff --git a/postcss.config.js b/postcss.config.js
deleted file mode 100644
index a5e9c1d..0000000
--- a/postcss.config.js
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * 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.
- */
-
-module.exports = {
-  plugins: {
-    autoprefixer: {}
-  }
-}
diff --git a/public/favicon.ico b/public/favicon.ico
deleted file mode 100644
index 05cb493..0000000
Binary files a/public/favicon.ico and /dev/null differ
diff --git a/public/img/icons/favicon-16x16.png b/public/img/icons/favicon-16x16.png
deleted file mode 100644
index 05cb493..0000000
Binary files a/public/img/icons/favicon-16x16.png and /dev/null differ
diff --git a/public/img/icons/favicon-32x32.png b/public/img/icons/favicon-32x32.png
deleted file mode 100644
index 05cb493..0000000
Binary files a/public/img/icons/favicon-32x32.png and /dev/null differ
diff --git a/public/index.html b/public/index.html
deleted file mode 100644
index c3907ad..0000000
--- a/public/index.html
+++ /dev/null
@@ -1,43 +0,0 @@
-<!--
-#
-# MIT License
-#
-# Copyright (c) 2018 Chong Guo
-# 
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-# 
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-# 
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-#
--->
-
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta charset="utf-8">
-    <meta http-equiv="X-UA-Compatible" content="IE=edge">
-    <meta name="viewport" content="width=device-width,initial-scale=1.0">
-    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
-    <title><%= webpackConfig.name %></title>
-  </head>
-  <body>
-    <noscript>
-      <strong>We're sorry but <%= webpackConfig.name %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
-    </noscript>
-    <div id="app"></div>
-    <!-- built files will be auto injected -->
-  </body>
-</html>
diff --git a/public/robots.txt b/public/robots.txt
deleted file mode 100644
index eb05362..0000000
--- a/public/robots.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-User-agent: *
-Disallow:
diff --git a/src/App.vue b/src/App.vue
deleted file mode 100644
index adf2931..0000000
--- a/src/App.vue
+++ /dev/null
@@ -1,33 +0,0 @@
-<!--
-#
-# 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.
-#
--->
-
-<template>
-  <div id="app">
-    <router-view />
-  </div>
-</template>
-
-<script lang="ts">
-import { Component, Vue } from 'vue-property-decorator'
-
-@Component({
-  name: 'App'
-})
-export default class extends Vue {}
-</script>
diff --git a/src/api/schema/consumers.ts b/src/api/schema/consumers.ts
deleted file mode 100644
index 06b72d8..0000000
--- a/src/api/schema/consumers.ts
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.
- */
-
-import request from '@/utils/request'
-
-import { IConsumerData } from '../types'
-
-export const defaultConsumerData: IConsumerData = {
-  username: '',
-  plugins: {}
-}
-
-export const updateOrCreateConsumer = (data: IConsumerData) =>
-  request({
-    url: '/consumers',
-    method: 'PUT',
-    data
-  })
-
-export const getList = () =>
-  request({
-    url: '/consumers',
-    method: 'GET'
-  })
-
-export const get = (username: string) =>
-  request({
-    url: `/consumers/${username}`,
-    method: 'GET'
-  })
-
-export const removeConsumer = (username: string) =>
-  request({
-    url: `/consumers/${username}`,
-    method: 'DELETE'
-  })
diff --git a/src/api/schema/plugins.ts b/src/api/schema/plugins.ts
deleted file mode 100644
index bc71e96..0000000
--- a/src/api/schema/plugins.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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.
- */
-
-import request from '@/utils/request'
-
-export const getPluginList = () =>
-  request({
-    url: '/plugins/list',
-    method: 'get'
-  })
diff --git a/src/api/schema/routes.ts b/src/api/schema/routes.ts
deleted file mode 100644
index a871a96..0000000
--- a/src/api/schema/routes.ts
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.
- */
-
-import request from '@/utils/request'
-import { IRouteData } from '../types'
-
-export const getList = () =>
-  request({
-    url: '/routes',
-    method: 'GET'
-  })
-
-export const updateRouter = (id: string, data: any) =>
-  request({
-    url: `/routes/${id}`,
-    method: 'PUT',
-    data
-  })
-
-export const getRouter = (id: string) =>
-  request({
-    url: `/routes/${id}`,
-    method: 'GET'
-  })
-
-export const removeRouter = (id: string) =>
-  request({
-    url: `/routes/${id}`,
-    method: 'DELETE'
-  })
-
-export const createRouter = (data: any) =>
-  request({
-    url: '/routes',
-    method: 'POST',
-    data
-  })
diff --git a/src/api/schema/schema.ts b/src/api/schema/schema.ts
deleted file mode 100644
index e58a27b..0000000
--- a/src/api/schema/schema.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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.
- */
-
-import request from '@/utils/request'
-
-export const getPluginSchema = (name: string) =>
-  request({
-    url: `/schema/plugins/${name}`,
-    method: 'get'
-  })
diff --git a/src/api/schema/services.ts b/src/api/schema/services.ts
deleted file mode 100644
index d6bb1bb..0000000
--- a/src/api/schema/services.ts
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.
- */
-
-import request from '@/utils/request'
-import { IServiceData } from '../types'
-
-export const getServiceList = () =>
-  request({
-    url: '/services',
-    method: 'get'
-  })
-
-export const updateService = (id: string, data: any) =>
-  request({
-    url: `/services/${id}`,
-    method: 'PUT',
-    data
-  })
-
-export const getService = (id: string) =>
-  request({
-    url: `/services/${id}`,
-    method: 'GET'
-  })
-
-export const removeService = (id: string) =>
-  request({
-    url: `/services/${id}`,
-    method: 'DELETE'
-  })
-
-export const createService = (data: any) =>
-  request({
-    url: '/services',
-    method: 'POST',
-    data
-  })
diff --git a/src/api/schema/ssl.ts b/src/api/schema/ssl.ts
deleted file mode 100644
index b945c14..0000000
--- a/src/api/schema/ssl.ts
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.
- */
-
-import request from '@/utils/request'
-
-import { ISSLData } from '../types'
-
-export const getSSLList = () =>
-  request({
-    url: '/ssl',
-    method: 'GET'
-  })
-
-export const updateSSL = (id: string, data: any) =>
-  request({
-    url: `/ssl/${id}`,
-    method: 'PUT',
-    data
-  })
-
-export const getSSL = (id: string) =>
-  request({
-    url: `/ssl/${id}`,
-    method: 'GET'
-  })
-
-export const removeSSL = (id: string) =>
-  request({
-    url: `/ssl/${id}`,
-    method: 'DELETE'
-  })
-
-export const createSSL = (data: any) =>
-  request({
-    url: '/ssl',
-    method: 'POST',
-    data
-  })
diff --git a/src/api/schema/upstream.ts b/src/api/schema/upstream.ts
deleted file mode 100644
index 04c6f03..0000000
--- a/src/api/schema/upstream.ts
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.
- */
-
-import request from '@/utils/request'
-
-export const updateStream = (id: string, data: any) =>
-  request({
-    url: `/upstreams/${id}`,
-    method: 'PUT',
-    data
-  })
-
-export const getUpstream = (id: string) =>
-  request({
-    url: `/upstreams/${id}`,
-    method: 'GET'
-  })
-
-export const removeUpstream = (id: string) =>
-  request({
-    url: `/upstreams/${id}`,
-    method: 'DELETE'
-  })
-
-export const createUpstream = (data: any) =>
-  request({
-    url: `/upstreams`,
-    method: 'POST',
-    data
-  })
-
-export const getUpstreamList = () =>
-  request({
-    url: `/upstreams`,
-    method: 'GET'
-  })
diff --git a/src/api/types.d.ts b/src/api/types.d.ts
deleted file mode 100644
index c80ec23..0000000
--- a/src/api/types.d.ts
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * 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.
- */
-
-export type TypeID = number | string
-export type TypePlugin = object
-
-export interface IConsumerData {
-  username: string
-  plugins?: TypePlugin
-}
-
-export interface IRouteData {
-  methods: []
-  plugins: TypePlugin
-  upstream: IUpstreamData
-  uri: string
-  host: string
-  remote_addr: string
-  service_id: TypeID
-  upstream_id: TypeID
-  id: TypeID
-}
-
-export interface IServiceData {
-  id: TypeID
-  plugins: TypePlugin
-  upstream: IUpstreamData
-  upstream_id: TypeID
-}
-
-export interface ISSLData {
-  cert: string
-  key: string
-  sni: string
-}
-
-export enum EnumUpstreamType {
-  chash,
-  roundrobin
-}
-
-export enum EnumUpstreamKey {
-  remote_addr
-}
-export interface IUpstreamData {
-  nodes: object
-  type: EnumUpstreamType
-  key?: EnumUpstreamKey
-  id?: TypeID
-}
-
-export enum EnumAction {
-  get,
-  set,
-  delete,
-  create
-}
-
-export interface IDataWrapper<T> {
-  node: {
-    value: T
-  },
-  action: EnumAction
-}
diff --git a/src/api/users.ts b/src/api/users.ts
deleted file mode 100644
index 591b787..0000000
--- a/src/api/users.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.
- */
-
-import request from '@/utils/request'
-
-export const getUserInfo = (data: any) =>
-  request({
-    url: '/users/info',
-    method: 'post',
-    data
-  })
-
-export const login = (data: any) =>
-  request({
-    url: '/users/login',
-    method: 'post',
-    data
-  })
-
-export const logout = () =>
-  request({
-    url: '/users/logout',
-    method: 'post'
-  })
diff --git a/src/components/Breadcrumb/index.vue b/src/components/Breadcrumb/index.vue
deleted file mode 100644
index 54c04ce..0000000
--- a/src/components/Breadcrumb/index.vue
+++ /dev/null
@@ -1,125 +0,0 @@
-<!--
-#
-# MIT License
-#
-# Copyright (c) 2018 Chong Guo
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-#
--->
-
-<template>
-  <el-breadcrumb
-    class="app-breadcrumb"
-    separator="/"
-  >
-    <transition-group name="breadcrumb">
-      <el-breadcrumb-item
-        v-for="(item, index) in breadcrumbs"
-        :key="item.path"
-      >
-        <span
-          v-if="item.redirect === 'noredirect' || index === breadcrumbs.length-1"
-          class="no-redirect"
-        >{{ $t('route.' + item.meta.title) }}</span>
-        <a
-          v-else
-          @click.prevent="handleLink(item)"
-        >{{ $t('route.' + item.meta.title) }}</a>
-      </el-breadcrumb-item>
-    </transition-group>
-  </el-breadcrumb>
-</template>
-
-<script lang="ts">
-import pathToRegexp from 'path-to-regexp'
-import { Component, Vue, Watch } from 'vue-property-decorator'
-import { RouteRecord, Route } from 'vue-router'
-
-@Component({
-  name: 'Breadcrumb'
-})
-export default class extends Vue {
-  private breadcrumbs: RouteRecord[] = []
-
-  @Watch('$route')
-  private onRouteChange(route: Route) {
-    // if you go to the redirect page, do not update the breadcrumbs
-    if (route.path.startsWith('/redirect/')) {
-      return
-    }
-    this.getBreadcrumb()
-  }
-
-  created() {
-    this.getBreadcrumb()
-  }
-
-  private getBreadcrumb() {
-    let matched = this.$route.matched.filter((item) => item.meta && item.meta.title)
-    const first = matched[0]
-    this.breadcrumbs = matched.filter((item) => {
-      return item.meta && item.meta.title && item.meta.breadcrumb !== false
-    })
-  }
-
-  private isDashboard(route: RouteRecord) {
-    const name = route && route.name
-    if (!name) {
-      return false
-    }
-    return name.trim().toLocaleLowerCase() === 'Dashboard'.toLocaleLowerCase()
-  }
-
-  private pathCompile(path: string) {
-    // To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
-    const { params } = this.$route
-    const toPath = pathToRegexp.compile(path)
-    return toPath(params)
-  }
-
-  private handleLink(item: any) {
-    const { redirect, path } = item
-    if (redirect) {
-      this.$router.push(redirect)
-      return
-    }
-    this.$router.push(this.pathCompile(path))
-  }
-}
-</script>
-
-<style lang="scss" scoped>
-.el-breadcrumb__inner,
-.el-breadcrumb__inner a {
-  font-weight: 400 !important;
-}
-
-.app-breadcrumb.el-breadcrumb {
-  display: inline-block;
-  font-size: 14px;
-  line-height: 50px;
-  margin-left: 8px;
-
-  .no-redirect {
-    color: #97a8be;
-    cursor: text;
-  }
-}
-</style>
diff --git a/src/components/Hamburger/index.vue b/src/components/Hamburger/index.vue
deleted file mode 100644
index e21e513..0000000
--- a/src/components/Hamburger/index.vue
+++ /dev/null
@@ -1,75 +0,0 @@
-<!--
-#
-# MIT License
-#
-# Copyright (c) 2018 Chong Guo
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-#
--->
-
-<template>
-  <div
-    :class="[{'is-active': isActive}]"
-    @click="toggleClick"
-  >
-    <svg
-      viewBox="0 0 100 80"
-      width="20"
-      height="20"
-    >
-      <rect
-        width="100"
-        height="20"
-      />
-      <rect
-        y="30"
-        width="100"
-        height="20"
-      />
-      <rect
-        y="60"
-        width="100"
-        height="20"
-      />
-    </svg>
-  </div>
-</template>
-
-<script lang="ts">
-import { Component, Prop, Vue } from 'vue-property-decorator'
-
-@Component({
-  name: 'Hamburger'
-})
-export default class extends Vue {
-  @Prop({ default: false }) private isActive!: boolean
-
-  private toggleClick() {
-    this.$emit('toggleClick')
-  }
-}
-</script>
-
-<style lang="scss" scoped>
-.svg-icon {
-  vertical-align: middle;
-}
-
-</style>
diff --git a/src/components/HeaderSearch/index.vue b/src/components/HeaderSearch/index.vue
deleted file mode 100644
index c1a2428..0000000
--- a/src/components/HeaderSearch/index.vue
+++ /dev/null
@@ -1,244 +0,0 @@
-<!--
-#
-# MIT License
-#
-# Copyright (c) 2018 Chong Guo
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-#
--->
-
-<template>
-  <div
-    id="header-search"
-    :class="{'show': show}"
-    class="header-search"
-  >
-    <svg-icon
-      class="search-icon"
-      name="search"
-      @click.stop="click"
-    />
-    <el-select
-      ref="headerSearchSelect"
-      v-model="search"
-      :remote-method="querySearch"
-      filterable
-      default-first-option
-      remote
-      placeholder="Search"
-      class="header-search-select"
-      @change="change"
-    >
-      <el-option
-        v-for="item in options"
-        :key="item.path"
-        :value="item"
-        :label="item.meta.title.join(' > ')"
-      />
-    </el-select>
-  </div>
-</template>
-
-<script lang="ts">
-import path from 'path'
-import Fuse from 'fuse.js' // A lightweight fuzzy-search module
-import { Component, Vue, Watch } from 'vue-property-decorator'
-import { RouteConfig } from 'vue-router'
-import { AppModule } from '@/store/modules/app'
-import { PermissionModule } from '@/store/modules/permission'
-import i18n from '@/lang' // Internationalization
-
-@Component({
-  name: 'HeaderSearch'
-})
-export default class extends Vue {
-  private search = ''
-  private show = false
-  private options: RouteConfig[] = []
-  private searchPool: RouteConfig[] = []
-  private fuse?: Fuse<RouteConfig, Fuse.FuseOptions<RouteConfig>>
-
-  get routes() {
-    return PermissionModule.routes
-  }
-
-  get lang() {
-    return AppModule.language
-  }
-
-  @Watch('lang')
-  private onLangChange() {
-    this.searchPool = this.generateRoutes(this.routes)
-  }
-
-  @Watch('routes')
-  private onRoutesChange() {
-    this.searchPool = this.generateRoutes(this.routes)
-  }
-
-  @Watch('searchPool')
-  private onSearchPoolChange(value: RouteConfig[]) {
-    this.initFuse(value)
-  }
-
-  @Watch('show')
-  private onShowChange(value: boolean) {
-    if (value) {
-      document.body.addEventListener('click', this.close)
-    } else {
-      document.body.removeEventListener('click', this.close)
-    }
-  }
-
-  mounted() {
-    this.searchPool = this.generateRoutes(this.routes)
-  }
-
-  private click() {
-    this.show = !this.show
-    if (this.show) {
-      this.$refs.headerSearchSelect && (this.$refs.headerSearchSelect as HTMLElement).focus()
-    }
-  }
-
-  private close() {
-    this.$refs.headerSearchSelect && (this.$refs.headerSearchSelect as HTMLElement).blur()
-    this.options = []
-    this.show = false
-  }
-
-  private change(route: RouteConfig) {
-    this.$router.push(route.path)
-    this.search = ''
-    this.options = []
-    this.$nextTick(() => {
-      this.show = false
-    })
-  }
-
-  private initFuse(list: RouteConfig[]) {
-    this.fuse = new Fuse(list, {
-      shouldSort: true,
-      threshold: 0.4,
-      location: 0,
-      distance: 100,
-      maxPatternLength: 32,
-      minMatchCharLength: 1,
-      keys: [{
-        name: 'title',
-        weight: 0.7
-      }, {
-        name: 'path',
-        weight: 0.3
-      }]
-    })
-  }
-
-  // Filter out the routes that can be displayed in the sidebar
-  // And generate the internationalized title
-  private generateRoutes(routes: RouteConfig[], basePath = '/', prefixTitle: string[] = []) {
-    let res: RouteConfig[] = []
-
-    for (const router of routes) {
-      // skip hidden router
-      if (router.meta && router.meta.hidden) {
-        continue
-      }
-
-      const data: RouteConfig = {
-        path: path.resolve(basePath, router.path),
-        meta: {
-          title: [...prefixTitle]
-        }
-      }
-
-      if (router.meta && router.meta.title) {
-        // generate internationalized title
-        const i18ntitle = i18n.t(`route.${router.meta.title}`).toString()
-        data.meta.title = [...data.meta.title, i18ntitle]
-        if (router.redirect !== 'noRedirect') {
-          // only push the routes with title
-          // special case: need to exclude parent router without redirect
-          res.push(data)
-        }
-      }
-
-      // recursive child routes
-      if (router.children) {
-        const tempRoutes = this.generateRoutes(router.children, data.path, data.meta.title)
-        if (tempRoutes.length >= 1) {
-          res = [...res, ...tempRoutes]
-        }
-      }
-    }
-    return res
-  }
-
-  private querySearch(query: string) {
-    if (query !== '') {
-      if (this.fuse) {
-        this.options = this.fuse.search(query) as any
-      }
-    } else {
-      this.options = []
-    }
-  }
-}
-</script>
-
-<style lang="scss" scoped>
-.header-search {
-  font-size: 0 !important;
-
-  .search-icon {
-    cursor: pointer;
-    font-size: 18px;
-    vertical-align: middle;
-  }
-
-  .header-search-select {
-    font-size: 18px;
-    transition: width 0.2s;
-    width: 0;
-    overflow: hidden;
-    background: transparent;
-    border-radius: 0;
-    display: inline-block;
-    vertical-align: middle;
-
-    .el-input__inner {
-      border-radius: 0;
-      border: 0;
-      padding-left: 0;
-      padding-right: 0;
-      box-shadow: none !important;
-      border-bottom: 1px solid #d9d9d9;
-      vertical-align: middle;
-    }
-  }
-
-  &.show {
-    .header-search-select {
-      width: 210px;
-      margin-left: 10px;
-    }
-  }
-}
-</style>
diff --git a/src/components/LangSelect/index.vue b/src/components/LangSelect/index.vue
deleted file mode 100644
index 937813a..0000000
--- a/src/components/LangSelect/index.vue
+++ /dev/null
@@ -1,77 +0,0 @@
-<!--
-#
-# MIT License
-#
-# Copyright (c) 2018 Chong Guo
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-#
--->
-
-<template>
-  <el-dropdown
-    trigger="click"
-    class="international"
-    @command="handleSetLanguage"
-  >
-    <div>
-      <svg-icon
-        name="language"
-        class="international-icon"
-      />
-    </div>
-    <el-dropdown-menu slot="dropdown">
-      <el-dropdown-item
-        :disabled="language==='zh'"
-        command="zh"
-      >
-        中文
-      </el-dropdown-item>
-      <el-dropdown-item
-        :disabled="language==='en'"
-        command="en"
-      >
-        English
-      </el-dropdown-item>
-    </el-dropdown-menu>
-  </el-dropdown>
-</template>
-
-<script lang="ts">
-import { Component, Vue, Watch } from 'vue-property-decorator'
-import { AppModule } from '@/store/modules/app'
-
-@Component({
-  name: 'Login'
-})
-export default class extends Vue {
-  get language() {
-    return AppModule.language
-  }
-
-  private handleSetLanguage(lang: string) {
-    this.$i18n.locale = lang
-    AppModule.SetLanguage(lang)
-    this.$message({
-      message: 'Switch Language Success',
-      type: 'success'
-    })
-  }
-}
-</script>
diff --git a/src/components/Pagination/index.vue b/src/components/Pagination/index.vue
deleted file mode 100644
index eb31aa1..0000000
--- a/src/components/Pagination/index.vue
+++ /dev/null
@@ -1,104 +0,0 @@
-<!--
-#
-# MIT License
-#
-# Copyright (c) 2018 Chong Guo
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-#
--->
-
-<template>
-  <div
-    :class="{'hidden': hidden}"
-    class="pagination-container"
-  >
-    <el-pagination
-      :background="background"
-      :current-page.sync="currentPage"
-      :page-size.sync="pageSize"
-      :layout="layout"
-      :page-sizes="pageSizes"
-      :total="total"
-      v-bind="$attrs"
-      @size-change="handleSizeChange"
-      @current-change="handleCurrentChange"
-    />
-  </div>
-</template>
-
-<script lang="ts">
-import { Component, Prop, Vue } from 'vue-property-decorator'
-import { scrollTo } from '@/utils/scroll-to'
-
-@Component({
-  name: 'Pagination'
-})
-export default class extends Vue {
-  @Prop({ required: true }) private total!: number
-  @Prop({ default: 1 }) private page!: number
-  @Prop({ default: 20 }) private limit!: number
-  @Prop({ default: () => [10, 20, 30, 50] }) private pageSizes!: number[]
-  @Prop({ default: 'total, sizes, prev, pager, next, jumper' }) private layout!: string
-  @Prop({ default: true }) private background!: boolean
-  @Prop({ default: true }) private autoScroll!: boolean
-  @Prop({ default: false }) private hidden!: boolean
-
-  get currentPage() {
-    return this.page
-  }
-
-  set currentPage(value) {
-    this.$emit('update:page', value)
-  }
-
-  get pageSize() {
-    return this.limit
-  }
-
-  set pageSize(value) {
-    this.$emit('update:limit', value)
-  }
-
-  handleSizeChange(value: number) {
-    this.$emit('pagination', { page: this.currentPage, limit: value })
-    if (this.autoScroll) {
-      scrollTo(0, 800)
-    }
-  }
-
-  handleCurrentChange(value: number) {
-    this.$emit('pagination', { page: value, limit: this.pageSize })
-    if (this.autoScroll) {
-      scrollTo(0, 800)
-    }
-  }
-}
-</script>
-
-<style lang="scss" scoped>
-.pagination-container {
-  background: #fff;
-  padding: 32px 16px;
-}
-
-.pagination-container.hidden {
-  display: none;
-}
-</style>
diff --git a/src/components/PluginDialog/index.vue b/src/components/PluginDialog/index.vue
deleted file mode 100644
index d31d4b9..0000000
--- a/src/components/PluginDialog/index.vue
+++ /dev/null
@@ -1,523 +0,0 @@
-<!--
-#
-# 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.
-#
--->
-
-<template>
-  <div class="plugin-dialog">
-    <el-dialog
-      :title="'Plugin ' + name + ' Edit'"
-      :visible.sync="showDialog"
-    >
-      <el-form
-        v-if="schema.oneOf"
-        ref="form"
-        :model="data"
-        :rules="rules"
-        :show-message="false"
-        class="oneof-plugin-wrapper"
-      >
-        <el-form-item
-          label="Option"
-          :rules="{
-            required: true, trigger: 'blur'
-          }"
-        >
-          <el-radio-group
-            v-model="data['radioKey']"
-            @change="handleOneOfChange"
-          >
-            <el-radio
-              v-for="(value, key) in schema.properties"
-              :key="key"
-              :label="key"
-            >
-              {{ key }}
-            </el-radio>
-          </el-radio-group>
-        </el-form-item>
-
-        <el-form-item
-          v-for="(value, index) in data.values"
-          :key="index"
-          :label="'Value' + (index + 1)"
-          :rules="{
-            required: true, trigger: 'blur'
-          }"
-        >
-          <el-input v-model="data['values'][index]" />
-          <el-button
-            v-if="data.values.length !== 1"
-            class="remove-value-btn"
-            type="danger"
-            @click.prevent="removeOneOfPropValue(index)"
-          >
-            Remove
-          </el-button>
-        </el-form-item>
-
-        <el-form-item>
-          <el-button
-            :disabled="oneOfPropHasEmptyValue"
-            @click="addValueInput"
-          >
-            {{ $t('button.addValue') }}
-          </el-button>
-        </el-form-item>
-      </el-form>
-
-      <el-form
-        v-if="!schema.oneOf"
-        ref="form"
-        :model="data"
-        :rules="rules"
-        :show-message="false"
-      >
-        <el-form-item
-          v-for="(index, key) in schema.properties"
-          :key="key"
-          :label="key"
-          label-width="160px"
-          :prop="key"
-        >
-          <!-- 分情况讨论 -->
-          <!-- number property -->
-          <el-input-number
-            v-if="schema.properties[key].type === 'integer' || schema.properties[key].type === 'number'"
-            v-model="data[key]"
-            :min="schema.properties[key].minimum || -99999999999"
-            :max="schema.properties[key].maximum || 99999999999"
-            label="描述文字"
-            @change="onPropertyChange(key, $event)"
-          />
-
-          <!-- enum property -->
-          <el-select
-            v-if="schema.properties[key].hasOwnProperty('enum')"
-            v-model="data[key]"
-            :clearable="true"
-            :placeholder="`Select a ${key}`"
-            @change="onPropertyChange(key, $event)"
-          >
-            <el-option
-              v-for="value in schema.properties[key]['enum']"
-              :key="value"
-              :label="value"
-              :value="value"
-            />
-          </el-select>
-
-          <!-- string property -->
-          <el-input
-            v-if="schema.properties[key].type === 'string' && !schema.properties[key].hasOwnProperty('enum')"
-            v-model="data[key]"
-            :placeholder="key"
-            @input="onPropertyChange(key, $event)"
-          />
-
-          <!-- boolean property -->
-          <el-switch
-            v-if="schema.properties[key].type === 'boolean' && !schema.properties[key].hasOwnProperty('enum')"
-            v-model="data[key]"
-            active-color="#13ce66"
-            inactive-color="#ff4949"
-          />
-
-          <!-- array property -->
-          <div
-            v-if="schema.properties[key].type === 'array'"
-            class="array-input-container"
-          >
-            <el-input
-              v-for="(arrayIndex) in arrayPropertiesLength[key]"
-              :key="arrayIndex"
-              v-model="data[key][arrayIndex]"
-              :placeholder="`${key} [${arrayIndex}]`"
-              @input="isDataChanged = true"
-            />
-
-            <el-button
-              @click="addArrayItem(key)"
-            >
-              {{ $t('button.addValue') }}
-            </el-button>
-          </div>
-
-          <!-- object property -->
-          <div
-            v-if="schema.properties[key].type === 'object'"
-            class="object-input-container"
-          >
-            <div
-              v-for="(objectItem, objectIndex) in objectPropertiesArray[key]"
-              :key="objectIndex"
-              class="object-input-item"
-            >
-              <el-input
-                v-model="objectPropertiesArray[key][objectIndex].key"
-                :placeholder="`${key} [key ${objectIndex}]`"
-                @input="onObjectPropertyChange(key, $event, true)"
-              />
-              <el-input
-                v-model="objectPropertiesArray[key][objectIndex].value"
-                :placeholder="`${key} [value ${objectIndex}]`"
-                @input="onObjectPropertyChange(key, $event, false)"
-              />
-              <el-button
-                @click="deleteObjectItem(key, objectIndex)"
-              >
-                {{ $t('button.delete') }}
-              </el-button>
-            </div>
-            <el-button
-              @click="addObjectItem(key)"
-            >
-              {{ $t('button.addValue') }}
-            </el-button>
-          </div>
-        </el-form-item>
-      </el-form>
-      <span
-        slot="footer"
-        class="dialog-footer"
-      >
-        <el-button
-          @click="onCancel"
-        >
-          {{ $t('button.cancel') }}
-        </el-button>
-        <el-button
-          type="primary"
-          :disabled="!isDataChanged && oneOfPropHasEmptyValue"
-          @click="onSave"
-        >
-          {{ $t('button.confirm') }}
-        </el-button>
-      </span>
-    </el-dialog>
-  </div>
-</template>
-
-<script lang="ts">
-import { Component, Prop, Vue, Watch } from 'vue-property-decorator'
-
-import { getPluginSchema } from '../../api/schema/schema'
-
-const uuidv1 = require('uuid/v1')
-
-@Component({
-  name: 'PluginDialog'
-})
-export default class extends Vue {
-  @Prop({ default: false }) private show!: boolean
-  @Prop({ default: '' }) private name!: string
-  @Prop({ default: null }) private pluginData!: any
-
-  private schema: any = {
-    properties: {}
-  }
-  private rules: any = {}
-  private data: any = {}
-  private isDataChanged: boolean = false
-  private showDialog: boolean = false
-  private arrayPropertiesLength = {}
-  private objectPropertiesArray = {}
-
-  @Watch('show')
-  private onShowChange(value: boolean) {
-    this.resetPlugin()
-    if (value) {
-      this.getschema(this.name)
-    }
-    this.showDialog = value
-  }
-
-  private resetPlugin() {
-    this.schema = {
-      properties: {}
-    }
-    this.rules = {}
-    this.data = {}
-    this.isDataChanged = false
-  }
-
-  private async getschema(name: string) {
-    const schema = await getPluginSchema(name) as any
-
-    if (!schema.properties) {
-      this.isDataChanged = true
-      return
-    }
-
-    this.schema = Object.assign({}, {
-      ...schema,
-      name: this.name
-    })
-
-    const rules = Object.assign({}, schema.properties)
-
-    for (let pluginName in rules) {
-      const plugin = Object.assign({}, rules[pluginName])
-
-      rules[pluginName] = {
-        trigger: 'blur'
-      }
-
-      if (schema.required) {
-        rules[pluginName].required = schema.required.includes(pluginName)
-      }
-
-      if (plugin.hasOwnProperty('type')) {
-        rules[pluginName]['type'] = plugin['type']
-      }
-
-      if (plugin.hasOwnProperty('minimum')) {
-        rules[pluginName]['min'] = plugin['minimum']
-      }
-
-      if (plugin.hasOwnProperty('maximum')) {
-        rules[pluginName]['max'] = plugin['maximum']
-      }
-
-      if (plugin.hasOwnProperty('enum')) {
-        rules[pluginName]['type'] = 'enum'
-        rules[pluginName]['enum'] = plugin['enum']
-      }
-    }
-
-    this.rules = rules
-
-    // Generate initial data and merge current data
-    let schemaKeys = {}
-    for (let key in schema.properties) {
-      if (schema.properties[key].default) {
-        schemaKeys[key] = schema.properties[key].default
-        continue
-      }
-
-      switch (schema.properties[key].type) {
-        case 'array':
-          schemaKeys[key] = []
-          this.arrayPropertiesLength[key] = [...new Array(this.pluginData[key] ? this.pluginData[key].length : schema.properties[key].minItems).keys()]
-          break
-        case 'object':
-          schemaKeys[key] = {}
-          this.objectPropertiesArray[key] = []
-          if (this.pluginData[key]) {
-            Object.keys(this.pluginData[key]).map(item => {
-              this.objectPropertiesArray[key].push({
-                key: item,
-                value: this.pluginData[key][item]
-              })
-            })
-          }
-          break
-        case 'boolean':
-          schemaKeys[key] = false
-          break
-        default:
-          schemaKeys[key] = ''
-      }
-    }
-
-    if (this.pluginData) {
-      this.data = Object.assign(schemaKeys, this.pluginData)
-    } else {
-      this.data = schemaKeys
-    }
-
-    if (this.name === 'key-auth' && !this.pluginData) {
-      this.data = {
-        key: uuidv1()
-      }
-
-      this.isDataChanged = true
-    }
-
-    // Edit plugin data
-    if (this.name === 'ip-restriction' && this.pluginData) {
-      const key = Object.keys(this.pluginData)[0]
-      this.$nextTick(() => {
-        this.data = {
-          radioKey: key,
-          values: this.pluginData[key]
-        }
-      })
-    }
-
-    // Create new plugin data
-    if (this.schema.oneOf) {
-      this.data = {
-        radioKey: Object.keys(this.schema.properties)[0],
-        values: ['']
-      }
-    }
-  }
-
-  private onCancel() {
-    this.$emit('hidePlugin')
-  }
-
-  private onSave() {
-    (this.$refs.form as any).validate((valid: boolean) => {
-      // 标记该插件数据是否通过校验
-      if (valid) {
-        // Reorganize an array of object properties into objects
-        this.data = Object.assign({}, this.data, this.reorganizeObjectProperty())
-        this.data = this.processOneOfProp(this.data)
-        this.$emit('save', this.name, this.data)
-        this.$message.warning(`${this.$t('message.clickSaveButton')}`)
-      } else {
-        return false
-      }
-    })
-  }
-
-  /**
-   * Add item to array property
-   * @param key
-   */
-  private addArrayItem(key: any) {
-    if (this.arrayPropertiesLength[key].length < this.schema.properties[key].maxItems) {
-      this.arrayPropertiesLength[key].push(this.arrayPropertiesLength[key].length)
-      this.$forceUpdate()
-    } else {
-      this.$message.warning(`${this.$t('message.cannotAddMoreItems')}`)
-    }
-  }
-
-  /**
-   * Add item to object property
-   * @param key
-   */
-  private addObjectItem(key: any) {
-    this.objectPropertiesArray[key].push({
-      key: '',
-      value: ''
-    })
-    this.isDataChanged = true
-    this.$forceUpdate()
-  }
-
-  /**
-   * Delete item form object property
-   * @param key
-   * @param index
-   */
-  private deleteObjectItem(key: any, index: number) {
-    this.objectPropertiesArray[key].splice(index, 1)
-    this.isDataChanged = true
-    this.$forceUpdate()
-  }
-
-  /**
-   * Reorganize an array of object properties into objects
-   */
-  private reorganizeObjectProperty() {
-    let data = {}
-    for (let i in this.objectPropertiesArray) {
-      let objectItem = {}
-      this.objectPropertiesArray[i].map((item: any) => {
-        objectItem[item.key] = item.value
-      })
-      data[i] = objectItem
-    }
-    return data
-  }
-
-  /**
-   * Force rerender on object property content changed
-   */
-  private onObjectPropertyChange() {
-    this.isDataChanged = true
-    this.$forceUpdate()
-  }
-
-  private onPropertyChange(key: any, value: any) {
-    this.data[key] = value
-    this.isDataChanged = true
-  }
-
-  private handleOneOfChange(e: any) {
-    this.data.values = ['']
-  }
-
-  get oneOfPropHasEmptyValue() {
-    return this.data.values ? this.data.values.find((value: string) => value === '') : true
-  }
-
-  private addValueInput() {
-    this.data.values = this.data.values.concat([''])
-  }
-
-  private removeOneOfPropValue(index: number) {
-    this.data.values = this.data.values.filter((item: any, _index: number) => index !== _index)
-  }
-
-  private processOneOfProp(data: any) {
-    if (!this.schema.oneOf) {
-      // remove empty field
-      for (let key in data) {
-        if (data[key] === '') {
-          delete data[key]
-        }
-        if (typeof data[key] === 'object' && Object.keys(data[key]).length === 0) {
-          delete data[key]
-        }
-      }
-      return data
-    }
-
-    return {
-      [this.data.radioKey]: this.data.values
-    }
-  }
-}
-</script>
-
-<style lang="scss">
-.plugin-dialog {
-  .el-form {
-    .el-form-item {
-      .el-form-item__content {
-        .el-input {
-          width: 200px !important;
-        }
-      }
-    }
-  }
-
-  .oneof-plugin-wrapper {
-    .remove-value-btn {
-      margin-left: 10px;
-    }
-  }
-
-  .array-input-container > * {
-    display: flex;
-    margin-top: 5px;
-  }
-
-  .object-input-container > * {
-    display: flex;
-    margin-top: 5px;
-    :not(:first-child){
-      margin-left: 5px;
-    }
-  }
-}
-</style>
diff --git a/src/components/Screenfull/index.vue b/src/components/Screenfull/index.vue
deleted file mode 100644
index 2ad6d56..0000000
--- a/src/components/Screenfull/index.vue
+++ /dev/null
@@ -1,79 +0,0 @@
-<!--
-#
-# MIT License
-#
-# Copyright (c) 2018 Chong Guo
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-#
--->
-
-<template>
-  <div id="screenfull">
-    <svg-icon
-      :name="isFullscreen? 'exit-fullscreen': 'fullscreen'"
-      @click="click"
-    />
-  </div>
-</template>
-
-<script lang="ts">
-import screenfull from 'screenfull'
-import { Component, Vue } from 'vue-property-decorator'
-
-const sf = screenfull
-
-@Component({
-  name: 'Screenfull'
-})
-export default class extends Vue {
-  private isFullscreen = false
-
-  mounted() {
-    if (sf && sf.enabled) {
-      sf.on('change', this.change)
-    }
-  }
-
-  beforeDestory() {
-    if (sf && sf.enabled) {
-      sf.off('change', this.change)
-    }
-  }
-
-  private change() {
-    if (sf && sf.enabled) {
-      this.isFullscreen = sf.isFullscreen
-    }
-  }
-
-  private click() {
-    if (sf) {
-      if (!sf.enabled) {
-        this.$message({
-          message: 'you browser can not work',
-          type: 'warning'
-        })
-        return false
-      }
-      sf.toggle()
-    }
-  }
-}
-</script>
diff --git a/src/components/VarArgs/index.vue b/src/components/VarArgs/index.vue
deleted file mode 100644
index 1abcdec..0000000
--- a/src/components/VarArgs/index.vue
+++ /dev/null
@@ -1,128 +0,0 @@
-<!--
-#
-# 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.
-#
--->
-
-<template>
-  <el-form>
-    <el-form-item
-      v-for="(item, index) in vars"
-      :key="index"
-      :label="'Var' + (index + 1)"
-      class="var-item"
-    >
-      <el-form-item :prop="'var.' + index + '.ip'">
-        <el-select
-          v-model="item.name"
-          :placeholder="$t('schema.route.inputMultipleValues')"
-          filterable
-          allow-create
-          default-first-option
-          @change="onChange"
-        >
-          <el-option
-            v-for="name in varNames"
-            :key="name"
-            :label="name"
-            :value="name"
-          />
-        </el-select>
-        <el-select
-          v-model="item.operator"
-          placeholder="Operator"
-          @change="onChange"
-        >
-          <el-option
-            v-for="operator in varOperator"
-            :key="operator"
-            :label="operator"
-            :value="operator"
-          />
-        </el-select>
-      </el-form-item>
-      <el-form-item>
-        <el-input
-          v-model="item.value"
-          placeholder=""
-          @input="onChange"
-        />
-      </el-form-item>
-      <el-form-item>
-        <el-button
-          type="danger"
-          @click.prevent="removeVar(index)"
-        >
-          {{ $t("button.delete") }}
-        </el-button>
-      </el-form-item>
-    </el-form-item>
-    <el-form-item>
-      <el-button @click="addVar">
-        {{ $t("button.add_var") }}
-      </el-button>
-    </el-form-item>
-  </el-form>
-</template>
-
-<script lang="ts">
-import { Component, Vue, Watch, Prop } from 'vue-property-decorator'
-
-@Component({
-  name: 'VarArgs'
-})
-export default class extends Vue {
-  @Prop({ default: () => [] }) private pVars!: any
-  private isFullscreen = false;
-  private get vars() {
-    const _vars = this.pVars.map((arr:Array<any>) => {
-      const [name, operator, value] = arr
-      return { name, operator, value }
-    })
-    return _vars
-  }
-  private varNames = ['remote_addr', 'host', 'uri', 'http_user_agent', 'http_referer', 'http_cookie', 'http_accept_language', 'request_uri', 'query_string', 'remote_port', 'hostname', 'arg_id'];
-
-  private varOperator = ['==', '~=', '>', '<', '~~'];
-
-  private onChange() {
-    const val = this.vars.map((e:any) => Object.values(e))
-    this.$emit('update:pVars', val)
-  }
-
-  private addVar() {
-    (this.vars as any).push({
-      name: null,
-      operator: null,
-      value: null
-    })
-    this.onChange()
-  }
-
-  private removeVar(index:number) {
-    this.$confirm('Do you want to remove the var?', 'Warning', {
-      confirmButtonText: 'Confirm',
-      cancelButtonText: 'Cancel',
-      type: 'warning'
-    })
-      .then(async() => {
-        this.vars.splice(index, 1)
-        this.onChange()
-      })
-      .catch(() => {})
-  }
-}
-</script>
diff --git a/src/lang/en.ts b/src/lang/en.ts
deleted file mode 100644
index 58623f7..0000000
--- a/src/lang/en.ts
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * 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.
- */
-
-export default {
-  route: {
-    dashboard: 'Dashboard',
-    i18n: 'I18n',
-    profile: 'Profile',
-    SchemaRoutes: 'Routes',
-    SchemaRoutesList: 'Routes',
-    SchemaRoutesEdit: 'Router Edit',
-    SchemaRoutesCreate: 'Router Create',
-    SchemaConsumers: 'Consumers',
-    SchemaConsumersList: 'Consumers',
-    SchemaConsumersEdit: 'Consumer Edit',
-    SchemaConsumersCreate: 'Consumer Create',
-    SchemaServices: 'Services',
-    SchemaServiceList: 'Services',
-    SchemaServiceCreate: 'Service Create',
-    SchemaServiceEdit: 'Service Edit',
-    SchemaSSL: 'SSL',
-    SchemaSSLList: 'SSL',
-    SchemaSSLEdit: 'SSL Edit',
-    SchemaSSLCreate: 'SSL Create',
-    SchemaUpstream: 'Upstream',
-    SchemaUpstreamList: 'Upstream',
-    SchemaUpstreamCreate: 'Upstream Create',
-    SchemaUpstreamEdit: 'Upstream Edit'
-  },
-  table: {
-    add: 'Add',
-    edit: 'Edit',
-    delete: 'Delete',
-    actions: 'Action'
-  },
-  navbar: {
-    logOut: 'Log Out'
-  },
-  login: {
-    title: 'APISIX Login',
-    logIn: 'Login',
-    username: 'Username',
-    password: 'Password'
-  },
-  tagsView: {
-    refresh: 'Refresh',
-    close: 'Close',
-    closeOthers: 'Close Others',
-    closeAll: 'Close All'
-  },
-  button: {
-    save: 'Save',
-    confirm: 'Confirm',
-    cancel: 'Cancel',
-    add_plugin: 'Add Plugin',
-    add_node: 'Add Node',
-    add_var: 'Add Var',
-    delete: 'Delete',
-    addValue: 'Add Value'
-  },
-  schema: {
-    route: {
-      inputMultipleValues: 'Input value then press return button',
-      propertyHostsTip: 'Any values are supported',
-      fileterFunc: 'User-defined filtering function,Begins with "function()" and ends with "end".'
-    }
-  },
-  upstream: {
-    websocket: {
-      EnabledTip: 'WebSocket enabled',
-      DisabledTip: 'WebSocket disabled'
-    },
-    keyTip: 'You can edit and input any value here,and press Enter to confirm.',
-    hashOnTip: 'Select a hash on.'
-  },
-  message: {
-    cannotAddMoreItems: 'You cannot add more item!',
-    clickSaveButton: 'Your data will be saved after you click the Save button!'
-  }
-}
diff --git a/src/lang/index.ts b/src/lang/index.ts
deleted file mode 100644
index 2671616..0000000
--- a/src/lang/index.ts
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.
- */
-
-import Vue from 'vue'
-import VueI18n from 'vue-i18n'
-
-import { getLanguage } from '@/utils/cookies'
-
-// element-ui built-in lang
-import elementEnLocale from 'element-ui/lib/locale/lang/en'
-import elementZhLocale from 'element-ui/lib/locale/lang/zh-CN'
-
-// User defined lang
-import enLocale from './en'
-import zhLocale from './zh'
-
-Vue.use(VueI18n)
-
-const messages = {
-  en: {
-    ...enLocale,
-    ...elementEnLocale
-  },
-  zh: {
-    ...zhLocale,
-    ...elementZhLocale
-  }
-}
-
-export const getLocale = () => {
-  const cookieLanguage = getLanguage()
-  if (cookieLanguage) {
-    return cookieLanguage
-  }
-
-  const language = navigator.language.toLowerCase()
-  const locales = Object.keys(messages)
-  for (const locale of locales) {
-    if (language.indexOf(locale) > -1) {
-      return locale
-    }
-  }
-
-  // Default language is english
-  return 'en'
-}
-
-const i18n = new VueI18n({
-  locale: getLocale(),
-  messages
-})
-
-export default i18n
diff --git a/src/lang/zh.ts b/src/lang/zh.ts
deleted file mode 100644
index 5eb56c4..0000000
--- a/src/lang/zh.ts
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 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.
- */
-
-export default {
-  route: {
-    dashboard: '首页',
-    i18n: '国际化',
-    profile: '个人中心',
-    SchemaRoutes: 'Routes',
-    SchemaRoutesList: 'Routes',
-    SchemaRoutesEdit: '编辑 Router',
-    SchemaRoutesCreate: '创建 Router',
-    SchemaConsumers: 'Consumers',
-    SchemaConsumersList: 'Consumers',
-    SchemaConsumersEdit: '编辑 Consumer',
-    SchemaConsumersCreate: '创建 Consumer',
-    SchemaServices: 'Services',
-    SchemaServiceList: 'Services',
-    SchemaServiceCreate: '创建 Service',
-    SchemaServiceEdit: '编辑 Service',
-    SchemaSSL: 'SSL',
-    SchemaSSLList: 'SSL',
-    SchemaSSLEdit: '编辑 SSL',
-    SchemaSSLCreate: '创建 SSL',
-    SchemaUpstream: 'Upstream',
-    SchemaUpstreamList: 'Upstream',
-    SchemaUpstreamCreate: '创建 Upstream',
-    SchemaUpstreamEdit: '编辑 Upstream'
-  },
-  table: {
-    add: '添加',
-    edit: '编辑',
-    delete: '删除',
-    actions: '操作'
-  },
-  navbar: {
-    logOut: '退出登录'
-  },
-  login: {
-    title: '系统登录',
-    logIn: '登录',
-    username: '账号',
-    password: '密码'
-  },
-  tagsView: {
-    refresh: '刷新',
-    close: '关闭',
-    closeOthers: '关闭其它',
-    closeAll: '关闭所有'
-  },
-  settings: {
-    title: '系统布局配置',
-    theme: '主题色',
-    showTagsView: '显示 Tags-View',
-    showSidebarLogo: '显示侧边栏 Logo',
-    fixedHeader: '固定 Header',
-    sidebarTextTheme: '侧边栏文字主题色'
-  },
-  button: {
-    save: '保存',
-    confirm: '确认',
-    cancel: '取消',
-    add_plugin: '添加 Plugin',
-    add_node: '添加 Node',
-    add_var: '添加 Var',
-    delete: '删除',
-    addValue: '添加值'
-  },
-  schema: {
-    route: {
-      inputMultipleValues: '输入值后并回车',
-      propertyHostsTip: '任何值均可',
-      fileterFunc: '用户自定义的过滤函数,以‘function()’开头,以‘end’结尾。'
-    }
-  },
-  upstream: {
-    websocket: {
-      EnabledTip: 'WebSocket 打开',
-      DisabledTip: 'WebSocket 关闭'
-    },
-    keyTip: '你可以编辑并输入任何值,输入值后回车确认。',
-    hashOnTip: '选择 chash 参数来源。'
-  },
-  message: {
-    cannotAddMoreItems: '不能添加更多项了!',
-    clickSaveButton: '你的数据将在点击保存按钮后被保存!'
-  }
-}
diff --git a/src/layout/components/AppMain.vue b/src/layout/components/AppMain.vue
deleted file mode 100644
index e7d12f6..0000000
--- a/src/layout/components/AppMain.vue
+++ /dev/null
@@ -1,83 +0,0 @@
-<!--
-#
-# MIT License
-#
-# Copyright (c) 2018 Chong Guo
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-#
--->
-
-<template>
-  <section class="app-main">
-    <transition
-      name="fade-transform"
-      mode="out-in"
-    >
-      <keep-alive :include="cachedViews">
-        <router-view :key="key" />
-      </keep-alive>
-    </transition>
-  </section>
-</template>
-
-<script lang="ts">
-import { Component, Vue } from 'vue-property-decorator'
-import { TagsViewModule } from '@/store/modules/tags-view'
-
-@Component({
-  name: 'AppMain'
-})
-export default class extends Vue {
-  get cachedViews() {
-    return TagsViewModule.cachedViews
-  }
-
-  get key() {
-    return this.$route.path
-  }
-}
-</script>
-
-<style lang="scss" scoped>
-.app-main {
-  /* 50= navbar  50  */
-  min-height: calc(100vh - 50px);
-  width: 100%;
-  position: relative;
-  overflow: hidden;
-}
-
-.fixed-header+.app-main {
-  padding-top: 50px;
-  height: 100vh;
-  overflow: auto;
-}
-
-.hasTagsView {
-  .app-main {
-    /* 84 = navbar + tags-view = 50 + 34 */
-    min-height: calc(100vh - 84px);
-  }
-
-  .fixed-header+.app-main {
-    padding-top: 84px;
-  }
-}
-</style>
diff --git a/src/layout/components/Navbar/index.vue b/src/layout/components/Navbar/index.vue
deleted file mode 100644
index 5de0aff..0000000
--- a/src/layout/components/Navbar/index.vue
+++ /dev/null
@@ -1,195 +0,0 @@
-<!--
-#
-# MIT License
-#
-# Copyright (c) 2018 Chong Guo
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-#
--->
-
-<template>
-  <div class="navbar">
-    <hamburger
-      id="hamburger-container"
-      :is-active="sidebar.opened"
-      class="hamburger-container"
-      @toggleClick="toggleSideBar"
-    />
-    <breadcrumb
-      id="breadcrumb-container"
-      class="breadcrumb-container"
-    />
-    <div class="right-menu">
-      <template v-if="device!=='mobile'">
-        <screenfull class="right-menu-item hover-effect" />
-        <lang-select class="right-menu-item hover-effect" />
-      </template>
-      <el-dropdown
-        class="avatar-container right-menu-item hover-effect"
-        trigger="click"
-      >
-        <div class="avatar-wrapper">
-          <img
-            :src="avatar"
-            class="user-avatar"
-          >
-          <i class="el-icon-caret-bottom" />
-        </div>
-        <el-dropdown-menu slot="dropdown">
-          <el-dropdown-item divided>
-            <span
-              style="display:block;"
-              @click="logout"
-            >{{ $t('navbar.logOut') }}</span>
-          </el-dropdown-item>
-        </el-dropdown-menu>
-      </el-dropdown>
-    </div>
-  </div>
-</template>
-
-<script lang="ts">
-import { Component, Vue } from 'vue-property-decorator'
-import { AppModule } from '@/store/modules/app'
-import { UserModule } from '@/store/modules/user'
-import Breadcrumb from '@/components/Breadcrumb/index.vue'
-import Hamburger from '@/components/Hamburger/index.vue'
-import HeaderSearch from '@/components/HeaderSearch/index.vue'
-import LangSelect from '@/components/LangSelect/index.vue'
-import Screenfull from '@/components/Screenfull/index.vue'
-
-@Component({
-  name: 'Navbar',
-  components: {
-    Breadcrumb,
-    Hamburger,
-    HeaderSearch,
-    LangSelect,
-    Screenfull
-  }
-})
-export default class extends Vue {
-  get sidebar() {
-    return AppModule.sidebar
-  }
-
-  get device() {
-    return AppModule.device.toString()
-  }
-
-  get avatar() {
-    return UserModule.avatar
-  }
-
-  private toggleSideBar() {
-    AppModule.ToggleSideBar(false)
-  }
-
-  private async logout() {
-    await UserModule.LogOut()
-    this.$router.push(`/login?redirect=${this.$route.fullPath}`)
-  }
-}
-</script>
-
-<style lang="scss" scoped>
-.navbar {
-  height: 50px;
-  overflow: hidden;
-  position: relative;
-  background: #fff;
-  box-shadow: 0 1px 4px rgba(0,21,41,.08);
-
-  .hamburger-container {
-    line-height: 46px;
-    height: 100%;
-    float: left;
-    padding: 0 15px;
-    cursor: pointer;
-    transition: background .3s;
-    -webkit-tap-highlight-color:transparent;
-
-    &:hover {
-      background: rgba(0, 0, 0, .025)
-    }
-  }
-
-  .breadcrumb-container {
-    float: left;
-  }
-
-  .errLog-container {
-    display: inline-block;
-    vertical-align: top;
-  }
-
-  .right-menu {
-    float: right;
-    height: 100%;
-    line-height: 50px;
-
-    &:focus {
-      outline: none;
-    }
-
-    .right-menu-item {
-      display: inline-block;
-      padding: 0 8px;
-      height: 100%;
-      font-size: 18px;
-      color: #5a5e66;
-      vertical-align: text-bottom;
-
-      &.hover-effect {
-        cursor: pointer;
-        transition: background .3s;
-
-        &:hover {
-          background: rgba(0, 0, 0, .025)
-        }
-      }
-    }
-
-    .avatar-container {
-      margin-right: 30px;
-
-      .avatar-wrapper {
-        margin-top: 5px;
-        position: relative;
-
-        .user-avatar {
-          cursor: pointer;
-          width: 40px;
-          height: 40px;
-          border-radius: 10px;
-        }
-
-        .el-icon-caret-bottom {
-          cursor: pointer;
-          position: absolute;
-          right: -20px;
-          top: 25px;
-          font-size: 12px;
-        }
-      }
-    }
-  }
-}
-</style>
diff --git a/src/layout/components/Sidebar/SidebarItem.vue b/src/layout/components/Sidebar/SidebarItem.vue
deleted file mode 100644
index c98fbb0..0000000
--- a/src/layout/components/Sidebar/SidebarItem.vue
+++ /dev/null
@@ -1,209 +0,0 @@
-<!--
-#
-# MIT License
-#
-# Copyright (c) 2018 Chong Guo
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-#
--->
-
-<template>
-  <div
-    v-if="!item.meta || !item.meta.hidden"
-    :class="['menu-wrapper', isCollapse ? 'simple-mode' : 'full-mode', {'first-level': isFirstLevel}]"
-  >
-    <template v-if="!alwaysShowRootMenu && theOnlyOneChild && !theOnlyOneChild.children">
-      <sidebar-item-link
-        v-if="theOnlyOneChild.meta"
-        :to="resolvePath(theOnlyOneChild.path)"
-      >
-        <el-menu-item
-          :index="resolvePath(theOnlyOneChild.path)"
-          :class="{'submenu-title-noDropdown': isFirstLevel}"
-        >
-          <svg-icon
-            v-if="theOnlyOneChild.meta.icon"
-            :name="theOnlyOneChild.meta.icon"
-          />
-          <span
-            v-if="theOnlyOneChild.meta.title"
-            slot="title"
-          >{{ $t('route.' + theOnlyOneChild.meta.title) }}</span>
-        </el-menu-item>
-      </sidebar-item-link>
-    </template>
-    <el-submenu
-      v-else
-      :index="resolvePath(item.path)"
-      popper-append-to-body
-    >
-      <template slot="title">
-        <svg-icon
-          v-if="item.meta && item.meta.icon"
-          :name="item.meta.icon"
-        />
-        <span
-          v-if="item.meta && item.meta.title"
-          slot="title"
-        >{{ $t('route.' + item.meta.title) }}</span>
-      </template>
-      <template v-if="item.children">
-        <sidebar-item
-          v-for="child in item.children"
-          :key="child.path"
-          :item="child"
-          :is-collapse="isCollapse"
-          :is-first-level="false"
-          :base-path="resolvePath(child.path)"
-          class="nest-menu"
-        />
-      </template>
-    </el-submenu>
-  </div>
-</template>
-
-<script lang="ts">
-import path from 'path'
-import { Component, Prop, Vue } from 'vue-property-decorator'
-import { Route, RouteConfig } from 'vue-router'
-import { isExternal } from '@/utils/validate'
-import SidebarItemLink from './SidebarItemLink.vue'
-
-@Component({
-  // Set 'name' here to prevent uglifyjs from causing recursive component not work
-  // See https://medium.com/haiiro-io/element-component-name-with-vue-class-component-f3b435656561 for detail
-  name: 'SidebarItem',
-  components: {
-    SidebarItemLink
-  }
-})
-export default class extends Vue {
-  @Prop({ required: true }) private item!: RouteConfig
-  @Prop({ default: false }) private isCollapse!: boolean
-  @Prop({ default: true }) private isFirstLevel!: boolean
-  @Prop({ default: '' }) private basePath!: string
-
-  get alwaysShowRootMenu() {
-    if (this.item.meta && this.item.meta.alwaysShow) {
-      return true
-    }
-    return false
-  }
-
-  get showingChildNumber() {
-    if (this.item.children) {
-      const showingChildren = this.item.children.filter((item) => {
-        if (item.meta && item.meta.hidden) {
-          return false
-        } else {
-          return true
-        }
-      })
-      return showingChildren.length
-    }
-    return 0
-  }
-
-  get theOnlyOneChild() {
-    if (this.showingChildNumber > 1) {
-      return null
-    }
-    if (this.item.children) {
-      for (let child of this.item.children) {
-        if (!child.meta || !child.meta.hidden) {
-          return child
-        }
-      }
-    }
-    // If there is no children, return itself with path removed,
-    // because this.basePath already conatins item's path information
-    return { ...this.item, path: '' }
-  }
-
-  private resolvePath(routePath: string) {
-    if (isExternal(routePath)) {
-      return routePath
-    }
-    if (isExternal(this.basePath)) {
-      return this.basePath
-    }
-    return path.resolve(this.basePath, routePath)
-  }
-}
-</script>
-
-<style lang="scss">
-.el-submenu.is-active > .el-submenu__title {
-  color: $subMenuActiveText !important;
-}
-
-.full-mode {
-  .nest-menu .el-submenu>.el-submenu__title,
-  .el-submenu .el-menu-item {
-    min-width: $sideBarWidth !important;
-    background-color: $subMenuBg !important;
-
-    &:hover {
-      background-color: $subMenuHover !important;
-    }
-  }
-}
-
-.simple-mode {
-  &.first-level {
-    .submenu-title-noDropdown {
-      padding: 0 !important;
-      position: relative;
-
-      .el-tooltip {
-        padding: 0 !important;
-      }
-    }
-
-    .el-submenu {
-      overflow: hidden;
-
-      &>.el-submenu__title {
-        padding: 0px !important;
-
-        .el-submenu__icon-arrow {
-          display: none;
-        }
-
-        &>span {
-          visibility: hidden;
-        }
-      }
-    }
-  }
-}
-</style>
-
-<style lang="scss" scoped>
-.svg-icon {
-  margin-right: 16px;
-}
-
-.simple-mode {
-  .svg-icon {
-    margin-left: 20px;
-  }
-}
-</style>
diff --git a/src/layout/components/Sidebar/SidebarItemLink.vue b/src/layout/components/Sidebar/SidebarItemLink.vue
deleted file mode 100644
index 7c80a86..0000000
--- a/src/layout/components/Sidebar/SidebarItemLink.vue
+++ /dev/null
@@ -1,56 +0,0 @@
-<!--
-#
-# MIT License
-#
-# Copyright (c) 2018 Chong Guo
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-#
--->
-
-<template>
-  <a
-    v-if="isExternal(to)"
-    :href="to"
-    target="_blank"
-    rel="noopener"
-  >
-    <slot />
-  </a>
-  <router-link
-    v-else
-    :to="to"
-  >
-    <slot />
-  </router-link>
-</template>
-
-<script lang="ts">
-import { Component, Prop, Vue } from 'vue-property-decorator'
-import { isExternal } from '@/utils/validate'
-
-@Component({
-  name: 'SidebarItemLink'
-})
-export default class extends Vue {
-  @Prop({ required: true }) private to!: string
-
-  private isExternal = isExternal
-}
-</script>
diff --git a/src/layout/components/Sidebar/SidebarLogo.vue b/src/layout/components/Sidebar/SidebarLogo.vue
deleted file mode 100644
index 4ddf188..0000000
--- a/src/layout/components/Sidebar/SidebarLogo.vue
+++ /dev/null
@@ -1,123 +0,0 @@
-<!--
-#
-# MIT License
-#
-# Copyright (c) 2018 Chong Guo
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-#
--->
-
-<template>
-  <div
-    class="sidebar-logo-container"
-    :class="{'collapse': collapse}"
-  >
-    <transition name="sidebarLogoFade">
-      <router-link
-        v-if="collapse"
-        key="collapse"
-        class="sidebar-logo-link"
-        to="/"
-      >
-        <img
-          src="favicon.ico"
-          class="sidebar-logo"
-        >
-      </router-link>
-      <router-link
-        v-else
-        key="expand"
-        class="sidebar-logo-link"
-        to="/"
-      >
-        <img
-          src="favicon.ico"
-          class="sidebar-logo"
-        >
-        <h1 class="sidebar-title">
-          {{ title }}
-        </h1>
-      </router-link>
-    </transition>
-  </div>
-</template>
-
-<script lang="ts">
-import { Component, Prop, Vue } from 'vue-property-decorator'
-
-@Component({
-  name: 'SidebarLogo'
-})
-export default class extends Vue {
-  @Prop({ required: true }) private collapse!: boolean
-
-  private title = 'APISIX'
-}
-</script>
-
-<style lang="scss" scoped>
-.sidebarLogoFade-enter-active {
-  transition: opacity 1.5s;
-}
-
-.sidebarLogoFade-enter,
-.sidebarLogoFade-leave-to {
-  opacity: 0;
-}
-
-.sidebar-logo-container {
-  position: relative;
-  width: 100%;
-  height: 50px;
-  line-height: 50px;
-  background: #304156f5;
-  text-align: center;
-  overflow: hidden;
-
-  & .sidebar-logo-link {
-    height: 100%;
-    width: 100%;
-
-    & .sidebar-logo {
-      width: 32px;
-      height: 32px;
-      vertical-align: middle;
-      margin-right: 12px;
-    }
-
-    & .sidebar-title {
-      display: inline-block;
-      margin: 0;
-      color: #fff;
-      font-weight: 600;
-      line-height: 50px;
-      font-size: 14px;
-      font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif;
-      vertical-align: middle;
-    }
-  }
-
-  &.collapse {
-    .sidebar-logo {
-      margin-right: 0px;
-    }
-  }
-}
-</style>
diff --git a/src/layout/components/Sidebar/index.vue b/src/layout/components/Sidebar/index.vue
deleted file mode 100644
index cfd367e..0000000
--- a/src/layout/components/Sidebar/index.vue
+++ /dev/null
@@ -1,156 +0,0 @@
-<!--
-#
-# MIT License
-#
-# Copyright (c) 2018 Chong Guo
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-#
--->
-
-<template>
-  <div :class="{'has-logo': showLogo}">
-    <sidebar-logo
-      v-if="showLogo"
-      :collapse="isCollapse"
-    />
-    <el-scrollbar wrap-class="scrollbar-wrapper">
-      <el-menu
-        :default-active="activeMenu"
-        :collapse="isCollapse"
-        :background-color="variables.menuBg"
-        :text-color="variables.menuText"
-        :active-text-color="menuActiveTextColor"
-        :unique-opened="false"
-        :collapse-transition="false"
-        mode="vertical"
-      >
-        <sidebar-item
-          v-for="route in routes"
-          :key="route.path"
-          :item="route"
-          :base-path="route.path"
-          :is-collapse="isCollapse"
-        />
-      </el-menu>
-    </el-scrollbar>
-  </div>
-</template>
-
-<script lang="ts">
-import { Component, Prop, Vue } from 'vue-property-decorator'
-import { AppModule } from '@/store/modules/app'
-import { PermissionModule } from '@/store/modules/permission'
-import { SettingsModule } from '@/store/modules/settings'
-import SidebarItem from './SidebarItem.vue'
-import SidebarLogo from './SidebarLogo.vue'
-import variables from '@/styles/_variables.scss'
-
-@Component({
-  name: 'SideBar',
-  components: {
-    SidebarItem,
-    SidebarLogo
-  }
-})
-export default class extends Vue {
-  get sidebar() {
-    return AppModule.sidebar
-  }
-
-  get routes() {
-    return PermissionModule.routes
-  }
-
-  get showLogo() {
-    return SettingsModule.showSidebarLogo
-  }
-
-  get menuActiveTextColor() {
-    if (SettingsModule.sidebarTextTheme) {
-      return SettingsModule.theme
-    } else {
-      return variables.menuActiveText
-    }
-  }
-
-  get variables() {
-    return variables
-  }
-
-  get activeMenu() {
-    const route = this.$route
-    const { meta, path } = route
-    // if set path, the sidebar will highlight the path you set
-    if (meta.activeMenu) {
-      return meta.activeMenu
-    }
-    return path
-  }
-
-  get isCollapse() {
-    return !this.sidebar.opened
-  }
-}
-</script>
-
-<style lang="scss">
-.sidebar-container {
-  // reset element-ui css
-  .horizontal-collapse-transition {
-    transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
-  }
-
-  .scrollbar-wrapper {
-    overflow-x: hidden !important;
-  }
-
-  .el-scrollbar__view {
-    height: 100%
-  }
-
-  .el-scrollbar__bar {
-    &.is-vertical {
-      right: 0px;
-    }
-
-    &.is-horizontal {
-      display: none;
-    }
-  }
-}
-</style>
-
-<style lang="scss" scoped>
-.el-scrollbar {
-  height: 100%
-}
-
-.has-logo {
-  .el-scrollbar {
-    height: calc(100% - 50px);
-  }
-}
-
-.el-menu {
-  border: none;
-  height: 100%;
-  width: 100% !important;
-}
-</style>
diff --git a/src/layout/components/TagsView/ScrollPane.vue b/src/layout/components/TagsView/ScrollPane.vue
deleted file mode 100644
index 77c61e1..0000000
--- a/src/layout/components/TagsView/ScrollPane.vue
+++ /dev/null
@@ -1,113 +0,0 @@
-<!--
-#
-# MIT License
-#
-# Copyright (c) 2018 Chong Guo
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-#
--->
-
-<template>
-  <el-scrollbar
-    ref="scrollContainer"
-    :vertical="false"
-    class="scroll-container"
-    @wheel.native.prevent="handleScroll"
-  >
-    <slot />
-  </el-scrollbar>
-</template>
-
-<script lang="ts">
-import { Component, Vue } from 'vue-property-decorator'
-
-const tagSpacing = 4
-
-@Component({
-  name: 'ScrollPane'
-})
-export default class extends Vue {
-  private handleScroll(e: MouseWheelEvent) {
-    const eventDelta = (e as any).wheelDelta || -e.deltaY * 40
-    const scrollContainer = this.$refs.scrollContainer as Vue
-    const scrollWrapper = scrollContainer.$refs.wrap as HTMLElement
-    scrollWrapper.scrollLeft = scrollWrapper.scrollLeft + eventDelta / 4
-  }
-
-  public moveToTarget(currentTag: HTMLElement) {
-    const scrollContainer = this.$refs.scrollContainer as Vue
-    const container = scrollContainer.$el as HTMLElement
-    const containerWidth = container.offsetWidth
-    const scrollWrapper = scrollContainer.$refs.wrap as HTMLElement
-    const tagList = this.$parent.$refs.tag as any[]
-
-    let firstTag = null
-    let lastTag = null
-
-    // find first tag and last tag
-    if (tagList.length > 0) {
-      firstTag = tagList[0]
-      lastTag = tagList[tagList.length - 1]
-    }
-
-    if (firstTag === currentTag) {
-      scrollWrapper.scrollLeft = 0
-    } else if (lastTag === currentTag) {
-      scrollWrapper.scrollLeft = scrollWrapper.scrollWidth - containerWidth
-    } else {
-      // find preTag and nextTag
-      const currentIndex = tagList.findIndex(item => item === currentTag)
-      const prevTag = tagList[currentIndex - 1]
-      const nextTag = tagList[currentIndex + 1]
-      // the tag's offsetLeft after of nextTag
-      const afterNextTagOffsetLeft = nextTag.$el.offsetLeft + nextTag.$el.offsetWidth + tagSpacing
-      // the tag's offsetLeft before of prevTag
-      const beforePrevTagOffsetLeft = prevTag.$el.offsetLeft - tagSpacing
-
-      if (afterNextTagOffsetLeft > scrollWrapper.scrollLeft + containerWidth) {
-        scrollWrapper.scrollLeft = afterNextTagOffsetLeft - containerWidth
-      } else if (beforePrevTagOffsetLeft < scrollWrapper.scrollLeft) {
-        scrollWrapper.scrollLeft = beforePrevTagOffsetLeft
-      }
-    }
-  }
-}
-</script>
-
-<style lang="scss">
-.scroll-container {
-  .el-scrollbar__bar {
-    bottom: 0px;
-  }
-
-  .el-scrollbar__wrap {
-    height: 49px;
-  }
-}
-</style>
-
-<style lang="scss" scoped>
-.scroll-container {
-  white-space: nowrap;
-  position: relative;
-  overflow: hidden;
-  width: 100%;
-}
-</style>
diff --git a/src/layout/components/TagsView/index.vue b/src/layout/components/TagsView/index.vue
deleted file mode 100644
index d87419c..0000000
--- a/src/layout/components/TagsView/index.vue
+++ /dev/null
@@ -1,359 +0,0 @@
-<!--
-#
-# MIT License
-#
-# Copyright (c) 2018 Chong Guo
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-#
--->
-
-<template>
-  <div
-    id="tags-view-container"
-    class="tags-view-container"
-  >
-    <scroll-pane
-      ref="scrollPane"
-      class="tags-view-wrapper"
-    >
-      <router-link
-        v-for="tag in visitedViews"
-        ref="tag"
-        :key="tag.path"
-        :class="isActive(tag) ? 'active' : ''"
-        :to="{path: tag.path, query: tag.query, fullPath: tag.fullPath}"
-        tag="span"
-        class="tags-view-item"
-        @click.middle.native="closeSelectedTag(tag)"
-        @contextmenu.prevent.native="openMenu(tag, $event)"
-      >
-        {{ $t('route.' + tag.meta.title) }}
-        <span
-          v-if="!tag.meta.affix"
-          class="el-icon-close"
-          @click.prevent.stop="closeSelectedTag(tag)"
-        />
-      </router-link>
-    </scroll-pane>
-    <ul
-      v-show="visible"
-      :style="{left: left+'px', top: top+'px'}"
-      class="contextmenu"
-    >
-      <li @click="refreshSelectedTag(selectedTag)">
-        {{ $t('tagsView.refresh') }}
-      </li>
-      <li
-        v-if="!(selectedTag.meta&&selectedTag.meta.affix)"
-        @click="closeSelectedTag(selectedTag)"
-      >
-        {{
-          $t('tagsView.close') }}
-      </li>
-      <li @click="closeOthersTags">
-        {{ $t('tagsView.closeOthers') }}
-      </li>
-      <li @click="closeAllTags(selectedTag)">
-        {{ $t('tagsView.closeAll') }}
-      </li>
-    </ul>
-  </div>
-</template>
-
-<script lang="ts">
-import path from 'path'
-import { Component, Vue, Watch } from 'vue-property-decorator'
-import VueRouter, { Route, RouteRecord, RouteConfig } from 'vue-router'
-import { PermissionModule } from '@/store/modules/permission'
-import { TagsViewModule, ITagView } from '@/store/modules/tags-view'
-import ScrollPane from './ScrollPane.vue'
-
-@Component({
-  name: 'TagsView',
-  components: {
-    ScrollPane
-  }
-})
-export default class extends Vue {
-  private visible: boolean = false
-  private top: number = 0
-  private left: number = 0
-  private selectedTag: ITagView = {}
-  private affixTags: ITagView[] = []
-
-  get visitedViews() {
-    return TagsViewModule.visitedViews
-  }
-
-  get routes() {
-    return PermissionModule.routes
-  }
-
-  @Watch('$route')
-  private onRouteChange() {
-    this.addTags()
-    this.moveToCurrentTag()
-  }
-
-  @Watch('visible')
-  private onVisibleChange(value: boolean) {
-    if (value) {
-      document.body.addEventListener('click', this.closeMenu)
-    } else {
-      document.body.removeEventListener('click', this.closeMenu)
-    }
-  }
-
-  mounted() {
-    this.initTags()
-    this.addTags()
-  }
-
-  private isActive(route: ITagView) {
-    return route.path === this.$route.path
-  }
-
-  private filterAffixTags(routes: RouteConfig[], basePath = '/') {
-    let tags: ITagView[] = []
-    routes.forEach(route => {
-      if (route.meta && route.meta.affix) {
-        const tagPath = path.resolve(basePath, route.path)
-        tags.push({
-          fullPath: tagPath,
-          path: tagPath,
-          name: route.name,
-          meta: { ...route.meta }
-        })
-      }
-      if (route.children) {
-        const childTags = this.filterAffixTags(route.children, route.path)
-        if (childTags.length >= 1) {
-          tags = [...tags, ...childTags]
-        }
-      }
-    })
-    return tags
-  }
-
-  private initTags() {
-    this.affixTags = this.filterAffixTags(this.routes)
-    for (const tag of this.affixTags) {
-      // Must have tag name
-      if (tag.name) {
-        TagsViewModule.addVisitedView(tag)
-      }
-    }
-  }
-
-  private addTags() {
-    const { name } = this.$route
-    if (name) {
-      TagsViewModule.addView(this.$route)
-    }
-    return false
-  }
-
-  private moveToCurrentTag() {
-    const tags = this.$refs.tag as any[] // TODO: better typescript support for router-link
-    this.$nextTick(() => {
-      for (const tag of tags) {
-        if ((tag.to as ITagView).path === this.$route.path) {
-          (this.$refs.scrollPane as ScrollPane).moveToTarget(tag as any)
-          // When query is different then update
-          if ((tag.to as ITagView).fullPath !== this.$route.fullPath) {
-            TagsViewModule.updateVisitedView(this.$route)
-          }
-          break
-        }
-      }
-    })
-  }
-
-  private refreshSelectedTag(view: ITagView) {
-    TagsViewModule.delCachedView(view)
-    const { fullPath } = view
-    this.$nextTick(() => {
-      this.$router.replace({
-        path: '/redirect' + fullPath
-      })
-    })
-  }
-
-  private closeSelectedTag(view: ITagView) {
-    TagsViewModule.delView(view)
-    if (this.isActive(view)) {
-      this.toLastView(TagsViewModule.visitedViews, view)
-    }
-  }
-
-  private closeOthersTags() {
-    this.$router.push(this.selectedTag)
-    TagsViewModule.delOthersViews(this.selectedTag)
-    this.moveToCurrentTag()
-  }
-
-  private closeAllTags(view: ITagView) {
-    TagsViewModule.delAllViews()
-    if (this.affixTags.some(tag => tag.path === this.$route.path)) {
-      return
-    }
-    this.toLastView(TagsViewModule.visitedViews, view)
-  }
-
-  private toLastView(visitedViews: ITagView[], view: ITagView) {
-    const latestView = visitedViews.slice(-1)[0]
-    if (latestView) {
-      this.$router.push(latestView)
-    } else {
-      // Default redirect to the home page if there is no tags-view, adjust it if you want
-      if (view.name === 'Dashboard') {
-        // to reload home page
-        this.$router.replace({ path: '/redirect' + view.fullPath })
-      } else {
-        this.$router.push('/')
-      }
-    }
-  }
-
-  private openMenu(tag: ITagView, e: MouseEvent) {
-    const menuMinWidth = 105
-    const offsetLeft = this.$el.getBoundingClientRect().left // container margin left
-    const offsetWidth = (this.$el as HTMLElement).offsetWidth // container width
-    const maxLeft = offsetWidth - menuMinWidth // left boundary
-    const left = e.clientX - offsetLeft + 15 // 15: margin right
-    if (left > maxLeft) {
-      this.left = maxLeft
-    } else {
-      this.left = left
-    }
-    this.top = e.clientY
-    this.visible = true
-    this.selectedTag = tag
-  }
-
-  private closeMenu() {
-    this.visible = false
-  }
-}
-</script>
-
-<style lang="scss">
-// Reset element css of el-icon-close
-.tags-view-wrapper {
-  .tags-view-item {
-    .el-icon-close {
-      width: 16px;
-      height: 16px;
-      vertical-align: 2px;
-      border-radius: 50%;
-      text-align: center;
-      transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
-      transform-origin: 100% 50%;
-
-      &:before {
-        transform: scale(0.6);
-        display: inline-block;
-        vertical-align: -3px;
-      }
-
-      &:hover {
-        background-color: #b4bccc;
-        color: #fff;
-      }
-    }
-  }
-}
-
-</style>
-<style lang="scss" scoped>
-.tags-view-container {
-  height: 34px;
-  width: 100%;
-  background: #fff;
-  border-bottom: 1px solid #d8dce5;
-  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .12), 0 0 3px 0 rgba(0, 0, 0, .04);
-
-  .tags-view-wrapper {
-    .tags-view-item {
-      display: inline-block;
-      position: relative;
-      cursor: pointer;
-      height: 26px;
-      line-height: 26px;
-      border: 1px solid #d8dce5;
-      color: #495060;
-      background: #fff;
-      padding: 0 8px;
-      font-size: 12px;
-      margin-left: 5px;
-      margin-top: 4px;
-
-      &:first-of-type {
-        margin-left: 15px;
-      }
-
-      &:last-of-type {
-        margin-right: 15px;
-      }
-
-      &.active {
-        background-color: #42b983;
-        color: #fff;
-        border-color: #42b983;
-
-        &::before {
-          content: '';
-          background: #fff;
-          display: inline-block;
-          width: 8px;
-          height: 8px;
-          border-radius: 50%;
-          position: relative;
-          margin-right: 2px;
-        }
-      }
-    }
-  }
-
-  .contextmenu {
-    margin: 0;
-    background: #fff;
-    z-index: 3000;
-    position: absolute;
-    list-style-type: none;
-    padding: 5px 0;
-    border-radius: 4px;
-    font-size: 12px;
-    font-weight: 400;
-    color: #333;
-    box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, .3);
-
-    li {
-      margin: 0;
-      padding: 7px 16px;
-      cursor: pointer;
-
-      &:hover {
-        background: #eee;
-      }
-    }
-  }
-}
-</style>
diff --git a/src/layout/components/index.ts b/src/layout/components/index.ts
deleted file mode 100644
index ec44cf9..0000000
--- a/src/layout/components/index.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-/**
- * MIT License
- *
- * Copyright (c) 2018 Chong Guo
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-export { default as AppMain } from './AppMain.vue'
-export { default as Navbar } from './Navbar/index.vue'
-export { default as Sidebar } from './Sidebar/index.vue'
-export { default as TagsView } from './TagsView/index.vue'
diff --git a/src/layout/index.vue b/src/layout/index.vue
deleted file mode 100644
index 7379e7d..0000000
--- a/src/layout/index.vue
+++ /dev/null
@@ -1,192 +0,0 @@
-<!--
-#
-# MIT License
-#
-# Copyright (c) 2018 Chong Guo
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-#
--->
-
-<template>
-  <div
-    :class="classObj"
-    class="app-wrapper"
-  >
-    <div
-      v-if="classObj.mobile && sidebar.opened"
-      class="drawer-bg"
-      @click="handleClickOutside"
-    />
-    <sidebar class="sidebar-container" />
-    <div
-      :class="{hasTagsView: showTagsView}"
-      class="main-container"
-    >
-      <div :class="{'fixed-header': fixedHeader}">
-        <navbar />
-        <tags-view v-if="showTagsView" />
-      </div>
-      <app-main />
-    </div>
-  </div>
-</template>
-
-<script lang="ts">
-import { Component } from 'vue-property-decorator'
-import { mixins } from 'vue-class-component'
-import { DeviceType, AppModule } from '@/store/modules/app'
-import { SettingsModule } from '@/store/modules/settings'
-import { AppMain, Navbar, Sidebar, TagsView } from './components'
-import ResizeMixin from './mixin/resize'
-
-@Component({
-  name: 'Layout',
-  components: {
-    AppMain,
-    Navbar,
-    Sidebar,
-    TagsView
-  }
-})
-export default class extends mixins(ResizeMixin) {
-  get classObj() {
-    return {
-      hideSidebar: !this.sidebar.opened,
-      openSidebar: this.sidebar.opened,
-      withoutAnimation: this.sidebar.withoutAnimation,
-      mobile: this.device === DeviceType.Mobile
-    }
-  }
-
-  get showSettings() {
-    return SettingsModule.showSettings
-  }
-
-  get showTagsView() {
-    return SettingsModule.showTagsView
-  }
-
-  get fixedHeader() {
-    return SettingsModule.fixedHeader
-  }
-
-  private handleClickOutside() {
-    AppModule.CloseSideBar(false)
-  }
-}
-</script>
-
-<style lang="scss" scoped>
-.app-wrapper {
-  @include clearfix;
-  position: relative;
-  height: 100%;
-  width: 100%;
-}
-
-.drawer-bg {
-  background: #000;
-  opacity: 0.3;
-  width: 100%;
-  top: 0;
-  height: 100%;
-  position: absolute;
-  z-index: 999;
-}
-
-.main-container {
-  min-height: 100%;
-  transition: margin-left .28s;
-  margin-left: $sideBarWidth;
-  position: relative;
-}
-
-.sidebar-container {
-  transition: width 0.28s;
-  width: $sideBarWidth !important;
-  height: 100%;
-  position: fixed;
-  font-size: 0px;
-  top: 0;
-  bottom: 0;
-  left: 0;
-  z-index: 1001;
-  overflow: hidden;
-}
-
-.fixed-header {
-  position: fixed;
-  top: 0;
-  right: 0;
-  z-index: 9;
-  width: calc(100% - #{$sideBarWidth});
-  transition: width 0.28s;
-}
-
-.hideSidebar {
-  .main-container {
-    margin-left: 54px;
-  }
-
-  .sidebar-container {
-    width: 54px !important;
-  }
-
-  .fixed-header {
-    width: calc(100% - 54px)
-  }
-}
-
-/* for mobile response 适配移动端 */
-.mobile {
-  .main-container {
-    margin-left: 0px;
-  }
-
-  .sidebar-container {
-    transition: transform .28s;
-    width: $sideBarWidth !important;
-  }
-
-  &.openSidebar {
-    position: fixed;
-    top: 0;
-  }
-
-  &.hideSidebar {
-    .sidebar-container {
-      pointer-events: none;
-      transition-duration: 0.3s;
-      transform: translate3d(-$sideBarWidth, 0, 0);
-    }
-  }
-
-  .fixed-header {
-    width: 100%;
-  }
-}
-
-.withoutAnimation {
-  .main-container,
-  .sidebar-container {
-    transition: none;
-  }
-}
-</style>
diff --git a/src/layout/mixin/resize.ts b/src/layout/mixin/resize.ts
deleted file mode 100644
index 8935e69..0000000
--- a/src/layout/mixin/resize.ts
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * MIT License
- *
- * Copyright (c) 2018 Chong Guo
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-import { Component, Vue, Watch } from 'vue-property-decorator'
-import { AppModule, DeviceType } from '@/store/modules/app'
-
-const WIDTH = 992 // refer to Bootstrap's responsive design
-
-@Component({
-  name: 'ResizeMixin'
-})
-export default class extends Vue {
-  get device() {
-    return AppModule.device
-  }
-
-  get sidebar() {
-    return AppModule.sidebar
-  }
-
-  @Watch('$route')
-  private onRouteChange() {
-    if (this.device === DeviceType.Mobile && this.sidebar.opened) {
-      AppModule.CloseSideBar(false)
-    }
-  }
-
-  beforeMount() {
-    window.addEventListener('resize', this.resizeHandler)
-  }
-
-  mounted() {
-    const isMobile = this.isMobile()
-    if (isMobile) {
-      AppModule.ToggleDevice(DeviceType.Mobile)
-      AppModule.CloseSideBar(true)
-    }
-  }
-
-  beforeDestroy() {
-    window.removeEventListener('resize', this.resizeHandler)
-  }
-
-  private isMobile() {
-    const rect = document.body.getBoundingClientRect()
-    return rect.width - 1 < WIDTH
-  }
-
-  private resizeHandler() {
-    if (!document.hidden) {
-      const isMobile = this.isMobile()
-      AppModule.ToggleDevice(isMobile ? DeviceType.Mobile : DeviceType.Desktop)
-      if (isMobile) {
-        AppModule.CloseSideBar(true)
-      }
-    }
-  }
-}
diff --git a/src/main.ts b/src/main.ts
deleted file mode 100644
index 88e5dec..0000000
--- a/src/main.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.
- */
-
-import Vue from 'vue'
-
-import 'normalize.css'
-import ElementUI from 'element-ui'
-import SvgIcon from 'vue-svgicon'
-import '@/styles/index.scss'
-import Component from 'vue-class-component'
-
-import App from '@/App.vue'
-import store from '@/store'
-import { AppModule } from '@/store/modules/app'
-import router from '@/router'
-import i18n from '@/lang'
-import '@/permission'
-
-Vue.use(ElementUI, {
-  size: AppModule.size, // Set element-ui default size
-  i18n: (key: string, value: string) => i18n.t(key, value)
-})
-
-Vue.use(SvgIcon, {
-  tagName: 'svg-icon',
-  defaultWidth: '1em',
-  defaultHeight: '1em'
-})
-
-Vue.config.productionTip = false
-
-Component.registerHooks([
-  'beforeRouteEnter',
-  'beforeRouteLeave',
-  'beforeRouteUpdate'
-])
-
-new Vue({
-  router,
-  store,
-  i18n,
-  render: (h) => h(App)
-}).$mount('#app')
diff --git a/src/permission.ts b/src/permission.ts
deleted file mode 100644
index b5194aa..0000000
--- a/src/permission.ts
+++ /dev/null
@@ -1,102 +0,0 @@
-/**
- * MIT License
- *
- * Copyright (c) 2018 Chong Guo
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
-*/
-
-import router from './router'
-import NProgress from 'nprogress'
-import 'nprogress/nprogress.css'
-import { Message } from 'element-ui'
-import { Route } from 'vue-router'
-import { UserModule } from '@/store/modules/user'
-import { PermissionModule } from '@/store/modules/permission'
-import i18n from '@/lang' // Internationalization
-import settings from './settings'
-
-NProgress.configure({ showSpinner: false })
-
-const whiteList = ['/login', '/auth-redirect']
-
-const getPageTitle = (key: string) => {
-  const hasKey = i18n.te(`route.${key}`)
-  if (hasKey) {
-    const pageName = i18n.t(`route.${key}`)
-    return `${pageName} - ${settings.title}`
-  }
-  return `${settings.title}`
-}
-
-router.beforeEach(async(to: Route, _: Route, next: any) => {
-  // Start progress bar
-  NProgress.start()
-
-  // Determine whether the user has logged in
-  if (UserModule.token) {
-    if (to.path === '/login') {
-      // If is logged in, redirect to the home page
-      next({ path: '/' })
-      NProgress.done()
-    } else {
-      // Check whether the user has obtained his permission roles
-      if (UserModule.roles.length === 0) {
-        try {
-          // Note: roles must be a object array! such as: ['admin'] or ['developer', 'editor']
-          await UserModule.GetUserInfo()
-          const roles = UserModule.roles
-          // Generate accessible routes map based on role
-          PermissionModule.GenerateRoutes(roles)
-          // Dynamically add accessible routes
-          router.addRoutes(PermissionModule.dynamicRoutes)
-          // Hack: ensure addRoutes is complete
-          // Set the replace: true, so the navigation will not leave a history record
-          next({ ...to, replace: true })
-        } catch (err) {
-          // Remove token and redirect to login page
-          UserModule.ResetToken()
-          Message.error(err || 'Has Error')
-          next(`/login?redirect=${to.path}`)
-          NProgress.done()
-        }
-      } else {
-        next()
-      }
-    }
-  } else {
-    // Has no token
-    if (whiteList.indexOf(to.path) !== -1) {
-      // In the free login whitelist, go directly
-      next()
-    } else {
-      // Other pages that do not have permission to access are redirected to the login page.
-      next(`/login?redirect=${to.path}`)
-      NProgress.done()
-    }
-  }
-})
-
-router.afterEach((to: Route) => {
-  // Finish progress bar
-  NProgress.done()
-
-  // set page title
-  document.title = getPageTitle(to.meta.title)
-})
diff --git a/src/router/index.ts b/src/router/index.ts
deleted file mode 100644
index 2ab4a5d..0000000
--- a/src/router/index.ts
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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.
- */
-
-import Vue from 'vue'
-import Router, { RouteConfig } from 'vue-router'
-
-/* Layout */
-import Layout from '@/layout/index.vue'
-
-/* Router modules */
-import SchemaRoutesRouter from './modules/schema/routes'
-import SchemaConsumersRouter from './modules/schema/consumers'
-import SchemaServicesRouter from './modules/schema/services'
-import SchemaSSLRouter from './modules/schema/ssl'
-import SchemaUpstreamRouter from './modules/schema/upstream'
-
-Vue.use(Router)
-
-export const constantRoutes: RouteConfig[] = [
-  {
-    path: '/login',
-    component: () => import('@/views/login/index.vue'),
-    meta: { hidden: true }
-  },
-  {
-    path: '/',
-    component: Layout,
-    redirect: '/schema/routes/list'
-  }
-]
-
-/**
- * asyncRoutes
- * the routes that need to be dynamically loaded based on user roles
-*/
-export const asyncRoutes: RouteConfig[] = [
-  SchemaRoutesRouter,
-  SchemaConsumersRouter,
-  SchemaServicesRouter,
-  SchemaSSLRouter,
-  SchemaUpstreamRouter,
-  {
-    path: '*',
-    redirect: '/404',
-    meta: { hidden: true }
-  }
-]
-
-const createRouter = () => new Router({
-  scrollBehavior: (to, from, savedPosition) => {
-    if (savedPosition) {
-      return savedPosition
-    } else {
-      return { x: 0, y: 0 }
-    }
-  },
-  base: process.env.BASE_URL,
-  routes: constantRoutes
-})
-
-const router = createRouter()
-
-export function resetRouter() {
-  const newRouter = createRouter();
-  (router as any).matcher = (newRouter as any).matcher // reset router
-}
-
-export default router
diff --git a/src/router/modules/schema/consumers.ts b/src/router/modules/schema/consumers.ts
deleted file mode 100644
index e9d53b1..0000000
--- a/src/router/modules/schema/consumers.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.
- */
-
-import { RouteConfig } from 'vue-router'
-import Layout from '@/layout/index.vue'
-
-const tableRoutes: RouteConfig = {
-  path: '/schema/consumers',
-  component: Layout,
-  name: 'SchemaConsumers',
-  meta: {
-    title: 'SchemaConsumers',
-    icon: 'table'
-  },
-  redirect: '/schema/consumers/list',
-  children: [
-    {
-      path: 'list',
-      component: () => import(/* webpackChunkName: "complex-table" */ '@/views/schema/consumers/list.vue'),
-      name: 'SchemaConsumersList',
-      meta: { title: 'SchemaConsumersList' }
-    }, {
-      path: 'edit/:username',
-      component: () => import('@/views/schema/consumers/edit.vue'),
-      name: 'SchemaConsumersEdit',
-      meta: {
-        title: 'SchemaConsumersEdit',
-        hidden: true
-      }
-    }, {
-      path: 'create',
-      component: () => import('@/views/schema/consumers/edit.vue'),
-      name: 'SchemaConsumersCreate',
-      meta: {
-        title: 'SchemaConsumersCreate',
-        hidden: true
-      }
-    }
-  ]
-}
-
-export default tableRoutes
diff --git a/src/router/modules/schema/routes.ts b/src/router/modules/schema/routes.ts
deleted file mode 100644
index ef7a2f2..0000000
--- a/src/router/modules/schema/routes.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.
- */
-
-import { RouteConfig } from 'vue-router'
-import Layout from '@/layout/index.vue'
-
-const tableRoutes: RouteConfig = {
-  path: '/schema/routes',
-  component: Layout,
-  name: 'SchemaRoutes',
-  meta: {
-    title: 'SchemaRoutes',
-    icon: 'table'
-  },
-  redirect: '/schema/routes/list',
-  children: [
-    {
-      path: 'list',
-      component: () => import('@/views/schema/routes/list.vue'),
-      name: 'SchemaRoutesList',
-      meta: { title: 'SchemaRoutesList' }
-    }, {
-      path: 'edit/:id',
-      component: () => import('@/views/schema/routes/edit.vue'),
-      name: 'SchemaRoutesEdit',
-      meta: {
-        title: 'SchemaRoutesEdit',
-        hidden: true
-      }
-    }, {
-      path: 'create',
-      component: () => import('@/views/schema/routes/edit.vue'),
-      name: 'SchemaRoutesCreate',
-      meta: {
-        title: 'SchemaRoutesCreate',
-        hidden: true
-      }
-    }
-  ]
-}
-
-export default tableRoutes
diff --git a/src/router/modules/schema/services.ts b/src/router/modules/schema/services.ts
deleted file mode 100644
index cb35d70..0000000
--- a/src/router/modules/schema/services.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.
- */
-
-import { RouteConfig } from 'vue-router'
-import Layout from '@/layout/index.vue'
-
-const tableRoutes: RouteConfig = {
-  path: '/schema/services',
-  component: Layout,
-  name: 'SchemaServices',
-  meta: {
-    title: 'SchemaServices',
-    icon: 'table'
-  },
-  redirect: '/schema/services/list',
-  children: [
-    {
-      path: 'list',
-      component: () => import('@/views/schema/service/list.vue'),
-      name: 'SchemaServiceList',
-      meta: { title: 'SchemaServiceList' }
-    }, {
-      path: 'edit/:id',
-      component: () => import('@/views/schema/service/edit.vue'),
-      name: 'SchemaServiceEdit',
-      meta: {
-        title: 'SchemaServiceEdit',
-        hidden: true
-      }
-    }, {
-      path: 'create',
-      component: () => import('@/views/schema/service/edit.vue'),
-      name: 'SchemaServiceCreate',
-      meta: {
-        title: 'SchemaServiceCreate',
-        hidden: true
-      }
-    }
-  ]
-}
-
-export default tableRoutes
diff --git a/src/router/modules/schema/ssl.ts b/src/router/modules/schema/ssl.ts
deleted file mode 100644
index 5afb069..0000000
--- a/src/router/modules/schema/ssl.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.
- */
-
-import { RouteConfig } from 'vue-router'
-import Layout from '@/layout/index.vue'
-
-const tableRoutes: RouteConfig = {
-  path: '/schema/ssl',
-  component: Layout,
-  name: 'SchemaSSL',
-  meta: {
-    title: 'SchemaSSL',
-    icon: 'table'
-  },
-  redirect: '/schema/ssl/list',
-  children: [
-    {
-      path: 'list',
-      component: () => import('@/views/schema/ssl/list.vue'),
-      name: 'SchemaSSLList',
-      meta: { title: 'SchemaSSLList' }
-    }, {
-      path: 'edit/:id',
-      component: () => import('@/views/schema/ssl/edit.vue'),
-      name: 'SchemaSSLEdit',
-      meta: {
-        title: 'SchemaSSLEdit',
-        hidden: true
-      }
-    }, {
-      path: 'create',
-      component: () => import('@/views/schema/ssl/edit.vue'),
-      name: 'SchemaSSLCreate',
-      meta: {
-        title: 'SchemaSSLCreate',
-        hidden: true
-      }
-    }
-  ]
-}
-
-export default tableRoutes
diff --git a/src/router/modules/schema/upstream.ts b/src/router/modules/schema/upstream.ts
deleted file mode 100644
index e803687..0000000
--- a/src/router/modules/schema/upstream.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.
- */
-
-import { RouteConfig } from 'vue-router'
-import Layout from '@/layout/index.vue'
-
-const tableUpstream: RouteConfig = {
-  path: '/schema/upstream',
-  component: Layout,
-  name: 'SchemaUpstream',
-  meta: {
-    title: 'SchemaUpstream',
-    icon: 'table'
-  },
-  redirect: '/schema/upstream/list',
-  children: [
-    {
-      path: 'list',
-      component: () => import('@/views/schema/upstream/list.vue'),
-      name: 'SchemaUpstreamList',
-      meta: { title: 'SchemaUpstreamList' }
-    }, {
-      path: 'edit/:id',
-      component: () => import('@/views/schema/upstream/edit.vue'),
-      name: 'SchemaUpstreamEdit',
-      meta: {
-        title: 'SchemaUpstreamEdit',
-        hidden: true
-      }
-    }, {
-      path: 'create',
-      component: () => import('@/views/schema/upstream/edit.vue'),
-      name: 'SchemaUpstreamCreate',
-      meta: {
-        title: 'SchemaUpstreamCreate',
-        hidden: true
-      }
-    }
-  ]
-}
-
-export default tableUpstream
diff --git a/src/settings.ts b/src/settings.ts
deleted file mode 100644
index 91ccd73..0000000
--- a/src/settings.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-/**
- * MIT License
- *
- * Copyright (c) 2018 Chong Guo
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
-*/
-
-interface ISettings {
-  title: string // Overrides the default title
-  showSettings: boolean // Controls settings panel display
-  showTagsView: boolean // Controls tagsview display
-  showSidebarLogo: boolean // Controls siderbar logo display
-  fixedHeader: boolean // If true, will fix the header component
-  errorLog: string[] // The env to enable the errorlog component, default 'production' only
-  sidebarTextTheme: boolean // If true, will change active text color for sidebar based on theme
-  devServerPort: number // Port number for webpack-dev-server
-}
-
-// You can customize below settings :)
-const settings: ISettings = {
-  title: 'Dashboard for APISIX',
-  showSettings: true,
-  showTagsView: true,
-  fixedHeader: false,
-  showSidebarLogo: true,
-  errorLog: ['production'],
-  sidebarTextTheme: true,
-  devServerPort: 9527
-}
-
-export default settings
diff --git a/src/shims.d.ts b/src/shims.d.ts
deleted file mode 100644
index 2858796..0000000
--- a/src/shims.d.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
- * MIT License
- *
- * Copyright (c) 2018 Chong Guo
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
-*/
-
-declare module '*.vue' {
-  import Vue from 'vue'
-  export default Vue
-}
-
-declare module 'element-ui/lib/locale/lang/*' {
-  export const elementLocale: any
-}
-
-declare module '*.gif' {
-  export const gif: any
-}
diff --git a/src/store/index.ts b/src/store/index.ts
deleted file mode 100644
index aa389a9..0000000
--- a/src/store/index.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.
- */
-
-import Vue from 'vue'
-import Vuex from 'vuex'
-import { IAppState } from './modules/app'
-import { IUserState } from './modules/user'
-import { ITagsViewState } from './modules/tags-view'
-import { IPermissionState } from './modules/permission'
-import { ISettingsState } from './modules/settings'
-
-Vue.use(Vuex)
-
-export interface IRootState {
-  app: IAppState
-  user: IUserState
-  tagsView: ITagsViewState
-  permission: IPermissionState
-  settings: ISettingsState
-}
-
-// Declare empty store first, dynamically register all modules later.
-export default new Vuex.Store<IRootState>({})
diff --git a/src/store/modules/app.ts b/src/store/modules/app.ts
deleted file mode 100644
index d002fe7..0000000
--- a/src/store/modules/app.ts
+++ /dev/null
@@ -1,116 +0,0 @@
-/**
- * MIT License
- *
- * Copyright (c) 2018 Chong Guo
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-import { VuexModule, Module, Mutation, Action, getModule } from 'vuex-module-decorators'
-import { getSidebarStatus, getSize, setSidebarStatus, setLanguage, setSize } from '@/utils/cookies'
-import { getLocale } from '@/lang'
-import store from '@/store'
-
-export enum DeviceType {
-  Mobile,
-  Desktop,
-}
-
-export interface IAppState {
-  device: DeviceType
-  sidebar: {
-    opened: boolean
-    withoutAnimation: boolean
-  }
-  language: string
-  size: string
-}
-
-@Module({ dynamic: true, store, name: 'app' })
-class App extends VuexModule implements IAppState {
-  public sidebar = {
-    opened: getSidebarStatus() !== 'closed',
-    withoutAnimation: false
-  }
-  public device = DeviceType.Desktop
-  public language = getLocale()
-  public size = getSize() || 'medium'
-
-  @Mutation
-  private TOGGLE_SIDEBAR(withoutAnimation: boolean) {
-    this.sidebar.opened = !this.sidebar.opened
-    this.sidebar.withoutAnimation = withoutAnimation
-    if (this.sidebar.opened) {
-      setSidebarStatus('opened')
-    } else {
-      setSidebarStatus('closed')
-    }
-  }
-
-  @Mutation
-  private CLOSE_SIDEBAR(withoutAnimation: boolean) {
-    this.sidebar.opened = false
-    this.sidebar.withoutAnimation = withoutAnimation
-    setSidebarStatus('closed')
-  }
-
-  @Mutation
-  private TOGGLE_DEVICE(device: DeviceType) {
-    this.device = device
-  }
-
-  @Mutation
-  private SET_LANGUAGE(language: string) {
-    this.language = language
-    setLanguage(this.language)
-  }
-
-  @Mutation
-  private SET_SIZE(size: string) {
-    this.size = size
-    setSize(this.size)
-  }
-
-  @Action
-  public ToggleSideBar(withoutAnimation: boolean) {
-    this.TOGGLE_SIDEBAR(withoutAnimation)
-  }
-
-  @Action
-  public CloseSideBar(withoutAnimation: boolean) {
-    this.CLOSE_SIDEBAR(withoutAnimation)
-  }
-
-  @Action
-  public ToggleDevice(device: DeviceType) {
-    this.TOGGLE_DEVICE(device)
-  }
-
-  @Action
-  public SetLanguage(language: string) {
-    this.SET_LANGUAGE(language)
-  }
-
-  @Action
-  public SetSize(size: string) {
-    this.SET_SIZE(size)
-  }
-}
-
-export const AppModule = getModule(App)
diff --git a/src/store/modules/permission.ts b/src/store/modules/permission.ts
deleted file mode 100644
index 9093d28..0000000
--- a/src/store/modules/permission.ts
+++ /dev/null
@@ -1,80 +0,0 @@
-/**
- * MIT License
- *
- * Copyright (c) 2018 Chong Guo
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-import { VuexModule, Module, Mutation, Action, getModule } from 'vuex-module-decorators'
-import { RouteConfig } from 'vue-router'
-import { asyncRoutes, constantRoutes } from '@/router'
-import store from '@/store'
-
-const hasPermission = (roles: string[], route: RouteConfig) => {
-  if (route.meta && route.meta.roles) {
-    return roles.some(role => route.meta.roles.includes(role))
-  } else {
-    return true
-  }
-}
-
-export const filterAsyncRoutes = (routes: RouteConfig[], roles: string[]) => {
-  const res: RouteConfig[] = []
-  routes.forEach(route => {
-    const r = { ...route }
-    if (hasPermission(roles, r)) {
-      if (r.children) {
-        r.children = filterAsyncRoutes(r.children, roles)
-      }
-      res.push(r)
-    }
-  })
-  return res
-}
-
-export interface IPermissionState {
-  routes: RouteConfig[]
-  dynamicRoutes: RouteConfig[]
-}
-
-@Module({ dynamic: true, store, name: 'permission' })
-class Permission extends VuexModule implements IPermissionState {
-  public routes: RouteConfig[] = []
-  public dynamicRoutes: RouteConfig[] = []
-
-  @Mutation
-  private SET_ROUTES(routes: RouteConfig[]) {
-    this.routes = constantRoutes.concat(routes)
-    this.dynamicRoutes = routes
-  }
-
-  @Action
-  public GenerateRoutes(roles: string[]) {
-    let accessedRoutes
-    if (roles.includes('admin')) {
-      accessedRoutes = asyncRoutes
-    } else {
-      accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
-    }
-    this.SET_ROUTES(accessedRoutes)
-  }
-}
-
-export const PermissionModule = getModule(Permission)
diff --git a/src/store/modules/settings.ts b/src/store/modules/settings.ts
deleted file mode 100644
index f3a0be5..0000000
--- a/src/store/modules/settings.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
- * MIT License
- *
- * Copyright (c) 2018 Chong Guo
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-import { VuexModule, Module, Mutation, Action, getModule } from 'vuex-module-decorators'
-import store from '@/store'
-import elementVariables from '@/styles/element-variables.scss'
-import defaultSettings from '@/settings'
-
-export interface ISettingsState {
-  theme: string
-  fixedHeader: boolean
-  showSettings: boolean
-  showTagsView: boolean
-  showSidebarLogo: boolean
-  sidebarTextTheme: boolean
-}
-
-@Module({ dynamic: true, store, name: 'settings' })
-class Settings extends VuexModule implements ISettingsState {
-  public theme = elementVariables.theme
-  public fixedHeader = defaultSettings.fixedHeader
-  public showSettings = defaultSettings.showSettings
-  public showTagsView = defaultSettings.showTagsView
-  public showSidebarLogo = defaultSettings.showSidebarLogo
-  public sidebarTextTheme = defaultSettings.sidebarTextTheme
-
-  @Mutation
-  private CHANGE_SETTING(payload: { key: string, value: any }) {
-    const { key, value } = payload
-    if (this.hasOwnProperty(key)) {
-      (this as any)[key] = value
-    }
-  }
-
-  @Action
-  public ChangeSetting(payload: { key: string, value: any}) {
-    this.CHANGE_SETTING(payload)
-  }
-}
-
-export const SettingsModule = getModule(Settings)
diff --git a/src/store/modules/tags-view.ts b/src/store/modules/tags-view.ts
deleted file mode 100644
index 0d744c3..0000000
--- a/src/store/modules/tags-view.ts
+++ /dev/null
@@ -1,165 +0,0 @@
-/**
- * MIT License
- *
- * Copyright (c) 2018 Chong Guo
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-import { VuexModule, Module, Mutation, Action, getModule } from 'vuex-module-decorators'
-import { Route } from 'vue-router'
-import store from '@/store'
-
-export interface ITagView extends Partial<Route> {
-  title?: string
-}
-
-export interface ITagsViewState {
-  visitedViews: ITagView[]
-  cachedViews: (string | undefined)[]
-}
-
-@Module({ dynamic: true, store, name: 'tagsView' })
-class TagsView extends VuexModule implements ITagsViewState {
-  public visitedViews: ITagView[] = []
-  public cachedViews: (string | undefined)[] = []
-
-  @Mutation
-  private ADD_VISITED_VIEW(view: ITagView) {
-    if (this.visitedViews.some(v => v.path === view.path)) return
-    this.visitedViews.push(
-      Object.assign({}, view, {
-        title: view.meta.title || 'no-name'
-      })
-    )
-  }
-
-  @Mutation
-  private ADD_CACHED_VIEW(view: ITagView) {
-    if (this.cachedViews.includes(view.name)) return
-    if (!view.meta.noCache) {
-      this.cachedViews.push(view.name)
-    }
-  }
-
-  @Mutation
-  private DEL_VISITED_VIEW(view: ITagView) {
-    for (const [i, v] of this.visitedViews.entries()) {
-      if (v.path === view.path) {
-        this.visitedViews.splice(i, 1)
-        break
-      }
-    }
-  }
-
-  @Mutation
-  private DEL_CACHED_VIEW(view: ITagView) {
-    for (const [i, v] of this.cachedViews.entries()) {
-      if (v === view.name) {
-        this.cachedViews.splice(i, 1)
-        break
-      }
-    }
-  }
-
-  @Mutation
-  private DEL_OTHERS_VISITED_VIEWS(view: ITagView) {
-    this.visitedViews = this.visitedViews.filter(v => {
-      return v.meta.affix || v.path === view.path
-    })
-  }
-
-  @Mutation
-  private DEL_OTHERS_CACHED_VIEWS(view: ITagView) {
-    for (const [i, v] of this.cachedViews.entries()) {
-      if (v === view.name) {
-        this.cachedViews = this.cachedViews.slice(i, i + 1)
-        break
-      }
-    }
-  }
-
-  @Mutation
-  private DEL_ALL_VISITED_VIEWS() {
-    // keep affix tags
-    const affixTags = this.visitedViews.filter(tag => tag.meta.affix)
-    this.visitedViews = affixTags
-  }
-
-  @Mutation
-  private DEL_ALL_CACHED_VIEWS() {
-    this.cachedViews = []
-  }
-
-  @Mutation
-  private UPDATE_VISITED_VIEW(view: ITagView) {
-    for (let v of this.visitedViews) {
-      if (v.path === view.path) {
-        v = Object.assign(v, view)
-        break
-      }
-    }
-  }
-
-  @Action
-  public addView(view: ITagView) {
-    this.ADD_VISITED_VIEW(view)
-    this.ADD_CACHED_VIEW(view)
-  }
-
-  @Action
-  public addVisitedView(view: ITagView) {
-    this.ADD_VISITED_VIEW(view)
-  }
-
-  @Action
-  public delView(view: ITagView) {
-    this.DEL_VISITED_VIEW(view)
-    this.DEL_CACHED_VIEW(view)
-  }
-
-  @Action
-  public delCachedView(view: ITagView) {
-    this.DEL_CACHED_VIEW(view)
-  }
-
-  @Action
-  public delOthersViews(view: ITagView) {
-    this.DEL_OTHERS_VISITED_VIEWS(view)
-    this.DEL_OTHERS_CACHED_VIEWS(view)
-  }
-
-  @Action
-  public delAllViews() {
-    this.DEL_ALL_VISITED_VIEWS()
-    this.DEL_ALL_CACHED_VIEWS()
-  }
-
-  @Action
-  public delAllCachedViews() {
-    this.DEL_ALL_CACHED_VIEWS()
-  }
-
-  @Action
-  public updateVisitedView(view: ITagView) {
-    this.UPDATE_VISITED_VIEW(view)
-  }
-}
-
-export const TagsViewModule = getModule(TagsView)
diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts
deleted file mode 100644
index 95d4785..0000000
--- a/src/store/modules/user.ts
+++ /dev/null
@@ -1,169 +0,0 @@
-/**
- * MIT License
- *
- * Copyright (c) 2018 Chong Guo
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-import { VuexModule, Module, Action, Mutation, getModule } from 'vuex-module-decorators'
-// import { login, logout, getUserInfo } from '@/api/users'
-import { getToken, setToken, removeToken } from '@/utils/cookies'
-import router, { resetRouter } from '@/router'
-import { PermissionModule } from './permission'
-import { TagsViewModule } from './tags-view'
-import store from '@/store'
-
-export interface IUserState {
-  token: string
-  name: string
-  avatar: string
-  introduction: string
-  roles: string[]
-  email: string
-}
-
-@Module({ dynamic: true, store, name: 'user' })
-class User extends VuexModule implements IUserState {
-  public token = getToken() || ''
-  public name = ''
-  public avatar = ''
-  public introduction = ''
-  public roles: string[] = []
-  public email = ''
-
-  @Mutation
-  private SET_TOKEN(token: string) {
-    this.token = token
-  }
-
-  @Mutation
-  private SET_NAME(name: string) {
-    this.name = name
-  }
-
-  @Mutation
-  private SET_AVATAR(avatar: string) {
-    this.avatar = avatar
-  }
-
-  @Mutation
-  private SET_INTRODUCTION(introduction: string) {
-    this.introduction = introduction
-  }
-
-  @Mutation
-  private SET_ROLES(roles: string[]) {
-    this.roles = roles
-  }
-
-  @Mutation
-  private SET_EMAIL(email: string) {
-    this.email = email
-  }
-
-  @Action
-  public async Login(userInfo: { username: string, password: string}) {
-    let { username, password } = userInfo
-    username = username.trim()
-    // TEMP: 在此处绕过登录
-    // const { data } = await login({ username, password })
-
-    const data = {
-      accessToken: username + '-token'
-    }
-
-    setToken(data.accessToken)
-    this.SET_TOKEN(data.accessToken)
-  }
-
-  @Action
-  public ResetToken() {
-    removeToken()
-    this.SET_TOKEN('')
-    this.SET_ROLES([])
-  }
-
-  @Action
-  public async GetUserInfo() {
-    if (this.token === '') {
-      throw Error('GetUserInfo: token is undefined!')
-    }
-    // TEMP: 暂时绕过登录
-    // const { data } = await getUserInfo({ /* Your params here */ })
-    const data = {
-      user: {
-        id: 0,
-        username: 'admin',
-        password: 'any',
-        name: 'Super Admin',
-        avatar: 'https://user-images.githubusercontent.com/2106987/68087873-a0543980-fe94-11e9-8203-62958ce69ed6.png',
-        introduction: 'I am a super administrator',
-        email: 'dev@apache.org',
-        phone: '1234567890',
-        roles: ['admin']
-      }
-    }
-
-    if (!data) {
-      throw Error('Verification failed, please Login again.')
-    }
-    const { roles, name, avatar, introduction, email } = data.user
-    // roles must be a non-empty array
-    if (!roles || roles.length <= 0) {
-      throw Error('GetUserInfo: roles must be a non-null array!')
-    }
-    this.SET_ROLES(roles)
-    this.SET_NAME(name)
-    this.SET_AVATAR(avatar)
-    this.SET_INTRODUCTION(introduction)
-    this.SET_EMAIL(email)
-  }
-
-  @Action
-  public async ChangeRoles(role: string) {
-    // Dynamically modify permissions
-    const token = role + '-token'
-    this.SET_TOKEN(token)
-    setToken(token)
-    await this.GetUserInfo()
-    resetRouter()
-    // Generate dynamic accessible routes based on roles
-    PermissionModule.GenerateRoutes(this.roles)
-    // Add generated routes
-    router.addRoutes(PermissionModule.dynamicRoutes)
-    // Reset visited views and cached views
-    TagsViewModule.delAllViews()
-  }
-
-  @Action
-  public async LogOut() {
-    if (this.token === '') {
-      throw Error('LogOut: token is undefined!')
-    }
-    // TEMP: 暂时跳过 API 注销
-    // await logout()
-    removeToken()
-    resetRouter()
-    this.SET_TOKEN('')
-    this.SET_ROLES([])
-  }
-}
-
-export const UserModule = getModule(User)
diff --git a/src/styles/_mixins.scss b/src/styles/_mixins.scss
deleted file mode 100644
index 74340c8..0000000
--- a/src/styles/_mixins.scss
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * MIT License
- *
- * Copyright (c) 2018 Chong Guo
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
-*/
-
-@mixin clearfix {
-  &:after {
-    content: "";
-    display: table;
-    clear: both;
-  }
-}
diff --git a/src/styles/_svgicon.scss b/src/styles/_svgicon.scss
deleted file mode 100644
index 3dd54b2..0000000
--- a/src/styles/_svgicon.scss
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * MIT License
- *
- * Copyright (c) 2018 Chong Guo
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
-*/
-
-/* recommended css code for vue-svgicon */
-.svg-icon {
-    display: inline-block;
-    width: 16px;
-    height: 16px;
-    color: inherit;
-    fill: none;
-    stroke: currentColor;
-    vertical-align: -0.15em;
-}
-
-.svg-fill {
-    fill: currentColor;
-    stroke: none;
-}
-
-.svg-up {
-    /* default */
-    transform: rotate(0deg);
-}
-
-.svg-right {
-    transform: rotate(90deg);
-}
-
-.svg-down {
-    transform: rotate(180deg);
-}
-
-.svg-left {
-    transform: rotate(-90deg);
-}
diff --git a/src/styles/_transition.scss b/src/styles/_transition.scss
deleted file mode 100644
index 30c1d9d..0000000
--- a/src/styles/_transition.scss
+++ /dev/null
@@ -1,73 +0,0 @@
-/**
- * MIT License
- *
- * Copyright (c) 2018 Chong Guo
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
-*/
-
-/* global transition css for vue.js */
-/* see https://vuejs.org/v2/guide/transitions.html for detail */
-
-/* fade */
-.fade-enter-active,
-.fade-leave-active {
-  transition: opacity 0.28s;
-}
-
-.fade-enter,
-.fade-leave-active {
-  opacity: 0;
-}
-
-/* fade-transform */
-.fade-transform-leave-active,
-.fade-transform-enter-active {
-  transition: all .5s;
-}
-
-.fade-transform-enter {
-  opacity: 0;
-  transform: translateX(-30px);
-}
-
-.fade-transform-leave-to {
-  opacity: 0;
-  transform: translateX(30px);
-}
-
-/* fade */
-.breadcrumb-enter-active,
-.breadcrumb-leave-active {
-  transition: all .5s;
-}
-
-.breadcrumb-enter,
-.breadcrumb-leave-active {
-  opacity: 0;
-  transform: translateX(20px);
-}
-
-.breadcrumb-move {
-  transition: all .5s;
-}
-
-.breadcrumb-leave-active {
-  position: absolute;
-}
diff --git a/src/styles/_variables.scss b/src/styles/_variables.scss
deleted file mode 100644
index 0cb9cb5..0000000
--- a/src/styles/_variables.scss
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * MIT License
- *
- * Copyright (c) 2018 Chong Guo
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
-*/
-
-/* base color */
-$blue:#324157;
-$light-blue:#3A71A8;
-$red:#C03639;
-$pink: #E65D6E;
-$green: #30B08F;
-$tiffany: #4AB7BD;
-$yellow:#FEC171;
-$panGreen: #30B08F;
-
-/* Sidebar */
-$sideBarWidth: 210px;
-$subMenuBg:#1f2d3d;
-$subMenuHover:#001528;
-$subMenuActiveText:#f4f4f5;
-$menuBg:#304156;
-$menuText:#bfcbd9;
-$menuActiveText:#409EFF; // Also see settings.sidebarTextTheme
-
-/* Login page */
-$lightGray: #eee;
-$darkGray:#889aa4;
-$loginBg: #2d3a4b;
-$loginCursorColor: #fff;
-
-// The :export directive is the magic sauce for webpack
-// https://mattferderer.com/use-sass-variables-in-typescript-and-javascript
-:export {
-  menuBg: $menuBg;
-  menuText: $menuText;
-  menuActiveText: $menuActiveText;
-}
diff --git a/src/styles/_variables.scss.d.ts b/src/styles/_variables.scss.d.ts
deleted file mode 100644
index a51ca70..0000000
--- a/src/styles/_variables.scss.d.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
- * MIT License
- *
- * Copyright (c) 2018 Chong Guo
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-export interface IScssVariables {
-  menuBg: string
-  menuText: string
-  menuActiveText: string
-}
-
-export const variables: IScssVariables
-
-export default variables
diff --git a/src/styles/element-variables.scss b/src/styles/element-variables.scss
deleted file mode 100644
index 8bb3e01..0000000
--- a/src/styles/element-variables.scss
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
- * MIT License
- *
- * Copyright (c) 2018 Chong Guo
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
-*/
-
-/* Override Element UI variables */
-$--color-primary: #1890ff;
-$--color-success: #13ce66;
-$--color-warning: #FFBA00;
-$--color-danger: #ff4949;
-$--color-info: #5d5d5d;
-$--button-font-weight: 400;
-$--color-text-regular: #1f2d3d;
-$--border-color-light: #dfe4ed;
-$--border-color-lighter: #e6ebf5;
-$--table-border:1px solid#dfe6ec;
-
-/* icon font path, required */
-$--font-path: '~element-ui/lib/theme-chalk/fonts';
-
-// Apply overrided variables in Element UI
-@import '~element-ui/packages/theme-chalk/src/index';
-
-// The :export directive is the magic sauce for webpack
-// https://mattferderer.com/use-sass-variables-in-typescript-and-javascript
-:export {
-  theme: $--color-primary;
-}
diff --git a/src/styles/element-variables.scss.d.ts b/src/styles/element-variables.scss.d.ts
deleted file mode 100644
index 833945d..0000000
--- a/src/styles/element-variables.scss.d.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * MIT License
- *
- * Copyright (c) 2018 Chong Guo
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-export interface IScssVariables {
-  theme: string
-}
-
-export const variables: IScssVariables
-
-export default variables
diff --git a/src/styles/index.scss b/src/styles/index.scss
deleted file mode 100644
index 75976a2..0000000
--- a/src/styles/index.scss
+++ /dev/null
@@ -1,183 +0,0 @@
-/**
- * MIT License
- *
- * Copyright (c) 2018 Chong Guo
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
-*/
-
-@import './element-variables.scss';
-@import './variables.scss';
-@import './mixins.scss';
-@import './transition.scss';
-@import './svgicon.scss';
-
-body {
-  height: 100%;
-  -moz-osx-font-smoothing: grayscale;
-  -webkit-font-smoothing: antialiased;
-  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
-}
-
-html {
-  height: 100%;
-}
-
-#app {
-  height: 100%;
-}
-
-*,
-*:before,
-*:after {
-  box-sizing: border-box;
-}
-
-a,
-a:focus,
-a:hover {
-  color: inherit;
-  outline: none;
-  text-decoration: none;
-}
-
-div:focus {
-  outline: none;
-}
-
-.clearfix {
-  @include clearfix;
-}
-
-label {
-  font-weight: 700;
-}
-
-.app-container {
-  padding: 20px;
-}
-
-.components-container {
-  margin: 30px 50px;
-  position: relative;
-}
-
-// Refine element ui upload
-.upload-container {
-  .el-upload {
-    width: 100%;
-
-    .el-upload-dragger {
-      width: 100%;
-      height: 200px;
-    }
-  }
-}
-
-aside {
-  background: #eef1f6;
-  color: #2c3e50;
-  padding: 8px 24px;
-  margin-bottom: 20px;
-  border-radius: 2px;
-  display: block;
-  line-height: 32px;
-  font-size: 16px;
-  -webkit-font-smoothing: antialiased;
-  -moz-osx-font-smoothing: grayscale;
-
-  a {
-    color: #337ab7;
-    cursor: pointer;
-
-    &:hover {
-      color: rgb(32, 160, 255);
-    }
-  }
-}
-
-.fixed-width {
-  .el-button--mini {
-    padding: 7px 10px;
-    width: 60px;
-  }
-}
-
-.filter-container {
-  padding-bottom: 10px;
-
-  .filter-item {
-    display: inline-block;
-    vertical-align: middle;
-    margin-bottom: 10px;
-  }
-}
-
-.link-type,
-.link-type:focus {
-  color: #337ab7;
-  cursor: pointer;
-
-  &:hover {
-    color: rgb(32, 160, 255);
-  }
-}
-
-.status-col {
-  .cell {
-    padding: 0 10px;
-    text-align: center;
-  }
-}
-
-.text-center {
-  text-align: center
-}
-
-.sub-navbar {
-  height: 50px;
-  line-height: 50px;
-  position: relative;
-  width: 100%;
-  text-align: right;
-  padding-right: 20px;
-  transition: 600ms ease position;
-  background: linear-gradient(90deg, rgba(32, 182, 249, 1) 0%, rgba(32, 182, 249, 1) 0%, rgba(33, 120, 241, 1) 100%, rgba(33, 120, 241, 1) 100%);
-
-  .subtitle {
-    font-size: 20px;
-    color: #fff;
-  }
-
-  &.draft {
-    background: #d0d0d0;
-  }
-
-  &.deleted {
-    background: #d0d0d0;
-  }
-}
-
-.no-padding {
-  padding: 0px !important;
-}
-
-.el-message-box {
-  vertical-align: baseline !important;
-}
\ No newline at end of file
diff --git a/src/utils/cookies.ts b/src/utils/cookies.ts
deleted file mode 100644
index 2aca434..0000000
--- a/src/utils/cookies.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * MIT License
- *
- * Copyright (c) 2018 Chong Guo
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-import Cookies from 'js-cookie'
-
-// App
-const sidebarStatusKey = 'sidebar_status'
-export const getSidebarStatus = () => Cookies.get(sidebarStatusKey)
-export const setSidebarStatus = (sidebarStatus: string) => Cookies.set(sidebarStatusKey, sidebarStatus)
-
-const languageKey = 'language'
-export const getLanguage = () => Cookies.get(languageKey)
-export const setLanguage = (language: string) => Cookies.set(languageKey, language)
-
-const sizeKey = 'size'
-export const getSize = () => Cookies.get(sizeKey)
-export const setSize = (size: string) => Cookies.set(sizeKey, size)
-
-// User
-const tokenKey = 'vue_typescript_admin_access_token'
-export const getToken = () => Cookies.get(tokenKey)
-export const setToken = (token: string) => Cookies.set(tokenKey, token)
-export const removeToken = () => Cookies.remove(tokenKey)
diff --git a/src/utils/index.ts b/src/utils/index.ts
deleted file mode 100644
index 0017073..0000000
--- a/src/utils/index.ts
+++ /dev/null
@@ -1,112 +0,0 @@
-/**
- * MIT License
- *
- * Copyright (c) 2018 Chong Guo
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-// Parse the time to string
-export const parseTime = (
-  time?: object | string | number,
-  cFormat?: string
-): string | null => {
-  if (time === undefined) {
-    return null
-  }
-  const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
-  let date: Date
-  if (typeof time === 'object') {
-    date = time as Date
-  } else {
-    if (typeof time === 'string' && /^[0-9]+$/.test(time)) {
-      time = parseInt(time)
-    }
-    if (typeof time === 'number' && time.toString().length === 10) {
-      time = time * 1000
-    }
-    date = new Date(time)
-  }
-  const formatObj: { [key: string]: number } = {
-    y: date.getFullYear(),
-    m: date.getMonth() + 1,
-    d: date.getDate(),
-    h: date.getHours(),
-    i: date.getMinutes(),
-    s: date.getSeconds(),
-    a: date.getDay()
-  }
-  const timeStr = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
-    let value = formatObj[key]
-    // Note: getDay() returns 0 on Sunday
-    if (key === 'a') {
-      return ['日', '一', '二', '三', '四', '五', '六'][value]
-    }
-    if (result.length > 0 && value < 10) {
-      return '0' + value
-    }
-    return String(value) || '0'
-  })
-  return timeStr
-}
-
-// Format and filter json data using filterKeys array
-export const formatJson = (filterKeys: any, jsonData: any) =>
-  jsonData.map((data: any) => filterKeys.map((key: string) => {
-    if (key === 'timestamp') {
-      return parseTime(data[key])
-    } else {
-      return data[key]
-    }
-  }))
-
-// Check if an element has a class
-export const hasClass = (ele: HTMLElement, className: string) => {
-  return !!ele.className.match(new RegExp('(\\s|^)' + className + '(\\s|$)'))
-}
-
-// Add class to element
-export const addClass = (ele: HTMLElement, className: string) => {
-  if (!hasClass(ele, className)) ele.className += ' ' + className
-}
-
-// Remove class from element
-export const removeClass = (ele: HTMLElement, className: string) => {
-  if (hasClass(ele, className)) {
-    const reg = new RegExp('(\\s|^)' + className + '(\\s|$)')
-    ele.className = ele.className.replace(reg, ' ')
-  }
-}
-
-// Toggle class for the selected element
-export const toggleClass = (ele: HTMLElement, className: string) => {
-  if (!ele || !className) {
-    return
-  }
-  let classString = ele.className
-  const nameIndex = classString.indexOf(className)
-  if (nameIndex === -1) {
-    classString += '' + className
-  } else {
-    classString =
-      classString.substr(0, nameIndex) +
-      classString.substr(nameIndex + className.length)
-  }
-  ele.className = classString
-}
diff --git a/src/utils/permission.ts b/src/utils/permission.ts
deleted file mode 100644
index 5112042..0000000
--- a/src/utils/permission.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * MIT License
- *
- * Copyright (c) 2018 Chong Guo
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-import { UserModule } from '@/store/modules/user'
-
-export const checkPermission = (value: string[]): boolean => {
-  if (value && value instanceof Array && value.length > 0) {
-    const roles = UserModule.roles
-    const permissionRoles = value
-    const hasPermission = roles.some(role => {
-      return permissionRoles.includes(role)
-    })
-    return hasPermission
-  } else {
-    console.error(`need roles! Like v-permission="['admin','editor']"`)
-    return false
-  }
-}
diff --git a/src/utils/request.ts b/src/utils/request.ts
deleted file mode 100644
index e730d5f..0000000
--- a/src/utils/request.ts
+++ /dev/null
@@ -1,59 +0,0 @@
-/**
- * MIT License
- *
- * Copyright (c) 2018 Chong Guo
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-import axios from 'axios'
-import { Message } from 'element-ui'
-
-const service = axios.create({
-  baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
-  timeout: 5000,
-  headers: {
-    'X-API-KEY': localStorage.getItem('GLOBAL_API_KEY')
-  }
-})
-
-service.interceptors.request.use(
-  (config) => {
-    return config
-  },
-  (error) => {
-    Promise.reject(error)
-  }
-)
-
-service.interceptors.response.use(
-  (response) => {
-    return response.data
-  },
-  (error) => {
-    Message({
-      message: error.response.data.error_msg || error.message,
-      type: 'error',
-      duration: 5 * 1000
-    })
-    return Promise.reject(error)
-  }
-)
-
-export default service
diff --git a/src/utils/scroll-to.ts b/src/utils/scroll-to.ts
deleted file mode 100644
index 082382a..0000000
--- a/src/utils/scroll-to.ts
+++ /dev/null
@@ -1,74 +0,0 @@
-/**
- * MIT License
- *
- * Copyright (c) 2018 Chong Guo
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-const easeInOutQuad = (t: number, b: number, c: number, d: number) => {
-  t /= d / 2
-  if (t < 1) {
-    return c / 2 * t * t + b
-  }
-  t--
-  return -c / 2 * (t * (t - 2) - 1) + b
-}
-
-// requestAnimationFrame for Smart Animating http://goo.gl/sx5sts
-const requestAnimFrame = (function() {
-  return window.requestAnimationFrame || window.webkitRequestAnimationFrame || (window as any).mozRequestAnimationFrame || function(callback) { window.setTimeout(callback, 1000 / 60) }
-})()
-
-// Because it's so fucking difficult to detect the scrolling element, just move them all
-const move = (amount: number) => {
-  document.documentElement.scrollTop = amount;
-  (document.body.parentNode as HTMLElement).scrollTop = amount
-  document.body.scrollTop = amount
-}
-
-const position = () => {
-  return document.documentElement.scrollTop || (document.body.parentNode as HTMLElement).scrollTop || document.body.scrollTop
-}
-
-export const scrollTo = (to: number, duration: number, callback?: Function) => {
-  const start = position()
-  const change = to - start
-  const increment = 20
-  let currentTime = 0
-  duration = (typeof (duration) === 'undefined') ? 500 : duration
-  const animateScroll = function() {
-    // increment the time
-    currentTime += increment
-    // find the value with the quadratic in-out easing function
-    const val = easeInOutQuad(currentTime, start, change, duration)
-    // move the document.body
-    move(val)
-    // do the animation unless its over
-    if (currentTime < duration) {
-      requestAnimFrame(animateScroll)
-    } else {
-      if (callback && typeof (callback) === 'function') {
-        // the animation is done so lets callback
-        callback()
-      }
-    }
-  }
-  animateScroll()
-}
diff --git a/src/utils/validate.ts b/src/utils/validate.ts
deleted file mode 100644
index b7a944c..0000000
--- a/src/utils/validate.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * MIT License
- *
- * Copyright (c) 2018 Chong Guo
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-export const isValidUsername = (str: string) => ['admin', 'editor'].indexOf(str.trim()) >= 0
-
-export const isExternal = (path: string) => /^(https?:|mailto:|tel:)/.test(path)
-
-export const isArray = (arg: any) => {
-  if (typeof Array.isArray === 'undefined') {
-    return Object.prototype.toString.call(arg) === '[object Array]'
-  }
-  return Array.isArray(arg)
-}
-
-export const isValidURL = (url: string) => {
-  const reg = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/
-  return reg.test(url)
-}
diff --git a/src/views/login/index.vue b/src/views/login/index.vue
deleted file mode 100644
index 3efe7c9..0000000
--- a/src/views/login/index.vue
+++ /dev/null
@@ -1,228 +0,0 @@
-<!--
-#
-# MIT License
-#
-# Copyright (c) 2018 Chong Guo
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-#
--->
-
-<template>
-  <div class="login-container">
-    <el-form
-      ref="loginForm"
-      :model="loginForm"
-      class="login-form"
-      autocomplete="on"
-      label-position="left"
-    >
-      <div class="title-container">
-        <h3 class="title">
-          {{ $t('login.title') }}
-        </h3>
-      </div>
-
-      <el-form-item prop="apikey">
-        <span class="svg-container">
-          <svg-icon name="user" />
-        </span>
-        <el-input
-          ref="apikey"
-          v-model="loginForm.apikey"
-          placeholder="Please input API KEY here"
-          name="apikey"
-          type="text"
-          autocomplete="on"
-        />
-      </el-form-item>
-
-      <el-button
-        :loading="loading"
-        type="primary"
-        style="width:100%; margin-bottom:30px;"
-        @click.native.prevent="handleLogin"
-      >
-        {{ $t('login.logIn') }}
-      </el-button>
-    </el-form>
-
-    <el-dialog
-      :title="$t('login.thirdparty')"
-      :visible.sync="showDialog"
-    >
-      {{ $t('login.thirdpartyTips') }}
-      <br>
-      <br>
-      <br>
-      <social-sign />
-    </el-dialog>
-  </div>
-</template>
-
-<script lang="ts">
-import { Component, Vue, Watch } from 'vue-property-decorator'
-import { Route } from 'vue-router'
-import { Form as ElForm, Input } from 'element-ui'
-import { UserModule } from '@/store/modules/user'
-import LangSelect from '@/components/LangSelect/index.vue'
-
-@Component({
-  name: 'Login',
-  components: {
-    LangSelect
-  }
-})
-export default class extends Vue {
-  private loginForm = {
-    apikey: ''
-  }
-  private loading = false
-  private showDialog = false
-  private redirect?: string
-
-  private async handleLogin() {
-    await UserModule.Login({ username: '', password: '' })
-    localStorage.setItem('GLOBAL_API_KEY', this.loginForm.apikey)
-    window.location.replace('/')
-  }
-}
-</script>
-
-<style lang="scss">
-// References: https://www.zhangxinxu.com/wordpress/2018/01/css-caret-color-first-line/
-@supports (-webkit-mask: none) and (not (cater-color: $loginCursorColor)) {
-  .login-container .el-input {
-    input { color: $loginCursorColor; }
-    input::first-line { color: $lightGray; }
-  }
-}
-
-.login-container {
-  .el-input {
-    display: inline-block;
-    height: 47px;
-    width: 85%;
-
-    input {
-      height: 47px;
-      background: transparent;
-      border: 0px;
-      border-radius: 0px;
-      padding: 12px 5px 12px 15px;
-      color: $lightGray;
-      caret-color: $loginCursorColor;
-      -webkit-appearance: none;
-
-      &:-webkit-autofill {
-        box-shadow: 0 0 0px 1000px $loginBg inset !important;
-        -webkit-text-fill-color: #fff !important;
-      }
-    }
-  }
-
-  .el-form-item {
-    border: 1px solid rgba(255, 255, 255, 0.1);
-    background: rgba(0, 0, 0, 0.1);
-    border-radius: 5px;
-    color: #454545;
-  }
-}
-</style>
-
-<style lang="scss" scoped>
-.login-container {
-  height: 100%;
-  width: 100%;
-  overflow: hidden;
-  background-color: $loginBg;
-
-  .login-form {
-    position: relative;
-    width: 520px;
-    max-width: 100%;
-    padding: 160px 35px 0;
-    margin: 0 auto;
-    overflow: hidden;
-  }
-
-  .tips {
-    font-size: 14px;
-    color: #fff;
-    margin-bottom: 10px;
-
-    span {
-      &:first-of-type {
-        margin-right: 16px;
-      }
-    }
-  }
-
-  .svg-container {
-    padding: 6px 5px 6px 15px;
-    color: $darkGray;
-    vertical-align: middle;
-    width: 30px;
-    display: inline-block;
-  }
-
-  .title-container {
-    position: relative;
-
-    .title {
-      font-size: 26px;
-      color: $lightGray;
-      margin: 0px auto 40px auto;
-      text-align: center;
-      font-weight: bold;
-    }
-
-    .set-language {
-      color: #fff;
-      position: absolute;
-      top: 3px;
-      font-size: 18px;
-      right: 0px;
-      cursor: pointer;
-    }
-  }
-
-  .show-pwd {
-    position: absolute;
-    right: 10px;
-    top: 7px;
-    font-size: 16px;
-    color: $darkGray;
-    cursor: pointer;
-    user-select: none;
-  }
-
-  .thirdparty-button {
-    position: absolute;
-    right: 0;
-    bottom: 6px;
-  }
-
-  @media only screen and (max-width: 470px) {
-    .thirdparty-button {
-      display: none;
-    }
-  }
-}
-</style>
diff --git a/src/views/schema/consumers/edit.vue b/src/views/schema/consumers/edit.vue
deleted file mode 100644
index d59174c..0000000
--- a/src/views/schema/consumers/edit.vue
+++ /dev/null
@@ -1,266 +0,0 @@
-<!--
-#
-# 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.
-#
--->
-
-<template>
-  <div class="consumers-wrapper">
-    <el-form
-      ref="form"
-      :model="form"
-      :rules="rules"
-      label-width="80px"
-      :show-message="false"
-    >
-      <el-form-item
-        label="Desc"
-      >
-        <el-input
-          v-model="form.desc"
-          placeholder="Description"
-        />
-      </el-form-item>
-
-      <el-form-item
-        label="name"
-        prop="username"
-      >
-        <el-input v-model="form.username" />
-      </el-form-item>
-
-      <el-form-item
-        v-for="(index, item) in form.plugins"
-        :key="item"
-        :label="&quot;plugin&quot;"
-        class="plugin-item"
-      >
-        <el-button
-          v-if="item !== 'tempPlugin'"
-          type="info"
-          plain
-          @click="showPlugin(item)"
-        >
-          {{ item }}
-        </el-button>
-
-        <el-button
-          v-if="item !== 'tempPlugin'"
-          type="danger"
-          @click.prevent="removePlugin(item)"
-        >
-          {{ $t('button.delete') }}
-        </el-button>
-
-        <el-select
-          v-if="item === 'tempPlugin'"
-          :value="null"
-          class="plugin-select"
-          placeholder="Select a Plugin"
-          @change="showPlugin"
-        >
-          <el-option
-            v-for="name in filteredPluginList"
-            :key="name"
-            :label="name"
-            :value="name"
-          />
-        </el-select>
-      </el-form-item>
-      <el-form-item>
-        <el-button
-          :disabled="!filteredPluginList.length"
-          @click="addPlugin"
-        >
-          {{ $t('button.add_plugin') }}
-        </el-button>
-      </el-form-item>
-
-      <el-form-item>
-        <el-button
-          type="primary"
-          @click="onSubmit"
-        >
-          {{ $t('button.save') }}
-        </el-button>
-        <el-button @click="toPreviousPage">
-          {{ $t('button.cancel') }}
-        </el-button>
-      </el-form-item>
-    </el-form>
-
-    <PluginDialog
-      :show="showPluginDialog"
-      :name="pluginName"
-      :plugin-data="form.plugins[pluginName]"
-      @hidePlugin="showPluginDialog = false"
-      @save="onPluginSave"
-    />
-  </div>
-</template>
-
-<script lang='ts'>
-import { Component, Vue } from 'vue-property-decorator'
-import { Form } from 'element-ui'
-
-import { getList, get, updateOrCreateConsumer } from '../../../api/schema/consumers'
-import { getPluginList } from '@/api/schema/plugins'
-import PluginDialog from '@/components/PluginDialog/index.vue'
-
-import { IConsumerData, IDataWrapper } from '../../../api/types'
-import { TagsViewModule } from '@/store/modules/tags-view'
-
-@Component({
-  name: 'ConsumerEdit',
-  components: {
-    PluginDialog
-  }
-})
-export default class extends Vue {
-  private isEditMode: boolean = false
-
-  private form = {
-    username: '',
-    plugins: {},
-    desc: ''
-  }
-
-  private rules = {
-    username: {
-      required: true
-    }
-  }
-
-  private pluginList = []
-  private pluginName: string = ''
-  private showPluginDialog: boolean = false
-
-  get filteredPluginList() {
-    return this.pluginList.filter(item => !this.form.plugins.hasOwnProperty(item))
-  }
-
-  created() {
-    this.isEditMode = (this.$route as any).name.indexOf('Create') === -1
-
-    if (this.isEditMode) {
-      this.getConsumerData()
-    }
-
-    this.getPluginList()
-  }
-
-  private async getConsumerData() {
-    const username = this.$route.params.username
-    const data = await get(username) as any
-
-    (this.form as any) = {
-      desc: data.node.value.desc,
-      username,
-      plugins: data.node.value.plugins
-    }
-  }
-
-  private async getPluginList() {
-    this.pluginList = await getPluginList() as any
-  }
-
-  private async addPlugin() {
-    if (this.form.plugins.hasOwnProperty('tempPlugin')) return
-
-    this.form.plugins = {
-      ...this.form.plugins,
-      tempPlugin: null
-    }
-  }
-
-  private async onSubmit() {
-    (this.$refs['form'] as any).validate(async(valid: boolean) => {
-      if (valid) {
-        delete this.form.plugins['tempPlugin']
-
-        let data = Object.assign({}, this.form)
-        Object.entries(data).forEach(([key, value]) => {
-          if (typeof data[key] === 'object') {
-            if (key !== 'plugins' && Object.keys(value).length === 0) {
-              delete data[key]
-            }
-          } else {
-            if (value === '') {
-              delete data[key]
-            }
-          }
-        })
-
-        await updateOrCreateConsumer(Object.assign({}, data))
-
-        this.$message.success(`${this.isEditMode ? 'Update the' : 'Create a'} consumer successfully!`)
-
-        if (this.isEditMode) return
-
-        TagsViewModule.delView(this.$route)
-        this.$nextTick(() => {
-          this.$router.push({
-            name: 'SchemaConsumersList'
-          })
-        })
-      } else {
-        return false
-      }
-    })
-  }
-
-  private async showPlugin(name: string) {
-    this.pluginName = name
-    this.showPluginDialog = true
-  }
-
-  private onPluginSave(name: string, data: any) {
-    delete this.form.plugins['tempPlugin']
-    this.showPluginDialog = false
-    this.form.plugins[name] = data
-  }
-
-  private toPreviousPage() {
-    this.$router.go(-1)
-  }
-
-  private removePlugin(name: any) {
-    this.$confirm(`Do you want to remove ${name} plugin?`, 'Warning', {
-      confirmButtonText: 'Confirm',
-      cancelButtonText: 'Cancel',
-      type: 'warning'
-    })
-      .then(async() => {
-        Vue.delete(this.form.plugins, name)
-      }).catch(() => {})
-  }
-}
-</script>
-
-<style lang='scss'>
-.consumers-wrapper {
-  padding: 20px;
-  .el-form {
-    .el-form-item {
-      .el-form-item__content {
-        .el-input {
-          width: 220px;
-        }
-      }
-    }
-  }
-}
-</style>
diff --git a/src/views/schema/consumers/list.vue b/src/views/schema/consumers/list.vue
deleted file mode 100644
index 1ecbaa9..0000000
--- a/src/views/schema/consumers/list.vue
+++ /dev/null
@@ -1,222 +0,0 @@
-<!--
-#
-# 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.
-#
--->
-
-<template>
-  <div class="app-container">
-    <div class="filter-container">
-      <el-button
-        class="filter-item"
-        style="margin-left: 10px;"
-        type="primary"
-        icon="el-icon-edit"
-        @click="handleCreate"
-      >
-        {{ $t('table.add') }}
-      </el-button>
-    </div>
-
-    <el-table
-      :key="tableKey"
-      v-loading="listLoading"
-      :data="tableData"
-      :border="false"
-      fit
-      highlight-current-row
-      style="width: 100%;"
-      @sort-change="sortChange"
-    >
-      <el-table-column
-        v-for="(item, index) of tableKeys"
-        :key="index"
-        :label="item.key"
-        :prop="item.key"
-        :width="item.width"
-        :class-name="item.align === 'left' ? '' : 'status-col'"
-        header-align="center"
-      />
-      <el-table-column
-        :label="$t('table.actions')"
-        align="center"
-        width="230"
-        class-name="fixed-width"
-      >
-        <template slot-scope="{row}">
-          <el-button
-            type="primary"
-            size="mini"
-            @click="handleToEdit(row)"
-          >
-            {{ $t('table.edit') }}
-          </el-button>
-
-          <el-button
-            v-if="row.status!=='deleted'"
-            size="mini"
-            type="danger"
-            @click="handleRemove(row)"
-          >
-            {{ $t('table.delete') }}
-          </el-button>
-        </template>
-      </el-table-column>
-    </el-table>
-  </div>
-</template>
-
-<script lang="ts">
-import { Component, Vue } from 'vue-property-decorator'
-import { Form } from 'element-ui'
-
-import Pagination from '../../../components/Pagination/index.vue'
-
-import { getList, removeConsumer } from '../../../api/schema/consumers'
-
-@Component({
-  name: 'ComplexTable',
-  components: {
-    Pagination
-  }
-})
-export default class extends Vue {
-  private tableKey = 0
-  private list: any[] = []
-  private total = 0
-  private listLoading = true
-  private listQuery = {
-    page: 1,
-    limit: 20,
-    importance: undefined,
-    title: undefined,
-    type: undefined,
-    sort: '+id'
-  }
-
-  private tableData: string[] = []
-  private tableKeys: any[] = []
-
-  created() {
-    this.getList()
-  }
-
-  private async getList() {
-    this.listLoading = true
-
-    this.tableKeys = [
-      {
-        key: 'username',
-        width: 300
-      }, {
-        key: 'description',
-        width: 300,
-        align: 'left'
-      }, {
-        key: 'plugins',
-        width: 400
-      }
-    ]
-
-    let { node: { nodes = [] } } = await getList() as any
-    nodes = [...nodes].map((item: any) => {
-      const pluginArr: any = []
-
-      const { value } = item
-      const username = value.username
-      const desc = value.desc
-
-      Object.entries(value.plugins as any).map(([ key, value ]: any) => {
-        pluginArr.push({
-          name: key,
-          key: value.key
-        })
-      })
-
-      return {
-        username,
-        plugins: pluginArr.map((item: any) => item.name).join(', '),
-        pluginArr,
-        description: desc
-      }
-    })
-
-    this.tableData = nodes
-    this.total = nodes.length
-
-    setTimeout(() => {
-      this.listLoading = false
-    }, 0.5 * 1000)
-  }
-
-  private handleFilter() {
-    this.listQuery.page = 1
-    this.getList()
-  }
-
-  private handleRemove(row: any) {
-    this.$confirm(`Do you want to remove consumer ${row.username}?`, 'Warning', {
-      confirmButtonText: 'Confirm',
-      cancelButtonText: 'Cancel',
-      type: 'warning'
-    })
-      .then(async() => {
-        await removeConsumer(row.username)
-        this.getList()
-        this.$message.success(`Remove consumer ${row.username} successfully!`)
-      })
-  }
-
-  private sortChange(data: any) {
-    const { prop, order } = data
-    if (prop === 'id') {
-      this.sortByID(order)
-    }
-  }
-
-  private sortByID(order: string) {
-    if (order === 'ascending') {
-      this.listQuery.sort = '+id'
-    } else {
-      this.listQuery.sort = '-id'
-    }
-    this.handleFilter()
-  }
-
-  private handleCreate() {
-    this.$router.push({
-      name: 'SchemaConsumersCreate'
-    })
-  }
-
-  private handleToEdit(row: any) {
-    this.$router.push({
-      name: 'SchemaConsumersEdit',
-      params: {
-        username: row.username
-      }
-    })
-  }
-}
-</script>
-
-<style lang="scss">
-.app-container {
-  .el-table::before {
-    height: 0 !important;
-  }
-}
-</style>
diff --git a/src/views/schema/routes/edit.vue b/src/views/schema/routes/edit.vue
deleted file mode 100644
index 80c5ded..0000000
--- a/src/views/schema/routes/edit.vue
+++ /dev/null
@@ -1,549 +0,0 @@
-<!--
-#
-# 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.
-#
--->
-
-<template>
-  <div class="container">
-    <el-form
-      ref="form"
-      :model="form"
-      :rules="rules"
-      label-width="80px"
-      :show-message="false"
-    >
-      <el-form-item
-        label="Desc"
-      >
-        <el-input
-          v-model="form.desc"
-          placeholder="Description"
-        />
-      </el-form-item>
-
-      <el-form-item
-        label="URIs"
-        prop="uris"
-      >
-        <el-select
-          v-model="form.uris"
-          allow-create
-          filterable
-          multiple
-          default-first-option
-          :placeholder="$t('schema.route.inputMultipleValues')"
-          @change="filterUriOptions"
-        >
-          <el-option
-            v-for="item in ExistedUris"
-            :key="item.value"
-            :label="item.label"
-            :value="item.value"
-          />
-        </el-select>
-      </el-form-item>
-
-      <el-form-item
-        label="Hosts"
-        prop="hosts"
-        placeholder="Hosts"
-      >
-        <el-select
-          v-model="form.hosts"
-          multiple
-          filterable
-          allow-create
-          default-first-option
-          :placeholder="$t('schema.route.inputMultipleValues')"
-        >
-          <el-option
-            v-for="item in ExistedHosts"
-            :key="item.value"
-            :label="item.label"
-            :value="item.value"
-          />
-        </el-select>
-        <p class="tip">
-          {{ $t('schema.route.propertyHostsTip') }}
-        </p>
-      </el-form-item>
-
-      <el-form-item
-        label="Remote Address"
-        prop="remote_addr"
-      >
-        <el-input
-          v-model="form.remote_addr"
-          placeholder="Remote Address"
-        />
-      </el-form-item>
-
-      <el-form-item
-        label="Methods"
-      >
-        <el-select
-          v-model="form.methods"
-          multiple
-          placeholder="Methods"
-        >
-          <el-option
-            v-for="item in methods"
-            :key="item"
-            :label="item"
-            :value="item"
-          />
-        </el-select>
-      </el-form-item>
-
-      <el-form-item
-        label="Upstream"
-        prop="upstream_id"
-      >
-        <el-select
-          v-model="form.upstream_id"
-          placeholder="Upstream"
-          clearable
-          filterable
-        >
-          <el-option
-            v-for="item in upstreamList"
-            :key="item.id"
-            :label="item.desc"
-            :value="item.id"
-          />
-        </el-select>
-      </el-form-item>
-
-      <el-form-item
-        label="Service"
-        prop="service_id"
-      >
-        <el-select
-          v-model="form.service_id"
-          placeholder="Service"
-          clearable
-          filterable
-        >
-          <el-option
-            v-for="item in serviceList"
-            :key="item.id"
-            :label="item.desc"
-            :value="item.id"
-          />
-        </el-select>
-      </el-form-item>
-
-      <el-form-item
-        v-for="(index, item) in form.plugins"
-        :key="item"
-        :label="&quot;plugin&quot;"
-        class="plugin-item"
-      >
-        <el-button
-          v-if="item !== 'tempPlugin'"
-          type="info"
-          plain
-          @click="showPlugin(item)"
-        >
-          {{ item }}
-        </el-button>
-
-        <el-button
-          v-if="item !== 'tempPlugin'"
-          type="danger"
-          @click.prevent="removePlugin(item)"
-        >
-          {{ $t('button.delete') }}
-        </el-button>
-
-        <el-select
-          v-if="item === 'tempPlugin'"
-          :value="null"
-          class="plugin-select"
-          placeholder="Select a Plugin"
-          @change="showPlugin"
-        >
-          <el-option
-            v-for="name in filteredPluginList"
-            :key="name"
-            :label="name"
-            :value="name"
-          />
-        </el-select>
-      </el-form-item>
-
-      <el-form-item>
-        <el-button
-          :disabled="!filteredPluginList.length"
-          @click="addPlugin"
-        >
-          {{ $t('button.add_plugin') }}
-        </el-button>
-      </el-form-item>
-      <VarArgs
-        :p-vars.sync="form.vars"
-        @onChange="onVarArgsChange"
-      />
-
-      <el-form-item
-        label="filter_func"
-        prop="filter_func"
-      >
-        <el-input
-          v-model="form.filter_func"
-          type="textarea"
-          :autosize="{minRows: 2, maxRows: 4}"
-          :placeholder="$t('schema.route.fileterFunc')"
-        />
-      </el-form-item>
-
-      <el-form-item>
-        <el-button
-          type="primary"
-          @click="onSubmit"
-        >
-          {{ $t('button.save') }}
-        </el-button>
-        <el-button @click="toPreviousPage">
-          {{ $t('button.cancel') }}
-        </el-button>
-      </el-form-item>
-    </el-form>
-    <PluginDialog
-      :show="showPluginDialog"
-      :name="pluginName"
-      :plugin-data="form.plugins[pluginName]"
-      @hidePlugin="showPluginDialog = false"
-      @save="onPluginSave"
-    />
-  </div>
-</template>
-
-<script lang='ts'>
-import { Component, Vue } from 'vue-property-decorator'
-import { Form } from 'element-ui'
-
-import PluginDialog from '@/components/PluginDialog/index.vue'
-import VarArgs from '@/components/VarArgs/index.vue'
-
-import { getRouter, createRouter, updateRouter } from '@/api/schema/routes'
-import { getPluginList } from '@/api/schema/plugins'
-import { getUpstreamList } from '@/api/schema/upstream'
-import { getServiceList } from '@/api/schema/services'
-import { TagsViewModule } from '@/store/modules/tags-view'
-
-import i18n from '@/lang'
-
-@Component({
-  name: 'RouterEdit',
-  components: {
-    PluginDialog,
-    VarArgs
-  }
-})
-
-export default class extends Vue {
-  private form = {
-    uris: [],
-    hosts: [],
-    remote_addr: '',
-    upstream_id: '',
-    service_id: '',
-    methods: [],
-    plugins: {},
-    vars: [],
-    desc: '',
-    filter_func: ''
-  }
-
-  // TODO: can add existed info from route list
-  private ExistedUris = [{}]
-  private ExistedHosts = [{}]
-  private validateFilterFuncRegexp = /^function\(\)[^]*?\bend$/
-
-  private rules = {
-    uris: {
-      required: true
-    },
-    filter_func: [
-      { pattern: this.validateFilterFuncRegexp, trigger: 'blur', message: i18n.t('schema.route.fileterFunc') }
-    ]
-  }
-  private isEditMode: boolean = false
-
-  private methods = [
-    'GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'
-  ]
-
-  private pluginList = []
-  private pluginName: string = ''
-  private showPluginDialog: boolean = false
-  private upstreamList = []
-  private serviceList = []
-
-  created() {
-    this.isEditMode = (this.$route as any).name.indexOf('Create') === -1
-
-    if (this.isEditMode) {
-      this.getData()
-    }
-
-    this.getPluginList()
-    this.getUpstreamList()
-    this.getServiceList()
-  }
-
-  get filteredPluginList() {
-    return this.pluginList.filter(item => !this.form.plugins.hasOwnProperty(item))
-  }
-
-  private reset() {
-    this.form = {
-      uris: [],
-      hosts: [],
-      remote_addr: '',
-      upstream_id: '',
-      service_id: '',
-      methods: [],
-      plugins: {},
-      vars: [],
-      desc: '',
-      filter_func: ''
-    }
-  }
-
-  filterDataWithRegex(val: any, regex: any) {
-    if (val.length > 0) {
-      const newArr: string[] = []
-      val.filter(function(item: any) {
-        if (typeof item === 'string') {
-          item = item.replace(/\s+/g, '')
-          if (regex.test(item)) {
-            newArr.push(item)
-          }
-        }
-      })
-
-      newArr.map(function(item: any, index: number) {
-        val[index] = item
-      })
-
-      if (val.length > newArr.length) {
-        val.splice(newArr.length, val.length)
-      }
-    }
-  }
-
-  private filterUriOptions(val: any) {
-    this.filterDataWithRegex(val, new RegExp('^([\\*\\./0-9a-zA-Z-_~@\\?\\!#$\\(\\)]+)$'))
-  }
-
-  private async getData() {
-    const { id } = this.$route.params
-    let {
-      node: {
-        value: {
-          uri = '',
-          uris = [],
-          hosts = [],
-          host = '',
-          remote_addr = '',
-          upstream_id = '',
-          service_id = '',
-          methods = [],
-          plugins = {},
-          vars = [],
-          desc = '',
-          filter_func = ''
-        }
-      }
-    } = await getRouter(id) as any
-
-    if (hosts.length === 0 && host.length > 0) {
-      hosts.push(host)
-    }
-
-    if (uris.length === 0 && uri.length > 0) {
-      uris.push(uri)
-    }
-
-    this.form = {
-      uris,
-      hosts,
-      remote_addr,
-      upstream_id,
-      service_id,
-      methods,
-      plugins,
-      vars,
-      desc,
-      filter_func
-    }
-  }
-
-  private async onSubmit() {
-    (this.$refs.form as any).validate(async(valid: boolean, invalidField: any) => {
-      if (valid) {
-        let data = Object.assign({}, this.form)
-        if (!data.methods.length) {
-          delete data.methods
-        }
-
-        Object.entries(data).forEach(([key, value]) => {
-          if (typeof data[key] === 'object') {
-            if (key !== 'plugins' && Object.keys(value).length === 0) {
-              delete data[key]
-            }
-          } else {
-            if (value === '') {
-              delete data[key]
-            }
-          }
-        })
-
-        delete data['tempPlugin']
-        if (this.isEditMode) {
-          await updateRouter(this.$route.params.id, data)
-        } else {
-          await createRouter(data)
-        }
-
-        this.$message.success(`${this.isEditMode ? 'Update the' : 'Create a'} service successfully!`)
-
-        if (!this.isEditMode) {
-          TagsViewModule.delView(this.$route)
-          this.$nextTick(() => {
-            this.$router.push({
-              name: 'SchemaRoutesList'
-            })
-          })
-        }
-      } else {
-        if (invalidField.filter_func) {
-          this.$message.warning(invalidField.filter_func[0].message)
-        }
-        return false
-      }
-    })
-  }
-
-  private toPreviousPage() {
-    this.$router.go(-1)
-  }
-
-  private async getUpstreamList() {
-    const {
-      node: {
-        nodes = []
-      }
-    } = await getUpstreamList() as any
-
-    this.upstreamList = nodes.map((item: any) => {
-      const id = item.key.match(/\/([0-9]+)/)[1]
-      return {
-        ...item.value,
-        id
-      }
-    })
-  }
-
-  private async getServiceList() {
-    const {
-      node: {
-        nodes = []
-      }
-    } = await getServiceList() as any
-
-    this.serviceList = nodes.map((item: any) => {
-      const id = item.key.match(/\/([0-9]+)/)[1]
-      return {
-        ...item.value,
-        id
-      }
-    })
-  }
-
-  private async getPluginList() {
-    this.pluginList = await getPluginList() as any
-  }
-
-  private async showPlugin(name: string) {
-    this.pluginName = name
-    this.showPluginDialog = true
-  }
-
-  private onPluginSave(name: string, data: any) {
-    delete this.form.plugins['tempPlugin']
-    this.showPluginDialog = false
-    this.form.plugins[name] = data
-  }
-
-  private async addPlugin() {
-    if (this.form.plugins.hasOwnProperty('tempPlugin')) return
-
-    this.form.plugins = {
-      ...this.form.plugins,
-      tempPlugin: null
-    }
-  }
-
-  private removePlugin(name: any) {
-    this.$confirm(`Do you want to remove ${name} plugin?`, 'Warning', {
-      confirmButtonText: 'Confirm',
-      cancelButtonText: 'Cancel',
-      type: 'warning'
-    })
-      .then(async() => {
-        Vue.delete(this.form.plugins, name)
-      }).catch(() => {})
-  }
-
-  private onVarArgsChange(val: any) {
-    this.form.vars = val
-  }
-}
-</script>
-
-<style lang='scss'>
-.container {
-  padding: 20px;
-  .el-form {
-    .el-form-item {
-      .el-form-item__content {
-        .el-input {
-          width: 300px;
-        }
-        .tip {
-          line-height: 24px;
-          font-size: 12px;
-          margin: 0;
-          color: #8e8c8c;
-        }
-      }
-    }
-  }
-  .var-item {
-    .el-form-item {
-      margin-bottom: 10px;
-      display: inline-block;
-      .el-form-item__content {
-        margin-right: 10px;
-      }
-    }
-  }
-}
-</style>
diff --git a/src/views/schema/routes/list.vue b/src/views/schema/routes/list.vue
deleted file mode 100644
index 2014c4d..0000000
--- a/src/views/schema/routes/list.vue
+++ /dev/null
@@ -1,252 +0,0 @@
-<!--
-#
-# 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.
-#
--->
-
-<template>
-  <div class="app-container">
-    <div class="filter-container">
-      <el-button
-        class="filter-item"
-        style="margin-left: 10px;"
-        type="primary"
-        icon="el-icon-edit"
-        @click="handleCreate"
-      >
-        {{ $t('table.add') }}
-      </el-button>
-    </div>
-
-    <el-table
-      :key="tableKey"
-      v-loading="listLoading"
-      :data="tableData"
-      :border="false"
-      fit
-      highlight-current-row
-      style="width: 100%;"
-      :default-sort="{prop: 'id', order: 'descending'}"
-      @sort-change="sortChange"
-    >
-      <el-table-column
-        v-for="(item, index) of tableKeys"
-        :key="index"
-        :label="item.key"
-        :prop="item.key"
-        :width="item.width"
-        :class-name="item.align === 'left' ? '' : 'status-col'"
-        header-align="center"
-      />
-      <el-table-column
-        :label="$t('table.actions')"
-        align="center"
-        width="200"
-        class-name="fixed-width"
-        fixed="right"
-      >
-        <template slot-scope="{row}">
-          <el-button
-            type="primary"
-            size="mini"
-            @click="handleToEdit(row)"
-          >
-            {{ $t('table.edit') }}
-          </el-button>
-
-          <el-button
-            v-if="row.status!=='deleted'"
-            size="mini"
-            type="danger"
-            @click="handleRemove(row)"
-          >
-            {{ $t('table.delete') }}
-          </el-button>
-        </template>
-      </el-table-column>
-    </el-table>
-  </div>
-</template>
-
-<script lang="ts">
-import { Component, Vue } from 'vue-property-decorator'
-import { Form } from 'element-ui'
-
-import Pagination from '../../../components/Pagination/index.vue'
-
-import { getList, removeRouter } from '../../../api/schema/routes'
-
-@Component({
-  name: 'RoutesList',
-  components: {
-    Pagination
-  }
-})
-export default class extends Vue {
-  private tableKey = 0
-  private list = []
-  private total = 0
-  private listLoading = true
-  private listQuery = {
-    page: 1,
-    limit: 20,
-    importance: undefined,
-    title: undefined,
-    type: undefined,
-    sort: '+id'
-  }
-
-  private tableData = []
-  private tableKeys: any[] = []
-
-  created() {
-    this.getList()
-  }
-
-  private async getList() {
-    this.listLoading = true
-    this.tableKeys = [
-      {
-        key: 'id',
-        width: 80
-      }, {
-        key: 'description',
-        width: 300,
-        align: 'left'
-      }, {
-        key: 'uri',
-        width: 200
-      }, {
-        key: 'host',
-        width: 200
-      }, {
-        key: 'remote_addr',
-        width: 200
-      }, {
-        key: 'upstream_id',
-        width: 200
-      }, {
-        key: 'service_id',
-        width: 200
-      }, {
-        key: 'methods',
-        width: 200
-      }, {
-        key: 'plugins',
-        width: 400
-      }
-    ]
-
-    let { node: { nodes = [] } } = await getList() as any
-    nodes = [...nodes].map((item: any) => {
-      const id = item.key.match(/\/([a-zA-Z0-9-_]+)$/)[1]
-      const fakeId = id
-
-      let {
-        uri = '',
-        host = '',
-        remote_addr = '',
-        upstream_id = '',
-        service_id = '',
-        methods = [],
-        plugins = {},
-        desc = ''
-      } = item.value
-
-      methods = methods.join(', ')
-
-      if (item.value.uris) {
-        uri = item.value.uris.join(', ')
-      }
-
-      if (item.value.hosts) {
-        host = item.value.hosts.join('\n ')
-      }
-
-      plugins = Object.keys(plugins as any).join(', ')
-
-      return {
-        id: fakeId,
-        realId: id,
-        uri,
-        host,
-        remote_addr,
-        upstream_id: upstream_id && String(upstream_id).replace(/^(0+)/, ''),
-        service_id: service_id && String(service_id).replace(/^(0+)/, ''),
-        methods,
-        plugins,
-        description: desc
-      }
-    })
-
-    this.tableData = nodes
-    this.total = nodes.length
-
-    setTimeout(() => {
-      this.listLoading = false
-    }, 0.5 * 1000)
-  }
-
-  private handleFilter() {
-    this.listQuery.page = 1
-    this.getList()
-  }
-
-  private handleRemove(row: any) {
-    this.$confirm(`Do you want to remove router ${row.id}?`, 'Warning', {
-      confirmButtonText: 'Confirm',
-      cancelButtonText: 'Cancel',
-      type: 'warning'
-    })
-      .then(async() => {
-        await removeRouter(row.realId)
-        this.getList()
-        this.$message.success(`Remove router ${row.id} successfully!`)
-      })
-  }
-
-  private sortChange(data: any) {
-    const { prop, order } = data
-    if (prop === 'id') {
-      this.sortByID(order)
-    }
-  }
-
-  private sortByID(order: string) {
-    if (order === 'ascending') {
-      this.listQuery.sort = '+id'
-    } else {
-      this.listQuery.sort = '-id'
-    }
-    this.handleFilter()
-  }
-
-  private handleCreate() {
-    this.$router.push({
-      name: 'SchemaRoutesCreate'
-    })
-  }
-
-  private handleToEdit(row: any) {
-    this.$router.push({
-      name: 'SchemaRoutesEdit',
-      params: {
-        id: row.realId
-      }
-    })
-  }
-}
-</script>
diff --git a/src/views/schema/service/edit.vue b/src/views/schema/service/edit.vue
deleted file mode 100644
index 9994b0a..0000000
--- a/src/views/schema/service/edit.vue
+++ /dev/null
@@ -1,300 +0,0 @@
-<!--
-#
-# 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.
-#
--->
-
-<template>
-  <div class="container">
-    <el-form
-      ref="form"
-      :model="form"
-      :rules="rules"
-      label-width="80px"
-      :show-message="false"
-    >
-      <el-form-item
-        label="Desc"
-      >
-        <el-input
-          v-model="form.desc"
-          placeholder="Description"
-        />
-      </el-form-item>
-
-      <el-form-item
-        label="Upstream"
-      >
-        <el-select
-          v-model="form.upstream_id"
-          placeholder="Upstream"
-        >
-          <el-option
-            v-for="item in upstreamList"
-            :key="item.id"
-            :label="item.desc"
-            :value="item.id"
-          />
-        </el-select>
-      </el-form-item>
-
-      <el-form-item
-        v-for="(index, item) in form.plugins"
-        :key="item"
-        :label="&quot;plugin&quot;"
-        class="plugin-item"
-      >
-        <el-button
-          v-if="item !== 'tempPlugin'"
-          type="info"
-          plain
-          @click="showPlugin(item)"
-        >
-          {{ item }}
-        </el-button>
-
-        <el-button
-          v-if="item !== 'tempPlugin'"
-          type="danger"
-          @click.prevent="removePlugin(item)"
-        >
-          {{ $t('button.delete') }}
-        </el-button>
-
-        <el-select
-          v-if="item === 'tempPlugin'"
-          :value="null"
-          class="plugin-select"
-          placeholder="Select a Plugin"
-          @change="showPlugin"
-        >
-          <el-option
-            v-for="name in filteredPluginList"
-            :key="name"
-            :label="name"
-            :value="name"
-          />
-        </el-select>
-      </el-form-item>
-
-      <el-form-item>
-        <el-button
-          :disabled="!filteredPluginList.length"
-          @click="addPlugin"
-        >
-          {{ $t('button.add_plugin') }}
-        </el-button>
-      </el-form-item>
-
-      <el-form-item>
-        <el-button
-          type="primary"
-          @click="onSubmit"
-        >
-          {{ $t('button.save') }}
-        </el-button>
-        <el-button @click="toPreviousPage">
-          {{ $t('button.cancel') }}
-        </el-button>
-      </el-form-item>
-    </el-form>
-    <PluginDialog
-      :show="showPluginDialog"
-      :name="pluginName"
-      :plugin-data="form.plugins[pluginName]"
-      @hidePlugin="showPluginDialog = false"
-      @save="onPluginSave"
-    />
-  </div>
-</template>
-
-<script lang='ts'>
-import { Component, Vue } from 'vue-property-decorator'
-import { Form } from 'element-ui'
-
-import PluginDialog from '@/components/PluginDialog/index.vue'
-
-import { getUpstreamList } from '@/api/schema/upstream'
-import { getService, createService, updateService } from '@/api/schema/services'
-import { getPluginList } from '@/api/schema/plugins'
-import { TagsViewModule } from '@/store/modules/tags-view'
-
-@Component({
-  name: 'RouterEdit',
-  components: {
-    PluginDialog
-  }
-})
-export default class extends Vue {
-  private form = {
-    plugins: {},
-    upstream_id: '',
-    desc: ''
-  }
-
-  private rules = {}
-  private isEditMode: boolean = false
-
-  private pluginList = []
-  private pluginName: string = ''
-  private showPluginDialog: boolean = false
-  private upstreamList = []
-
-  created() {
-    this.isEditMode = (this.$route as any).name.indexOf('Create') === -1
-
-    this.getUpstreamList()
-    this.getPluginList()
-
-    if (this.isEditMode) {
-      this.getData()
-    }
-  }
-
-  get filteredPluginList() {
-    return this.pluginList.filter(item => !this.form.plugins.hasOwnProperty(item))
-  }
-
-  private toPreviousPage() {
-    this.$router.go(-1)
-  }
-
-  private async getData() {
-    const { id } = this.$route.params
-    let {
-      node: {
-        value: {
-          plugins = {},
-          upstream_id = '',
-          desc = ''
-        }
-      }
-    } = (await getService(id)) as any
-
-    this.form = {
-      plugins,
-      upstream_id,
-      desc
-    }
-  }
-
-  private async getUpstreamList() {
-    const {
-      node: {
-        nodes = []
-      }
-    } = await getUpstreamList() as any
-
-    this.upstreamList = nodes.map((item: any) => {
-      const id = item.key.match(/\/([0-9]+)/)[1]
-      return {
-        ...item.value,
-        id
-      }
-    })
-  }
-
-  private async getPluginList() {
-    this.pluginList = await getPluginList() as any
-  }
-
-  private async showPlugin(name: string) {
-    this.pluginName = name
-    this.showPluginDialog = true
-  }
-
-  private onPluginSave(name: string, data: any) {
-    delete this.form.plugins['tempPlugin']
-    this.showPluginDialog = false
-    this.form.plugins[name] = data
-  }
-
-  private async addPlugin() {
-    if (this.form.plugins.hasOwnProperty('tempPlugin')) return
-
-    this.form.plugins = {
-      ...this.form.plugins,
-      tempPlugin: null
-    }
-  }
-
-  private async onSubmit() {
-    (this.$refs.form as any).validate(async(valid: boolean) => {
-      console.log('onSubmit', this.form)
-
-      if (valid) {
-        let data = Object.assign({}, this.form)
-        Object.entries(data).forEach(([key, value]) => {
-          if (typeof data[key] === 'object') {
-            if (key !== 'plugins' && Object.keys(value).length === 0) {
-              delete data[key]
-            }
-          } else {
-            if (value === '') {
-              delete data[key]
-            }
-          }
-        })
-
-        if (this.isEditMode) {
-          await updateService(this.$route.params.id, data)
-        } else {
-          await createService(data)
-        }
-
-        this.$message.success(`${this.isEditMode ? 'Update the' : 'Create a'} service successfully!`)
-
-        if (!this.isEditMode) {
-          TagsViewModule.delView(this.$route)
-          this.$nextTick(() => {
-            this.$router.push({
-              name: 'SchemaServiceList'
-            })
-          })
-        }
-      } else {
-        return false
-      }
-    })
-  }
-
-  private removePlugin(name: any) {
-    this.$confirm(`Do you want to remove ${name} plugin?`, 'Warning', {
-      confirmButtonText: 'Confirm',
-      cancelButtonText: 'Cancel',
-      type: 'warning'
-    })
-      .then(async() => {
-        Vue.delete(this.form.plugins, name)
-      }).catch(() => {})
-  }
-}
-</script>
-
-<style lang='scss'>
-.container {
-  padding: 20px;
-  .el-form {
-    .el-form-item {
-      .el-form-item__content {
-        .el-input {
-          width: 220px;
-        }
-      }
-    }
-  }
-}
-</style>
diff --git a/src/views/schema/service/list.vue b/src/views/schema/service/list.vue
deleted file mode 100644
index c4f424c..0000000
--- a/src/views/schema/service/list.vue
+++ /dev/null
@@ -1,215 +0,0 @@
-<!--
-#
-# 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.
-#
--->
-
-<template>
-  <div class="app-container">
-    <div class="filter-container">
-      <el-button
-        class="filter-item"
-        style="margin-left: 10px;"
-        type="primary"
-        icon="el-icon-edit"
-        @click="handleCreate"
-      >
-        {{ $t('table.add') }}
-      </el-button>
-    </div>
-
-    <el-table
-      :key="tableKey"
-      v-loading="listLoading"
-      :data="tableData"
-      :border="false"
-      fit
-      highlight-current-row
-      style="width: 100%;"
-      :default-sort="{prop: 'id', order: 'descending'}"
-      @sort-change="sortChange"
-    >
-      <el-table-column
-        v-for="(item, index) of tableKeys"
-        :key="index"
-        :label="item.key"
-        :prop="item.key"
-        :width="item.width"
-        :class-name="item.align === 'left' ? '' : 'status-col'"
-        header-align="center"
-      />
-      <el-table-column
-        :label="$t('table.actions')"
-        align="center"
-        width="230"
-        class-name="fixed-width"
-      >
-        <template slot-scope="{row}">
-          <el-button
-            type="primary"
-            size="mini"
-            @click="handleToEdit(row)"
-          >
-            {{ $t('table.edit') }}
-          </el-button>
-
-          <el-button
-            v-if="row.status!=='deleted'"
-            size="mini"
-            type="danger"
-            @click="handleRemove(row)"
-          >
-            {{ $t('table.delete') }}
-          </el-button>
-        </template>
-      </el-table-column>
-    </el-table>
-  </div>
-</template>
-
-<script lang="ts">
-import { Component, Vue } from 'vue-property-decorator'
-import { Form } from 'element-ui'
-
-import Pagination from '@/components/Pagination/index.vue'
-
-import { getServiceList, removeService } from '@/api/schema/services'
-
-@Component({
-  name: 'ServiceList',
-  components: {
-    Pagination
-  }
-})
-export default class extends Vue {
-  private tableKey = 0
-  private list = []
-  private total = 0
-  private listLoading = true
-  private listQuery = {
-    page: 1,
-    limit: 20,
-    importance: undefined,
-    title: undefined,
-    type: undefined,
-    sort: '+id'
-  }
-
-  private tableData = []
-  private tableKeys: any[] = []
-
-  created() {
-    this.getList()
-  }
-
-  private async getList() {
-    this.listLoading = true
-
-    this.tableKeys = [
-      {
-        key: 'id',
-        width: 100
-      }, {
-        key: 'description',
-        width: 300,
-        align: 'left'
-      }, {
-        key: 'plugins',
-        width: 400
-      }
-    ]
-    let { node: { nodes = [] } } = await getServiceList() as any
-    nodes = [...nodes].map((item: any) => {
-      const id = item.key.match(/\/([a-zA-Z0-9-_]+)$/)[1]
-      const fakeId = id
-      const desc = item.value.desc
-
-      const pluginArr: any[] = []
-      if (item.value.plugins !== undefined) {
-        Object.entries(item.value.plugins as any).map(([ key, value ]: any) => {
-          pluginArr.push({
-            name: key,
-            key: value.key
-          })
-        })
-      }
-
-      return {
-        id: fakeId,
-        realId: id,
-        plugins: pluginArr.map((item: any) => item.name).join(', '),
-        description: desc
-      }
-    })
-
-    this.tableData = nodes
-    this.total = nodes.length
-
-    setTimeout(() => {
-      this.listLoading = false
-    }, 0.5 * 1000)
-  }
-
-  private handleFilter() {
-    this.listQuery.page = 1
-    this.getList()
-  }
-
-  private handleRemove(row: any) {
-    this.$confirm(`Do you want to remove service ${row.id}?`, 'Warning', {
-      confirmButtonText: 'Confirm',
-      cancelButtonText: 'Cancel',
-      type: 'warning'
-    })
-      .then(async() => {
-        await removeService(row.realId)
-        this.getList()
-        this.$message.success(`Remove service ${row.id} successfully!`)
-      })
-  }
-
-  private sortChange(data: any) {
-    const { prop, order } = data
-    if (prop === 'id') {
-      this.sortByID(order)
-    }
-  }
-
-  private sortByID(order: string) {
-    if (order === 'ascending') {
-      this.listQuery.sort = '+id'
-    } else {
-      this.listQuery.sort = '-id'
-    }
-    this.handleFilter()
-  }
-
-  private handleCreate() {
-    this.$router.push({
-      name: 'SchemaServiceCreate'
-    })
-  }
-
-  private handleToEdit(row: any) {
-    this.$router.push({
-      name: 'SchemaServiceEdit',
-      params: {
-        id: row.realId
-      }
-    })
-  }
-}
-</script>
diff --git a/src/views/schema/ssl/edit.vue b/src/views/schema/ssl/edit.vue
deleted file mode 100644
index 09c30bf..0000000
--- a/src/views/schema/ssl/edit.vue
+++ /dev/null
@@ -1,191 +0,0 @@
-<!--
-#
-# 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.
-#
--->
-
-<template>
-  <div class="container">
-    <el-form
-      ref="form"
-      :model="form"
-      :rules="rules"
-      label-width="80px"
-      :show-message="false"
-    >
-      <el-form-item
-        label="SNI"
-        prop="sni"
-      >
-        <el-input
-          v-model="form.sni"
-          placeholder="SNI"
-        />
-      </el-form-item>
-
-      <el-form-item
-        label="CERT"
-        prop="cert"
-      >
-        <el-input
-          v-model="form.cert"
-          placeholder="CERT"
-          type="textarea"
-          :rows="7"
-        />
-      </el-form-item>
-
-      <el-form-item
-        label="KEY"
-        prop="key"
-      >
-        <el-input
-          v-model="form.key"
-          placeholder="KEY"
-          type="textarea"
-          :rows="7"
-        />
-      </el-form-item>
-
-      <el-form-item>
-        <el-button
-          type="primary"
-          @click="onSubmit"
-        >
-          {{ $t('button.save') }}
-        </el-button>
-        <el-button @click="toPreviousPage">
-          {{ $t('button.cancel') }}
-        </el-button>
-      </el-form-item>
-    </el-form>
-  </div>
-</template>
-
-<script lang='ts'>
-import { Component, Vue } from 'vue-property-decorator'
-import { Form } from 'element-ui'
-
-import { TagsViewModule } from '@/store/modules/tags-view'
-import { getSSL, updateSSL, createSSL } from '@/api/schema/ssl'
-
-@Component({
-  name: 'RouterEdit'
-})
-export default class extends Vue {
-  private form = {
-    sni: '',
-    cert: '',
-    key: ''
-  };
-
-  private rules = {
-    sni: {
-      required: true
-    },
-    cert: {
-      required: true
-    },
-    key: {
-      required: true
-    }
-  }
-  private isEditMode: boolean = false;
-
-  created() {
-    this.isEditMode = (this.$route as any).name.indexOf('Create') === -1
-
-    if (this.isEditMode) {
-      this.getData()
-    }
-  }
-
-  private async getData() {
-    const { id } = this.$route.params
-    let {
-      node: {
-        value: {
-          sni = '',
-          cert = '',
-          key = ''
-        }
-      }
-    } = (await getSSL(id)) as any
-
-    this.form = {
-      sni,
-      cert,
-      key
-    }
-  }
-
-  private async onSubmit() {
-    (this.$refs.form as any).validate(async(valid: boolean) => {
-      console.log('onSubmit', this.form)
-
-      if (valid) {
-        let data = Object.assign({}, this.form)
-        Object.entries(data).forEach(([key, value]) => {
-          if (value === '') {
-            delete data[key]
-          }
-        })
-
-        if (this.isEditMode) {
-          await updateSSL(this.$route.params.id, data)
-        } else {
-          await createSSL(data)
-        }
-
-        this.$message.success(
-          `${this.isEditMode ? 'Update the' : 'Create a'} ssl successfully!`
-        )
-
-        if (!this.isEditMode) {
-          TagsViewModule.delView(this.$route)
-          this.$nextTick(() => {
-            this.$router.push({
-              name: 'SchemaSSLList'
-            })
-          })
-        }
-      } else {
-        return false
-      }
-    })
-  }
-
-  private toPreviousPage() {
-    this.$router.go(-1)
-  }
-}
-</script>
-
-<style lang='scss'>
-.container {
-  padding: 20px;
-  .el-form-item {
-    .el-form-item__content {
-      .el-input {
-        width: 300px;
-      }
-      .el-textarea {
-        width: 400px;
-      }
-    }
-  }
-}
-</style>
diff --git a/src/views/schema/ssl/list.vue b/src/views/schema/ssl/list.vue
deleted file mode 100644
index ff20897..0000000
--- a/src/views/schema/ssl/list.vue
+++ /dev/null
@@ -1,206 +0,0 @@
-<!--
-#
-# 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.
-#
--->
-
-<template>
-  <div class="app-container">
-    <div class="filter-container">
-      <el-button
-        class="filter-item"
-        style="margin-left: 10px;"
-        type="primary"
-        icon="el-icon-edit"
-        @click="handleCreate"
-      >
-        {{ $t('table.add') }}
-      </el-button>
-    </div>
-
-    <el-table
-      :key="tableKey"
-      v-loading="listLoading"
-      :data="tableData"
-      :border="false"
-      fit
-      highlight-current-row
-      style="width: 100%;"
-      :default-sort="{prop: 'id', order: 'descending'}"
-      @sort-change="sortChange"
-    >
-      <el-table-column
-        v-for="(item, index) of tableKeys"
-        :key="index"
-        :label="item.key"
-        :prop="item.key"
-        :width="item.width"
-        class-name="status-col"
-      />
-      <el-table-column
-        :label="$t('table.actions')"
-        align="center"
-        width="230"
-        class-name="fixed-width"
-      >
-        <template slot-scope="{row}">
-          <el-button
-            type="primary"
-            size="mini"
-            @click="handleToEdit(row)"
-          >
-            {{ $t('table.edit') }}
-          </el-button>
-
-          <el-button
-            v-if="row.status!=='deleted'"
-            size="mini"
-            type="danger"
-            @click="handleRemove(row)"
-          >
-            {{ $t('table.delete') }}
-          </el-button>
-        </template>
-      </el-table-column>
-    </el-table>
-  </div>
-</template>
-
-<script lang="ts">
-import { Component, Vue } from 'vue-property-decorator'
-import { Form } from 'element-ui'
-
-import Pagination from '@/components/Pagination/index.vue'
-
-import { getSSLList, removeSSL } from '@/api/schema/ssl'
-
-@Component({
-  name: 'UpstreamList',
-  components: {
-    Pagination
-  }
-})
-export default class extends Vue {
-  private tableKey = 0
-  private list = []
-  private total = 0
-  private listLoading = true
-  private listQuery = {
-    page: 1,
-    limit: 20,
-    importance: undefined,
-    title: undefined,
-    type: undefined,
-    sort: '+id'
-  }
-
-  private tableData = []
-  private tableKeys: any[] = []
-
-  created() {
-    this.getList()
-  }
-
-  private async getList() {
-    this.listLoading = true
-
-    this.tableKeys = [
-      {
-        key: 'id',
-        width: 100
-      }, {
-        key: 'sni',
-        width: 300
-      }
-    ]
-    let { node: { nodes = [] } } = await getSSLList() as any
-    nodes = [...nodes].map((item: any) => {
-      const id = item.key.match(/\/([a-zA-Z0-9-_]+)$/)[1]
-      const fakeId = id
-
-      return {
-        id: fakeId,
-        realId: id,
-        sni: item.value.sni
-      }
-    })
-
-    this.tableData = nodes
-    this.total = nodes.length
-
-    setTimeout(() => {
-      this.listLoading = false
-    }, 0.5 * 1000)
-  }
-
-  private handleFilter() {
-    this.listQuery.page = 1
-    this.getList()
-  }
-
-  private handleRemove(row: any) {
-    this.$confirm(`Do you want to remove ssl ${row.id}?`, 'Warning', {
-      confirmButtonText: 'Confirm',
-      cancelButtonText: 'Cancel',
-      type: 'warning'
-    })
-      .then(async() => {
-        await removeSSL(row.realId)
-        this.getList()
-        this.$message.success(`Remove ssl ${row.id} successfully!`)
-      })
-  }
-
-  private sortChange(data: any) {
-    const { prop, order } = data
-    if (prop === 'id') {
-      this.sortByID(order)
-    }
-  }
-
-  private sortByID(order: string) {
-    if (order === 'ascending') {
-      this.listQuery.sort = '+id'
-    } else {
-      this.listQuery.sort = '-id'
-    }
-    this.handleFilter()
-  }
-
-  private handleCreate() {
-    this.$router.push({
-      name: 'SchemaSSLCreate'
-    })
-  }
-
-  private handleToEdit(row: any) {
-    this.$router.push({
-      name: 'SchemaSSLEdit',
-      params: {
-        id: row.realId
-      }
-    })
-  }
-}
-</script>
-
-<style lang="scss">
-.app-container {
-  .el-table::before {
-    height: 0 !important;
-  }
-}
-</style>
diff --git a/src/views/schema/upstream/edit.vue b/src/views/schema/upstream/edit.vue
deleted file mode 100644
index 445e42d..0000000
--- a/src/views/schema/upstream/edit.vue
+++ /dev/null
@@ -1,434 +0,0 @@
-<!--
-#
-# 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.
-#
--->
-
-<template>
-  <div class="container">
-    <el-form
-      ref="form"
-      :model="form"
-      :rules="rules"
-      label-width="80px"
-      :show-message="false"
-    >
-      <el-form-item
-        label="Desc"
-      >
-        <el-input
-          v-model="form.desc"
-          placeholder="Description"
-        />
-      </el-form-item>
-
-      <el-form-item
-        label="Type"
-        prop="type"
-      >
-        <el-select
-          v-model="form.type"
-          placeholder="Select a Type"
-          @change="typeSelectorChange"
-        >
-          <el-option
-            v-for="item in types"
-            :key="item"
-            :label="item"
-            :value="item"
-          />
-        </el-select>
-      </el-form-item>
-
-      <el-form-item
-        label="Hash On"
-      >
-        <el-select
-          v-model="form.hash_on"
-          filterable
-          default-first-option
-          value-key="form.hash_on"
-          :disabled="form.type !== 'chash'"
-        >
-          <el-option
-            v-for="item in defaultHashOnKeys"
-            :key="item.value"
-            :label="item.label"
-            :value="item.value"
-          />
-        </el-select>
-        <p class="tip">
-          {{ $t('upstream.hashOnTip') }}
-        </p>
-      </el-form-item>
-
-      <el-form-item
-        label="Key"
-      >
-        <el-select
-          v-model="form.key"
-          placeholder="Input a Key"
-          allow-create
-          filterable
-          default-first-option
-          value-key="form.key"
-          clearable
-          :disabled="form.type !== 'chash'"
-        >
-          <el-option
-            v-for="item in defaultHashKeys"
-            :key="item.value"
-            :label="item.label"
-            :value="item.value"
-          />
-        </el-select>
-        <p class="tip">
-          {{ $t('upstream.keyTip') }}
-        </p>
-      </el-form-item>
-
-      <el-form-item
-        label="WebSocket"
-      >
-        <el-switch
-          v-model="form.enable_websocket"
-
-          active-color="#13ce66"
-          inactive-color="#ff4949"
-        />
-        <p class="tip">
-          {{ form.enable_websocket ? $t('upstream.websocket.EnabledTip') : $t('upstream.websocket.DisabledTip') }}
-        </p>
-      </el-form-item>
-
-      <el-form-item
-        v-for="(item, index) in form.nodes"
-        :key="index"
-        :label="'Node' + (index + 1)"
-        class="node-item"
-      >
-        <el-form-item
-          :rules="[{required: true, pattern: IPAndURLRegexp, type: 'string'}]"
-          :prop="'nodes.' + index + '.ip'"
-        >
-          <el-input
-            v-model="item.ip"
-            placeholder="IP/HOST"
-          />
-        </el-form-item>
-        <el-form-item
-          :rules="[{required: true}]"
-          :prop="'nodes.' + index + '.port'"
-        >
-          <el-input
-            v-model="item.port"
-            placeholder="Port"
-            type="number"
-          />
-        </el-form-item>
-        <el-form-item
-          :rules="[{required: true}]"
-          :prop="'nodes.' + index + '.weights'"
-        >
-          <el-input
-            v-model="item.weights"
-            placeholder="Weights"
-            type="number"
-          />
-        </el-form-item>
-        <el-form-item>
-          <el-button
-            type="danger"
-            @click.prevent="removeNode(item)"
-          >
-            {{ $t('button.delete') }}
-          </el-button>
-        </el-form-item>
-      </el-form-item>
-
-      <el-form-item>
-        <el-button
-          @click="addNode"
-        >
-          {{ $t('button.add_node') }}
-        </el-button>
-      </el-form-item>
-
-      <el-form-item>
-        <el-button
-          type="primary"
-          @click="onSubmit"
-        >
-          {{ $t('button.save') }}
-        </el-button>
-        <el-button @click="toPreviousPage">
-          {{ $t('button.cancel') }}
-        </el-button>
-      </el-form-item>
-    </el-form>
-  </div>
-</template>
-
-<script lang='ts'>
-import { Component, Vue } from 'vue-property-decorator'
-import { Form } from 'element-ui'
-
-import { getUpstream, createUpstream, updateStream } from '../../../api/schema/upstream'
-import { TagsViewModule } from '@/store/modules/tags-view'
-
-@Component({
-  name: 'RouterEdit'
-})
-export default class extends Vue {
-  private IPAndURLRegexp = /^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3})$|^((([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9]*[A-Za-z0-9]))$/
-  private form = {
-    type: null,
-    key: null,
-    nodes: [],
-    desc: '',
-    enable_websocket: null,
-    hash_on: null
-  }
-
-  private rules = {
-    type: {
-      required: true
-    }
-  }
-  private isEditMode: boolean = false
-
-  private types = ['roundrobin', 'chash']
-
-  private defaultHashOnKeys = [
-    {
-      value: 'vars',
-      label: 'vars'
-    },
-    {
-      value: 'header',
-      label: 'header'
-    },
-    {
-      value: 'cookie',
-      label: 'cookie'
-    },
-    {
-      value: 'consumer',
-      label: 'consumer'
-    }
-  ]
-
-  private defaultHashKeys = [
-    {
-      value: 'remote_addr',
-      label: 'remote_addr'
-    },
-    {
-      value: 'host',
-      label: 'host'
-    },
-    {
-      value: 'uri',
-      label: 'uri'
-    },
-    {
-      value: 'server_name',
-      label: 'server_name'
-    },
-    {
... 10053 lines suppressed ...