├── .gitignore ├── LICENSE ├── README.md ├── babel.config.js ├── package-lock.json ├── package.json ├── public └── index.html └── src ├── App.vue ├── assets └── graph.png ├── components ├── car │ ├── CarCard.vue │ ├── CarInfoWindow.vue │ └── CarRegWindow.vue ├── help │ └── DocWindow.vue └── layout │ ├── AppToolbar.vue │ ├── LoadingAnim.vue │ ├── NavDrawer.vue │ ├── NotificationBar.vue │ └── WalletHolder.vue ├── main.js ├── plugins └── vuetify.js ├── router └── index.js ├── store ├── index.js └── modules │ ├── info.js │ └── layout.js └── views └── Car.vue /.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 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 SIMBA Chain 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 | # Car Demo 2 2 | 3 | > A Vue.js project for Simbachain Dapp Client (Live Demo: https://cardemo.simbachain.com) 4 | 5 | ## Project setup 6 | 7 | ##### 1. Create and configure an app on Simba Dashboard with the default `carDemo2` smart contract at `https://app.simbachain.com/` 8 | 9 | ##### 2. Generate an `apiKey` for the app on `App-View` page 10 | 11 | ##### 3. Open `src/store/modules/info.js` and replace `yourApiUrl` and `yourApiKey` with yours 12 | 13 | ``` 14 | npm install 15 | ``` 16 | 17 | ### Compiles and hot-reloads for development 18 | ``` 19 | npm run serve 20 | ``` 21 | 22 | ### Compiles and minifies for production 23 | ``` 24 | npm run build 25 | ``` 26 | 27 | ### Lints and fixes files 28 | ``` 29 | npm run lint 30 | ``` 31 | 32 | ### Customize configuration 33 | See [Configuration Reference](https://cli.vuejs.org/config/). 34 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cardemo2", 3 | "version": "0.1.0", 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 | "@simbachain/libsimba-js": "^0.5.3", 12 | "axios": "^0.19.2", 13 | "core-js": "^3.6.4", 14 | "vue": "^2.6.11", 15 | "vue-router": "^3.1.6", 16 | "vue-uuid": "^1.1.1", 17 | "vuetify": "^2.2.21", 18 | "vuex": "^3.1.3" 19 | }, 20 | "devDependencies": { 21 | "@vue/cli-plugin-babel": "~4.3.0", 22 | "@vue/cli-plugin-eslint": "~4.3.0", 23 | "@vue/cli-service": "~4.3.0", 24 | "babel-eslint": "^10.1.0", 25 | "eslint": "^6.7.2", 26 | "eslint-plugin-vue": "^6.2.2", 27 | "vue-template-compiler": "^2.6.11" 28 | }, 29 | "eslintConfig": { 30 | "root": true, 31 | "env": { 32 | "node": true 33 | }, 34 | "extends": [ 35 | "plugin:vue/essential", 36 | "eslint:recommended" 37 | ], 38 | "parserOptions": { 39 | "parser": "babel-eslint" 40 | }, 41 | "rules": {} 42 | }, 43 | "browserslist": [ 44 | "> 1%", 45 | "last 2 versions", 46 | "not dead" 47 | ] 48 | } 49 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Car Demo 2 9 | 10 | 11 | 12 | 13 | 16 |
17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | -------------------------------------------------------------------------------- /src/assets/graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SIMBAChain/CarDemo/fce2a7e4f583c37b2e56d75e88e4aa78278dee35/src/assets/graph.png -------------------------------------------------------------------------------- /src/components/car/CarCard.vue: -------------------------------------------------------------------------------- 1 | 30 | 31 | -------------------------------------------------------------------------------- /src/components/car/CarInfoWindow.vue: -------------------------------------------------------------------------------- 1 | 95 | 96 | -------------------------------------------------------------------------------- /src/components/car/CarRegWindow.vue: -------------------------------------------------------------------------------- 1 | 47 | 48 | -------------------------------------------------------------------------------- /src/components/help/DocWindow.vue: -------------------------------------------------------------------------------- 1 | 88 | 89 | -------------------------------------------------------------------------------- /src/components/layout/AppToolbar.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 46 | 47 | 50 | -------------------------------------------------------------------------------- /src/components/layout/LoadingAnim.vue: -------------------------------------------------------------------------------- 1 | 54 | 55 | -------------------------------------------------------------------------------- /src/components/layout/NavDrawer.vue: -------------------------------------------------------------------------------- 1 | 31 | 32 | 57 | -------------------------------------------------------------------------------- /src/components/layout/NotificationBar.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 41 | -------------------------------------------------------------------------------- /src/components/layout/WalletHolder.vue: -------------------------------------------------------------------------------- 1 | 58 | 59 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import vuetify from './plugins/vuetify' 4 | import router from './router' 5 | import store from './store' 6 | // import UUID from 'vue-uuid' 7 | 8 | Vue.config.productionTip = false 9 | 10 | // Vue.use(UUID) 11 | 12 | new Vue({ 13 | vuetify, 14 | router, 15 | store, 16 | render: h => h(App), 17 | }).$mount('#app') 18 | -------------------------------------------------------------------------------- /src/plugins/vuetify.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuetify from 'vuetify' 3 | import 'vuetify/dist/vuetify.min.css' 4 | 5 | Vue.use(Vuetify) 6 | 7 | const opts = { 8 | theme: { 9 | dark: true 10 | } 11 | } 12 | 13 | export default new Vuetify(opts) -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import VueRouter from 'vue-router' 3 | import Car from '../views/Car.vue' 4 | 5 | Vue.use(VueRouter) 6 | 7 | const routes = [ 8 | { 9 | path: '/', 10 | name: 'Car', 11 | component: Car 12 | } 13 | ] 14 | 15 | const router = new VueRouter({ 16 | mode: 'history', 17 | base: process.env.BASE_URL, 18 | routes 19 | }) 20 | 21 | export default router 22 | -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import createLogger from 'vuex/dist/logger' 4 | 5 | import layout from './modules/layout' 6 | import info from './modules/info' 7 | 8 | Vue.use(Vuex) 9 | 10 | const debug = process.env.NODE_ENV !== 'production' 11 | 12 | export default new Vuex.Store({ 13 | modules: { 14 | layout, 15 | info 16 | }, 17 | strict: debug, 18 | plugins: [ 19 | ...(debug ? [createLogger()] : []) 20 | ] 21 | }) 22 | -------------------------------------------------------------------------------- /src/store/modules/info.js: -------------------------------------------------------------------------------- 1 | import * as libsimba from '@simbachain/libsimba-js' 2 | 3 | const url = 'yourApiUrl' 4 | const apiKey = 'YourApiKey' 5 | 6 | let wallet = new libsimba.LocalWallet() 7 | let simba = null 8 | 9 | // initial state 10 | const state = { 11 | address: null, 12 | walletStatus: null, 13 | simbaInitialized: false, 14 | cars: [], 15 | carsImg:[] 16 | } 17 | 18 | // getters 19 | const getters = { 20 | getSimba: () => simba, 21 | getWallet: async () => await wallet 22 | } 23 | 24 | // actions 25 | const actions = { 26 | async setSimba ({ commit, dispatch }) { 27 | commit('SET', { type: 'simbaInitialized', data: false }) 28 | simba = await libsimba.getSimbaInstance(url, null, apiKey) 29 | commit('SET', { type: 'simbaInitialized', data: true }) 30 | setInterval(() => dispatch('getCars'), 8000) 31 | }, 32 | async getCars ({ state, commit, dispatch}) { 33 | let txns = await simba.getMethodTransactions('car', {}) 34 | commit('SET', { type: 'cars', data: txns.data() }) 35 | state.cars.filter(car => !state.carsImg.find(carImg => carImg.id === car.id)).forEach(noImg => dispatch('getCarImg', noImg.id)) 36 | }, 37 | async getCarImg({ state, commit }, payload) { 38 | let blob = await simba.getFileFromBundleForTransaction(payload, 0, false) 39 | if (state.carsImg.find(carImg => carImg.id === payload)) { 40 | return 41 | } 42 | commit('SET', { type: 'carsImg', data: [...state.carsImg, { id: payload, file: URL.createObjectURL(blob) }]}) 43 | }, 44 | async setWallet ({ commit }) { 45 | commit('SET', { type: 'walletStatus', data: 'init' }) 46 | 47 | if (wallet.walletExists()) { 48 | commit('SET', { type: 'walletStatus', data: 'unlocking' }) 49 | await wallet.unlockWallet('password') 50 | } else { 51 | commit('SET', { type: 'walletStatus', data: 'generating' }) 52 | await wallet.generateWallet('password') 53 | } 54 | simba.setWallet(wallet) 55 | commit('SET', { type: 'walletStatus', data: 'unlocked' }) 56 | commit('SET', { type: 'address', data: await wallet.getAddress() }) 57 | } 58 | } 59 | 60 | // mutations 61 | const mutations = { 62 | SET (state, payload) { 63 | state[payload.type] = payload.data 64 | } 65 | } 66 | 67 | export default { 68 | namespaced: true, 69 | state, 70 | getters, 71 | actions, 72 | mutations 73 | } 74 | -------------------------------------------------------------------------------- /src/store/modules/layout.js: -------------------------------------------------------------------------------- 1 | // initial state 2 | const state = { 3 | snackbar: null, 4 | drawer: false, 5 | 6 | carRegWindow: false, 7 | carInfoWindow: false, 8 | currentSelectedCarId: null, 9 | 10 | helpDocWindow: false 11 | } 12 | 13 | // getters 14 | const getters = {} 15 | 16 | // actions 17 | const actions = { 18 | 19 | } 20 | 21 | // mutations 22 | const mutations = { 23 | SET (state, payload) { 24 | state[payload.type] = payload.data 25 | } 26 | } 27 | 28 | export default { 29 | namespaced: true, 30 | state, 31 | getters, 32 | actions, 33 | mutations 34 | } 35 | -------------------------------------------------------------------------------- /src/views/Car.vue: -------------------------------------------------------------------------------- 1 | 37 | 38 | 80 | --------------------------------------------------------------------------------