├── .browserslistrc ├── .env ├── .env.development ├── .eslintrc.js ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── dependabot.yml ├── pull_request_template.md └── workflows │ ├── check.yml │ └── release.yml ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── babel.config.js ├── jsconfig.json ├── package-lock.json ├── package.json ├── postcss.config.js ├── public ├── favicon.ico ├── img │ └── icons │ │ ├── android-chrome-192x192.png │ │ ├── android-chrome-512x512.png │ │ ├── apple-touch-icon-120x120.png │ │ ├── apple-touch-icon-152x152.png │ │ ├── apple-touch-icon-180x180.png │ │ ├── apple-touch-icon-60x60.png │ │ ├── apple-touch-icon-76x76.png │ │ ├── apple-touch-icon.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── msapplication-icon-144x144.png │ │ ├── mstile-150x150.png │ │ └── safari-pinned-tab.svg ├── index.html ├── manifest.json └── robots.txt ├── src ├── App.vue ├── api │ ├── ajax.js │ ├── auth.js │ ├── book.js │ ├── category.js │ └── format.js ├── assets │ └── logo.png ├── components │ ├── ConfirmDialog.vue │ └── ViewBase.vue ├── const.js ├── main.js ├── plugins │ ├── custom.js │ ├── dialog │ │ └── index.js │ ├── fortawesome.js │ └── vue-material.js ├── registerServiceWorker.js ├── router │ └── router.js ├── store │ ├── mutation-types.js │ └── store.js └── views │ ├── AboutView.vue │ ├── CreateCard.vue │ ├── EditCard.vue │ ├── HomeView.vue │ └── LoginView.vue └── vue.config.js /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not ie <= 8 4 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | # environment variables for common 2 | 3 | VUE_APP_API_ROOT=/ -------------------------------------------------------------------------------- /.env.development: -------------------------------------------------------------------------------- 1 | # environment variables for development 2 | 3 | VUE_APP_API_ROOT=http://localhost:8080 -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true 5 | }, 6 | 'extends': [ 7 | 'plugin:vue/essential', 8 | 'eslint:recommended' 9 | ], 10 | rules: { 11 | 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', 12 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off' 13 | }, 14 | parserOptions: { 15 | parser: 'babel-eslint' 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[BUG]" 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Summary 11 | > Write the actual behavior and the purpose to modify. 12 | 13 | ## Cause 14 | > Why such a problem happened? 15 | 16 | ### To reproduce 17 | Perform the follwing steps to reproduce the problem. 18 | 19 | 1. … 20 | 1. … 21 | 22 | ## Expected behavior 23 | Expected the follwing behavior. 24 | 25 | ## How to deal with this issue 26 | > How do you fix it? 27 | 28 | ## Notes 29 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "[NEW]" 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Purpose 11 | > What is it necessary for? 12 | 13 | ## Expected behavior 14 | Expected the follwing behavior. 15 | 16 | ## How to deal with this issue 17 | > How do you fix it? 18 | 19 | ## Notes 20 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | - package-ecosystem: github-actions 8 | directory: "/" 9 | schedule: 10 | interval: daily -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ### Fixes #[ISSUE NUMBER]. 2 | 3 | Changes proposed in this pull request: 4 | 5 | - ... 6 | - ... 7 | - ... 8 | 9 | by [YOUR NAME] 10 | -------------------------------------------------------------------------------- /.github/workflows/check.yml: -------------------------------------------------------------------------------- 1 | name: check 2 | 3 | on: 4 | pull_request: 5 | branches: [ master ] 6 | 7 | jobs: 8 | check: 9 | name: check 10 | runs-on: ubuntu-latest 11 | strategy: 12 | matrix: 13 | node-version: [14.x] 14 | steps: 15 | - uses: actions/checkout@v3.2.0 16 | - name: eslint review 17 | uses: reviewdog/action-eslint@v1.17 18 | with: 19 | github_token: ${{ secrets.github_token }} 20 | reporter: github-pr-review 21 | eslint_flags: 'src/**/*.{vue,js}' 22 | - name: use Node.js ${{ matrix.node-version }} 23 | uses: actions/setup-node@v3.5.1 24 | with: 25 | node-version: ${{ matrix.node-version }} 26 | - name: install package 27 | run: npm install 28 | - name: build vue code 29 | run: npm run build -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: release 2 | on: 3 | push: 4 | tags: 5 | - "v[0-9]+.[0-9]+.[0-9]+" 6 | jobs: 7 | Release: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v3.2.0 11 | with: 12 | fetch-depth: 50 13 | - uses: notlmn/release-with-changelog@v3.6.1 14 | with: 15 | token: ${{ secrets.GITHUB_TOKEN }} 16 | exclude: '^polish|^bump|^typo' 17 | commit-template: '- {hash} {title}' 18 | template: | 19 | ### Changelog 20 | 21 | {commits} 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw? 22 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribution 2 | ## Preface 3 | Thank you for considering contributing to this sample application. 4 | I would like to create the sample application such as helpful when you would like to develop a web application using golang. 5 | 6 | ## How to report a bug 7 | Please create a issue which wrote about the following points when you report a bug. 8 | 9 | 1. Version of golang you are using 10 | 1. Operating system you are using 11 | 1. Reprocedure 12 | 1. Expected behavior 13 | 14 | Also, please write about it when you know the causes and how to fix the bug. 15 | 16 | 1. Cause 17 | 1. How to fix 18 | 19 | ## How to suggest a feature or enhancement 20 | Please create a issue which wrote that purpose and expected behavior, when you have functions which you would like to implement as a sample. 21 | 22 | 1. Purpose 23 | 1. Expected behavoir, What kind of function do you propose? 24 | 1. How to develop 25 | 26 | ## How to create a pull request 27 | You can feel free to fork this repository, fix the source code and create a pull request when you have noticed that you can resolve a issue. 28 | And after that, please check passed the check workflow of GitHub Action. 29 | 30 | I will check your pull request, and I may suggest some improvements or alternatives. 31 | If there was no problem, I will merge your changes. 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Yuta Kuroki 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vuejs-webapp-sample 2 | 3 | [![license](https://img.shields.io/github/license/ybkuroki/vuejs-webapp-sample?style=for-the-badge)](https://github.com/ybkuroki/vuejs-webapp-sample/blob/master/LICENSE) 4 | [![workflow](https://img.shields.io/github/actions/workflow/status/ybkuroki/vuejs-webapp-sample/check.yml?label=check&logo=github&style=for-the-badge)](https://github.com/ybkuroki/vuejs-webapp-sample/actions?query=workflow%3Acheck) 5 | [![release](https://img.shields.io/github/release/ybkuroki/vuejs-webapp-sample?style=for-the-badge&logo=github)](https://github.com/ybkuroki/vuejs-webapp-sample/releases) 6 | 7 | ## Preface 8 | This sample project uses [Vue.js](https://vuejs.org/index.html) and [Vue Material](https://vuematerial.io/). It provides only Web UI. So, I recommend using the [golang-webapp-sample](https://github.com/ybkuroki/golang-webapp-sample) project as Back End Application. 9 | 10 | ## Install 11 | Perform the following steps: 12 | 1. Download and install [Node.js](https://nodejs.org/en/). 13 | 1. Download and install [Visual Studio Code(VS Code)](https://code.visualstudio.com/). 14 | 1. Install [vetur](https://github.com/vuejs/vetur) extension for VS Code. 15 | 1. Clone this repository. 16 | 1. Download and install npm packages. 17 | ```bash 18 | npm install 19 | ``` 20 | 21 | ## Starting Server 22 | Perform the following steps: 23 | 1. Perform [golang-webapp-sample](https://github.com/ybkuroki/golang-webapp-sample) project. 24 | 1. Start the development server. 25 | ```bash 26 | npm run serve 27 | ``` 28 | 1. When startup is complete, the console shows the following message: 29 | ``` 30 | DONE Compiled successfully in *****ms 31 | 32 | App running at: 33 | - Local: http://localhost:3000/ 34 | - Network: http://192.168.***.***:3000/ 35 | 36 | Note that the development build is not optimized. 37 | To create a production build, run npm run build. 38 | ``` 39 | 1. Access the following URL in the Chrome. 40 | [http://localhost:3000](http://localhost:3000) 41 | 42 | ## Creating a Production Build 43 | Perform the following command: 44 | ```bash 45 | npm run build 46 | ``` 47 | 48 | ## Project Map 49 | The following figure is the map of this sample project. 50 | 51 | ``` 52 | - vuejs-webapp-sample 53 | + public … Contains resouces of this project. 54 | - src 55 | + assets … Contains source codes that Webpack doesn't need to build. 56 | + components … Contains components of Vue. 57 | + ajax … Implement the common library for Ajax. 58 | + router … Define Vue Router. 59 | + store … Define Vuex 60 | + views … Define views of this project. 61 | - App.vue … Define a base view of this project. 62 | - main.js … Entry point. 63 | - babel.config … Babel Configuration. 64 | - package.json … Define npm packages. 65 | - vue.config.js … Vue CLI Configuration. 66 | ``` 67 | 68 | ## Views 69 | There are the following views in this sample. 70 | 71 | |View Name|File Name|Description| 72 | |:---|:---|:---| 73 | |Login View|``Login.vue``|The view for session authentication with username and password. This view is created and based on [the example of vue-material](https://github.com/vuematerial/examples).| 74 | |Home View|``Home.vue``|The view showing search results.| 75 | |About View|``About.vue``|The view showing this application information.| 76 | 77 | ## Libraries 78 | This sample uses the following library. 79 | 80 | |Library Name|Version|Description| 81 | |:---|:---:|:---| 82 | |vue-cli|5.0.8|The tool for Vue.js Development.| 83 | |Vue.js|2.7.0|JavaScript Framework| 84 | |Vue Router|3.6.5|Library for Routing.| 85 | |Vuex|3.6.2|Flux library for Vue.js| 86 | |axios|0.27.2|library for Ajax.| 87 | |vue-material|1.0.0-beta-14|CSS Framework| 88 | 89 | ## Contribution 90 | Please read CONTRIBUTING.md for proposing new functions, reporting bugs and submitting pull requests before contributing to this repository. 91 | 92 | ## License 93 | The License of this sample is *MIT License*. 94 | 95 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [ 3 | "./src/**/*" 4 | ] 5 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vuejs-webapp-sample", 3 | "version": "2.0.5", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "@fortawesome/fontawesome-svg-core": "^6.2.1", 12 | "@fortawesome/free-brands-svg-icons": "^6.2.1", 13 | "@fortawesome/free-solid-svg-icons": "^6.2.1", 14 | "@fortawesome/vue-fontawesome": "^2.0.9", 15 | "axios": "^1.2.1", 16 | "core-js": "^3.26.1", 17 | "register-service-worker": "^1.7.2", 18 | "vue": "^2.7.13", 19 | "vue-material": "^1.0.0-beta-14", 20 | "vue-router": "^3.6.5", 21 | "vuex": "^3.6.2" 22 | }, 23 | "devDependencies": { 24 | "@vue/cli-plugin-babel": "^5.0.8", 25 | "@vue/cli-plugin-eslint": "^5.0.8", 26 | "@vue/cli-plugin-pwa": "^5.0.8", 27 | "@vue/cli-service": "^5.0.8", 28 | "babel-eslint": "^10.1.0", 29 | "eslint": "^7.32.0", 30 | "eslint-plugin-vue": "^8.6.0", 31 | "vue-template-compiler": "^2.7.13" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | autoprefixer: {} 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/vuejs-webapp-sample/36c1b85197e41b4b7c034dd53159a4e528472c6c/public/favicon.ico -------------------------------------------------------------------------------- /public/img/icons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/vuejs-webapp-sample/36c1b85197e41b4b7c034dd53159a4e528472c6c/public/img/icons/android-chrome-192x192.png -------------------------------------------------------------------------------- /public/img/icons/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/vuejs-webapp-sample/36c1b85197e41b4b7c034dd53159a4e528472c6c/public/img/icons/android-chrome-512x512.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/vuejs-webapp-sample/36c1b85197e41b4b7c034dd53159a4e528472c6c/public/img/icons/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/vuejs-webapp-sample/36c1b85197e41b4b7c034dd53159a4e528472c6c/public/img/icons/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/vuejs-webapp-sample/36c1b85197e41b4b7c034dd53159a4e528472c6c/public/img/icons/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/vuejs-webapp-sample/36c1b85197e41b4b7c034dd53159a4e528472c6c/public/img/icons/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/vuejs-webapp-sample/36c1b85197e41b4b7c034dd53159a4e528472c6c/public/img/icons/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/vuejs-webapp-sample/36c1b85197e41b4b7c034dd53159a4e528472c6c/public/img/icons/apple-touch-icon.png -------------------------------------------------------------------------------- /public/img/icons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/vuejs-webapp-sample/36c1b85197e41b4b7c034dd53159a4e528472c6c/public/img/icons/favicon-16x16.png -------------------------------------------------------------------------------- /public/img/icons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/vuejs-webapp-sample/36c1b85197e41b4b7c034dd53159a4e528472c6c/public/img/icons/favicon-32x32.png -------------------------------------------------------------------------------- /public/img/icons/msapplication-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/vuejs-webapp-sample/36c1b85197e41b4b7c034dd53159a4e528472c6c/public/img/icons/msapplication-icon-144x144.png -------------------------------------------------------------------------------- /public/img/icons/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/vuejs-webapp-sample/36c1b85197e41b4b7c034dd53159a4e528472c6c/public/img/icons/mstile-150x150.png -------------------------------------------------------------------------------- /public/img/icons/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.11, written by Peter Selinger 2001-2013 9 | 10 | 12 | 148 | 149 | 150 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | vuejs-webapp-sample 9 | 10 | 11 | 12 | 13 | 16 |
17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vuejs-webapp-sample", 3 | "short_name": "vuejs-webapp-sample", 4 | "icons": [ 5 | { 6 | "src": "./img/icons/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "./img/icons/android-chrome-512x512.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "start_url": "./index.html", 17 | "display": "standalone", 18 | "background_color": "#000000", 19 | "theme_color": "#4DBA87" 20 | } 21 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | -------------------------------------------------------------------------------- /src/api/ajax.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | 3 | axios.defaults.withCredentials = true 4 | axios.defaults.baseURL = process.env.VUE_APP_API_ROOT 5 | 6 | export default class Ajax { 7 | 8 | static get(url, data = {}, success, failure) { 9 | const params = this.createParameter(data) 10 | axios 11 | .get(url, {params: params}) 12 | .then(res => { 13 | if (success) success(res.data) 14 | }) 15 | .catch(err => { 16 | if (failure) failure(err) 17 | }) 18 | } 19 | 20 | static post(url, data = {}, success, failure) { 21 | axios 22 | .post(url, data) 23 | .then(res => { 24 | if (success) success(res.data) 25 | }) 26 | .catch(err => { 27 | if (failure) failure(err) 28 | }) 29 | } 30 | 31 | static put(url, data = {}, success, failure) { 32 | axios 33 | .put(url, data) 34 | .then(res => { 35 | if (success) success(res.data) 36 | }) 37 | .catch(err => { 38 | if (failure) failure(err) 39 | }) 40 | } 41 | 42 | static delete(url, data = {}, success, failure) { 43 | axios 44 | .delete(url, data) 45 | .then(res => { 46 | if (success) success(res.data) 47 | }) 48 | .catch(err => { 49 | if (failure) failure(err) 50 | }) 51 | } 52 | 53 | static createParameter(data = {}) { 54 | const params = new URLSearchParams(); 55 | Object.keys(data).forEach(key => { 56 | if (data[key]) { 57 | params.append(key, data[key]); 58 | } 59 | }); 60 | return params 61 | } 62 | } -------------------------------------------------------------------------------- /src/api/auth.js: -------------------------------------------------------------------------------- 1 | import Ajax from '@/api/ajax.js' 2 | import { apiAuth } from '@/const.js' 3 | 4 | export default { 5 | loginStatus(success, failure) { 6 | Ajax.get(apiAuth.LoginStatus, {}, success, failure) 7 | }, 8 | loginAccount(success) { 9 | Ajax.get(apiAuth.LoginAccount, {}, success, () => false) 10 | }, 11 | login(data, success, failure) { 12 | Ajax.post(apiAuth.Login, data, success, failure) 13 | }, 14 | logout(success) { 15 | Ajax.post(apiAuth.Logout, {}, success, () => false) 16 | } 17 | } -------------------------------------------------------------------------------- /src/api/book.js: -------------------------------------------------------------------------------- 1 | import Ajax from '@/api/ajax.js' 2 | import { ApiBook } from '@/const.js' 3 | 4 | export default { 5 | get(data, success) { 6 | Ajax.get(ApiBook + `/${data.id}`, "", success, () => false) 7 | }, 8 | search(data, success) { 9 | Ajax.get(ApiBook, data, success, () => false) 10 | }, 11 | create(data, success, failure) { 12 | Ajax.post(ApiBook, data, success, failure) 13 | }, 14 | edit(data, success, failure) { 15 | Ajax.put(ApiBook + `/${data.id}`, data, success, failure) 16 | }, 17 | delete(data, success) { 18 | Ajax.delete(ApiBook + `/${data}`, "", success, () => false) 19 | } 20 | } -------------------------------------------------------------------------------- /src/api/category.js: -------------------------------------------------------------------------------- 1 | import Ajax from '@/api/ajax.js' 2 | import { ApiCategory } from '@/const.js' 3 | 4 | export default { 5 | list(success) { 6 | Ajax.get(ApiCategory, {}, success, () => false) 7 | } 8 | } -------------------------------------------------------------------------------- /src/api/format.js: -------------------------------------------------------------------------------- 1 | import Ajax from '@/api/ajax.js' 2 | import { ApiFormat } from '@/const.js' 3 | 4 | export default { 5 | list(success) { 6 | Ajax.get(ApiFormat, {}, success, () => false) 7 | } 8 | } -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spider-yamet/vuejs-webapp-sample/36c1b85197e41b4b7c034dd53159a4e528472c6c/src/assets/logo.png -------------------------------------------------------------------------------- /src/components/ConfirmDialog.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | -------------------------------------------------------------------------------- /src/components/ViewBase.vue: -------------------------------------------------------------------------------- 1 | 56 | 57 | 88 | 89 | -------------------------------------------------------------------------------- /src/const.js: -------------------------------------------------------------------------------- 1 | 2 | export const AppInfo = { 3 | AppName: "vuejs-webapp-sample", 4 | AppDeveloper: "ybkuroki", 5 | GithubLink: "https://github.com/ybkuroki/vuejs-webapp-sample" 6 | }; 7 | 8 | const api = "/api" 9 | const apiAuthBase = api + "/auth" 10 | 11 | export const ApiBook = api + "/books" 12 | export const ApiCategory = api + "/categories" 13 | export const ApiFormat = api + "/formats" 14 | 15 | export const apiAuth = { 16 | LoginStatus: apiAuthBase + "/loginStatus", 17 | LoginAccount: apiAuthBase + "/loginAccount", 18 | Login: apiAuthBase + "/login", 19 | Logout: apiAuthBase + "/logout" 20 | } -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from '@/App.vue' 3 | import router from '@/router/router' 4 | import store from '@/store/store' 5 | import '@/registerServiceWorker' 6 | 7 | import '@/plugins/vue-material' 8 | import '@/plugins/fortawesome' 9 | import '@/plugins/custom' 10 | 11 | Vue.config.productionTip = false 12 | 13 | new Vue({ 14 | router, 15 | store, 16 | render: h => h(App) 17 | }).$mount('#app') 18 | -------------------------------------------------------------------------------- /src/plugins/custom.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Dialog from '@/plugins/dialog' 3 | 4 | Vue.use(Dialog) -------------------------------------------------------------------------------- /src/plugins/dialog/index.js: -------------------------------------------------------------------------------- 1 | import Confirm from '@/components/ConfirmDialog.vue' 2 | 3 | export default class Dialog { 4 | static install(Vue) { 5 | Vue.mixin({ 6 | methods: { 7 | $confirm(message) { 8 | return new Promise((resolve) => { 9 | const VM = Vue.extend(Confirm); 10 | new VM({ 11 | propsData: { 12 | message, 13 | success: () => resolve(true), 14 | failure: () => resolve(false), 15 | } 16 | }) 17 | }) 18 | } 19 | } 20 | }) 21 | } 22 | } -------------------------------------------------------------------------------- /src/plugins/fortawesome.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | 3 | import { library } from '@fortawesome/fontawesome-svg-core' 4 | import { faSignOutAlt } from '@fortawesome/free-solid-svg-icons' 5 | import { faGithub } from '@fortawesome/free-brands-svg-icons' 6 | import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome' 7 | 8 | library.add(faGithub) 9 | library.add(faSignOutAlt) 10 | Vue.component('font-awesome-icon', FontAwesomeIcon) -------------------------------------------------------------------------------- /src/plugins/vue-material.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | 3 | import { 4 | MdApp, MdButton, MdCard, MdContent, MdDrawer, 5 | MdField, MdIcon, MdSnackbar, MdSpeedDial, MdToolbar, 6 | MdProgress, MdList, MdSubheader, MdMenu, MdDialog, MdDialogConfirm 7 | } from 'vue-material/dist/components' 8 | import 'vue-material/dist/vue-material.min.css' 9 | import 'vue-material/dist/theme/default.css' 10 | 11 | Vue.use(MdApp) 12 | Vue.use(MdButton) 13 | Vue.use(MdCard) 14 | Vue.use(MdContent) 15 | Vue.use(MdDrawer) 16 | Vue.use(MdField) 17 | Vue.use(MdIcon) 18 | Vue.use(MdSnackbar) 19 | Vue.use(MdSpeedDial) 20 | Vue.use(MdToolbar) 21 | Vue.use(MdProgress) 22 | Vue.use(MdList) 23 | Vue.use(MdSubheader) 24 | Vue.use(MdMenu) 25 | Vue.use(MdDialog) 26 | Vue.use(MdDialogConfirm) 27 | -------------------------------------------------------------------------------- /src/registerServiceWorker.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { register } from 'register-service-worker' 4 | 5 | if (process.env.NODE_ENV === 'production') { 6 | register(`${process.env.BASE_URL}service-worker.js`, { 7 | ready () { 8 | console.log( 9 | 'App is being served from cache by a service worker.\n' + 10 | 'For more details, visit https://goo.gl/AFskqB' 11 | ) 12 | }, 13 | registered () { 14 | console.log('Service worker has been registered.') 15 | }, 16 | cached () { 17 | console.log('Content has been cached for offline use.') 18 | }, 19 | updatefound () { 20 | console.log('New content is downloading.') 21 | }, 22 | updated () { 23 | console.log('New content is available; please refresh.') 24 | }, 25 | offline () { 26 | console.log('No internet connection found. App is running in offline mode.') 27 | }, 28 | error (error) { 29 | console.error('Error during service worker registration:', error) 30 | } 31 | }) 32 | } 33 | -------------------------------------------------------------------------------- /src/router/router.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import Login from '@/views/LoginView.vue' 4 | import Home from '@/views/HomeView.vue' 5 | import About from '@/views/AboutView.vue' 6 | 7 | Vue.use(Router) 8 | 9 | var router = new Router({ 10 | base: process.env.BASE_URL, 11 | routes: [ 12 | { path: '/login', component: Login, meta: { anonymous: true } }, 13 | { path: '/home', name: 'home', component: Home }, 14 | { path: '/about', name: 'about', component: About }, 15 | { path: '/*', redirect: '/home' } 16 | ] 17 | }) 18 | 19 | router.beforeEach((to, from, next) => { 20 | if (to.matched.some(m => m.meta.anonymous)) { 21 | next() 22 | } else { 23 | Vue.nextTick(() => router.app.$children[0].checkLogin(to, from, next)) 24 | } 25 | }) 26 | export default router -------------------------------------------------------------------------------- /src/store/mutation-types.js: -------------------------------------------------------------------------------- 1 | export const GET_LOGIN_ACCOUNT = 'GET_LOGIN_ACCOUNT' 2 | export const GET_CATEGORY = 'GET_CATEGORY' 3 | export const GET_FORMAT = 'GET_FORMAT' -------------------------------------------------------------------------------- /src/store/store.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | 4 | import AuthApi from '@/api/auth.js' 5 | import CategoryApi from '@/api/category.js' 6 | import FormatApi from '@/api/format.js' 7 | import * as types from '@/store/mutation-types.js' 8 | 9 | Vue.use(Vuex) 10 | 11 | const state = {account: null, category: null, format: null} 12 | 13 | // It's performed action when it calls dispatch() method in components. 14 | // Action calls Web API using ajax. It's executed mutations when calls commit() method. 15 | const actions = { 16 | [types.GET_LOGIN_ACCOUNT]({ commit }) { 17 | AuthApi.loginAccount((body) => commit(types.GET_LOGIN_ACCOUNT, body)) 18 | }, 19 | [types.GET_CATEGORY] ({ commit }) { 20 | CategoryApi.list((body) => commit(types.GET_CATEGORY, body)) 21 | }, 22 | [types.GET_FORMAT] ({ commit }) { 23 | FormatApi.list((body) => commit(types.GET_FORMAT, body)) 24 | } 25 | } 26 | 27 | // Get the state which is updated. 28 | const getters = { 29 | getLoginAccount(state) { 30 | return state.account 31 | }, 32 | getCategory(state) { 33 | return state.category 34 | }, 35 | getFormat(state) { 36 | return state.format 37 | } 38 | } 39 | 40 | // mutations updates own state. 41 | const mutations = { 42 | [types.GET_LOGIN_ACCOUNT](state, account) { 43 | state.account = account 44 | }, 45 | [types.GET_CATEGORY] (state, category) { 46 | state.category = category 47 | }, 48 | [types.GET_FORMAT] (state, format) { 49 | state.format = format 50 | } 51 | } 52 | 53 | const store = new Vuex.Store({ 54 | state, 55 | getters, 56 | actions, 57 | mutations 58 | }) 59 | export default store -------------------------------------------------------------------------------- /src/views/AboutView.vue: -------------------------------------------------------------------------------- 1 | 27 | 28 | -------------------------------------------------------------------------------- /src/views/CreateCard.vue: -------------------------------------------------------------------------------- 1 | 33 | 34 | -------------------------------------------------------------------------------- /src/views/EditCard.vue: -------------------------------------------------------------------------------- 1 | 51 | 52 | -------------------------------------------------------------------------------- /src/views/HomeView.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 45 | 46 | 92 | -------------------------------------------------------------------------------- /src/views/LoginView.vue: -------------------------------------------------------------------------------- 1 | 36 | 37 | 71 | 72 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | devServer: { 3 | port: 3000 4 | }, 5 | productionSourceMap: false, 6 | pwa: { 7 | workboxPluginMode: 'GenerateSW', 8 | workboxOptions: { 9 | cacheId: 'vuejs-webapp-sample', 10 | swDest: 'service-worker.js', 11 | clientsClaim: true, 12 | runtimeCaching: [ 13 | { 14 | urlPattern: new RegExp('/api/*'), 15 | handler: 'NetworkFirst', 16 | options: { 17 | cacheName: 'api', 18 | expiration: { 19 | maxAgeSeconds: 60 * 60 * 24 20 | }, 21 | fetchOptions: { 22 | mode: 'cors', 23 | }, 24 | matchOptions: { 25 | ignoreSearch: true, 26 | }, 27 | } 28 | } 29 | ] 30 | } 31 | } 32 | } --------------------------------------------------------------------------------