fix: added webpack dev config Merge branch 'master' of git.bubblev.org:bubblev/bubble-web into feat/babel-root-plugin feat: implement header feat: implement reusable button component chore: add webpack config to git ignore chore: comment webpack proxy config Merge branch 'master' of git.bubblev.org:bubblev/bubble-web into feat/babel-root-plugin feat: add color palette feat: integrate babel-root-plugin feat: integrate babel-root-plugin Co-authored-by: Tyler <everdev0923@gmail.com> Reviewed-on: https://git.bubblev.org/bubblev/bubble-web/pulls/15pull/17/head
@@ -1782,6 +1782,17 @@ | |||||
} | } | ||||
} | } | ||||
}, | }, | ||||
"clone-deep": { | |||||
"version": "4.0.1", | |||||
"resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", | |||||
"integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", | |||||
"dev": true, | |||||
"requires": { | |||||
"is-plain-object": "^2.0.4", | |||||
"kind-of": "^6.0.2", | |||||
"shallow-clone": "^3.0.0" | |||||
} | |||||
}, | |||||
"collection-visit": { | "collection-visit": { | ||||
"version": "1.0.0", | "version": "1.0.0", | ||||
"resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", | "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", | ||||
@@ -3029,6 +3040,85 @@ | |||||
"integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", | "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", | ||||
"dev": true | "dev": true | ||||
}, | }, | ||||
"file-loader": { | |||||
"version": "6.0.0", | |||||
"resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.0.0.tgz", | |||||
"integrity": "sha512-/aMOAYEFXDdjG0wytpTL5YQLfZnnTmLNjn+AIrJ/6HVnTfDqLsVKUUwkDf4I4kgex36BvjuXEn/TX9B/1ESyqQ==", | |||||
"dev": true, | |||||
"requires": { | |||||
"loader-utils": "^2.0.0", | |||||
"schema-utils": "^2.6.5" | |||||
}, | |||||
"dependencies": { | |||||
"ajv": { | |||||
"version": "6.12.3", | |||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz", | |||||
"integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==", | |||||
"dev": true, | |||||
"requires": { | |||||
"fast-deep-equal": "^3.1.1", | |||||
"fast-json-stable-stringify": "^2.0.0", | |||||
"json-schema-traverse": "^0.4.1", | |||||
"uri-js": "^4.2.2" | |||||
} | |||||
}, | |||||
"ajv-keywords": { | |||||
"version": "3.5.1", | |||||
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.1.tgz", | |||||
"integrity": "sha512-KWcq3xN8fDjSB+IMoh2VaXVhRI0BBGxoYp3rx7Pkb6z0cFjYR9Q9l4yZqqals0/zsioCmocC5H6UvsGD4MoIBA==", | |||||
"dev": true | |||||
}, | |||||
"emojis-list": { | |||||
"version": "3.0.0", | |||||
"resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", | |||||
"integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", | |||||
"dev": true | |||||
}, | |||||
"fast-deep-equal": { | |||||
"version": "3.1.3", | |||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", | |||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", | |||||
"dev": true | |||||
}, | |||||
"json5": { | |||||
"version": "2.1.3", | |||||
"resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", | |||||
"integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", | |||||
"dev": true, | |||||
"requires": { | |||||
"minimist": "^1.2.5" | |||||
} | |||||
}, | |||||
"loader-utils": { | |||||
"version": "2.0.0", | |||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", | |||||
"integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", | |||||
"dev": true, | |||||
"requires": { | |||||
"big.js": "^5.2.2", | |||||
"emojis-list": "^3.0.0", | |||||
"json5": "^2.1.2" | |||||
} | |||||
}, | |||||
"minimist": { | |||||
"version": "1.2.5", | |||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", | |||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", | |||||
"dev": true | |||||
}, | |||||
"schema-utils": { | |||||
"version": "2.7.0", | |||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", | |||||
"integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", | |||||
"dev": true, | |||||
"requires": { | |||||
"@types/json-schema": "^7.0.4", | |||||
"ajv": "^6.12.2", | |||||
"ajv-keywords": "^3.4.1" | |||||
} | |||||
} | |||||
} | |||||
}, | |||||
"file-uri-to-path": { | "file-uri-to-path": { | ||||
"version": "1.0.0", | "version": "1.0.0", | ||||
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", | "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", | ||||
@@ -6304,6 +6394,15 @@ | |||||
"safe-buffer": "^5.0.1" | "safe-buffer": "^5.0.1" | ||||
} | } | ||||
}, | }, | ||||
"shallow-clone": { | |||||
"version": "3.0.1", | |||||
"resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", | |||||
"integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", | |||||
"dev": true, | |||||
"requires": { | |||||
"kind-of": "^6.0.2" | |||||
} | |||||
}, | |||||
"shebang-command": { | "shebang-command": { | ||||
"version": "1.2.0", | "version": "1.2.0", | ||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", | ||||
@@ -8110,6 +8209,16 @@ | |||||
"uuid": "^3.3.2" | "uuid": "^3.3.2" | ||||
} | } | ||||
}, | }, | ||||
"webpack-merge": { | |||||
"version": "5.0.9", | |||||
"resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.0.9.tgz", | |||||
"integrity": "sha512-P4teh6O26xIDPugOGX61wPxaeP918QOMjmzhu54zTVcLtOS28ffPWtnv+ilt3wscwBUCL2WNMnh97XkrKqt9Fw==", | |||||
"dev": true, | |||||
"requires": { | |||||
"clone-deep": "^4.0.1", | |||||
"wildcard": "^2.0.0" | |||||
} | |||||
}, | |||||
"webpack-sources": { | "webpack-sources": { | ||||
"version": "1.4.3", | "version": "1.4.3", | ||||
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", | "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", | ||||
@@ -8157,6 +8266,12 @@ | |||||
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", | "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", | ||||
"integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" | "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" | ||||
}, | }, | ||||
"wildcard": { | |||||
"version": "2.0.0", | |||||
"resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", | |||||
"integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", | |||||
"dev": true | |||||
}, | |||||
"worker-farm": { | "worker-farm": { | ||||
"version": "1.7.0", | "version": "1.7.0", | ||||
"resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", | "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", | ||||
@@ -7,7 +7,8 @@ | |||||
}, | }, | ||||
"license": "LicenseRef-LICENSE.md", | "license": "LicenseRef-LICENSE.md", | ||||
"scripts": { | "scripts": { | ||||
"start": "webpack-dev-server --open" | |||||
"start": "webpack-dev-server --open", | |||||
"dev": "webpack-dev-server --open --config webpack.config.dev.js" | |||||
}, | }, | ||||
"dependencies": { | "dependencies": { | ||||
"babel-plugin-root-import": "^6.5.0", | "babel-plugin-root-import": "^6.5.0", | ||||
@@ -30,6 +31,7 @@ | |||||
"babel-preset-stage-3": "^6.24.1", | "babel-preset-stage-3": "^6.24.1", | ||||
"babel-preset-vue": "^2.0.2", | "babel-preset-vue": "^2.0.2", | ||||
"copy-webpack-plugin": "^5.1.1", | "copy-webpack-plugin": "^5.1.1", | ||||
"file-loader": "^6.0.0", | |||||
"css-loader": "^2.1.1", | "css-loader": "^2.1.1", | ||||
"html-webpack-plugin": "^3.2.0", | "html-webpack-plugin": "^3.2.0", | ||||
"path": "^0.12.7", | "path": "^0.12.7", | ||||
@@ -37,6 +39,7 @@ | |||||
"vue-template-compiler": "^2.6.10", | "vue-template-compiler": "^2.6.10", | ||||
"webpack": "^4.39.3", | "webpack": "^4.39.3", | ||||
"webpack-cli": "^3.3.8", | "webpack-cli": "^3.3.8", | ||||
"webpack-dev-server": "^3.8.0" | |||||
"webpack-dev-server": "^3.8.0", | |||||
"webpack-merge": "^5.0.9" | |||||
} | } | ||||
} | } |
@@ -0,0 +1,45 @@ | |||||
<template> | |||||
<div | |||||
class="d-flex justify-content-center align-items-center container header" | |||||
> | |||||
<img src="/small-BubbleLogo-Horizontal-BlackText.png" height="40" /> | |||||
<div class="flex-grow-1"></div> | |||||
<div class="navbar d-flex justify-content-center align-items-center "> | |||||
<router-link to="/help" class="d-flex align-items-center"> | |||||
<Button link>HELP</Button> | |||||
</router-link> | |||||
<router-link to="/sign-up" class="d-flex align-items-center"> | |||||
<Button link>SIGN UP</Button> | |||||
</router-link> | |||||
<router-link to="/help" class="d-flex align-items-center"> | |||||
<Button color="default">SIGN IN</Button> | |||||
</router-link> | |||||
</div> | |||||
</div> | |||||
</template> | |||||
<style lang="scss" scoped> | |||||
.header { | |||||
background-color: white; | |||||
height: 85px; | |||||
.navbar { | |||||
height: 100%; | |||||
} | |||||
.navbar a { | |||||
height: 100%; | |||||
text-decoration: none; | |||||
} | |||||
} | |||||
</style> | |||||
<script> | |||||
import { Button } from '~/_components/shared'; | |||||
export default { | |||||
components: { | |||||
Button, | |||||
}, | |||||
}; | |||||
</script> |
@@ -0,0 +1 @@ | |||||
export { default as Header } from './Header'; |
@@ -0,0 +1,94 @@ | |||||
<template> | |||||
<button | |||||
v-bind="$attrs" | |||||
@click="click($event)" | |||||
:class="{ | |||||
round: round, | |||||
block: block, | |||||
[`color-${color}`]: color, | |||||
link: link, | |||||
}" | |||||
class="app-btn" | |||||
> | |||||
<span class="btn--text"> | |||||
<slot></slot> | |||||
</span> | |||||
</button> | |||||
</template> | |||||
<style lang="scss" scoped> | |||||
@import '../../_scss/_variables'; | |||||
.app-btn { | |||||
font-size: 14px; | |||||
box-shadow: 0px 0px 0px 0px rgba(0, 0, 0, 0); | |||||
transition: all 300ms ease 0ms; | |||||
max-height: 100%; | |||||
height: 60px; | |||||
cursor: pointer; | |||||
border: none; | |||||
// &:hover { | |||||
// box-shadow: 0px 5px 5px 0px rgba(0, 0, 0, 0.2); | |||||
// } | |||||
&.round { | |||||
border-radius: 50px; | |||||
} | |||||
&.block { | |||||
display: block; | |||||
} | |||||
.btn--text { | |||||
padding: 5px 20px; | |||||
} | |||||
&.link { | |||||
background-color: transparent; | |||||
color: #737373; | |||||
.btn--text { | |||||
padding: 0 5px; | |||||
} | |||||
} | |||||
// TODP: color schemas | |||||
&.color-default { | |||||
background: linear-gradient(300deg, #b838c9 -5%, #ee2f8e 95%); | |||||
color: white; | |||||
} | |||||
} | |||||
</style> | |||||
<script> | |||||
export default { | |||||
props: { | |||||
round: { | |||||
type: Boolean, | |||||
default: true, | |||||
}, | |||||
block: { | |||||
type: Boolean, | |||||
default: false, | |||||
}, | |||||
link: { | |||||
type: Boolean, | |||||
default: false, | |||||
}, | |||||
color: { | |||||
type: String, | |||||
default: '', | |||||
}, | |||||
}, | |||||
data() { | |||||
return {}; | |||||
}, | |||||
methods: { | |||||
click(event) { | |||||
this.$emit('click', event); | |||||
}, | |||||
}, | |||||
}; | |||||
</script> |
@@ -0,0 +1 @@ | |||||
export { default as Button } from './Button'; |
@@ -0,0 +1,3 @@ | |||||
html, body { | |||||
font-family: 'Luto'; | |||||
} |
@@ -0,0 +1,77 @@ | |||||
// color codes | |||||
$deep-purple: #3607a6; | |||||
$deep-purple-1: #4709d7; | |||||
$deep-purple-2: #5814f5; | |||||
$deep-purple-3: #6628f6; | |||||
$deep-purple-4: #733bf7; | |||||
$deep-purple-5: #814ff8; | |||||
$deep-purple-6: #8f62f8; | |||||
$deep-purple-7: #3a07b0; | |||||
$deep-purple-8: #ba9efa; | |||||
$deep-purple-9: #d5c5fc; | |||||
$deep-purple-10: #e3d8fd; | |||||
$vivid-navy: #221fe0; | |||||
$vivid-navy-1: #3c3ae4; | |||||
$vivid-navy-2: #4e4be7; | |||||
$vivid-navy-3: #605de9; | |||||
$vivid-navy-4: #716feb; | |||||
$vivid-navy-5: #8381ee; | |||||
$vivid-navy-6: #9593f0; | |||||
$vivid-navy-7: #a7a5f3; | |||||
$vivid-navy-8: #bab7f6; | |||||
$vivid-navy-9: #cbc9f8; | |||||
$vivid-navy-10: #dcdafb; | |||||
$strong-purple: #7a11b1; | |||||
$strong-purple-1: #8c14cc; | |||||
$strong-purple-2: #9916df; | |||||
$strong-purple-3: #aa33eb; | |||||
$strong-purple-4: #b245ed; | |||||
$strong-purple-5: #c16af0; | |||||
$strong-purple-6: #c97df2; | |||||
$strong-purple-7: #d9a2f6; | |||||
$strong-purple-8: #e0b5f8; | |||||
$strong-purple-9: #e8c7fa; | |||||
$strong-purple-10: #f0d9fc; | |||||
$vivid-pink: #f92c8b; | |||||
$vivid-pink-1: #f94d9d; | |||||
$vivid-pink-2: #f962a8; | |||||
$vivid-pink-3: #fa75b3; | |||||
$vivid-pink-4: #fb89be; | |||||
$vivid-pink-5: #fb9dc9; | |||||
$vivid-pink-6: #fcb1d4; | |||||
$vivid-pink-7: #fdc4df; | |||||
$vivid-pink-8: #fed8e9; | |||||
$vivid-pink-9: #feebf4; | |||||
$vivid-pink-10: #fdf5f9; | |||||
$light-blue: #54c7ea; | |||||
$light-blue-1: #6ecfed; | |||||
$light-blue-2: #80d5ef; | |||||
$light-blue-3: #92dbf2; | |||||
$light-blue-4: #a4e1f4; | |||||
$light-blue-5: #b6e7f6; | |||||
$light-blue-6: #c9edf8; | |||||
$light-blue-7: #d7eef8; | |||||
$light-blue-8: #dbf3fa; | |||||
$light-blue-9: #e4f3f9; | |||||
$light-blue-10: #edf9fd; | |||||
$bright-cyan: #2ed1a1; | |||||
$bright-cyan-1: #47d7ac; | |||||
$bright-cyan-2: #58dab3; | |||||
$bright-cyan-3: #68debb; | |||||
$bright-cyan-4: #79e2c2; | |||||
$bright-cyan-5: #8ae5ca; | |||||
$bright-cyan-6: #9be9d1; | |||||
$bright-cyan-7: #abedd9; | |||||
$bright-cyan-8: #bcf1e1; | |||||
$bright-cyan-9: #cdf4e8; | |||||
$bright-cyan-10: #def8f0; | |||||
// fonts | |||||
$default-font-family: 'Lato'; |
@@ -1,45 +1,123 @@ | |||||
<!-- Copyright (c) 2020 Bubble, Inc. All rights reserved. For personal (non-commercial) use, see license: https://getbubblenow.com/bubble-license/ --> | <!-- Copyright (c) 2020 Bubble, Inc. All rights reserved. For personal (non-commercial) use, see license: https://getbubblenow.com/bubble-license/ --> | ||||
<template> | <template> | ||||
<div> | |||||
<h2>{{messages.form_title_login}}</h2> | |||||
<h4 v-if="resetPasswordMessageSent === true" class="alert-success">{{messages.message_resetPassword_sent}}</h4> | |||||
<h4 v-if="submitted && errors.has('approvalToken')" class="invalid-feedback d-block">{{ errors.first('approvalToken') }}</h4> | |||||
<form @submit.prevent="handleSubmit"> | |||||
<div class="form-group"> | |||||
<label for="name">{{messages.field_label_email}}</label> | |||||
<input type="text" v-model="name" name="name" class="form-control" :class="{ 'is-invalid': submitted && !name }" /> | |||||
<div v-show="submitted && !name" class="invalid-feedback">Name is required</div> | |||||
<div v-if="submitted && errors.has('account')" class="invalid-feedback d-block">{{ errors.first('account') }}</div> | |||||
<div v-if="submitted && errors.has('name')" class="invalid-feedback d-block">{{ errors.first('name') }}</div> | |||||
</div> | |||||
<div class="form-group"> | |||||
<label htmlFor="password">{{messages.field_label_password}}</label> | |||||
<input type="password" v-model="password" name="password" class="form-control" :class="{ 'is-invalid': submitted && !password }" /> | |||||
<div v-if="submitted && errors.has('password')" class="invalid-feedback d-block">{{ errors.first('password') }}</div> | |||||
</div> | |||||
<div v-if="showTotp" class="form-group"> | |||||
<p>{{messages.message_login_authenticator_auth}}</p> | |||||
<label htmlFor="totpToken">{{messages.field_label_totp_code}}</label> | |||||
<input v-validate="'required'" v-model="totpToken" name="totpToken" class="form-control"/> | |||||
<div v-if="submitted && errors.has('totpToken')" class="invalid-feedback d-block">{{ errors.first('totpToken') }}</div> | |||||
</div> | |||||
<div v-if="configs && configs.locked === true && (configs.launchLock === null || configs.launchLock)" class="form-group"> | |||||
<label htmlFor="unlockKey">{{messages.field_label_unlock_key}}</label> | |||||
<input type="password" v-model="unlockKey" name="unlockKey" class="form-control" :class="{ 'is-invalid': submitted && !unlockKey }" /> | |||||
<div v-show="submitted && !unlockKey" class="invalid-feedback">Unlock Key is required</div> | |||||
<div v-if="submitted && errors.has('unlockKey')" class="invalid-feedback d-block">{{ errors.first('unlockKey') }}</div> | |||||
</div> | |||||
<div class="form-group"> | |||||
<div><small v-html="messages.message_login_agreeToTerms"></small><hr/></div> | |||||
<button class="btn btn-primary" :disabled="status.loggingIn">{{messages.button_label_login}}</button> | |||||
<img v-show="status.loggingIn" :src="loadingImgSrc" /> | |||||
<router-link v-if="configs && configs.allowRegistration" to="/register" class="btn btn-link">{{messages.button_label_register}}</router-link> | |||||
</div> | |||||
<div class="form-group"> | |||||
<router-link to="/forgotPassword" class="btn btn-link">{{messages.button_label_forgotPassword}}</router-link> | |||||
</div> | |||||
</form> | |||||
</div> | |||||
<div> | |||||
<h2>{{ messages.form_title_login }}</h2> | |||||
<h4 v-if="resetPasswordMessageSent === true" class="alert-success"> | |||||
{{ messages.message_resetPassword_sent }} | |||||
</h4> | |||||
<h4 | |||||
v-if="submitted && errors.has('approvalToken')" | |||||
class="invalid-feedback d-block" | |||||
> | |||||
{{ errors.first('approvalToken') }} | |||||
</h4> | |||||
<form @submit.prevent="handleSubmit"> | |||||
<div class="form-group"> | |||||
<label for="name">{{ messages.field_label_email }}</label> | |||||
<input | |||||
type="text" | |||||
v-model="name" | |||||
name="name" | |||||
class="form-control" | |||||
:class="{ 'is-invalid': submitted && !name }" | |||||
/> | |||||
<div v-show="submitted && !name" class="invalid-feedback"> | |||||
Name is required | |||||
</div> | |||||
<div | |||||
v-if="submitted && errors.has('account')" | |||||
class="invalid-feedback d-block" | |||||
> | |||||
{{ errors.first('account') }} | |||||
</div> | |||||
<div | |||||
v-if="submitted && errors.has('name')" | |||||
class="invalid-feedback d-block" | |||||
> | |||||
{{ errors.first('name') }} | |||||
</div> | |||||
</div> | |||||
<div class="form-group"> | |||||
<label htmlFor="password">{{ messages.field_label_password }}</label> | |||||
<input | |||||
type="password" | |||||
v-model="password" | |||||
name="password" | |||||
class="form-control" | |||||
:class="{ 'is-invalid': submitted && !password }" | |||||
/> | |||||
<div | |||||
v-if="submitted && errors.has('password')" | |||||
class="invalid-feedback d-block" | |||||
> | |||||
{{ errors.first('password') }} | |||||
</div> | |||||
</div> | |||||
<div v-if="showTotp" class="form-group"> | |||||
<p>{{ messages.message_login_authenticator_auth }}</p> | |||||
<label htmlFor="totpToken">{{ messages.field_label_totp_code }}</label> | |||||
<input | |||||
v-validate="'required'" | |||||
v-model="totpToken" | |||||
name="totpToken" | |||||
class="form-control" | |||||
/> | |||||
<div | |||||
v-if="submitted && errors.has('totpToken')" | |||||
class="invalid-feedback d-block" | |||||
> | |||||
{{ errors.first('totpToken') }} | |||||
</div> | |||||
</div> | |||||
<div | |||||
v-if=" | |||||
configs && | |||||
configs.locked === true && | |||||
(configs.launchLock === null || configs.launchLock) | |||||
" | |||||
class="form-group" | |||||
> | |||||
<label htmlFor="unlockKey">{{ messages.field_label_unlock_key }}</label> | |||||
<input | |||||
type="password" | |||||
v-model="unlockKey" | |||||
name="unlockKey" | |||||
class="form-control" | |||||
:class="{ 'is-invalid': submitted && !unlockKey }" | |||||
/> | |||||
<div v-show="submitted && !unlockKey" class="invalid-feedback"> | |||||
Unlock Key is required | |||||
</div> | |||||
<div | |||||
v-if="submitted && errors.has('unlockKey')" | |||||
class="invalid-feedback d-block" | |||||
> | |||||
{{ errors.first('unlockKey') }} | |||||
</div> | |||||
</div> | |||||
<div class="form-group"> | |||||
<div> | |||||
<small v-html="messages.message_login_agreeToTerms"></small> | |||||
<hr /> | |||||
</div> | |||||
<button class="btn btn-primary" :disabled="status.loggingIn"> | |||||
{{ messages.button_label_login }} | |||||
</button> | |||||
<img v-show="status.loggingIn" :src="loadingImgSrc" /> | |||||
<router-link | |||||
v-if="configs && configs.allowRegistration" | |||||
to="/register" | |||||
class="btn btn-link" | |||||
>{{ messages.button_label_register }}</router-link | |||||
> | |||||
</div> | |||||
<div class="form-group"> | |||||
<router-link to="/forgotPassword" class="btn btn-link">{{ | |||||
messages.button_label_forgotPassword | |||||
}}</router-link> | |||||
</div> | |||||
</form> | |||||
</div> | |||||
</template> | </template> | ||||
<script> | <script> | ||||
@@ -47,47 +125,55 @@ import { mapState, mapActions } from 'vuex'; | |||||
import { loadingImgSrc } from '~/_store'; | import { loadingImgSrc } from '~/_store'; | ||||
export default { | export default { | ||||
data () { | |||||
return { | |||||
name: '', | |||||
password: '', | |||||
totpToken: null, | |||||
unlockKey: (this.$route.query && this.$route.query.k) ? this.$route.query.k : null, | |||||
showTotp: false, | |||||
submitted: false, | |||||
loadingImgSrc: loadingImgSrc | |||||
} | |||||
data() { | |||||
return { | |||||
name: '', | |||||
password: '', | |||||
totpToken: null, | |||||
unlockKey: | |||||
this.$route.query && this.$route.query.k ? this.$route.query.k : null, | |||||
showTotp: false, | |||||
submitted: false, | |||||
loadingImgSrc: loadingImgSrc, | |||||
}; | |||||
}, | |||||
created() { | |||||
this.loadSystemConfigs(); | |||||
}, | |||||
computed: { | |||||
...mapState('account', [ | |||||
'status', | |||||
'loginError', | |||||
'resetPasswordMessageSent', | |||||
]), | |||||
...mapState('system', ['configs', 'messages']), | |||||
}, | |||||
methods: { | |||||
...mapActions('account', ['login', 'logout']), | |||||
...mapActions('system', ['loadSystemConfigs']), | |||||
handleSubmit(e) { | |||||
this.errors.clear(); | |||||
this.submitted = true; | |||||
const { name, password, totpToken, unlockKey } = this; | |||||
if (name && password) { | |||||
this.login({ | |||||
user: { name, password, totpToken, unlockKey }, | |||||
systemConfigs: this.configs, | |||||
messages: this.messages, | |||||
errors: this.errors, | |||||
}); | |||||
} | |||||
}, | }, | ||||
created () { | |||||
this.loadSystemConfigs(); | |||||
}, | |||||
watch: { | |||||
loginError(e) { | |||||
if ( | |||||
(e && e === 'err_totpToken_required') || | |||||
e === 'err_totpToken_invalid' | |||||
) { | |||||
this.showTotp = true; | |||||
} | |||||
}, | }, | ||||
computed: { | |||||
...mapState('account', ['status', 'loginError', 'resetPasswordMessageSent']), | |||||
...mapState('system', ['configs', 'messages']) | |||||
}, | |||||
methods: { | |||||
...mapActions('account', ['login', 'logout']), | |||||
...mapActions('system', ['loadSystemConfigs']), | |||||
handleSubmit (e) { | |||||
this.errors.clear(); | |||||
this.submitted = true; | |||||
const { name, password, totpToken, unlockKey } = this; | |||||
if (name && password) { | |||||
this.login({ | |||||
user: {name, password, totpToken, unlockKey}, | |||||
systemConfigs: this.configs, | |||||
messages: this.messages, | |||||
errors: this.errors | |||||
}); | |||||
} | |||||
} | |||||
}, | |||||
watch: { | |||||
loginError (e) { | |||||
if (e && e === 'err_totpToken_required' || e === 'err_totpToken_invalid') { | |||||
this.showTotp = true; | |||||
} | |||||
} | |||||
} | |||||
}, | |||||
}; | }; | ||||
</script> | </script> |
@@ -0,0 +1,10 @@ | |||||
const webpackMerge = require('webpack-merge'); | |||||
module.exports = webpackMerge.merge(require('./webpack.config.js'), { | |||||
mode: 'development', | |||||
devServer: { | |||||
proxy: { | |||||
'/api': 'http://beta.bubv.net:8888', | |||||
}, | |||||
}, | |||||
}); |
@@ -34,6 +34,14 @@ module.exports = { | |||||
test: /\.s[ac]ss$/i, | test: /\.s[ac]ss$/i, | ||||
use: ['style-loader', 'css-loader', 'sass-loader'], | use: ['style-loader', 'css-loader', 'sass-loader'], | ||||
}, | }, | ||||
{ | |||||
test: /\.(png|jpe?g|gif)$/i, | |||||
use: [ | |||||
{ | |||||
loader: 'file-loader', | |||||
}, | |||||
], | |||||
}, | |||||
], | ], | ||||
}, | }, | ||||
plugins: [ | plugins: [ | ||||
@@ -44,9 +52,6 @@ module.exports = { | |||||
], | ], | ||||
devServer: { | devServer: { | ||||
historyApiFallback: true, | historyApiFallback: true, | ||||
// proxy: { | |||||
// '/api': 'http://beta.bubv.net:8888' | |||||
// } | |||||
}, | }, | ||||
externals: { | externals: { | ||||
// global app config object | // global app config object | ||||