Add components for login form and customer field
This commit is contained in:
		
							parent
							
								
									e537d8e3a6
								
							
						
					
					
						commit
						dee27b51f5
					
				
					 5 changed files with 328 additions and 0 deletions
				
			
		
							
								
								
									
										154
									
								
								src/components/customers/ByjoveCustomerField.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								src/components/customers/ByjoveCustomerField.vue
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,154 @@ | |||
| <template> | ||||
|   <b-field :label="label" expanded | ||||
|            :type="fieldType"> | ||||
| 
 | ||||
|     <byjove-autocomplete v-if="!readonly && !useDropdown" | ||||
|                          v-model="customerUUID" | ||||
|                          :service-url="autocompleteUrl" | ||||
|                          @input="customerChanged"> | ||||
|     </byjove-autocomplete> | ||||
| 
 | ||||
|     <b-select v-if="!readonly && useDropdown" | ||||
|               v-model="customerUUID" | ||||
|               @input="customerChanged"> | ||||
| 
 | ||||
|       <option v-for="customer in customers" | ||||
|               :key="customer.uuid" | ||||
|               :value="customer.uuid"> | ||||
|         {{ customer.name }} | ||||
|       </option> | ||||
| 
 | ||||
|     </b-select> | ||||
| 
 | ||||
|     <router-link v-if="readonly" | ||||
|                  :to="`/customers/${value}`"> | ||||
|       {{ readonlyDisplay || value }} | ||||
|     </router-link> | ||||
| 
 | ||||
|   </b-field> | ||||
| </template> | ||||
| 
 | ||||
| <script> | ||||
| import ByjoveAutocomplete from '../autocomplete' | ||||
| export default { | ||||
|     name: 'ByjoveCustomerField', | ||||
| 
 | ||||
|     components: { | ||||
|         ByjoveAutocomplete, | ||||
|     }, | ||||
| 
 | ||||
|     props: { | ||||
|         name: { | ||||
|             type: String, | ||||
|         }, | ||||
|         label: { | ||||
|             type: String, | ||||
|             default: "Customer", | ||||
|         }, | ||||
|         value: { | ||||
|             type: String, | ||||
|         }, | ||||
|         readonly: { | ||||
|             type: Boolean, | ||||
|             default: false, | ||||
|         }, | ||||
|         readonlyDisplay: { | ||||
|             type: String, | ||||
|         }, | ||||
|         required: { | ||||
|             type: Boolean, | ||||
|             default: false, | ||||
|         }, | ||||
|         dropdown: { | ||||
|             type: Boolean, | ||||
|             default: null, | ||||
|         }, | ||||
|         autocompleteUrl: { | ||||
|             type: String, | ||||
|             // TODO: should not hard-code the "full" api endpoint url here | ||||
|             default: '/api/customers/autocomplete', | ||||
|         }, | ||||
|     }, | ||||
| 
 | ||||
|     data() { | ||||
|         return { | ||||
|             inited: false, | ||||
|             customerUUID: null, | ||||
|             customers: [], | ||||
|         } | ||||
|     }, | ||||
| 
 | ||||
|     computed: { | ||||
| 
 | ||||
|         fieldType() { | ||||
|             if (this.required && !this.customerUUID) { | ||||
|                 return 'is-danger' | ||||
|             } | ||||
|         }, | ||||
| 
 | ||||
|         useDropdown() { | ||||
| 
 | ||||
|             // use whatever caller specified, if they did so | ||||
|             if (this.dropdown !== null) { | ||||
|                 return this.dropdown | ||||
|             } | ||||
| 
 | ||||
|             // use setting, provided session is loaded | ||||
|             if (this.$store.state.session_established) { | ||||
|                 return this.$store.state.settings['customer_field_dropdown'] | ||||
|             } | ||||
| 
 | ||||
|             // otherwise assume false by default | ||||
|             return false | ||||
|         }, | ||||
| 
 | ||||
|     }, | ||||
| 
 | ||||
|     created() { | ||||
|         this.init() | ||||
|     }, | ||||
| 
 | ||||
|     watch: { | ||||
|         '$store.state.session_established': 'init', | ||||
|     }, | ||||
| 
 | ||||
|     methods: { | ||||
| 
 | ||||
|         init() { | ||||
|             // only need to init once | ||||
|             if (this.inited) { | ||||
|                 return | ||||
|             } | ||||
| 
 | ||||
|             // cannot init until session is established | ||||
|             if (!this.$store.state.session_established) { | ||||
|                 return | ||||
|             } | ||||
| 
 | ||||
|             this.inited = true | ||||
| 
 | ||||
|             // fetch any needed data | ||||
|             this.fetchData() | ||||
|         }, | ||||
| 
 | ||||
|         fetchData() { | ||||
| 
 | ||||
|             // nothing to fetch if not using dropdown | ||||
|             if (!this.useDropdown) { | ||||
|                 return | ||||
|             } | ||||
| 
 | ||||
|             // get all customers for dropdown | ||||
|             this.$http.get('/api/customers?sort=name|asc').then(response => { | ||||
|                 this.customers = response.data.customers | ||||
|             }) | ||||
|         }, | ||||
| 
 | ||||
|         customerChanged(value) { | ||||
|             this.$emit('input', value) | ||||
|         }, | ||||
| 
 | ||||
|     }, | ||||
| 
 | ||||
| } | ||||
| </script> | ||||
							
								
								
									
										27
									
								
								src/components/customers/index.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/components/customers/index.js
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | |||
| import ByjoveCustomerField from './ByjoveCustomerField.vue' | ||||
| 
 | ||||
| // Declare install function executed by Vue.use()
 | ||||
| export function install(Vue) { | ||||
|     if (install.installed) return; | ||||
|     install.installed = true; | ||||
|     Vue.component('ByjoveCustomerField', ByjoveCustomerField); | ||||
| } | ||||
| 
 | ||||
| // Create module definition for Vue.use()
 | ||||
| const plugin = { | ||||
|     install, | ||||
| }; | ||||
| 
 | ||||
| // Auto-install when vue is found (eg. in browser via <script> tag)
 | ||||
| let GlobalVue = null; | ||||
| if (typeof window !== 'undefined') { | ||||
|     GlobalVue = window.Vue; | ||||
| } else if (typeof global !== 'undefined') { | ||||
|     GlobalVue = global.Vue; | ||||
| } | ||||
| if (GlobalVue) { | ||||
|     GlobalVue.use(plugin); | ||||
| } | ||||
| 
 | ||||
| // To allow use as module (npm/webpack/etc.) export component
 | ||||
| export default ByjoveCustomerField | ||||
|  | @ -2,9 +2,11 @@ import ByjoveApp from './app' | |||
| import ByjoveMenu from './menu' | ||||
| import ByjoveLogo from './logo' | ||||
| import ByjoveFeedback from './feedback' | ||||
| import ByjoveLogin from './login' | ||||
| import ByjoveAutocomplete from './autocomplete' | ||||
| import ByjoveModelIndex from './model-index' | ||||
| import ByjoveModelCrud from './model-crud' | ||||
| import ByjoveCustomerField from './customers' | ||||
| import ByjoveInventory from './inventory' | ||||
| import ByjoveReceiving from './receiving' | ||||
| 
 | ||||
|  | @ -13,9 +15,11 @@ export { | |||
|     ByjoveMenu, | ||||
|     ByjoveLogo, | ||||
|     ByjoveFeedback, | ||||
|     ByjoveLogin, | ||||
|     ByjoveAutocomplete, | ||||
|     ByjoveModelIndex, | ||||
|     ByjoveModelCrud, | ||||
|     ByjoveCustomerField, | ||||
|     ByjoveInventory, | ||||
|     ByjoveReceiving, | ||||
| } | ||||
|  |  | |||
							
								
								
									
										116
									
								
								src/components/login/ByjoveLogin.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								src/components/login/ByjoveLogin.vue
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,116 @@ | |||
| <template> | ||||
|   <div class="byjove-login"> | ||||
|     <form> | ||||
| 
 | ||||
|       <byjove-logo centered :appsettings="appsettings"> | ||||
|       </byjove-logo> | ||||
| 
 | ||||
|       <b-field label="Username"> | ||||
|         <b-input v-model="username" /> | ||||
|       </b-field> | ||||
| 
 | ||||
|       <b-field label="Password"> | ||||
|         <b-input v-model="password" type="password" /> | ||||
|       </b-field> | ||||
| 
 | ||||
|       <div v-if="loginError" style="color: red;"> | ||||
|         {{ loginError }} | ||||
|       </div> | ||||
| 
 | ||||
|       <div class="buttons"> | ||||
|         <b-button type="is-primary" | ||||
|                   @click="attemptLogin()" | ||||
|                   :disabled="loginFormDisabled" | ||||
|                   expanded> | ||||
|           Login | ||||
|         </b-button> | ||||
|       </div> | ||||
| 
 | ||||
|     </form> | ||||
|   </div> | ||||
| </template> | ||||
| 
 | ||||
| <script> | ||||
| import ByjoveLogo from '../logo' | ||||
| 
 | ||||
| export default { | ||||
|     name: 'ByjoveLogin', | ||||
|     components: { | ||||
|         ByjoveLogo, | ||||
|     }, | ||||
|     props: { | ||||
|         appsettings: Object, | ||||
|     }, | ||||
|     data() { | ||||
|         return { | ||||
|             inited: false, | ||||
|             username: null, | ||||
|             password: null, | ||||
|             loginError: null, | ||||
|         } | ||||
|     }, | ||||
|     computed: { | ||||
| 
 | ||||
|         loginFormDisabled: function() { | ||||
|             if (!this.username) { | ||||
|                 return true | ||||
|             } else if (!this.password) { | ||||
|                 return true | ||||
|             } | ||||
|             return false | ||||
|         }, | ||||
| 
 | ||||
|     }, | ||||
|     created() { | ||||
|         this.init() | ||||
|     }, | ||||
|     watch: { | ||||
|         '$store.state.session_established': 'init', | ||||
|     }, | ||||
|     methods: { | ||||
| 
 | ||||
|         init() { | ||||
|             if (this.inited) return | ||||
| 
 | ||||
|             // cannot init until session is established | ||||
|             if (!this.$store.state.session_established) { | ||||
|                 return | ||||
|             } | ||||
| 
 | ||||
|             this.inited = true | ||||
| 
 | ||||
|             // send logged-in users to "home" page | ||||
|             if (this.$store.state.user) { | ||||
|                 this.$router.push('/') | ||||
|             } | ||||
|         }, | ||||
| 
 | ||||
|         attemptLogin() { | ||||
| 
 | ||||
|             // clear any previous login error | ||||
|             this.loginError = null | ||||
| 
 | ||||
|             // post credentials to login API | ||||
|             let creds = { | ||||
|                 username: this.username, | ||||
|                 password: this.password, | ||||
|             } | ||||
|             this.$http.post('/api/login', creds).then(response => { | ||||
|                 if (response.data.ok) { | ||||
| 
 | ||||
|                     // login successful; let the app know | ||||
|                     this.$loginUser(response.data.user) | ||||
| 
 | ||||
|                     // send user to "home" page | ||||
|                     this.$router.push('/') | ||||
| 
 | ||||
|                 } else { | ||||
|                     // login failed | ||||
|                     this.loginError = response.data.error; | ||||
|                 } | ||||
|             }) | ||||
|         }, | ||||
| 
 | ||||
|     }, | ||||
| } | ||||
| </script> | ||||
							
								
								
									
										27
									
								
								src/components/login/index.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/components/login/index.js
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | |||
| import ByjoveLogin from './ByjoveLogin.vue' | ||||
| 
 | ||||
| // Declare install function executed by Vue.use()
 | ||||
| export function install(Vue) { | ||||
|     if (install.installed) return; | ||||
|     install.installed = true; | ||||
|     Vue.component('ByjoveLogin', ByjoveLogin); | ||||
| } | ||||
| 
 | ||||
| // Create module definition for Vue.use()
 | ||||
| const plugin = { | ||||
|     install, | ||||
| }; | ||||
| 
 | ||||
| // Auto-install when vue is found (eg. in browser via <script> tag)
 | ||||
| let GlobalVue = null; | ||||
| if (typeof window !== 'undefined') { | ||||
|     GlobalVue = window.Vue; | ||||
| } else if (typeof global !== 'undefined') { | ||||
|     GlobalVue = global.Vue; | ||||
| } | ||||
| if (GlobalVue) { | ||||
|     GlobalVue.use(plugin); | ||||
| } | ||||
| 
 | ||||
| // To allow use as module (npm/webpack/etc.) export component
 | ||||
| export default ByjoveLogin | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lance Edgar
						Lance Edgar