mirror of
				https://github.com/crater-invoice/crater.git
				synced 2025-10-31 05:31:10 -04:00 
			
		
		
		
	build version 400
This commit is contained in:
		| @ -1,266 +0,0 @@ | ||||
| <template> | ||||
|   <div class="card-body"> | ||||
|     <form action="" @submit.prevent="next()"> | ||||
|       <p class="form-title">{{ $t('wizard.company_info') }}</p> | ||||
|       <p class="form-desc">{{ $t('wizard.company_info_desc') }}</p> | ||||
|       <div class="row mb-4"> | ||||
|         <div class="col-md-6"> | ||||
|           <label class="input-label">{{ $tc('settings.company_info.company_logo') }}</label> | ||||
|           <div id="pick-avatar" class="image-upload-box"> | ||||
|             <div class="overlay"> | ||||
|               <font-awesome-icon class="white-icon" icon="camera"/> | ||||
|             </div> | ||||
|             <img v-if="previewLogo" :src="previewLogo" class="preview-logo"> | ||||
|             <div v-else class="upload-content"> | ||||
|               <font-awesome-icon class="upload-icon" icon="cloud-upload-alt"/> | ||||
|               <p class="upload-text"> {{ $t('general.choose_file') }} </p> | ||||
|             </div> | ||||
|           </div> | ||||
|         </div> | ||||
|         <avatar-cropper | ||||
|           :labels="{ submit: 'Submit', cancel: 'Cancel'}" | ||||
|           :cropper-options="cropperOptions" | ||||
|           :output-options="cropperOutputOptions" | ||||
|           :output-quality="0.8" | ||||
|           :upload-handler="cropperHandler" | ||||
|           trigger="#pick-avatar" | ||||
|           @changed="setFileObject" | ||||
|           @error="handleUploadError" | ||||
|         /> | ||||
|       </div> | ||||
|       <div class="row"> | ||||
|         <div class="col-md-6"> | ||||
|           <label class="form-label">{{ $t('wizard.company_name') }}</label><span class="text-danger"> *</span> | ||||
|           <base-input | ||||
|             :invalid="$v.companyData.name.$error" | ||||
|             v-model.trim="companyData.name" | ||||
|             type="text" | ||||
|             name="name" | ||||
|             @input="$v.companyData.name.$touch()" | ||||
|           /> | ||||
|           <div v-if="$v.companyData.name.$error"> | ||||
|             <span v-if="!$v.companyData.name.required" class="text-danger">{{ $tc('validation.required') }}</span> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="col-md-6"> | ||||
|           <label class="form-label">{{ $t('wizard.country') }}</label><span class="text-danger"> *</span> | ||||
|           <base-select | ||||
|             v-model="country" | ||||
|             :class="{'error': $v.companyData.country_id.$error }" | ||||
|             :options="countries" | ||||
|             :searchable="true" | ||||
|             :allow-empty="false" | ||||
|             :show-labels="false" | ||||
|             :placeholder="$t('general.select_country')" | ||||
|             track-by="id" | ||||
|             label="name" | ||||
|           /> | ||||
|           <div v-if="$v.companyData.country_id.$error"> | ||||
|             <span v-if="!$v.companyData.country_id.required" class="text-danger">{{ $tc('validation.required') }}</span> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="row"> | ||||
|         <div class="col-md-6"> | ||||
|           <label class="form-label">{{ $t('wizard.state') }}</label> | ||||
|           <base-input | ||||
|             v-model="companyData.state" | ||||
|             name="state" | ||||
|             type="text" | ||||
|           /> | ||||
|         </div> | ||||
|         <div class="col-md-6"> | ||||
|           <label class="form-label">{{ $t('wizard.city') }}</label> | ||||
|           <base-input | ||||
|             v-model="companyData.city" | ||||
|             name="city" | ||||
|             type="text" | ||||
|           /> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="row"> | ||||
|         <div class="col-md-6"> | ||||
|           <label class="form-label">{{ $t('wizard.address') }}</label> | ||||
|           <base-text-area | ||||
|             :invalid="$v.companyData.address_street_1.$error" | ||||
|             v-model.trim="companyData.address_street_1" | ||||
|             :placeholder="$t('general.street_1')" | ||||
|             name="billing_street1" | ||||
|             rows="2" | ||||
|             @input="$v.companyData.address_street_1.$touch()" | ||||
|           /> | ||||
|           <div v-if="$v.companyData.address_street_1.$error"> | ||||
|             <span v-if="!$v.companyData.address_street_1.maxLength" class="text-danger">{{ $t('validation.description_maxlength') }}</span> | ||||
|           </div> | ||||
|           <base-text-area | ||||
|             :invalid="$v.companyData.address_street_2.$error" | ||||
|             v-model="companyData.address_street_2" | ||||
|             :placeholder="$t('general.street_2')" | ||||
|             name="billing_street2" | ||||
|             rows="2" | ||||
|             @input="$v.companyData.address_street_2.$touch()" | ||||
|           /> | ||||
|           <div v-if="$v.companyData.address_street_2.$error"> | ||||
|             <span v-if="!$v.companyData.address_street_2.maxLength" class="text-danger">{{ $t('validation.description_maxlength') }}</span> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="col-md-6"> | ||||
|           <div class="row"> | ||||
|             <div class="col-md-12"> | ||||
|               <label class="form-label">{{ $t('wizard.zip_code') }}</label> | ||||
|               <base-input | ||||
|                 v-model.trim="companyData.zip" | ||||
|                 type="text" | ||||
|                 name="zip" | ||||
|               /> | ||||
|             </div> | ||||
|           </div> | ||||
|           <div class="row"> | ||||
|             <div class="col-md-12"> | ||||
|               <label class="form-label">{{ $t('wizard.phone') }}</label> | ||||
|               <base-input | ||||
|                 v-model.trim="companyData.phone" | ||||
|                 type="text" | ||||
|                 name="phone" | ||||
|               /> | ||||
|             </div> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|       <base-button | ||||
|         :loading="loading" | ||||
|         class="pull-right" | ||||
|         icon="save" | ||||
|         color="theme" | ||||
|         type="submit" | ||||
|       > | ||||
|         {{ $t('wizard.save_cont') }} | ||||
|       </base-button> | ||||
|     </form> | ||||
|   </div> | ||||
| </template> | ||||
| <script> | ||||
| import MultiSelect from 'vue-multiselect' | ||||
| import AvatarCropper from 'vue-avatar-cropper' | ||||
| import { validationMixin } from 'vuelidate' | ||||
| const { required, maxLength } = require('vuelidate/lib/validators') | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
|     MultiSelect, | ||||
|     AvatarCropper | ||||
|   }, | ||||
|   mixins: [validationMixin], | ||||
|   data () { | ||||
|     return { | ||||
|       cropperOutputOptions: { | ||||
|         width: 150, | ||||
|         height: 150 | ||||
|       }, | ||||
|       cropperOptions: { | ||||
|         autoCropArea: 1, | ||||
|         viewMode: 0, | ||||
|         movable: true, | ||||
|         zoomable: true | ||||
|       }, | ||||
|       companyData: { | ||||
|         logo: '', | ||||
|         name: null, | ||||
|         address_street_1: '', | ||||
|         address_street_2: '', | ||||
|         city: '', | ||||
|         state: '', | ||||
|         country_id: '', | ||||
|         zip: '', | ||||
|         phone: '' | ||||
|       }, | ||||
|       loading: false, | ||||
|       step: 1, | ||||
|       countries: [], | ||||
|       country: null, | ||||
|       previewLogo: null | ||||
|     } | ||||
|   }, | ||||
|   validations: { | ||||
|     companyData: { | ||||
|       name: { | ||||
|         required | ||||
|       }, | ||||
|       country_id: { | ||||
|         required | ||||
|       }, | ||||
|       address_street_1: { | ||||
|         maxLength: maxLength(255) | ||||
|       }, | ||||
|       address_street_2: { | ||||
|         maxLength: maxLength(255) | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   watch: { | ||||
|     country ({ id }) { | ||||
|       this.companyData.country_id = id | ||||
|       return true | ||||
|     } | ||||
|   }, | ||||
|   mounted () { | ||||
|     this.fetchCountry() | ||||
|   }, | ||||
|   methods: { | ||||
|     cropperHandler (cropper) { | ||||
|       this.previewLogo = cropper.getCroppedCanvas().toDataURL(this.cropperOutputMime) | ||||
|     }, | ||||
|     setFileObject (file) { | ||||
|       this.fileObject = file | ||||
|     }, | ||||
|     handleUploadError (message, type, xhr) { | ||||
|       window.toastr['error']('Oops! Something went wrong...') | ||||
|     }, | ||||
|     async next () { | ||||
|       this.$v.companyData.$touch() | ||||
|       if (this.$v.companyData.$invalid) { | ||||
|         return true | ||||
|       } | ||||
|       this.loading = true | ||||
|       let response = await window.axios.post('/api/admin/onboarding/company', this.companyData) | ||||
|  | ||||
|       if (response.data) { | ||||
|         if (this.fileObject && this.previewLogo) { | ||||
|           let logoData = new FormData() | ||||
|           logoData.append('company_logo', JSON.stringify({ | ||||
|             name: this.fileObject.name, | ||||
|             data: this.previewLogo | ||||
|           })) | ||||
|  | ||||
|           await axios.post('/api/admin/onboarding/company/upload-logo', logoData, { | ||||
|             headers: { | ||||
|               'Content-Type': 'multipart/form-data', | ||||
|               'company': response.data.user.company.id | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|  | ||||
|         this.$emit('next') | ||||
|         this.loading = false | ||||
|       } | ||||
|     }, | ||||
|     onFileChange (e) { | ||||
|       var input = event.target | ||||
|       this.companyData.logo = input.files[0] | ||||
|       if (input.files && input.files[0]) { | ||||
|         var reader = new FileReader() | ||||
|         reader.onload = (e) => { | ||||
|           this.previewLogo = e.target.result | ||||
|         } | ||||
|         reader.readAsDataURL(input.files[0]) | ||||
|       } | ||||
|     }, | ||||
|     async fetchCountry () { | ||||
|       let res = await window.axios.get('/api/countries') | ||||
|       if (res) { | ||||
|         this.countries = res.data.countries | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
| @ -1,219 +0,0 @@ | ||||
| <template> | ||||
|   <div class="card-body"> | ||||
|     <form action="" @submit.prevent="next()"> | ||||
|       <p class="form-title">{{ $t('wizard.database.database') }}</p> | ||||
|       <p class="form-desc">{{ $t('wizard.database.desc') }}</p> | ||||
|       <div class="row mt-5"> | ||||
|         <div class="col-md-6"> | ||||
|           <label class="form-label">{{ $t('wizard.database.app_url') }}</label> | ||||
|           <span class="text-danger"> * </span> | ||||
|           <base-input | ||||
|             :invalid="$v.databaseData.app_url.$error" | ||||
|             v-model.trim="databaseData.app_url" | ||||
|             type="text" | ||||
|             name="name" | ||||
|             @input="$v.databaseData.app_url.$touch()" | ||||
|           /> | ||||
|           <div v-if="$v.databaseData.app_url.$error"> | ||||
|             <span v-if="!$v.databaseData.app_url.required" class="text-danger"> | ||||
|               {{ $tc('validation.required') }} | ||||
|             </span> | ||||
|             <span v-if="!$v.databaseData.app_url.isUrl" class="text-danger"> | ||||
|               {{ $tc('validation.invalid_url') }} | ||||
|             </span> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="col-md-6"> | ||||
|           <label class="form-label">{{ $t('wizard.database.connection') }}</label> | ||||
|           <span class="text-danger"> *</span> | ||||
|           <base-select | ||||
|             v-model="databaseData.database_connection" | ||||
|             :invalid="$v.databaseData.database_connection.$error" | ||||
|             :options="connections" | ||||
|             :searchable="true" | ||||
|             :show-labels="false" | ||||
|             @change="$v.databaseData.database_connection.$touch()" | ||||
|           /> | ||||
|           <div v-if="$v.databaseData.database_connection.$error"> | ||||
|             <span v-if="!$v.databaseData.database_connection.required" class="text-danger"> | ||||
|               {{ $tc('validation.required') }} | ||||
|             </span> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="row"> | ||||
|         <div class="col-md-6"> | ||||
|           <label class="form-label">{{ $t('wizard.database.port') }}</label> | ||||
|           <span class="text-danger"> *</span> | ||||
|           <base-input | ||||
|             :invalid="$v.databaseData.database_port.$error" | ||||
|             v-model.trim="databaseData.database_port" | ||||
|             type="text" | ||||
|             name="database_port" | ||||
|             @input="$v.databaseData.database_port.$touch()" | ||||
|           /> | ||||
|           <div v-if="$v.databaseData.database_port.$error"> | ||||
|             <span v-if="!$v.databaseData.database_port.required" class="text-danger"> | ||||
|               {{ $tc('validation.required') }} | ||||
|             </span> | ||||
|             <span v-if="!$v.databaseData.database_port.numeric" class="text-danger"> | ||||
|               {{ $tc('validation.numbers_only') }} | ||||
|             </span> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="col-md-6"> | ||||
|           <label class="form-label">{{ $t('wizard.database.db_name') }}</label> | ||||
|           <span class="text-danger"> *</span> | ||||
|           <base-input | ||||
|             :invalid="$v.databaseData.database_name.$error" | ||||
|             v-model.trim="databaseData.database_name" | ||||
|             type="text" | ||||
|             name="database_name" | ||||
|             @input="$v.databaseData.database_name.$touch()" | ||||
|           /> | ||||
|           <div v-if="$v.databaseData.database_name.$error"> | ||||
|             <span v-if="!$v.databaseData.database_name.required" class="text-danger"> | ||||
|               {{ $tc('validation.required') }} | ||||
|             </span> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="row"> | ||||
|         <div class="col-md-6"> | ||||
|           <label class="form-label">{{ $t('wizard.database.username') }}</label> | ||||
|           <span class="text-danger"> *</span> | ||||
|           <base-input | ||||
|             :invalid="$v.databaseData.database_username.$error" | ||||
|             v-model.trim="databaseData.database_username" | ||||
|             type="text" | ||||
|             name="database_username" | ||||
|             @input="$v.databaseData.database_username.$touch()" | ||||
|           /> | ||||
|           <div v-if="$v.databaseData.database_username.$error"> | ||||
|             <span v-if="!$v.databaseData.database_username.required" class="text-danger"> | ||||
|               {{ $tc('validation.required') }} | ||||
|             </span> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="col-md-6"> | ||||
|           <label class="form-label">{{ $t('wizard.database.password') }}</label> | ||||
|           <base-input | ||||
|             v-model.trim="databaseData.database_password" | ||||
|             type="password" | ||||
|             name="name" | ||||
|           /> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="row"> | ||||
|         <div class="col-md-6"> | ||||
|           <label class="form-label">{{ $t('wizard.database.host') }}</label> | ||||
|           <span class="text-danger"> *</span> | ||||
|           <base-input | ||||
|             :invalid="$v.databaseData.database_hostname.$error" | ||||
|             v-model.trim="databaseData.database_hostname" | ||||
|             type="text" | ||||
|             name="database_hostname" | ||||
|             @input="$v.databaseData.database_hostname.$touch()" | ||||
|           /> | ||||
|           <div v-if="$v.databaseData.database_hostname.$error"> | ||||
|             <span v-if="!$v.databaseData.database_hostname.required" class="text-danger"> | ||||
|               {{ $tc('validation.required') }} | ||||
|             </span> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|       <base-button | ||||
|         :loading="loading" | ||||
|         class="pull-right mt-5" | ||||
|         icon="save" | ||||
|         color="theme" | ||||
|         type="submit" | ||||
|       > | ||||
|         {{ $t('wizard.save_cont') }} | ||||
|       </base-button> | ||||
|     </form> | ||||
|   </div> | ||||
| </template> | ||||
| <script> | ||||
| import MultiSelect from 'vue-multiselect' | ||||
| import { validationMixin } from 'vuelidate' | ||||
| const { required, numeric, url } = require('vuelidate/lib/validators') | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
|     MultiSelect | ||||
|   }, | ||||
|   mixins: [validationMixin], | ||||
|   data () { | ||||
|     return { | ||||
|       databaseData: { | ||||
|         database_connection: 'mysql', | ||||
|         database_hostname: '127.0.0.1', | ||||
|         database_port: '3306', | ||||
|         database_name: null, | ||||
|         database_username: null, | ||||
|         database_password: null, | ||||
|         app_url: window.location.origin | ||||
|       }, | ||||
|       loading: false, | ||||
|       connections: [ | ||||
|         'sqlite', | ||||
|         'mysql', | ||||
|         'pgsql', | ||||
|         'sqlsrv' | ||||
|       ] | ||||
|     } | ||||
|   }, | ||||
|   validations: { | ||||
|     databaseData: { | ||||
|       database_connection: { | ||||
|         required | ||||
|       }, | ||||
|       database_hostname: { | ||||
|         required | ||||
|       }, | ||||
|       database_port: { | ||||
|         required, | ||||
|         numeric | ||||
|       }, | ||||
|       database_name: { | ||||
|         required | ||||
|       }, | ||||
|       database_username: { | ||||
|         required | ||||
|       }, | ||||
|       app_url: { | ||||
|         required, | ||||
|         isUrl (val) { | ||||
|           return this.$utils.checkValidUrl(val) | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     async next () { | ||||
|       this.$v.databaseData.$touch() | ||||
|       if (this.$v.databaseData.$invalid) { | ||||
|         return true | ||||
|       } | ||||
|       this.loading = true | ||||
|       try { | ||||
|         let response = await window.axios.post('/api/admin/onboarding/environment/database', this.databaseData) | ||||
|         if (response.data.success) { | ||||
|           this.$emit('next') | ||||
|           window.toastr['success'](this.$t('wizard.success.' + response.data.success)) | ||||
|           return true | ||||
|         } else if (response.data.error) { | ||||
|           window.toastr['error'](this.$t('wizard.errors.' + response.data.error)) | ||||
|         } else if (response.data.error_message) { | ||||
|           window.toastr['error'](response.data.error_message) | ||||
|         } | ||||
|       } catch (e) { | ||||
|         window.toastr['error'](e.response.data.message) | ||||
|       } finally { | ||||
|         this.loading = false | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
| @ -1,78 +0,0 @@ | ||||
| <template> | ||||
|   <div class="card-body"> | ||||
|     <form action="" @submit.prevent="next()"> | ||||
|       <p class="form-title">{{ $t('wizard.mail.mail_config') }}</p> | ||||
|       <p class="form-desc">{{ $t('wizard.mail.mail_config_desc') }}</p> | ||||
|       <component | ||||
|         :is="mail_driver" | ||||
|         :config-data="mailConfigData" | ||||
|         :loading="loading" | ||||
|         :mail-drivers="mail_drivers" | ||||
|         @on-change-driver="(val) => mail_driver = mailConfigData.mail_driver = val" | ||||
|         @submit-data="next" | ||||
|       /> | ||||
|     </form> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import MultiSelect from 'vue-multiselect' | ||||
| import { validationMixin } from 'vuelidate' | ||||
| import Smtp from './mailDriver/Smtp' | ||||
| import Mailgun from './mailDriver/Mailgun' | ||||
| import Ses from './mailDriver/Ses' | ||||
| import Basic from './mailDriver/Basic' | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
|     MultiSelect, | ||||
|     Smtp, | ||||
|     Mailgun, | ||||
|     Ses, | ||||
|     sendmail: Basic, | ||||
|     mail: Basic | ||||
|   }, | ||||
|   mixins: [validationMixin], | ||||
|   data () { | ||||
|     return { | ||||
|       mailConfigData: { | ||||
|         mail_driver: 'mail' | ||||
|       }, | ||||
|       mail_driver: 'mail', | ||||
|       loading: false, | ||||
|       mail_drivers: [] | ||||
|     } | ||||
|   }, | ||||
|   created () { | ||||
|     this.getMailDrivers() | ||||
|   }, | ||||
|   methods: { | ||||
|     async getMailDrivers () { | ||||
|       this.loading = true | ||||
|  | ||||
|       let response = await window.axios.get('/api/admin/onboarding/environment/mail') | ||||
|  | ||||
|       if (response.data) { | ||||
|         this.mail_drivers = response.data | ||||
|         this.loading = false | ||||
|       } | ||||
|     }, | ||||
|     async next (mailConfigData) { | ||||
|       this.loading = true | ||||
|       try { | ||||
|         let response = await window.axios.post('/api/admin/onboarding/environment/mail', mailConfigData) | ||||
|         if (response.data.success) { | ||||
|           this.$emit('next') | ||||
|           window.toastr['success'](this.$t('wizard.success.' + response.data.success)) | ||||
|         } else { | ||||
|           window.toastr['error'](this.$t('wizard.errors.' + response.data.error)) | ||||
|         } | ||||
|         this.loading = false | ||||
|         return true | ||||
|       } catch (e) { | ||||
|         window.toastr['error']('Something went wrong') | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
| @ -1,113 +0,0 @@ | ||||
| <template> | ||||
|   <div class="wizard"> | ||||
|     <div class="step-indicator"> | ||||
|       <img | ||||
|         id="logo-crater" | ||||
|         src="/assets/img/crater-logo.png" | ||||
|         alt="Crater Logo" | ||||
|         class="logo-main" | ||||
|       > | ||||
|       <div class="indicator-line"> | ||||
|         <div class="center"> | ||||
|           <div class="steps" :class="{'active': step === 1, 'completed': step > 1}"> | ||||
|             <font-awesome-icon v-if="step > 1" icon="check" class="icon-check"/> | ||||
|           </div> | ||||
|           <div class="steps" :class="{'active': step === 2, 'completed': step > 2}"> | ||||
|             <font-awesome-icon v-if="step > 2" icon="check" class="icon-check"/> | ||||
|           </div> | ||||
|           <div class="steps" :class="{'active': step === 3, 'completed': step > 3}"> | ||||
|             <font-awesome-icon v-if="step > 3" icon="check" class="icon-check"/> | ||||
|           </div> | ||||
|           <div class="steps" :class="{'active': step === 4, 'completed': step > 4}"> | ||||
|             <font-awesome-icon v-if="step > 4" icon="check" class="icon-check"/> | ||||
|           </div> | ||||
|           <div class="steps" :class="{'active': step === 5, 'completed': step > 5}"> | ||||
|             <font-awesome-icon v-if="step > 5" icon="check" class="icon-check"/> | ||||
|           </div> | ||||
|           <div class="steps" :class="{'active': step === 6, 'completed': step > 6}"> | ||||
|             <font-awesome-icon v-if="step > 6" icon="check" class="icon-check"/> | ||||
|           </div> | ||||
|           <div class="steps" :class="{'active': step === 7, 'completed': step > 7}"> | ||||
|             <font-awesome-icon v-if="step > 7" icon="check" class="icon-check"/> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <div class="form-content"> | ||||
|       <div class="card wizard-card"> | ||||
|         <component | ||||
|           :is="tab" | ||||
|           @next="setTab" | ||||
|         /> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
| <script> | ||||
| import SystemRequirement from './SystemRequirement' | ||||
| import Permission from './Permission' | ||||
| import Database from './Database' | ||||
| import EmailConfiguration from './EmailConfiguration' | ||||
| import UserProfile from './UserProfile' | ||||
| import CompanyInfo from './CompanyInfo' | ||||
| import Settings from './Settings' | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
|     step_1: SystemRequirement, | ||||
|     step_2: Permission, | ||||
|     step_3: Database, | ||||
|     step_4: EmailConfiguration, | ||||
|     step_5: UserProfile, | ||||
|     step_6: CompanyInfo, | ||||
|     step_7: Settings | ||||
|   }, | ||||
|   data () { | ||||
|     return { | ||||
|       loading: false, | ||||
|       tab: 'step_1', | ||||
|       step: 1 | ||||
|     } | ||||
|   }, | ||||
|   created () { | ||||
|     this.getOnboardingData() | ||||
|   }, | ||||
|   methods: { | ||||
|     async getOnboardingData () { | ||||
|       let response = await window.axios.get('/api/admin/onboarding') | ||||
|       if (response.data) { | ||||
|         if (response.data.profile_complete === 'COMPLETED') { | ||||
|           this.$router.push('/admin/dashboard') | ||||
|  | ||||
|           return | ||||
|         } | ||||
|  | ||||
|         let dbStep = parseInt(response.data.profile_complete) | ||||
|  | ||||
|         if (dbStep) { | ||||
|           this.step = dbStep + 1 | ||||
|           this.tab = `step_${dbStep + 1}` | ||||
|         } | ||||
|  | ||||
|         this.languages = response.data.languages | ||||
|         this.currencies = response.data.currencies | ||||
|         this.dateFormats = response.data.date_formats | ||||
|         this.timeZones = response.data.time_zones | ||||
|  | ||||
|         // this.settingData.currency = this.currencies.find(currency => currency.id === 1) | ||||
|         // this.settingData.language = this.languages.find(language => language.code === 'en') | ||||
|         // this.settingData.dateFormat = this.dateFormats.find(dateFormat => dateFormat.value === 'd M Y') | ||||
|       } | ||||
|     }, | ||||
|     setTab (data) { | ||||
|       this.step++ | ||||
|  | ||||
|       if (this.step <= 7) { | ||||
|         this.tab = 'step_' + this.step | ||||
|       } else { | ||||
|         // window.location.reload() | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
| @ -1,86 +0,0 @@ | ||||
| <template> | ||||
|   <div class="card-body permissions"> | ||||
|     <p class="form-title">{{ $t('wizard.permissions.permissions') }}</p> | ||||
|     <p class="form-desc">{{ $t('wizard.permissions.permission_desc') }}</p> | ||||
|     <div class="d-flex justify-content-start"> | ||||
|       <div class="lists col-md-6"> | ||||
|         <div | ||||
|           v-for="(permission, index) in permissions" | ||||
|           :key="index" | ||||
|           class="row list-items" | ||||
|         > | ||||
|  | ||||
|           <div class="col-sm-9 left-item"> | ||||
|             {{ permission.folder }} | ||||
|           </div> | ||||
|           <div class="col-sm-3 right-item"> | ||||
|             <span v-if="permission.isSet" class="verified"/> | ||||
|             <span v-else class="not-verified"/> | ||||
|             <span>{{ permission.permission }}</span> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <base-button | ||||
|       v-if="isContinue" | ||||
|       class="pull-right mt-5" | ||||
|       icon="arrow-right" | ||||
|       right-icon | ||||
|       color="theme" | ||||
|       @click="next" | ||||
|     > | ||||
|       {{ $t('wizard.continue') }} | ||||
|     </base-button> | ||||
|   </div> | ||||
| </template> | ||||
| <script> | ||||
| export default { | ||||
|   data () { | ||||
|     return { | ||||
|       loading: false, | ||||
|       permissions: [], | ||||
|       errors: false, | ||||
|       isContinue: false | ||||
|     } | ||||
|   }, | ||||
|   created () { | ||||
|     this.getPermissions() | ||||
|   }, | ||||
|   methods: { | ||||
|     async getPermissions () { | ||||
|       this.loading = true | ||||
|  | ||||
|       let response = await window.axios.get('/api/admin/onboarding/permissions', this.profileData) | ||||
|  | ||||
|       if (response.data) { | ||||
|         this.permissions = response.data.permissions.permissions | ||||
|         this.errors = response.data.permissions.errors | ||||
|         let self = this | ||||
|  | ||||
|         if (this.errors) { | ||||
|           swal({ | ||||
|             title: this.$t('wizard.permissions.permission_confirm_title'), | ||||
|             text: this.$t('wizard.permissions.permission_confirm_desc'), | ||||
|             icon: 'warning', | ||||
|             buttons: true, | ||||
|             dangerMode: true | ||||
|           }).then(async (willConfirm) => { | ||||
|             if (willConfirm) { | ||||
|               self.isContinue = true | ||||
|             } | ||||
|           }) | ||||
|         } else { | ||||
|           this.isContinue = true | ||||
|         } | ||||
|  | ||||
|         this.loading = false | ||||
|       } | ||||
|     }, | ||||
|     async next () { | ||||
|       this.loading = true | ||||
|       await this.$emit('next') | ||||
|       this.loading = false | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
| @ -1,219 +0,0 @@ | ||||
| <template> | ||||
|   <div class="card-body"> | ||||
|     <form action="" @submit.prevent="next()"> | ||||
|       <p class="form-title">{{ $t('wizard.preferences') }}</p> | ||||
|       <p class="form-desc">{{ $t('wizard.preferences_desc') }}</p> | ||||
|       <div class="row"> | ||||
|         <div class="col-md-6"> | ||||
|           <label class="form-label">{{ $t('wizard.currency') }}</label> | ||||
|           <span class="text-danger"> *</span> | ||||
|           <base-select | ||||
|             v-model="settingData.currency" | ||||
|             :class="{'error': $v.settingData.currency.$error }" | ||||
|             :options="currencies" | ||||
|             :custom-label="currencyNameWithCode" | ||||
|             :searchable="true" | ||||
|             :show-labels="false" | ||||
|             :placeholder="$t('settings.currencies.select_currency')" | ||||
|             track-by="id" | ||||
|             label="name" | ||||
|             @input="$v.settingData.currency.$touch()" | ||||
|           /> | ||||
|           <div v-if="$v.settingData.currency.$error"> | ||||
|             <span v-if="!$v.settingData.currency.required" class="text-danger">{{ $tc('validation.required') }}</span> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="col-md-6"> | ||||
|           <label class="form-label">{{ $t('wizard.language') }}</label><span class="text-danger"> *</span> | ||||
|           <base-select | ||||
|             v-model="settingData.language" | ||||
|             :class="{'error': $v.settingData.language.$error }" | ||||
|             :options="languages" | ||||
|             :searchable="true" | ||||
|             :show-labels="false" | ||||
|             :placeholder="$t('settings.preferences.select_language')" | ||||
|             label="name" | ||||
|             @input="$v.settingData.language.$touch()" | ||||
|           /> | ||||
|           <div v-if="$v.settingData.language.$error"> | ||||
|             <span v-if="!$v.settingData.language.required" class="text-danger">{{ $tc('validation.required') }}</span> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="row"> | ||||
|         <div class="col-md-6"> | ||||
|           <label class="form-label">{{ $t('wizard.date_format') }}</label><span class="text-danger"> *</span> | ||||
|           <base-select | ||||
|             v-model="settingData.dateFormat" | ||||
|             :class="{'error': $v.settingData.dateFormat.$error }" | ||||
|             :options="dateFormats" | ||||
|             :searchable="true" | ||||
|             :show-labels="false" | ||||
|             :placeholder="$t('settings.preferences.select_date_formate')" | ||||
|             label="display_date" | ||||
|             @input="$v.settingData.dateFormat.$touch()" | ||||
|           /> | ||||
|           <div v-if="$v.settingData.dateFormat.$error"> | ||||
|             <span v-if="!$v.settingData.dateFormat.required" class="text-danger">{{ $tc('validation.required') }}</span> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="col-md-6"> | ||||
|           <label class="form-label">{{ $t('wizard.time_zone') }}</label><span class="text-danger"> *</span> | ||||
|           <base-select | ||||
|             v-model="settingData.timeZone" | ||||
|             :class="{'error': $v.settingData.timeZone.$error }" | ||||
|             :options="timeZones" | ||||
|             :searchable="true" | ||||
|             :show-labels="false" | ||||
|             :placeholder="$t('settings.preferences.select_date_formate')" | ||||
|             label="key" | ||||
|             @input="$v.settingData.timeZone.$touch()" | ||||
|           /> | ||||
|           <div v-if="$v.settingData.timeZone.$error"> | ||||
|             <span v-if="!$v.settingData.timeZone.required" class="text-danger">{{ $tc('validation.required') }}</span> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="row"> | ||||
|         <div class="col-md-6"> | ||||
|           <label class="form-label">{{ $t('wizard.fiscal_year') }}</label><span class="text-danger"> *</span> | ||||
|           <base-select | ||||
|             v-model="settingData.fiscalYear" | ||||
|             :class="{'error': $v.settingData.fiscalYear.$error }" | ||||
|             :options="fiscalYears" | ||||
|             :searchable="true" | ||||
|             :show-labels="false" | ||||
|             :placeholder="$t('settings.preferences.select_financial_year')" | ||||
|             label="key" | ||||
|             @input="$v.settingData.fiscalYear.$touch()" | ||||
|           /> | ||||
|           <div v-if="$v.settingData.fiscalYear.$error"> | ||||
|             <span v-if="!$v.settingData.fiscalYear.required" class="text-danger">{{ $tc('customers.errors.required') }}</span> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|       <base-button :loading="loading" class="pull-right" icon="save" color="theme" type="submit"> | ||||
|         {{ $t('wizard.save_cont') }} | ||||
|       </base-button> | ||||
|     </form> | ||||
|   </div> | ||||
| </template> | ||||
| <script> | ||||
| import MultiSelect from 'vue-multiselect' | ||||
| import { validationMixin } from 'vuelidate' | ||||
| import Ls from '../../services/ls' | ||||
| import { mapActions } from 'vuex' | ||||
| const { required, minLength, email } = require('vuelidate/lib/validators') | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
|     MultiSelect | ||||
|   }, | ||||
|   mixins: [validationMixin], | ||||
|   data () { | ||||
|     return { | ||||
|       settingData: { | ||||
|         language: null, | ||||
|         currency: null, | ||||
|         timeZone: null, | ||||
|         dateFormat: null, | ||||
|         fiscalYear: null | ||||
|       }, | ||||
|       loading: false, | ||||
|       step: 1, | ||||
|       languages: [], | ||||
|       currencies: [], | ||||
|       timeZones: [], | ||||
|       dateFormats: [], | ||||
|       fiscalYears: [] | ||||
|     } | ||||
|   }, | ||||
|   validations: { | ||||
|     settingData: { | ||||
|       currency: { | ||||
|         required | ||||
|       }, | ||||
|       language: { | ||||
|         required | ||||
|       }, | ||||
|       dateFormat: { | ||||
|         required | ||||
|       }, | ||||
|       timeZone: { | ||||
|         required | ||||
|       }, | ||||
|       fiscalYear: { | ||||
|         required | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   mounted () { | ||||
|     this.getOnboardingData() | ||||
|   }, | ||||
|   methods: { | ||||
|     currencyNameWithCode ({name, code}) { | ||||
|       return `${code} - ${name}` | ||||
|     }, | ||||
|     ...mapActions('auth', [ | ||||
|       'loginOnBoardingUser' | ||||
|     ]), | ||||
|     async getOnboardingData () { | ||||
|       let response = await window.axios.get('/api/admin/onboarding') | ||||
|       if (response.data) { | ||||
|         if (response.data.profile_complete === 'COMPLETED') { | ||||
|           this.$router.push('/admin/dashboard') | ||||
|  | ||||
|           return | ||||
|         } | ||||
|  | ||||
|         let dbStep = parseInt(response.data.profile_complete) | ||||
|  | ||||
|         if (dbStep) { | ||||
|           this.step = dbStep + 1 | ||||
|         } | ||||
|  | ||||
|         this.languages = response.data.languages | ||||
|         this.currencies = response.data.currencies | ||||
|         this.dateFormats = response.data.date_formats | ||||
|         this.timeZones = response.data.time_zones | ||||
|         this.fiscalYears = response.data.fiscal_years | ||||
|  | ||||
|         this.settingData.currency = this.currencies.find(currency => currency.id === 1) | ||||
|         this.settingData.language = this.languages.find(language => language.code === 'en') | ||||
|         this.settingData.dateFormat = response.data.date_formats.find(dateFormat => dateFormat.carbon_format_value == 'd M Y') | ||||
|         this.settingData.timeZone = this.timeZones.find(timeZone => timeZone.value === 'UTC') | ||||
|         this.settingData.fiscalYear = this.fiscalYears.find(fiscalYear => fiscalYear.value === '1-12') | ||||
|       } | ||||
|     }, | ||||
|     async next () { | ||||
|       this.$v.settingData.$touch() | ||||
|  | ||||
|       if (this.$v.settingData.$invalid) { | ||||
|         return true | ||||
|       } | ||||
|  | ||||
|       this.loading = true | ||||
|  | ||||
|       let data = { | ||||
|         currency: this.settingData.currency.id, | ||||
|         time_zone: this.settingData.timeZone.value, | ||||
|         language: this.settingData.language.code, | ||||
|         fiscal_year: this.settingData.fiscalYear.value, | ||||
|         carbon_date_format: this.settingData.dateFormat.carbon_format_value, | ||||
|         moment_date_format: this.settingData.dateFormat.moment_format_value | ||||
|       } | ||||
|  | ||||
|       let response = await window.axios.post('/api/admin/onboarding/settings', data) | ||||
|  | ||||
|       if (response.data) { | ||||
|         // this.$emit('next') | ||||
|         this.loading = false | ||||
|         Ls.set('auth.token', response.data.token) | ||||
|         this.loginOnBoardingUser(response.data.token) | ||||
|         window.toastr['success']('Login Successful') | ||||
|         this.$router.push('/admin/dashboard') | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
| @ -1,112 +0,0 @@ | ||||
| <template> | ||||
|   <div class="card-body"> | ||||
|     <p class="form-title">{{ $t('wizard.req.system_req') }}</p> | ||||
|     <p class="form-desc">{{ $t('wizard.req.system_req_desc') }}</p> | ||||
|     <div v-if="phpSupportInfo" class="d-flex justify-content-start"> | ||||
|       <div class="col-md-6"> | ||||
|         <div class="row list-items"> | ||||
|           <div class="col-md-9 left-item"> | ||||
|             {{ $t('wizard.req.php_req_version', { version: phpSupportInfo.minimum }) }} | ||||
|           </div> | ||||
|           <div class="col-md-3 right-item justify-content-end"> | ||||
|             {{ phpSupportInfo.current }} | ||||
|             <span v-if="phpSupportInfo.supported" class="verified"/> | ||||
|             <span v-else class="not-verified"/> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <div v-if="requirements" class="d-flex justify-content-start"> | ||||
|       <div class="col-md-6"> | ||||
|         <div | ||||
|           v-for="(requirement, index) in requirements" | ||||
|           :key="index" | ||||
|           class="row list-items" | ||||
|         > | ||||
|  | ||||
|           <div class="col-md-9 left-item"> | ||||
|             {{ index }} | ||||
|           </div> | ||||
|           <div class="col-md-3 right-item  justify-content-end"> | ||||
|             <span v-if="requirement" class="verified"/> | ||||
|             <span v-else class="not-verified"/> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <base-button | ||||
|       v-if="hasNext" | ||||
|       :loading="loading" | ||||
|       class="pull-right mt-4" | ||||
|       icon="arrow-right" | ||||
|       color="theme" | ||||
|       right-icon | ||||
|       @click="next" | ||||
|     > | ||||
|       {{ $t('wizard.continue') }} | ||||
|     </base-button> | ||||
|     <base-button | ||||
|       v-if="!requirements" | ||||
|       :loading="loading" | ||||
|       class="pull-right mt-4" | ||||
|       color="theme" | ||||
|       @click="getRequirements" | ||||
|     > | ||||
|       {{ $t('wizard.req.check_req') }} | ||||
|     </base-button> | ||||
|   </div> | ||||
| </template> | ||||
| <script> | ||||
| import MultiSelect from 'vue-multiselect' | ||||
| import { validationMixin } from 'vuelidate' | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
|     MultiSelect | ||||
|   }, | ||||
|   mixins: [validationMixin], | ||||
|   data () { | ||||
|     return { | ||||
|       requirements: null, | ||||
|       phpSupportInfo: null, | ||||
|       loading: false, | ||||
|       isShow: true | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     hasNext () { | ||||
|       if (this.requirements) { | ||||
|         let isRequired = true | ||||
|         for (const key in this.requirements) { | ||||
|           if (!this.requirements[key]) { | ||||
|             isRequired = false | ||||
|           } | ||||
|         } | ||||
|         return this.requirements && this.phpSupportInfo.supported && isRequired | ||||
|       } | ||||
|       return false | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     listToggle  () { | ||||
|       this.isShow = !this.isShow | ||||
|     }, | ||||
|     async getRequirements () { | ||||
|       this.loading = true | ||||
|  | ||||
|       let response = await window.axios.get('/api/admin/onboarding/requirements', this.profileData) | ||||
|  | ||||
|       if (response.data) { | ||||
|         this.requirements = response.data.requirements.requirements.php | ||||
|         this.phpSupportInfo = response.data.phpSupportInfo | ||||
|         this.loading = false | ||||
|       } | ||||
|     }, | ||||
|     async next () { | ||||
|       this.loading = true | ||||
|       await this.$emit('next') | ||||
|       this.loading = false | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
| @ -1,204 +0,0 @@ | ||||
| <template> | ||||
|   <div class="card-body"> | ||||
|     <form action="" @submit.prevent="next()"> | ||||
|       <p class="form-title">{{ $t('wizard.account_info') }}</p> | ||||
|       <p class="form-desc">{{ $t('wizard.account_info_desc') }}</p> | ||||
|       <div class="row mb-4"> | ||||
|         <div class="col-md-6"> | ||||
|           <label class="form-label">{{ $tc('settings.account_settings.profile_picture') }}</label> | ||||
|           <div id="pick-avatar" class="image-upload-box avatar-upload"> | ||||
|             <div class="overlay"> | ||||
|               <font-awesome-icon class="white-icon" icon="camera"/> | ||||
|             </div> | ||||
|             <img v-if="previewAvatar" :src="previewAvatar" class="preview-logo"> | ||||
|             <div v-else class="upload-content"> | ||||
|               <font-awesome-icon class="upload-icon" icon="cloud-upload-alt"/> | ||||
|               <p class="upload-text"> {{ $tc('general.choose_file') }} </p> | ||||
|             </div> | ||||
|           </div> | ||||
|         </div> | ||||
|         <avatar-cropper | ||||
|           :labels="{ submit: 'submit', cancel: 'Cancel'}" | ||||
|           :cropper-options="cropperOptions" | ||||
|           :output-options="cropperOutputOptions" | ||||
|           :output-quality="0.8" | ||||
|           :upload-handler="cropperHandler" | ||||
|           trigger="#pick-avatar" | ||||
|           @changed="setFileObject" | ||||
|           @error="handleUploadError" | ||||
|         /> | ||||
|       </div> | ||||
|       <div class="row"> | ||||
|         <div class="col-md-6"> | ||||
|           <label class="form-label">{{ $t('wizard.name') }}</label><span class="text-danger"> *</span> | ||||
|           <base-input | ||||
|             :invalid="$v.profileData.name.$error" | ||||
|             v-model.trim="profileData.name" | ||||
|             type="text" | ||||
|             name="name" | ||||
|             @input="$v.profileData.name.$touch()" | ||||
|           /> | ||||
|           <div v-if="$v.profileData.name.$error"> | ||||
|             <span v-if="!$v.profileData.name.required" class="text-danger">{{ $tc('validation.required') }}</span> | ||||
|             <span v-if="!$v.profileData.name.minLength" class="text-danger"> {{ $tc('validation.name_min_length', $v.profileData.name.$params.minLength.min, { count: $v.profileData.name.$params.minLength.min }) }} </span> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="col-md-6"> | ||||
|           <label class="form-label">{{ $t('wizard.email') }}</label><span class="text-danger"> *</span> | ||||
|           <base-input | ||||
|             :invalid="$v.profileData.email.$error" | ||||
|             v-model.trim="profileData.email" | ||||
|             type="text" | ||||
|             name="email" | ||||
|             @input="$v.profileData.email.$touch()" | ||||
|           /> | ||||
|           <div v-if="$v.profileData.email.$error"> | ||||
|             <span v-if="!$v.profileData.email.required" class="text-danger">{{ $tc('validation.required') }}</span> | ||||
|             <span v-if="!$v.profileData.email.email" class="text-danger">{{ $tc('validation.email_incorrect') }}</span> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="row"> | ||||
|         <div class="col-md-6"> | ||||
|           <label class="form-label">{{ $t('wizard.password') }}</label><span class="text-danger"> *</span> | ||||
|           <base-input | ||||
|             :invalid="$v.profileData.password.$error" | ||||
|             v-model.trim="profileData.password" | ||||
|             type="password" | ||||
|             name="password" | ||||
|             @input="$v.profileData.password.$touch()" | ||||
|           /> | ||||
|           <div v-if="$v.profileData.password.$error"> | ||||
|             <span v-if="!$v.profileData.password.required" class="text-danger">{{ $tc('validation.required') }}</span> | ||||
|             <span v-if="!$v.profileData.password.minLength" class="text-danger"> {{ $tc('validation.password_min_length', $v.profileData.password.$params.minLength.min, {count: $v.profileData.password.$params.minLength.min}) }} </span> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="col-md-6"> | ||||
|           <label class="form-label">{{ $t('wizard.confirm_password') }}</label><span class="text-danger"> *</span> | ||||
|           <base-input | ||||
|             :invalid="$v.profileData.confirm_password.$error" | ||||
|             v-model.trim="profileData.confirm_password" | ||||
|             type="password" | ||||
|             name="confirm_password" | ||||
|             @input="$v.profileData.confirm_password.$touch()" | ||||
|           /> | ||||
|           <div v-if="$v.profileData.confirm_password.$error"> | ||||
|             <span v-if="!$v.profileData.confirm_password.sameAsPassword" class="text-danger">{{ $tc('validation.password_incorrect') }}</span> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|       <base-button | ||||
|         :loading="loading" | ||||
|         class="pull-right mt-4" | ||||
|         icon="save" | ||||
|         color="theme" | ||||
|         type="submit" | ||||
|       > | ||||
|         {{ $t('wizard.save_cont') }} | ||||
|       </base-button> | ||||
|     </form> | ||||
|   </div> | ||||
| </template> | ||||
| <script> | ||||
| import AvatarCropper from 'vue-avatar-cropper' | ||||
| import { validationMixin } from 'vuelidate' | ||||
| import { mapActions } from 'vuex' | ||||
| const { required, requiredIf, sameAs, minLength, email } = require('vuelidate/lib/validators') | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
|     AvatarCropper | ||||
|   }, | ||||
|   mixins: [validationMixin], | ||||
|   data () { | ||||
|     return { | ||||
|       cropperOutputOptions: { | ||||
|         width: 150, | ||||
|         height: 150 | ||||
|       }, | ||||
|       cropperOptions: { | ||||
|         autoCropArea: 1, | ||||
|         viewMode: 0, | ||||
|         movable: true, | ||||
|         zoomable: true | ||||
|       }, | ||||
|       profileData: { | ||||
|         name: null, | ||||
|         email: null, | ||||
|         password: null, | ||||
|         confirm_password: null | ||||
|       }, | ||||
|       loading: false, | ||||
|       previewAvatar: '/images/default-avatar.jpg', | ||||
|       fileObject: null | ||||
|     } | ||||
|   }, | ||||
|   validations: { | ||||
|     profileData: { | ||||
|       name: { | ||||
|         required, | ||||
|         minLength: minLength(3) | ||||
|       }, | ||||
|       email: { | ||||
|         email, | ||||
|         required | ||||
|       }, | ||||
|       password: { | ||||
|         required, | ||||
|         minLength: minLength(8) | ||||
|       }, | ||||
|       confirm_password: { | ||||
|         required: requiredIf('isRequired'), | ||||
|         sameAsPassword: sameAs('password') | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     isRequired () { | ||||
|       if (this.profileData.password === null || this.profileData.password === undefined || this.profileData.password === '') { | ||||
|         return false | ||||
|       } | ||||
|       return true | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     ...mapActions('userProfile', [ | ||||
|       'uploadOnboardAvatar' | ||||
|     ]), | ||||
|     cropperHandler (cropper) { | ||||
|       this.previewAvatar = cropper.getCroppedCanvas().toDataURL(this.cropperOutputMime) | ||||
|     }, | ||||
|     setFileObject (file) { | ||||
|       this.fileObject = file | ||||
|     }, | ||||
|     handleUploadError (message, type, xhr) { | ||||
|       window.toastr['error']('Oops! Something went wrong...') | ||||
|     }, | ||||
|     async next () { | ||||
|       this.$v.profileData.$touch() | ||||
|       if (this.$v.profileData.$invalid) { | ||||
|         return true | ||||
|       } | ||||
|       this.loading = true | ||||
|       let response = await window.axios.post('/api/admin/onboarding/profile', this.profileData) | ||||
|       console.log('user_id', response.data.user.id) | ||||
|  | ||||
|       if (response.data) { | ||||
|         if (this.fileObject && this.previewAvatar) { | ||||
|           let avatarData = new FormData() | ||||
|           avatarData.append('admin_avatar', JSON.stringify({ | ||||
|             name: this.fileObject.name, | ||||
|             data: this.previewAvatar, | ||||
|             id: response.data.user.id | ||||
|           })) | ||||
|  | ||||
|           this.uploadOnboardAvatar(avatarData) | ||||
|         } | ||||
|         this.$emit('next') | ||||
|         this.loading = false | ||||
|       } | ||||
|       return true | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
							
								
								
									
										89
									
								
								resources/assets/js/views/wizard/Wizard.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								resources/assets/js/views/wizard/Wizard.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,89 @@ | ||||
| <template> | ||||
|   <div | ||||
|     class="flex flex-col items-center justify-between w-full h-32 pt-10 step-indicator" | ||||
|   > | ||||
|     <img | ||||
|       id="logo-crater" | ||||
|       src="/assets/img/crater-logo.png" | ||||
|       alt="Crater Logo" | ||||
|       class="h-12" | ||||
|     /> | ||||
|     <sw-wizard | ||||
|       :steps="7" | ||||
|       :currentStep.sync="step" | ||||
|       :allow-navigation-redirect="false" | ||||
|     > | ||||
|       <component :is="tab" @next="setTab" /> | ||||
|     </sw-wizard> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import SystemRequirement from './WizardSystemRequirementStep' | ||||
| import Permission from './WizardPermissionStep' | ||||
| import Database from './WizardDatabaseStep' | ||||
| import EmailConfiguration from './WizardEmailConfigStep' | ||||
| import UserProfile from './WizardUserProfileStep' | ||||
| import CompanyInfo from './WizardCompanyInfoStep' | ||||
| import Settings from './WizardSettingsStep' | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
|     step_1: SystemRequirement, | ||||
|     step_2: Permission, | ||||
|     step_3: Database, | ||||
|     step_4: EmailConfiguration, | ||||
|     step_5: UserProfile, | ||||
|     step_6: CompanyInfo, | ||||
|     step_7: Settings, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       profile_complete: null, | ||||
|       loading: false, | ||||
|       tab: 'step_1', | ||||
|       step: 1, | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.getProfileComplete() | ||||
|   }, | ||||
|   methods: { | ||||
|     async getProfileComplete() { | ||||
|       let response = await axios.get('/api/v1/onboarding/wizard-step') | ||||
|  | ||||
|       if (response.data.profile_complete === 'COMPLETED') { | ||||
|         this.$router.push('/admin/dashboard') | ||||
|  | ||||
|         return | ||||
|       } | ||||
|  | ||||
|       let dbStep = parseInt(response.data.profile_complete) | ||||
|  | ||||
|       if (dbStep) { | ||||
|         this.step = dbStep + 1 | ||||
|         this.tab = `step_${dbStep + 1}` | ||||
|       } | ||||
|     }, | ||||
|     async setProfileComplete(data) { | ||||
|       let status = { | ||||
|         profile_complete: data, | ||||
|       } | ||||
|  | ||||
|       let response = await axios.post('/api/v1/onboarding/wizard-step', status) | ||||
|     }, | ||||
|     async setTab(data) { | ||||
|       if (data) { | ||||
|         this.setProfileComplete(data) | ||||
|       } | ||||
|       this.step++ | ||||
|  | ||||
|       if (this.step <= 7) { | ||||
|         this.tab = 'step_' + this.step | ||||
|       } else { | ||||
|         // window.location.reload() | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
							
								
								
									
										324
									
								
								resources/assets/js/views/wizard/WizardCompanyInfoStep.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										324
									
								
								resources/assets/js/views/wizard/WizardCompanyInfoStep.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,324 @@ | ||||
| <template> | ||||
|   <sw-wizard-step | ||||
|     :title="$t('wizard.company_info')" | ||||
|     :description="$t('wizard.company_info_desc')" | ||||
|   > | ||||
|     <base-loader v-if="isFetching" :show-bg-overlay="true" /> | ||||
|     <form action="" @submit.prevent="next()"> | ||||
|       <div> | ||||
|         <div class="grid grid-cols-1 mb-4 md:grid-cols-2 md:mb-6"> | ||||
|           <sw-input-group :label="$tc('settings.company_info.company_logo')"> | ||||
|             <div | ||||
|               id="logo-box" | ||||
|               class="relative flex items-center justify-center h-24 p-5 mt-2 bg-transparent border-2 border-gray-200 border-dashed rounded-md image-upload-box" | ||||
|             > | ||||
|               <img | ||||
|                 v-if="previewLogo" | ||||
|                 :src="previewLogo" | ||||
|                 class="absolute opacity-100 preview-logo" | ||||
|                 style="max-height: 80%; animation: fadeIn 2s ease" | ||||
|               /> | ||||
|               <div v-else class="flex flex-col items-center"> | ||||
|                 <cloud-upload-icon | ||||
|                   class="h-5 mb-2 text-xl leading-6 text-gray-400" | ||||
|                 /> | ||||
|                 <p class="text-xs leading-4 text-center text-gray-400"> | ||||
|                   Drag a file here or | ||||
|                   <span id="pick-avatar" class="cursor-pointer text-primary-500" | ||||
|                     >browse</span | ||||
|                   > | ||||
|                   to choose a file | ||||
|                 </p> | ||||
|               </div> | ||||
|             </div> | ||||
|  | ||||
|             <sw-avatar | ||||
|               trigger="#logo-box" | ||||
|               :preview-avatar="previewLogo" | ||||
|               @changed="onChange" | ||||
|               @uploadHandler="onUploadHandler" | ||||
|               @handleUploadError="onHandleUploadError" | ||||
|             > | ||||
|               <template v-slot:icon> | ||||
|                 <cloud-upload-icon | ||||
|                   class="h-5 mb-2 text-xl leading-6 text-gray-400" | ||||
|                 /> | ||||
|               </template> | ||||
|             </sw-avatar> | ||||
|           </sw-input-group> | ||||
|         </div> | ||||
|  | ||||
|         <div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 md:mb-6"> | ||||
|           <sw-input-group | ||||
|             :label="$t('wizard.company_name')" | ||||
|             :error="companyNameError" | ||||
|             required | ||||
|           > | ||||
|             <sw-input | ||||
|               :invalid="$v.companyData.name.$error" | ||||
|               v-model.trim="companyData.name" | ||||
|               type="text" | ||||
|               name="name" | ||||
|               @input="$v.companyData.name.$touch()" | ||||
|             /> | ||||
|           </sw-input-group> | ||||
|           <sw-input-group | ||||
|             :label="$t('wizard.country')" | ||||
|             :error="countryError" | ||||
|             required | ||||
|           > | ||||
|             <sw-select | ||||
|               v-model="country" | ||||
|               :class="{ error: $v.companyData.country_id.$error }" | ||||
|               :options="countries" | ||||
|               :searchable="true" | ||||
|               :allow-empty="false" | ||||
|               :show-labels="false" | ||||
|               :placeholder="$t('general.select_country')" | ||||
|               track-by="id" | ||||
|               label="name" | ||||
|             /> | ||||
|           </sw-input-group> | ||||
|         </div> | ||||
|  | ||||
|         <div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 md:mb-6"> | ||||
|           <sw-input-group :label="$t('wizard.state')"> | ||||
|             <sw-input v-model="companyData.state" name="state" type="text" /> | ||||
|           </sw-input-group> | ||||
|  | ||||
|           <sw-input-group :label="$t('wizard.city')"> | ||||
|             <sw-input v-model="companyData.city" name="city" type="text" /> | ||||
|           </sw-input-group> | ||||
|         </div> | ||||
|  | ||||
|         <div class="grid grid-cols-1 gap-4 mb-6 md:grid-cols-2"> | ||||
|           <div> | ||||
|             <sw-input-group | ||||
|               :label="$t('wizard.address')" | ||||
|               :error="address1Error" | ||||
|             > | ||||
|               <sw-textarea | ||||
|                 :invalid="$v.companyData.address_street_1.$error" | ||||
|                 v-model.trim="companyData.address_street_1" | ||||
|                 :placeholder="$t('general.street_1')" | ||||
|                 name="billing_street1" | ||||
|                 rows="2" | ||||
|                 @input="$v.companyData.address_street_1.$touch()" | ||||
|               /> | ||||
|             </sw-input-group> | ||||
|  | ||||
|             <sw-input-group :error="address2Error" class="mt-1 lg:mt-2 md:mt-2"> | ||||
|               <sw-textarea | ||||
|                 :invalid="$v.companyData.address_street_2.$error" | ||||
|                 v-model="companyData.address_street_2" | ||||
|                 :placeholder="$t('general.street_2')" | ||||
|                 name="billing_street2" | ||||
|                 rows="2" | ||||
|                 @input="$v.companyData.address_street_2.$touch()" | ||||
|               /> | ||||
|             </sw-input-group> | ||||
|           </div> | ||||
|  | ||||
|           <div> | ||||
|             <sw-input-group :label="$t('wizard.zip_code')"> | ||||
|               <sw-input v-model.trim="companyData.zip" type="text" name="zip" /> | ||||
|             </sw-input-group> | ||||
|  | ||||
|             <sw-input-group :label="$t('wizard.phone')" class="mt-4"> | ||||
|               <sw-input | ||||
|                 v-model.trim="companyData.phone" | ||||
|                 type="text" | ||||
|                 name="phone" | ||||
|               /> | ||||
|             </sw-input-group> | ||||
|           </div> | ||||
|         </div> | ||||
|  | ||||
|         <sw-button | ||||
|           :loading="isLoading" | ||||
|           :disabled="isLoading" | ||||
|           class="mt-4" | ||||
|           variant="primary" | ||||
|           type="submit" | ||||
|         > | ||||
|           <save-icon v-if="!isLoading" class="mr-2" /> | ||||
|           {{ $t('wizard.save_cont') }} | ||||
|         </sw-button> | ||||
|       </div> | ||||
|     </form> | ||||
|   </sw-wizard-step> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { CloudUploadIcon } from '@vue-hero-icons/solid' | ||||
| import { mapActions } from 'vuex' | ||||
| const { required, maxLength } = require('vuelidate/lib/validators') | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
|     CloudUploadIcon | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       companyData: { | ||||
|         logo: '', | ||||
|         name: null, | ||||
|         address_street_1: '', | ||||
|         address_street_2: '', | ||||
|         city: '', | ||||
|         state: '', | ||||
|         country_id: '', | ||||
|         zip: '', | ||||
|         phone: '', | ||||
|       }, | ||||
|       isLoading: false, | ||||
|       isFetching: false, | ||||
|       step: 1, | ||||
|       countries: [], | ||||
|       country: null, | ||||
|       previewLogo: null, | ||||
|       fileObject: null, | ||||
|       cropperOutputMime: '', | ||||
|     } | ||||
|   }, | ||||
|   validations: { | ||||
|     companyData: { | ||||
|       name: { | ||||
|         required, | ||||
|       }, | ||||
|       country_id: { | ||||
|         required, | ||||
|       }, | ||||
|       address_street_1: { | ||||
|         maxLength: maxLength(255), | ||||
|       }, | ||||
|       address_street_2: { | ||||
|         maxLength: maxLength(255), | ||||
|       }, | ||||
|     }, | ||||
|   }, | ||||
|   watch: { | ||||
|     country({ id }) { | ||||
|       this.companyData.country_id = id | ||||
|       return true | ||||
|     }, | ||||
|   }, | ||||
|   computed: { | ||||
|     companyNameError() { | ||||
|       if (!this.$v.companyData.name.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.companyData.name.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|     countryError() { | ||||
|       if (!this.$v.companyData.country_id.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.companyData.country_id.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|     address1Error() { | ||||
|       if (!this.$v.companyData.address_street_1.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.companyData.address_street_1.maxLength) { | ||||
|         return this.$t('validation.description_maxlength') | ||||
|       } | ||||
|     }, | ||||
|     address2Error() { | ||||
|       if (!this.$v.companyData.address_street_2.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.companyData.address_street_2.maxLength) { | ||||
|         return this.$t('validation.description_maxlength') | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
|   mounted() { | ||||
|     this.fetchCountries() | ||||
|   }, | ||||
|   methods: { | ||||
|     ...mapActions('company', ['setSelectedCompany']), | ||||
|  | ||||
|     onUploadHandler(cropper) { | ||||
|       this.previewLogo = cropper | ||||
|         .getCroppedCanvas() | ||||
|         .toDataURL(this.cropperOutputMime) | ||||
|     }, | ||||
|  | ||||
|     onHandleUploadError() { | ||||
|       window.toastr['error']('Oops! Something went wrong...') | ||||
|     }, | ||||
|  | ||||
|     onChange(file) { | ||||
|       this.cropperOutputMime = file.type | ||||
|       this.fileObject = file | ||||
|     }, | ||||
|  | ||||
|     async next() { | ||||
|       this.$v.companyData.$touch() | ||||
|  | ||||
|       if (this.$v.companyData.$invalid) { | ||||
|         return true | ||||
|       } | ||||
|  | ||||
|       this.isLoading = true | ||||
|  | ||||
|       let response = await window.axios.put('/api/v1/company', this.companyData) | ||||
|  | ||||
|       if (response.data) { | ||||
|         this.setSelectedCompany(response.data.company) | ||||
|  | ||||
|         if (this.fileObject && this.previewLogo) { | ||||
|           let logoData = new FormData() | ||||
|           logoData.append( | ||||
|             'company_logo', | ||||
|             JSON.stringify({ | ||||
|               name: this.fileObject.name, | ||||
|               data: this.previewLogo, | ||||
|             }) | ||||
|           ) | ||||
|  | ||||
|           await axios.post('/api/v1/company/upload-logo', logoData, { | ||||
|             headers: { | ||||
|               'Content-Type': 'multipart/form-data', | ||||
|               company: response.data.company.id, | ||||
|             }, | ||||
|           }) | ||||
|         } | ||||
|  | ||||
|         this.$emit('next', 6) | ||||
|         this.isLoading = false | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     onFileChange(e) { | ||||
|       var input = event.target | ||||
|       this.companyData.logo = input.files[0] | ||||
|       if (input.files && input.files[0]) { | ||||
|         var reader = new FileReader() | ||||
|         reader.onload = (e) => { | ||||
|           this.previewLogo = e.target.result | ||||
|         } | ||||
|         reader.readAsDataURL(input.files[0]) | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     async fetchCountries() { | ||||
|       this.isFetching = true | ||||
|       let res = await window.axios.get('/api/v1/countries') | ||||
|       if (res) { | ||||
|         this.countries = res.data.countries | ||||
|       } | ||||
|       this.isFetching = false | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
							
								
								
									
										103
									
								
								resources/assets/js/views/wizard/WizardDatabaseStep.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								resources/assets/js/views/wizard/WizardDatabaseStep.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,103 @@ | ||||
| <template> | ||||
|   <sw-wizard-step | ||||
|     :title="$t('wizard.database.database')" | ||||
|     :description="$t('wizard.database.desc')" | ||||
|   > | ||||
|     <base-loader v-if="isFetching" :show-bg-overlay="true" /> | ||||
|     <component | ||||
|       :is="database_connection" | ||||
|       :config-data="databaseData" | ||||
|       :is-loading="isLoading" | ||||
|       :is-fetching="isFetching" | ||||
|       @on-change-driver="getDatabaseConfig" | ||||
|       @submit-data="next" | ||||
|     /> | ||||
|   </sw-wizard-step> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { validationMixin } from 'vuelidate' | ||||
| import Mysql from './database/MysqlDatabase' | ||||
| import Pgsql from './database/PgsqlDatabase' | ||||
| import Sqlite from './database/SqliteDatabase' | ||||
| import Sqlsrv from './database/SqlsrvDatabase' | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
|     Mysql, | ||||
|     Pgsql, | ||||
|     Sqlite, | ||||
|     Sqlsrv, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       databaseData: { | ||||
|         database_connection: 'mysql', | ||||
|       }, | ||||
|       isLoading: false, | ||||
|       isFetching: false, | ||||
|       database_connection: 'mysql', | ||||
|       connections: ['sqlite', 'mysql', 'pgsql', 'sqlsrv'], | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.getDatabaseConfig(this.database_connection) | ||||
|   }, | ||||
|   methods: { | ||||
|     async getDatabaseConfig(connection) { | ||||
|       this.isLoading = this.isFetching = true | ||||
|  | ||||
|       let params = { | ||||
|         connection, | ||||
|       } | ||||
|  | ||||
|       let response = await window.axios.get( | ||||
|         '/api/v1/onboarding/database/config', | ||||
|         { params } | ||||
|       ) | ||||
|  | ||||
|       if (response.data.success) { | ||||
|         this.databaseData = response.data.config | ||||
|         this.database_connection = connection | ||||
|         this.databaseData.database_connection = connection | ||||
|         this.isLoading = this.isFetching = false | ||||
|       } | ||||
|     }, | ||||
|     async next(databaseData) { | ||||
|       this.isLoading = this.isFetching = true | ||||
|       try { | ||||
|         await window.axios.get('/sanctum/csrf-cookie') | ||||
|  | ||||
|         let response = await window.axios.post( | ||||
|           '/api/v1/onboarding/database/config', | ||||
|           databaseData | ||||
|         ) | ||||
|  | ||||
|         await window.axios.get('/sanctum/csrf-cookie') | ||||
|  | ||||
|         if (response.data.success) { | ||||
|           await window.axios.post('/api/v1/onboarding/finish') | ||||
|  | ||||
|           this.$emit('next', 3) | ||||
|  | ||||
|           window.toastr['success']( | ||||
|             this.$t('wizard.success.' + response.data.success) | ||||
|           ) | ||||
|  | ||||
|           return true | ||||
|         } else if (response.data.error) { | ||||
|           window.toastr['error']( | ||||
|             this.$t('wizard.errors.' + response.data.error) | ||||
|           ) | ||||
|         } else if (response.data.error_message) { | ||||
|           window.toastr['error'](response.data.error_message) | ||||
|         } | ||||
|       } catch (e) { | ||||
|         window.toastr['error'](e.response.data.message) | ||||
|       } finally { | ||||
|         this.isLoading = this.isFetching = false | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
							
								
								
									
										87
									
								
								resources/assets/js/views/wizard/WizardEmailConfigStep.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								resources/assets/js/views/wizard/WizardEmailConfigStep.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,87 @@ | ||||
| <template> | ||||
|   <sw-wizard-step | ||||
|     :title="$t('wizard.mail.mail_config')" | ||||
|     :description="$t('wizard.mail.mail_config_desc')" | ||||
|   > | ||||
|     <base-loader v-if="isFetching" :show-bg-overlay="true" /> | ||||
|     <form action="" @submit.prevent="next()"> | ||||
|       <component | ||||
|         :is="mail_driver" | ||||
|         :config-data="mailConfigData" | ||||
|         :loading="isLoading" | ||||
|         :mail-drivers="mail_drivers" | ||||
|         @on-change-driver=" | ||||
|           (val) => (mail_driver = mailConfigData.mail_driver = val) | ||||
|         " | ||||
|         @submit-data="next" | ||||
|       /> | ||||
|     </form> | ||||
|   </sw-wizard-step> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import Smtp from './mail-driver/SmtpMailDriver' | ||||
| import Mailgun from './mail-driver/MailgunMailDriver' | ||||
| import Ses from './mail-driver/SesMailDriver' | ||||
| import Basic from './mail-driver/BasicMailDriver' | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
|     Smtp, | ||||
|     Mailgun, | ||||
|     Ses, | ||||
|     sendmail: Basic, | ||||
|     mail: Basic, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       mailConfigData: { | ||||
|         mail_driver: 'mail', | ||||
|       }, | ||||
|       mail_driver: 'mail', | ||||
|       isLoading: false, | ||||
|       isFetching: false, | ||||
|       mail_drivers: [], | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.getMailDrivers() | ||||
|   }, | ||||
|   methods: { | ||||
|     async getMailDrivers() { | ||||
|       this.isLoading = this.isFetching = true | ||||
|  | ||||
|       let response = await window.axios.get('/api/v1/mail/drivers') | ||||
|  | ||||
|       if (response.data) { | ||||
|         this.mail_drivers = response.data | ||||
|         this.isLoading = this.isFetching = false | ||||
|       } | ||||
|     }, | ||||
|     async next(mailConfigData) { | ||||
|       this.isLoading = this.isFetching = true | ||||
|       try { | ||||
|         let response = await window.axios.post( | ||||
|           '/api/v1/mail/config', | ||||
|           mailConfigData | ||||
|         ) | ||||
|         if (response.data.success) { | ||||
|           this.$emit('next', 4) | ||||
|           window.toastr['success']( | ||||
|             this.$t('wizard.success.' + response.data.success) | ||||
|           ) | ||||
|         } else { | ||||
|           window.toastr['error']( | ||||
|             this.$t('wizard.errors.' + response.data.error) | ||||
|           ) | ||||
|         } | ||||
|         this.isLoading = this.isFetching = false | ||||
|         return true | ||||
|       } catch (e) { | ||||
|         this.isLoading = this.isFetching = false | ||||
|         window.toastr['error']('Something went wrong') | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
							
								
								
									
										103
									
								
								resources/assets/js/views/wizard/WizardPermissionStep.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								resources/assets/js/views/wizard/WizardPermissionStep.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,103 @@ | ||||
| <template> | ||||
|   <sw-wizard-step | ||||
|     :title="$t('wizard.permissions.permissions')" | ||||
|     :description="$t('wizard.permissions.permission_desc')" | ||||
|   > | ||||
|     <base-loader v-if="isFetching" :show-bg-overlay="true" /> | ||||
|     <div class="relative"> | ||||
|       <div | ||||
|         v-for="(permission, index) in permissions" | ||||
|         :key="index" | ||||
|         class="border border-gray-200" | ||||
|       > | ||||
|         <div class="grid grid-flow-row grid-cols-3 lg:gap-24 sm:gap-4"> | ||||
|           <div class="col-span-2 p-3"> | ||||
|             {{ permission.folder }} | ||||
|           </div> | ||||
|           <div class="p-3 text-right"> | ||||
|             <span | ||||
|               v-if="permission.isSet" | ||||
|               class="inline-block w-4 h-4 ml-3 mr-2 rounded-full bg-success" | ||||
|             /> | ||||
|             <span | ||||
|               v-else | ||||
|               class="inline-block w-4 h-4 ml-3 mr-2 rounded-full bg-danger" | ||||
|             /> | ||||
|             <span>{{ permission.permission }}</span> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|  | ||||
|       <sw-button | ||||
|         v-show="!isFetching" | ||||
|         :loading="isLoading" | ||||
|         :disabled="isLoading" | ||||
|         class="mt-10" | ||||
|         variant="primary" | ||||
|         @click="next" | ||||
|       > | ||||
|         {{ $t('wizard.continue') }} | ||||
|         <arrow-right-icon class="h-5 ml-2 -mr-1" /> | ||||
|       </sw-button> | ||||
|     </div> | ||||
|   </sw-wizard-step> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { ArrowRightIcon } from '@vue-hero-icons/solid' | ||||
| export default { | ||||
|   components: { | ||||
|     ArrowRightIcon, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       isFetching: false, | ||||
|       isLoading: false, | ||||
|       permissions: [], | ||||
|       errors: false, | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.getPermissions() | ||||
|   }, | ||||
|   methods: { | ||||
|     async getPermissions() { | ||||
|       this.isLoading = this.isFetching = true | ||||
|  | ||||
|       let response = await window.axios.get( | ||||
|         '/api/v1/onboarding/permissions', | ||||
|         this.profileData | ||||
|       ) | ||||
|  | ||||
|       if (response.data) { | ||||
|         this.permissions = response.data.permissions.permissions | ||||
|         this.errors = response.data.permissions.errors | ||||
|         let self = this | ||||
|  | ||||
|         if (this.errors) { | ||||
|           swal({ | ||||
|             title: this.$t('wizard.permissions.permission_confirm_title'), | ||||
|             text: this.$t('wizard.permissions.permission_confirm_desc'), | ||||
|             icon: 'warning', | ||||
|             buttons: true, | ||||
|             dangerMode: true, | ||||
|           }).then(async (willConfirm) => { | ||||
|             if (willConfirm) { | ||||
|               self.isLoading = this.isFetching = false | ||||
|             } | ||||
|           }) | ||||
|         } else { | ||||
|           this.isLoading = this.isFetching = false | ||||
|         } | ||||
|  | ||||
|         this.isLoading = this.isFetching = false | ||||
|       } | ||||
|     }, | ||||
|     async next() { | ||||
|       this.isLoading = true | ||||
|       await this.$emit('next') | ||||
|       this.isLoading = false | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
							
								
								
									
										297
									
								
								resources/assets/js/views/wizard/WizardSettingsStep.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										297
									
								
								resources/assets/js/views/wizard/WizardSettingsStep.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,297 @@ | ||||
| <template> | ||||
|   <sw-wizard-step | ||||
|     :title="$t('wizard.preferences')" | ||||
|     :description="$t('wizard.preferences_desc')" | ||||
|   > | ||||
|     <base-loader v-if="isFetching" :show-bg-overlay="true" /> | ||||
|     <form action="" @submit.prevent="next"> | ||||
|       <div> | ||||
|         <div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 md:mb-6"> | ||||
|           <sw-input-group | ||||
|             :label="$t('wizard.currency')" | ||||
|             :error="currencyError" | ||||
|             required | ||||
|           > | ||||
|             <sw-select | ||||
|               v-model="settingData.currency" | ||||
|               :class="{ error: $v.settingData.currency.$error }" | ||||
|               :options="currencies" | ||||
|               :custom-label="currencyNameWithCode" | ||||
|               :searchable="true" | ||||
|               :show-labels="false" | ||||
|               :placeholder="$t('settings.currencies.select_currency')" | ||||
|               track-by="id" | ||||
|               label="name" | ||||
|               @input="$v.settingData.currency.$touch()" | ||||
|             /> | ||||
|           </sw-input-group> | ||||
|  | ||||
|           <sw-input-group | ||||
|             :label="$t('settings.preferences.default_language')" | ||||
|             :error="languageError" | ||||
|             required | ||||
|           > | ||||
|             <sw-select | ||||
|               v-model="settingData.language" | ||||
|               :class="{ error: $v.settingData.language.$error }" | ||||
|               :options="languages" | ||||
|               :searchable="true" | ||||
|               :show-labels="false" | ||||
|               :placeholder="$t('settings.preferences.select_language')" | ||||
|               label="name" | ||||
|               @input="$v.settingData.language.$touch()" | ||||
|             /> | ||||
|           </sw-input-group> | ||||
|         </div> | ||||
|  | ||||
|         <div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 md:mb-6"> | ||||
|           <sw-input-group | ||||
|             :label="$t('wizard.date_format')" | ||||
|             :error="dateFormatError" | ||||
|             required | ||||
|           > | ||||
|             <sw-select | ||||
|               v-model="settingData.dateFormat" | ||||
|               :class="{ error: $v.settingData.dateFormat.$error }" | ||||
|               :options="dateFormats" | ||||
|               :searchable="true" | ||||
|               :show-labels="false" | ||||
|               :placeholder="$t('settings.preferences.select_date_format')" | ||||
|               label="display_date" | ||||
|               @input="$v.settingData.dateFormat.$touch()" | ||||
|             /> | ||||
|           </sw-input-group> | ||||
|  | ||||
|           <sw-input-group | ||||
|             :label="$t('wizard.time_zone')" | ||||
|             :error="timeZoneError" | ||||
|             required | ||||
|           > | ||||
|             <sw-select | ||||
|               v-model="settingData.timeZone" | ||||
|               :class="{ error: $v.settingData.timeZone.$error }" | ||||
|               :options="timeZones" | ||||
|               :searchable="true" | ||||
|               :show-labels="false" | ||||
|               :placeholder="$t('settings.preferences.select_time_zone')" | ||||
|               label="key" | ||||
|               @input="$v.settingData.timeZone.$touch()" | ||||
|             /> | ||||
|           </sw-input-group> | ||||
|         </div> | ||||
|  | ||||
|         <div class="grid grid-cols-1 gap-4 mb-6 md:grid-cols-2"> | ||||
|           <sw-input-group | ||||
|             :label="$t('wizard.fiscal_year')" | ||||
|             :error="fiscalYearError" | ||||
|             required | ||||
|           > | ||||
|             <sw-select | ||||
|               v-model="settingData.fiscalYear" | ||||
|               :class="{ error: $v.settingData.fiscalYear.$error }" | ||||
|               :options="fiscalYears" | ||||
|               :searchable="true" | ||||
|               :show-labels="false" | ||||
|               :placeholder="$t('settings.preferences.select_financial_year')" | ||||
|               label="key" | ||||
|               @input="$v.settingData.fiscalYear.$touch()" | ||||
|             /> | ||||
|           </sw-input-group> | ||||
|         </div> | ||||
|         <sw-button | ||||
|           :loading="isLoading" | ||||
|           :disabled="isLoading" | ||||
|           variant="primary" | ||||
|           type="submit" | ||||
|           class="mt-4" | ||||
|         > | ||||
|           <save-icon v-if="!isLoading" class="mr-2" /> | ||||
|           {{ $t('wizard.save_cont') }} | ||||
|         </sw-button> | ||||
|       </div> | ||||
|     </form> | ||||
|   </sw-wizard-step> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import Ls from '../../services/ls' | ||||
| import { mapActions, mapGetters } from 'vuex' | ||||
|  | ||||
| const { required, minLength, email } = require('vuelidate/lib/validators') | ||||
|  | ||||
| export default { | ||||
|   data() { | ||||
|     return { | ||||
|       settingData: { | ||||
|         language: null, | ||||
|         currency: null, | ||||
|         timeZone: null, | ||||
|         dateFormat: null, | ||||
|         fiscalYear: null, | ||||
|       }, | ||||
|       isLoading: false, | ||||
|       isFetching: false, | ||||
|       step: 1, | ||||
|     } | ||||
|   }, | ||||
|   validations: { | ||||
|     settingData: { | ||||
|       currency: { | ||||
|         required, | ||||
|       }, | ||||
|       language: { | ||||
|         required, | ||||
|       }, | ||||
|       dateFormat: { | ||||
|         required, | ||||
|       }, | ||||
|       timeZone: { | ||||
|         required, | ||||
|       }, | ||||
|       fiscalYear: { | ||||
|         required, | ||||
|       }, | ||||
|     }, | ||||
|   }, | ||||
|   computed: { | ||||
|     ...mapGetters([ | ||||
|       'languages', | ||||
|       'currencies', | ||||
|       'timeZones', | ||||
|       'dateFormats', | ||||
|       'fiscalYears', | ||||
|     ]), | ||||
|  | ||||
|     ...mapGetters('company', ['defaultFiscalYear', 'defaultTimeZone']), | ||||
|     currencyError() { | ||||
|       if (!this.$v.settingData.currency.$error) { | ||||
|         return '' | ||||
|       } | ||||
|       if (!this.$v.settingData.currency.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|     languageError() { | ||||
|       if (!this.$v.settingData.language.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.settingData.language.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|     dateFormatError() { | ||||
|       if (!this.$v.settingData.dateFormat.$error) { | ||||
|         return '' | ||||
|       } | ||||
|       if (!this.$v.settingData.dateFormat.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|     timeZoneError() { | ||||
|       if (!this.$v.settingData.timeZone.$error) { | ||||
|         return '' | ||||
|       } | ||||
|       if (!this.$v.settingData.timeZone.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|     fiscalYearError() { | ||||
|       if (!this.$v.settingData.fiscalYear.$error) { | ||||
|         return '' | ||||
|       } | ||||
|       if (!this.$v.settingData.fiscalYear.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
|   mounted() { | ||||
|     // this.getOnboardingData() | ||||
|     this.setInitialData() | ||||
|   }, | ||||
|   methods: { | ||||
|     ...mapActions('company', ['updateCompanySettings', 'setSelectedCompany']), | ||||
|     ...mapActions([ | ||||
|       'fetchLanguages', | ||||
|       'fetchCurrencies', | ||||
|       'fetchFiscalYears', | ||||
|       'fetchDateFormats', | ||||
|       'fetchTimeZones', | ||||
|     ]), | ||||
|     async setInitialData() { | ||||
|       this.isFetching = true | ||||
|       await this.fetchCurrencies() | ||||
|       await this.fetchDateFormats() | ||||
|       await this.fetchLanguages() | ||||
|       await this.fetchFiscalYears() | ||||
|       await this.fetchTimeZones() | ||||
|       await this.fetchLanguages() | ||||
|  | ||||
|       this.settingData.currency = this.currencies.find( | ||||
|         (currency) => currency.id === 1 | ||||
|       ) | ||||
|       this.settingData.language = this.languages.find( | ||||
|         (language) => language.code === 'en' | ||||
|       ) | ||||
|       this.settingData.dateFormat = this.dateFormats.find( | ||||
|         (dateFormat) => dateFormat.carbon_format_value == 'd M Y' | ||||
|       ) | ||||
|  | ||||
|       this.settingData.timeZone = this.timeZones.find( | ||||
|         (timeZone) => timeZone.value === 'UTC' | ||||
|       ) | ||||
|  | ||||
|       this.settingData.fiscalYear = this.fiscalYears.find( | ||||
|         (fiscalYear) => fiscalYear.value === '1-12' | ||||
|       ) | ||||
|       this.isFetching = false | ||||
|     }, | ||||
|     currencyNameWithCode({ name, code }) { | ||||
|       return `${code} - ${name}` | ||||
|     }, | ||||
|     async next() { | ||||
|       this.$v.settingData.$touch() | ||||
|  | ||||
|       if (this.$v.settingData.$invalid) { | ||||
|         return true | ||||
|       } | ||||
|  | ||||
|       this.isLoading = true | ||||
|  | ||||
|       let data = { | ||||
|         settings: { | ||||
|           currency: this.settingData.currency.id, | ||||
|           time_zone: this.settingData.timeZone.value, | ||||
|           language: this.settingData.language.code, | ||||
|           fiscal_year: this.settingData.fiscalYear.value, | ||||
|           carbon_date_format: this.settingData.dateFormat.carbon_format_value, | ||||
|           moment_date_format: this.settingData.dateFormat.moment_format_value, | ||||
|         }, | ||||
|       } | ||||
|  | ||||
|       let response = await this.updateCompanySettings(data) | ||||
|  | ||||
|       if (response.data) { | ||||
|         this.isLoading = false | ||||
|         this.updateUserSettings() | ||||
|         Ls.set('auth.token', response.data.token) | ||||
|       } | ||||
|     }, | ||||
|     async updateUserSettings() { | ||||
|       let data = { | ||||
|         settings: { | ||||
|           language: this.settingData.language.code, | ||||
|         }, | ||||
|       } | ||||
|  | ||||
|       let response = await axios.put('/api/v1/me/settings', data) | ||||
|  | ||||
|       if (response.data) { | ||||
|         this.$emit('next', 'COMPLETED') | ||||
|         window.toastr['success']('Login Successful') | ||||
|         this.$router.push('/admin/dashboard') | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
							
								
								
									
										129
									
								
								resources/assets/js/views/wizard/WizardSystemRequirementStep.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								resources/assets/js/views/wizard/WizardSystemRequirementStep.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,129 @@ | ||||
| <template> | ||||
|   <sw-wizard-step | ||||
|     :title="$t('wizard.req.system_req')" | ||||
|     :description="$t('wizard.req.system_req_desc')" | ||||
|   > | ||||
|     <div class="w-full md:w-2/3"> | ||||
|       <div class="mb-6"> | ||||
|         <div | ||||
|           v-if="phpSupportInfo" | ||||
|           class="grid grid-flow-row grid-cols-3 p-3 border border-gray-200 lg:gap-24 sm:gap-4" | ||||
|         > | ||||
|           <div class="col-span-2 text-sm"> | ||||
|             {{ | ||||
|               $t('wizard.req.php_req_version', { | ||||
|                 version: phpSupportInfo.minimum, | ||||
|               }) | ||||
|             }} | ||||
|           </div> | ||||
|           <div class="text-right"> | ||||
|             {{ phpSupportInfo.current }} | ||||
|             <span | ||||
|               v-if="phpSupportInfo.supported" | ||||
|               class="inline-block w-4 h-4 ml-3 mr-2 rounded-full bg-success" | ||||
|             /> | ||||
|             <span | ||||
|               v-else | ||||
|               class="inline-block w-4 h-4 ml-3 mr-2 rounded-full bg-danger" | ||||
|             /> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div v-if="requirements"> | ||||
|           <div | ||||
|             v-for="(requirement, index) in requirements" | ||||
|             :key="index" | ||||
|             class="grid grid-flow-row grid-cols-3 p-3 border border-gray-200 lg:gap-24 sm:gap-4" | ||||
|           > | ||||
|             <div class="col-span-2 text-sm"> | ||||
|               {{ index }} | ||||
|             </div> | ||||
|             <div class="text-right"> | ||||
|               <span | ||||
|                 v-if="requirement" | ||||
|                 class="inline-block w-4 h-4 ml-3 mr-2 rounded-full bg-success" | ||||
|               /> | ||||
|               <span | ||||
|                 v-else | ||||
|                 class="inline-block w-4 h-4 ml-3 mr-2 rounded-full bg-danger" | ||||
|               /> | ||||
|             </div> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|       <sw-button | ||||
|         v-if="hasNext" | ||||
|         class="mt-4 pull-right" | ||||
|         variant="primary" | ||||
|         @click="next" | ||||
|       > | ||||
|         {{ $t('wizard.continue') }} | ||||
|         <arrow-right-icon class="h-5 ml-2 -mr-1" /> | ||||
|       </sw-button> | ||||
|       <sw-button | ||||
|         v-if="!requirements" | ||||
|         :loading="isLoading" | ||||
|         :disabled="isLoading" | ||||
|         class="mt-4" | ||||
|         variant="primary" | ||||
|         @click="getRequirements" | ||||
|       > | ||||
|         {{ $t('wizard.req.check_req') }} | ||||
|       </sw-button> | ||||
|     </div> | ||||
|   </sw-wizard-step> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { ArrowRightIcon } from '@vue-hero-icons/solid' | ||||
| export default { | ||||
|   components: { | ||||
|     ArrowRightIcon, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       requirements: null, | ||||
|       phpSupportInfo: null, | ||||
|       isLoading: false, | ||||
|       isShow: true, | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     hasNext() { | ||||
|       if (this.requirements) { | ||||
|         let isRequired = true | ||||
|         for (const key in this.requirements) { | ||||
|           if (!this.requirements[key]) { | ||||
|             isRequired = false | ||||
|           } | ||||
|         } | ||||
|         return this.requirements && this.phpSupportInfo.supported && isRequired | ||||
|       } | ||||
|       return false | ||||
|     }, | ||||
|   }, | ||||
|   methods: { | ||||
|     listToggle() { | ||||
|       this.isShow = !this.isShow | ||||
|     }, | ||||
|     async getRequirements() { | ||||
|       this.isLoading = true | ||||
|  | ||||
|       let response = await window.axios.get( | ||||
|         '/api/v1/onboarding/requirements', | ||||
|         this.profileData | ||||
|       ) | ||||
|  | ||||
|       if (response.data) { | ||||
|         this.requirements = response.data.requirements.requirements.php | ||||
|         this.phpSupportInfo = response.data.phpSupportInfo | ||||
|         this.isLoading = false | ||||
|       } | ||||
|     }, | ||||
|     async next() { | ||||
|       this.isLoading = true | ||||
|       await this.$emit('next') | ||||
|       this.isLoading = false | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
							
								
								
									
										265
									
								
								resources/assets/js/views/wizard/WizardUserProfileStep.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										265
									
								
								resources/assets/js/views/wizard/WizardUserProfileStep.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,265 @@ | ||||
| <template> | ||||
|   <sw-wizard-step | ||||
|     :title="$t('wizard.account_info')" | ||||
|     :description="$t('wizard.account_info_desc')" | ||||
|   > | ||||
|     <form action="" @submit.prevent="next()"> | ||||
|       <div class="grid grid-cols-1 mb-4 md:grid-cols-2 md:mb-6"> | ||||
|         <sw-input-group | ||||
|           :label="$tc('settings.account_settings.profile_picture')" | ||||
|         > | ||||
|           <sw-avatar | ||||
|             :preview-avatar="previewAvatar" | ||||
|             :label="$tc('general.choose_file')" | ||||
|             @changed="onChange" | ||||
|             @uploadHandler="onUploadHandler" | ||||
|             @handleUploadError="onHandleUploadError" | ||||
|           > | ||||
|             <template v-slot:icon> | ||||
|               <cloud-upload-icon | ||||
|                 class="h-5 mb-2 text-xl leading-6 text-gray-400" | ||||
|               /> | ||||
|             </template> | ||||
|           </sw-avatar> | ||||
|         </sw-input-group> | ||||
|       </div> | ||||
|  | ||||
|       <div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 md:mb-6"> | ||||
|         <sw-input-group :label="$t('wizard.name')" :error="nameError" required> | ||||
|           <sw-input | ||||
|             :invalid="$v.profileData.name.$error" | ||||
|             v-model.trim="profileData.name" | ||||
|             type="text" | ||||
|             name="name" | ||||
|             @input="$v.profileData.name.$touch()" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|  | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.email')" | ||||
|           :error="emailError" | ||||
|           required | ||||
|         > | ||||
|           <sw-input | ||||
|             :invalid="$v.profileData.email.$error" | ||||
|             v-model.trim="profileData.email" | ||||
|             type="text" | ||||
|             name="email" | ||||
|             @input="$v.profileData.email.$touch()" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|       </div> | ||||
|  | ||||
|       <div class="grid grid-cols-1 gap-4 mb-6 md:grid-cols-2"> | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.password')" | ||||
|           :error="passwordError" | ||||
|           required | ||||
|         > | ||||
|           <sw-input | ||||
|             :invalid="$v.profileData.password.$error" | ||||
|             v-model.trim="profileData.password" | ||||
|             type="password" | ||||
|             name="password" | ||||
|             @input="$v.profileData.password.$touch()" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|  | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.confirm_password')" | ||||
|           :error="confirmPasswordError" | ||||
|           required | ||||
|         > | ||||
|           <sw-input | ||||
|             :invalid="$v.profileData.confirm_password.$error" | ||||
|             v-model.trim="profileData.confirm_password" | ||||
|             type="password" | ||||
|             name="confirm_password" | ||||
|             @input="$v.profileData.confirm_password.$touch()" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|       </div> | ||||
|  | ||||
|       <sw-button | ||||
|         :loading="isLoading" | ||||
|         :disabled="isLoading" | ||||
|         variant="primary" | ||||
|         type="submit" | ||||
|         class="mt-4" | ||||
|       > | ||||
|         <save-icon v-if="!isLoading" class="mr-2" /> | ||||
|         {{ $t('wizard.save_cont') }} | ||||
|       </sw-button> | ||||
|     </form> | ||||
|   </sw-wizard-step> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { CloudUploadIcon } from '@vue-hero-icons/solid' | ||||
| import { mapActions } from 'vuex' | ||||
| const { | ||||
|   required, | ||||
|   requiredIf, | ||||
|   sameAs, | ||||
|   minLength, | ||||
|   email, | ||||
| } = require('vuelidate/lib/validators') | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
|     CloudUploadIcon, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       profileData: { | ||||
|         name: null, | ||||
|         email: null, | ||||
|         password: null, | ||||
|         confirm_password: null, | ||||
|       }, | ||||
|       isLoading: false, | ||||
|       previewAvatar: '/images/default-avatar.jpg', | ||||
|       fileObject: null, | ||||
|       cropperOutputMime: '', | ||||
|     } | ||||
|   }, | ||||
|   validations: { | ||||
|     profileData: { | ||||
|       name: { | ||||
|         required, | ||||
|         minLength: minLength(3), | ||||
|       }, | ||||
|       email: { | ||||
|         email, | ||||
|         required, | ||||
|       }, | ||||
|       password: { | ||||
|         required, | ||||
|         minLength: minLength(8), | ||||
|       }, | ||||
|       confirm_password: { | ||||
|         required: requiredIf('isRequired'), | ||||
|         sameAsPassword: sameAs('password'), | ||||
|       }, | ||||
|     }, | ||||
|   }, | ||||
|   computed: { | ||||
|     emailError() { | ||||
|       if (!this.$v.profileData.email.$error) { | ||||
|         return '' | ||||
|       } | ||||
|       if (!this.$v.profileData.email.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.profileData.email.email) { | ||||
|         return this.$tc('validation.email_incorrect') | ||||
|       } | ||||
|     }, | ||||
|     nameError() { | ||||
|       if (!this.$v.profileData.name.$error) { | ||||
|         return '' | ||||
|       } | ||||
|       if (!this.$v.profileData.name.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.profileData.name.minLength) { | ||||
|         return this.$tc( | ||||
|           'validation.name_min_length', | ||||
|           this.$v.profileData.name.$params.minLength.min, | ||||
|           { count: this.$v.profileData.name.$params.minLength.min } | ||||
|         ) | ||||
|       } | ||||
|     }, | ||||
|     passwordError() { | ||||
|       if (!this.$v.profileData.password.$error) { | ||||
|         return '' | ||||
|       } | ||||
|       if (!this.$v.profileData.password.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|       if (!this.$v.profileData.password.minLength) { | ||||
|         return this.$tc( | ||||
|           'validation.password_min_length', | ||||
|           this.$v.profileData.password.$params.minLength.min, | ||||
|           { count: this.$v.profileData.password.$params.minLength.min } | ||||
|         ) | ||||
|       } | ||||
|     }, | ||||
|     confirmPasswordError() { | ||||
|       if (!this.$v.profileData.confirm_password.$error) { | ||||
|         return '' | ||||
|       } | ||||
|       if (!this.$v.profileData.confirm_password.sameAsPassword) { | ||||
|         return this.$tc('validation.password_incorrect') | ||||
|       } | ||||
|     }, | ||||
|     isRequired() { | ||||
|       if ( | ||||
|         this.profileData.password === null || | ||||
|         this.profileData.password === undefined || | ||||
|         this.profileData.password === '' | ||||
|       ) { | ||||
|         return false | ||||
|       } | ||||
|       return true | ||||
|     }, | ||||
|   }, | ||||
|   methods: { | ||||
|     ...mapActions('user', ['uploadAvatar']), | ||||
|     onUploadHandler(cropper) { | ||||
|       this.previewAvatar = cropper | ||||
|         .getCroppedCanvas() | ||||
|         .toDataURL(this.cropperOutputMime) | ||||
|     }, | ||||
|     onHandleUploadError() { | ||||
|       window.toastr['error']('Oops! Something went wrong...') | ||||
|     }, | ||||
|     onChange(file) { | ||||
|       this.cropperOutputMime = file.type | ||||
|       this.fileObject = file | ||||
|     }, | ||||
|     async next() { | ||||
|       this.$v.profileData.$touch() | ||||
|       if (this.$v.profileData.$invalid) { | ||||
|         return true | ||||
|       } | ||||
|       this.isLoading = true | ||||
|       let response = await window.axios.put('/api/v1/me', this.profileData) | ||||
|  | ||||
|       if (response.data) { | ||||
|         if (this.fileObject && this.previewAvatar) { | ||||
|           let avatarData = new FormData() | ||||
|           avatarData.append( | ||||
|             'admin_avatar', | ||||
|             JSON.stringify({ | ||||
|               name: this.fileObject.name, | ||||
|               data: this.previewAvatar, | ||||
|               id: response.data.user.id, | ||||
|             }) | ||||
|           ) | ||||
|  | ||||
|           this.uploadAvatar(avatarData) | ||||
|         } | ||||
|         this.$emit('next', 5) | ||||
|         this.isLoading = false | ||||
|       } | ||||
|       return true | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss"> | ||||
| .avatar-upload { | ||||
|   @keyframes fadeIn { | ||||
|     0% { | ||||
|       opacity: 0; | ||||
|     } | ||||
|     100% { | ||||
|       opacity: 1; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										306
									
								
								resources/assets/js/views/wizard/database/MysqlDatabase.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										306
									
								
								resources/assets/js/views/wizard/database/MysqlDatabase.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,306 @@ | ||||
| <template> | ||||
|   <form action="" @submit.prevent="next()"> | ||||
|     <div> | ||||
|       <div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 lg:mb-6 md:mb-6"> | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.app_url')" | ||||
|           :error="urlError" | ||||
|           required | ||||
|         > | ||||
|           <sw-input | ||||
|             :invalid="$v.databaseData.app_url.$error" | ||||
|             v-model.trim="databaseData.app_url" | ||||
|             type="text" | ||||
|             name="name" | ||||
|             @input="$v.databaseData.app_url.$touch()" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|  | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.app_domain')" | ||||
|           :error="domainError" | ||||
|           required | ||||
|         > | ||||
|           <sw-input | ||||
|             :invalid="$v.databaseData.app_domain.$error" | ||||
|             v-model.trim="databaseData.app_domain" | ||||
|             type="text" | ||||
|             name="name" | ||||
|             placeholder="crater.com" | ||||
|             @input="$v.databaseData.app_domain.$touch()" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|       </div> | ||||
|  | ||||
|       <div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 lg:mb-6 md:mb-6"> | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.connection')" | ||||
|           :error="connectionError" | ||||
|           required | ||||
|         > | ||||
|           <sw-select | ||||
|             v-model="databaseData.database_connection" | ||||
|             :invalid="$v.databaseData.database_connection.$error" | ||||
|             :options="connections" | ||||
|             :searchable="true" | ||||
|             :allow-empty="false" | ||||
|             :show-labels="false" | ||||
|             @input="onChangeConnection" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|  | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.port')" | ||||
|           :error="portError" | ||||
|           required | ||||
|         > | ||||
|           <sw-input | ||||
|             :invalid="$v.databaseData.database_port.$error" | ||||
|             v-model.trim="databaseData.database_port" | ||||
|             type="text" | ||||
|             name="database_port" | ||||
|             @input="$v.databaseData.database_port.$touch()" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|       </div> | ||||
|  | ||||
|       <div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 lg:mb-6 md:mb-6"> | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.db_name')" | ||||
|           :error="nameError" | ||||
|           required | ||||
|         > | ||||
|           <sw-input | ||||
|             :invalid="$v.databaseData.database_name.$error" | ||||
|             v-model.trim="databaseData.database_name" | ||||
|             type="text" | ||||
|             name="database_name" | ||||
|             @input="$v.databaseData.database_name.$touch()" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|  | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.username')" | ||||
|           :error="usernameError" | ||||
|           required | ||||
|         > | ||||
|           <sw-input | ||||
|             :invalid="$v.databaseData.database_username.$error" | ||||
|             v-model.trim="databaseData.database_username" | ||||
|             type="text" | ||||
|             name="database_username" | ||||
|             @input="$v.databaseData.database_username.$touch()" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|       </div> | ||||
|  | ||||
|       <div class="grid grid-cols-1 gap-4 mb-6 md:grid-cols-2"> | ||||
|         <sw-input-group :label="$t('wizard.database.password')"> | ||||
|           <sw-input | ||||
|             v-model.trim="databaseData.database_password" | ||||
|             type="password" | ||||
|             name="name" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|  | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.host')" | ||||
|           :error="hostnameError" | ||||
|           required | ||||
|         > | ||||
|           <sw-input | ||||
|             :invalid="$v.databaseData.database_hostname.$error" | ||||
|             v-model.trim="databaseData.database_hostname" | ||||
|             type="text" | ||||
|             name="database_hostname" | ||||
|             @input="$v.databaseData.database_hostname.$touch()" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|       </div> | ||||
|       <sw-button | ||||
|         v-show="!isFetching" | ||||
|         :loading="isLoading" | ||||
|         :disabled="isLoading" | ||||
|         variant="primary" | ||||
|         class="mt-4" | ||||
|         type="submit" | ||||
|       > | ||||
|         <save-icon v-if="!isLoading" class="h-5 mr-2" /> | ||||
|         {{ $t('wizard.save_cont') }} | ||||
|       </sw-button> | ||||
|     </div> | ||||
|   </form> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { SaveIcon } from '@vue-hero-icons/outline' | ||||
| import { validationMixin } from 'vuelidate' | ||||
| const { required, numeric, url } = require('vuelidate/lib/validators') | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
|     SaveIcon, | ||||
|   }, | ||||
|    props: { | ||||
|     configData: { | ||||
|       type: Object, | ||||
|       require: true, | ||||
|       default: Object, | ||||
|     }, | ||||
|     isLoading: { | ||||
|       type: Boolean, | ||||
|       require: true, | ||||
|       default: false, | ||||
|     }, | ||||
|     isFetching: { | ||||
|       type: Boolean, | ||||
|       require: true, | ||||
|       default: false, | ||||
|     }, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       databaseData: { | ||||
|         database_connection: 'mysql', | ||||
|         database_hostname: '127.0.0.1', | ||||
|         database_port: '3306', | ||||
|         database_name: null, | ||||
|         database_username: null, | ||||
|         database_password: null, | ||||
|         app_url: window.location.origin, | ||||
|         app_domain: window.location.origin.replace(/(^\w+:|^)\/\//, ''), | ||||
|       }, | ||||
|       connections: ['sqlite', 'mysql', 'pgsql', 'sqlsrv'], | ||||
|     } | ||||
|   }, | ||||
|   validations: { | ||||
|     databaseData: { | ||||
|       database_connection: { | ||||
|         required, | ||||
|       }, | ||||
|       database_hostname: { | ||||
|         required, | ||||
|       }, | ||||
|       database_port: { | ||||
|         required, | ||||
|         numeric, | ||||
|       }, | ||||
|       database_name: { | ||||
|         required, | ||||
|       }, | ||||
|       database_username: { | ||||
|         required, | ||||
|       }, | ||||
|       app_url: { | ||||
|         required, | ||||
|         isUrl(val) { | ||||
|           return this.$utils.checkValidUrl(val) | ||||
|         }, | ||||
|       }, | ||||
|       app_domain: { | ||||
|         required, | ||||
|         isUrl(val) { | ||||
|           return this.$utils.checkValidDomainUrl(val) | ||||
|         }, | ||||
|       }, | ||||
|     }, | ||||
|   }, | ||||
|   computed: { | ||||
|     urlError() { | ||||
|       if (!this.$v.databaseData.app_url.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.app_url.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.app_url.isUrl) { | ||||
|         return this.$tc('validation.invalid_url') | ||||
|       } | ||||
|     }, | ||||
|     domainError() { | ||||
|       if (!this.$v.databaseData.app_domain.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.app_domain.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.app_domain.isUrl) { | ||||
|         return this.$tc('validation.invalid_domain_url') | ||||
|       } | ||||
|     }, | ||||
|     connectionError() { | ||||
|       if (!this.$v.databaseData.database_connection.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.database_connection.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|     portError() { | ||||
|       if (!this.$v.databaseData.database_port.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.database_port.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.database_port.numeric) { | ||||
|         return this.$tc('validation.numbers_only') | ||||
|       } | ||||
|     }, | ||||
|     nameError() { | ||||
|       if (!this.$v.databaseData.database_name.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.database_name.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|     usernameError() { | ||||
|       if (!this.$v.databaseData.database_username.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.database_username.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|     hostnameError() { | ||||
|       if (!this.$v.databaseData.database_hostname.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.database_hostname.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
|   mounted() { | ||||
|     for (const key in this.databaseData) { | ||||
|       if (this.configData.hasOwnProperty(key)) { | ||||
|         this.databaseData[key] = this.configData[key] | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     async next() { | ||||
|       this.$v.databaseData.$touch() | ||||
|       if (!this.$v.databaseData.$invalid) { | ||||
|         this.$emit('submit-data', this.databaseData) | ||||
|       } | ||||
|       return false | ||||
|     }, | ||||
|     onChangeConnection() { | ||||
|       this.$v.databaseData.database_connection.$touch() | ||||
|       this.$emit('on-change-driver', this.databaseData.database_connection) | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
							
								
								
									
										306
									
								
								resources/assets/js/views/wizard/database/PgsqlDatabase.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										306
									
								
								resources/assets/js/views/wizard/database/PgsqlDatabase.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,306 @@ | ||||
| <template> | ||||
|   <form action="" @submit.prevent="next()"> | ||||
|     <div> | ||||
|       <div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 lg:mb-6 md:mb-6"> | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.app_url')" | ||||
|           :error="urlError" | ||||
|           required | ||||
|         > | ||||
|           <sw-input | ||||
|             :invalid="$v.databaseData.app_url.$error" | ||||
|             v-model.trim="databaseData.app_url" | ||||
|             type="text" | ||||
|             name="name" | ||||
|             @input="$v.databaseData.app_url.$touch()" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|  | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.app_domain')" | ||||
|           :error="domainError" | ||||
|           required | ||||
|         > | ||||
|           <sw-input | ||||
|             :invalid="$v.databaseData.app_domain.$error" | ||||
|             v-model.trim="databaseData.app_domain" | ||||
|             type="text" | ||||
|             name="name" | ||||
|             placeholder="crater.com" | ||||
|             @input="$v.databaseData.app_domain.$touch()" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|       </div> | ||||
|  | ||||
|       <div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 lg:mb-6 md:mb-6"> | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.connection')" | ||||
|           :error="connectionError" | ||||
|           required | ||||
|         > | ||||
|           <sw-select | ||||
|             v-model="databaseData.database_connection" | ||||
|             :invalid="$v.databaseData.database_connection.$error" | ||||
|             :options="connections" | ||||
|             :searchable="true" | ||||
|             :allow-empty="false" | ||||
|             :show-labels="false" | ||||
|             @input="onChangeConnection" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|  | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.port')" | ||||
|           :error="portError" | ||||
|           required | ||||
|         > | ||||
|           <sw-input | ||||
|             :invalid="$v.databaseData.database_port.$error" | ||||
|             v-model.trim="databaseData.database_port" | ||||
|             type="text" | ||||
|             name="database_port" | ||||
|             @input="$v.databaseData.database_port.$touch()" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|       </div> | ||||
|  | ||||
|       <div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 lg:mb-6 md:mb-6"> | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.db_name')" | ||||
|           :error="nameError" | ||||
|           required | ||||
|         > | ||||
|           <sw-input | ||||
|             :invalid="$v.databaseData.database_name.$error" | ||||
|             v-model.trim="databaseData.database_name" | ||||
|             type="text" | ||||
|             name="database_name" | ||||
|             @input="$v.databaseData.database_name.$touch()" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|  | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.username')" | ||||
|           :error="usernameError" | ||||
|           required | ||||
|         > | ||||
|           <sw-input | ||||
|             :invalid="$v.databaseData.database_username.$error" | ||||
|             v-model.trim="databaseData.database_username" | ||||
|             type="text" | ||||
|             name="database_username" | ||||
|             @input="$v.databaseData.database_username.$touch()" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|       </div> | ||||
|  | ||||
|       <div class="grid grid-cols-1 gap-4 mb-6 md:grid-cols-2"> | ||||
|         <sw-input-group :label="$t('wizard.database.password')"> | ||||
|           <sw-input | ||||
|             v-model.trim="databaseData.database_password" | ||||
|             type="password" | ||||
|             name="name" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|  | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.host')" | ||||
|           :error="hostnameError" | ||||
|           required | ||||
|         > | ||||
|           <sw-input | ||||
|             :invalid="$v.databaseData.database_hostname.$error" | ||||
|             v-model.trim="databaseData.database_hostname" | ||||
|             type="text" | ||||
|             name="database_hostname" | ||||
|             @input="$v.databaseData.database_hostname.$touch()" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|       </div> | ||||
|       <sw-button | ||||
|         v-show="!isFetching" | ||||
|         :loading="isLoading" | ||||
|         :disabled="isLoading" | ||||
|         variant="primary" | ||||
|         class="mt-4" | ||||
|         type="submit" | ||||
|       > | ||||
|         <save-icon v-if="!isLoading" class="h-5 mr-2" /> | ||||
|         {{ $t('wizard.save_cont') }} | ||||
|       </sw-button> | ||||
|     </div> | ||||
|   </form> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { SaveIcon } from '@vue-hero-icons/outline' | ||||
| import { validationMixin } from 'vuelidate' | ||||
| const { required, numeric, url } = require('vuelidate/lib/validators') | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
|     SaveIcon, | ||||
|   }, | ||||
|   props: { | ||||
|     configData: { | ||||
|       type: Object, | ||||
|       require: true, | ||||
|       default: Object, | ||||
|     }, | ||||
|     isLoading: { | ||||
|       type: Boolean, | ||||
|       require: true, | ||||
|       default: false, | ||||
|     }, | ||||
|     isFetching: { | ||||
|       type: Boolean, | ||||
|       require: true, | ||||
|       default: false, | ||||
|     }, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       databaseData: { | ||||
|         database_connection: 'mysql', | ||||
|         database_hostname: '127.0.0.1', | ||||
|         database_port: '3306', | ||||
|         database_name: null, | ||||
|         database_username: null, | ||||
|         database_password: null, | ||||
|         app_url: window.location.origin, | ||||
|         app_domain: window.location.origin.replace(/(^\w+:|^)\/\//, ''), | ||||
|       }, | ||||
|       connections: ['sqlite', 'mysql', 'pgsql', 'sqlsrv'], | ||||
|     } | ||||
|   }, | ||||
|    computed: { | ||||
|     urlError() { | ||||
|       if (!this.$v.databaseData.app_url.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.app_url.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.app_url.isUrl) { | ||||
|         return this.$tc('validation.invalid_url') | ||||
|       } | ||||
|     }, | ||||
|     domainError() { | ||||
|       if (!this.$v.databaseData.app_domain.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.app_domain.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.app_domain.isUrl) { | ||||
|         return this.$tc('validation.invalid_domain_url') | ||||
|       } | ||||
|     }, | ||||
|     connectionError() { | ||||
|       if (!this.$v.databaseData.database_connection.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.database_connection.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|     portError() { | ||||
|       if (!this.$v.databaseData.database_port.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.database_port.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.database_port.numeric) { | ||||
|         return this.$tc('validation.numbers_only') | ||||
|       } | ||||
|     }, | ||||
|     nameError() { | ||||
|       if (!this.$v.databaseData.database_name.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.database_name.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|     usernameError() { | ||||
|       if (!this.$v.databaseData.database_username.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.database_username.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|     hostnameError() { | ||||
|       if (!this.$v.databaseData.database_hostname.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.database_hostname.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
|   validations: { | ||||
|     databaseData: { | ||||
|       database_connection: { | ||||
|         required, | ||||
|       }, | ||||
|       database_hostname: { | ||||
|         required, | ||||
|       }, | ||||
|       database_port: { | ||||
|         required, | ||||
|         numeric, | ||||
|       }, | ||||
|       database_name: { | ||||
|         required, | ||||
|       }, | ||||
|       database_username: { | ||||
|         required, | ||||
|       }, | ||||
|       app_url: { | ||||
|         required, | ||||
|         isUrl(val) { | ||||
|           return this.$utils.checkValidUrl(val) | ||||
|         }, | ||||
|       }, | ||||
|       app_domain: { | ||||
|         required, | ||||
|         isUrl(val) { | ||||
|           return this.$utils.checkValidDomainUrl(val) | ||||
|         }, | ||||
|       }, | ||||
|     }, | ||||
|   }, | ||||
|   mounted() { | ||||
|     for (const key in this.databaseData) { | ||||
|       if (this.configData.hasOwnProperty(key)) { | ||||
|         this.databaseData[key] = this.configData[key] | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     async next() { | ||||
|       this.$v.databaseData.$touch() | ||||
|       if (!this.$v.databaseData.$invalid) { | ||||
|         this.$emit('submit-data', this.databaseData) | ||||
|       } | ||||
|       return false | ||||
|     }, | ||||
|     onChangeConnection() { | ||||
|       this.$v.databaseData.database_connection.$touch() | ||||
|       this.$emit('on-change-driver', this.databaseData.database_connection) | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
							
								
								
									
										208
									
								
								resources/assets/js/views/wizard/database/SqliteDatabase.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										208
									
								
								resources/assets/js/views/wizard/database/SqliteDatabase.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,208 @@ | ||||
| <template> | ||||
|   <form action="" @submit.prevent="next()"> | ||||
|     <div> | ||||
|       <div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 lg:mb-6 md:mb-6"> | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.app_url')" | ||||
|           :error="urlError" | ||||
|           required | ||||
|         > | ||||
|           <sw-input | ||||
|             :invalid="$v.databaseData.app_url.$error" | ||||
|             v-model.trim="databaseData.app_url" | ||||
|             type="text" | ||||
|             name="name" | ||||
|             @input="$v.databaseData.app_url.$touch()" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|  | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.app_domain')" | ||||
|           :error="domainError" | ||||
|           required | ||||
|         > | ||||
|           <sw-input | ||||
|             :invalid="$v.databaseData.app_domain.$error" | ||||
|             v-model.trim="databaseData.app_domain" | ||||
|             type="text" | ||||
|             name="name" | ||||
|             placeholder="crater.com" | ||||
|             @input="$v.databaseData.app_domain.$touch()" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|       </div> | ||||
|  | ||||
|       <div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 lg:mb-6 md:mb-6"> | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.connection')" | ||||
|           :error="connectionError" | ||||
|           required | ||||
|         > | ||||
|           <sw-select | ||||
|             v-model="databaseData.database_connection" | ||||
|             :invalid="$v.databaseData.database_connection.$error" | ||||
|             :options="connections" | ||||
|             :allow-empty="false" | ||||
|             :searchable="true" | ||||
|             :show-labels="false" | ||||
|             @input="onChangeConnection" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|  | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.db_path')" | ||||
|           :error="nameError" | ||||
|           required | ||||
|         > | ||||
|           <sw-input | ||||
|             :invalid="$v.databaseData.database_name.$error" | ||||
|             v-model.trim="databaseData.database_name" | ||||
|             type="text" | ||||
|             name="database_name" | ||||
|             @input="$v.databaseData.database_name.$touch()" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|       </div> | ||||
|  | ||||
|       <sw-button | ||||
|         v-show="!isFetching" | ||||
|         :loading="isLoading" | ||||
|         :disabled="isLoading" | ||||
|         variant="primary" | ||||
|         class="mt-4" | ||||
|         type="submit" | ||||
|       > | ||||
|         <save-icon v-if="!isLoading" class="h-5 mr-2" /> | ||||
|         {{ $t('wizard.save_cont') }} | ||||
|       </sw-button> | ||||
|     </div> | ||||
|   </form> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { SaveIcon } from '@vue-hero-icons/outline' | ||||
| import { validationMixin } from 'vuelidate' | ||||
| const { required, numeric, url } = require('vuelidate/lib/validators') | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
|     SaveIcon, | ||||
|   }, | ||||
|   props: { | ||||
|     configData: { | ||||
|       type: Object, | ||||
|       require: true, | ||||
|       default: Object, | ||||
|     }, | ||||
|     isLoading: { | ||||
|       type: Boolean, | ||||
|       require: true, | ||||
|       default: false, | ||||
|     }, | ||||
|     isFetching: { | ||||
|       type: Boolean, | ||||
|       require: true, | ||||
|       default: false, | ||||
|     }, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       databaseData: { | ||||
|         database_connection: 'mysql', | ||||
|         database_name: null, | ||||
|         app_url: window.location.origin, | ||||
|         app_domain: window.location.origin.replace(/(^\w+:|^)\/\//, ''), | ||||
|       }, | ||||
|       connections: ['sqlite', 'mysql', 'pgsql', 'sqlsrv'], | ||||
|     } | ||||
|   }, | ||||
|   validations: { | ||||
|     databaseData: { | ||||
|       database_connection: { | ||||
|         required, | ||||
|       }, | ||||
|       database_name: { | ||||
|         required, | ||||
|       }, | ||||
|       app_url: { | ||||
|         required, | ||||
|         isUrl(val) { | ||||
|           return this.$utils.checkValidUrl(val) | ||||
|         }, | ||||
|       }, | ||||
|       app_domain: { | ||||
|         required, | ||||
|         isUrl(val) { | ||||
|           return this.$utils.checkValidDomainUrl(val) | ||||
|         }, | ||||
|       }, | ||||
|     }, | ||||
|   }, | ||||
|   computed: { | ||||
|     urlError() { | ||||
|       if (!this.$v.databaseData.app_url.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.app_url.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.app_url.isUrl) { | ||||
|         return this.$tc('validation.invalid_url') | ||||
|       } | ||||
|     }, | ||||
|     domainError() { | ||||
|       if (!this.$v.databaseData.app_domain.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.app_domain.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.app_domain.isUrl) { | ||||
|         return this.$tc('validation.invalid_domain_url') | ||||
|       } | ||||
|     }, | ||||
|     connectionError() { | ||||
|       if (!this.$v.databaseData.database_connection.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.database_connection.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|     nameError() { | ||||
|       if (!this.$v.databaseData.database_name.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.database_name.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
|   mounted() { | ||||
|     for (const key in this.databaseData) { | ||||
|       if (this.configData.hasOwnProperty(key)) { | ||||
|         this.databaseData[key] = this.configData[key] | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     async next() { | ||||
|       this.$v.databaseData.$touch() | ||||
|       if (!this.$v.databaseData.$invalid) { | ||||
|         this.$emit('submit-data', this.databaseData) | ||||
|       } | ||||
|       return false | ||||
|     }, | ||||
|     onChangeConnection() { | ||||
|       this.$v.databaseData.database_connection.$touch() | ||||
|       this.$emit('on-change-driver', this.databaseData.database_connection) | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
							
								
								
									
										306
									
								
								resources/assets/js/views/wizard/database/SqlsrvDatabase.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										306
									
								
								resources/assets/js/views/wizard/database/SqlsrvDatabase.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,306 @@ | ||||
| <template> | ||||
|   <form action="" @submit.prevent="next()"> | ||||
|     <div> | ||||
|       <div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 lg:mb-6 md:mb-6"> | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.app_url')" | ||||
|           :error="urlError" | ||||
|           required | ||||
|         > | ||||
|           <sw-input | ||||
|             :invalid="$v.databaseData.app_url.$error" | ||||
|             v-model.trim="databaseData.app_url" | ||||
|             type="text" | ||||
|             name="name" | ||||
|             @input="$v.databaseData.app_url.$touch()" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|  | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.app_domain')" | ||||
|           :error="domainError" | ||||
|           required | ||||
|         > | ||||
|           <sw-input | ||||
|             :invalid="$v.databaseData.app_domain.$error" | ||||
|             v-model.trim="databaseData.app_domain" | ||||
|             type="text" | ||||
|             name="name" | ||||
|             placeholder="crater.com" | ||||
|             @input="$v.databaseData.app_domain.$touch()" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|       </div> | ||||
|  | ||||
|       <div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 lg:mb-6 md:mb-6"> | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.connection')" | ||||
|           :error="connectionError" | ||||
|           required | ||||
|         > | ||||
|           <sw-select | ||||
|             v-model="databaseData.database_connection" | ||||
|             :invalid="$v.databaseData.database_connection.$error" | ||||
|             :options="connections" | ||||
|             :searchable="true" | ||||
|             :show-labels="false" | ||||
|             :allow-empty="false" | ||||
|             @input="onChangeConnection" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|  | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.port')" | ||||
|           :error="portError" | ||||
|           required | ||||
|         > | ||||
|           <sw-input | ||||
|             :invalid="$v.databaseData.database_port.$error" | ||||
|             v-model.trim="databaseData.database_port" | ||||
|             type="text" | ||||
|             name="database_port" | ||||
|             @input="$v.databaseData.database_port.$touch()" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|       </div> | ||||
|  | ||||
|       <div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 lg:mb-6 md:mb-6"> | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.db_name')" | ||||
|           :error="nameError" | ||||
|           required | ||||
|         > | ||||
|           <sw-input | ||||
|             :invalid="$v.databaseData.database_name.$error" | ||||
|             v-model.trim="databaseData.database_name" | ||||
|             type="text" | ||||
|             name="database_name" | ||||
|             @input="$v.databaseData.database_name.$touch()" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|  | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.username')" | ||||
|           :error="usernameError" | ||||
|           required | ||||
|         > | ||||
|           <sw-input | ||||
|             :invalid="$v.databaseData.database_username.$error" | ||||
|             v-model.trim="databaseData.database_username" | ||||
|             type="text" | ||||
|             name="database_username" | ||||
|             @input="$v.databaseData.database_username.$touch()" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|       </div> | ||||
|  | ||||
|       <div class="grid grid-cols-1 gap-4 mb-6 md:grid-cols-2"> | ||||
|         <sw-input-group :label="$t('wizard.database.password')"> | ||||
|           <sw-input | ||||
|             v-model.trim="databaseData.database_password" | ||||
|             type="password" | ||||
|             name="name" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|  | ||||
|         <sw-input-group | ||||
|           :label="$t('wizard.database.host')" | ||||
|           :error="hostnameError" | ||||
|           required | ||||
|         > | ||||
|           <sw-input | ||||
|             :invalid="$v.databaseData.database_hostname.$error" | ||||
|             v-model.trim="databaseData.database_hostname" | ||||
|             type="text" | ||||
|             name="database_hostname" | ||||
|             @input="$v.databaseData.database_hostname.$touch()" | ||||
|           /> | ||||
|         </sw-input-group> | ||||
|       </div> | ||||
|       <sw-button | ||||
|         v-show="!isFetching" | ||||
|         :loading="isLoading" | ||||
|         :disabled="isLoading" | ||||
|         variant="primary" | ||||
|         class="mt-4" | ||||
|         type="submit" | ||||
|       > | ||||
|         <save-icon v-if="!isLoading" class="h-5 mr-2" /> | ||||
|         {{ $t('wizard.save_cont') }} | ||||
|       </sw-button> | ||||
|     </div> | ||||
|   </form> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { SaveIcon } from '@vue-hero-icons/outline' | ||||
| import { validationMixin } from 'vuelidate' | ||||
| const { required, numeric, url } = require('vuelidate/lib/validators') | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
|     SaveIcon, | ||||
|   }, | ||||
|    props: { | ||||
|     configData: { | ||||
|       type: Object, | ||||
|       require: true, | ||||
|       default: Object, | ||||
|     }, | ||||
|     isLoading: { | ||||
|       type: Boolean, | ||||
|       require: true, | ||||
|       default: false, | ||||
|     }, | ||||
|     isFetching: { | ||||
|       type: Boolean, | ||||
|       require: true, | ||||
|       default: false, | ||||
|     }, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       databaseData: { | ||||
|         database_connection: 'mysql', | ||||
|         database_hostname: '127.0.0.1', | ||||
|         database_port: '3306', | ||||
|         database_name: null, | ||||
|         database_username: null, | ||||
|         database_password: null, | ||||
|         app_url: window.location.origin, | ||||
|         app_domain: window.location.origin.replace(/(^\w+:|^)\/\//, ''), | ||||
|       }, | ||||
|       connections: ['sqlite', 'mysql', 'pgsql', 'sqlsrv'], | ||||
|     } | ||||
|   }, | ||||
|   validations: { | ||||
|     databaseData: { | ||||
|       database_connection: { | ||||
|         required, | ||||
|       }, | ||||
|       database_hostname: { | ||||
|         required, | ||||
|       }, | ||||
|       database_port: { | ||||
|         required, | ||||
|         numeric, | ||||
|       }, | ||||
|       database_name: { | ||||
|         required, | ||||
|       }, | ||||
|       database_username: { | ||||
|         required, | ||||
|       }, | ||||
|       app_url: { | ||||
|         required, | ||||
|         isUrl(val) { | ||||
|           return this.$utils.checkValidUrl(val) | ||||
|         }, | ||||
|       }, | ||||
|       app_domain: { | ||||
|         required, | ||||
|         isUrl(val) { | ||||
|           return this.$utils.checkValidDomainUrl(val) | ||||
|         }, | ||||
|       }, | ||||
|     }, | ||||
|   }, | ||||
|   computed: { | ||||
|     urlError() { | ||||
|       if (!this.$v.databaseData.app_url.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.app_url.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.app_url.isUrl) { | ||||
|         return this.$tc('validation.invalid_url') | ||||
|       } | ||||
|     }, | ||||
|     domainError() { | ||||
|       if (!this.$v.databaseData.app_domain.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.app_domain.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.app_domain.isUrl) { | ||||
|         return this.$tc('validation.invalid_domain_url') | ||||
|       } | ||||
|     }, | ||||
|     connectionError() { | ||||
|       if (!this.$v.databaseData.database_connection.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.database_connection.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|     portError() { | ||||
|       if (!this.$v.databaseData.database_port.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.database_port.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.database_port.numeric) { | ||||
|         return this.$tc('validation.numbers_only') | ||||
|       } | ||||
|     }, | ||||
|     nameError() { | ||||
|       if (!this.$v.databaseData.database_name.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.database_name.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|     usernameError() { | ||||
|       if (!this.$v.databaseData.database_username.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.database_username.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|     hostnameError() { | ||||
|       if (!this.$v.databaseData.database_hostname.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.databaseData.database_hostname.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
|    mounted() { | ||||
|     for (const key in this.databaseData) { | ||||
|       if (this.configData.hasOwnProperty(key)) { | ||||
|         this.databaseData[key] = this.configData[key] | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     async next() { | ||||
|       this.$v.databaseData.$touch() | ||||
|       if (!this.$v.databaseData.$invalid) { | ||||
|         this.$emit('submit-data', this.databaseData) | ||||
|       } | ||||
|       return false | ||||
|     }, | ||||
|     onChangeConnection() { | ||||
|       this.$v.databaseData.database_connection.$touch() | ||||
|       this.$emit('on-change-driver', this.databaseData.database_connection) | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
							
								
								
									
										160
									
								
								resources/assets/js/views/wizard/mail-driver/BasicMailDriver.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										160
									
								
								resources/assets/js/views/wizard/mail-driver/BasicMailDriver.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,160 @@ | ||||
| <template> | ||||
|   <form @submit.prevent="saveEmailConfig"> | ||||
|     <div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 md:mb-6"> | ||||
|       <sw-input-group | ||||
|         :label="$t('wizard.mail.driver')" | ||||
|         :error="driverError" | ||||
|         required | ||||
|       > | ||||
|         <sw-select | ||||
|           v-model="mailConfigData.mail_driver" | ||||
|           :invalid="$v.mailConfigData.mail_driver.$error" | ||||
|           :options="mailDrivers" | ||||
|           :allow-empty="false" | ||||
|           :searchable="true" | ||||
|           :show-labels="false" | ||||
|           @input="onChangeDriver" | ||||
|         /> | ||||
|       </sw-input-group> | ||||
|     </div> | ||||
|  | ||||
|     <div class="grid grid-cols-1 gap-4 mb-6 md:grid-cols-2"> | ||||
|       <sw-input-group | ||||
|         :label="$t('wizard.mail.from_name')" | ||||
|         :error="fromNameError" | ||||
|         required | ||||
|       > | ||||
|         <sw-input | ||||
|           :invalid="$v.mailConfigData.from_name.$error" | ||||
|           v-model.trim="mailConfigData.from_name" | ||||
|           type="text" | ||||
|           name="name" | ||||
|           @input="$v.mailConfigData.from_name.$touch()" | ||||
|         /> | ||||
|       </sw-input-group> | ||||
|       <sw-input-group | ||||
|         :label="$t('wizard.mail.from_mail')" | ||||
|         :error="fromMailError" | ||||
|         required | ||||
|       > | ||||
|         <sw-input | ||||
|           :invalid="$v.mailConfigData.from_mail.$error" | ||||
|           v-model.trim="mailConfigData.from_mail" | ||||
|           type="text" | ||||
|           name="from_mail" | ||||
|           @input="$v.mailConfigData.from_mail.$touch()" | ||||
|         /> | ||||
|       </sw-input-group> | ||||
|     </div> | ||||
|  | ||||
|     <sw-button | ||||
|       :loading="loading" | ||||
|       :disabled="loading" | ||||
|       variant="primary" | ||||
|       type="submit" | ||||
|       class="mt-4" | ||||
|     > | ||||
|       <save-icon v-if="!loading" class="mr-2" /> | ||||
|       {{ $t('general.save') }} | ||||
|     </sw-button> | ||||
|   </form> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| const { required, email } = require('vuelidate/lib/validators') | ||||
|  | ||||
| export default { | ||||
|   props: { | ||||
|     configData: { | ||||
|       type: Object, | ||||
|       require: true, | ||||
|       default: Object, | ||||
|     }, | ||||
|     loading: { | ||||
|       type: Boolean, | ||||
|       require: true, | ||||
|       default: false, | ||||
|     }, | ||||
|     mailDrivers: { | ||||
|       type: Array, | ||||
|       require: true, | ||||
|       default: Array, | ||||
|     }, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       mailConfigData: { | ||||
|         mail_driver: '', | ||||
|         mail_host: '', | ||||
|         from_mail: '', | ||||
|         from_name: '', | ||||
|       }, | ||||
|     } | ||||
|   }, | ||||
|   validations: { | ||||
|     mailConfigData: { | ||||
|       mail_driver: { | ||||
|         required, | ||||
|       }, | ||||
|       from_mail: { | ||||
|         required, | ||||
|         email, | ||||
|       }, | ||||
|       from_name: { | ||||
|         required, | ||||
|       }, | ||||
|     }, | ||||
|   }, | ||||
|   computed: { | ||||
|     driverError() { | ||||
|       if (!this.$v.mailConfigData.mail_driver.$error) { | ||||
|         return '' | ||||
|       } | ||||
|       if (!this.$v.mailConfigData.mail_driver.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|     fromMailError() { | ||||
|       if (!this.$v.mailConfigData.from_mail.$error) { | ||||
|         return '' | ||||
|       } | ||||
|       if (!this.$v.mailConfigData.from_mail.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.mailConfigData.from_mail.email) { | ||||
|         return this.$tc('validation.email_incorrect') | ||||
|       } | ||||
|     }, | ||||
|     fromNameError() { | ||||
|       if (!this.$v.mailConfigData.from_name.$error) { | ||||
|         return '' | ||||
|       } | ||||
|       if (!this.$v.mailConfigData.from_name.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
|   mounted() { | ||||
|     for (const key in this.mailConfigData) { | ||||
|       if (this.configData.hasOwnProperty(key)) { | ||||
|         this.mailConfigData[key] = this.configData[key] | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     async saveEmailConfig() { | ||||
|       this.$v.mailConfigData.$touch() | ||||
|       if (!this.$v.mailConfigData.$invalid) { | ||||
|         this.$emit('submit-data', this.mailConfigData) | ||||
|       } | ||||
|  | ||||
|       return false | ||||
|     }, | ||||
|     onChangeDriver() { | ||||
|       this.$v.mailConfigData.mail_driver.$touch() | ||||
|       this.$emit('on-change-driver', this.mailConfigData.mail_driver) | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
| @ -0,0 +1,260 @@ | ||||
| <template> | ||||
|   <form @submit.prevent="saveEmailConfig"> | ||||
|     <div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 lg:mb-6 md:mb-6"> | ||||
|       <sw-input-group | ||||
|         :label="$t('wizard.mail.driver')" | ||||
|         :error="driverError" | ||||
|         required | ||||
|       > | ||||
|         <sw-select | ||||
|           v-model="mailConfigData.mail_driver" | ||||
|           :invalid="$v.mailConfigData.mail_driver.$error" | ||||
|           :options="mailDrivers" | ||||
|           :searchable="true" | ||||
|           :allow-empty="false" | ||||
|           :show-labels="false" | ||||
|           @input="onChangeDriver" | ||||
|         /> | ||||
|       </sw-input-group> | ||||
|  | ||||
|       <sw-input-group | ||||
|         :label="$t('wizard.mail.mailgun_domain')" | ||||
|         :error="domainError" | ||||
|         required | ||||
|       > | ||||
|         <sw-input | ||||
|           :invalid="$v.mailConfigData.mail_mailgun_domain.$error" | ||||
|           v-model.trim="mailConfigData.mail_mailgun_domain" | ||||
|           type="text" | ||||
|           name="mailgun_domain" | ||||
|           @input="$v.mailConfigData.mail_mailgun_domain.$touch()" | ||||
|         /> | ||||
|       </sw-input-group> | ||||
|     </div> | ||||
|     <div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 lg:mb-6 md:mb-6"> | ||||
|       <sw-input-group | ||||
|         :label="$t('wizard.mail.mailgun_secret')" | ||||
|         :error="secretError" | ||||
|         required | ||||
|       > | ||||
|         <sw-input | ||||
|           :invalid="$v.mailConfigData.mail_mailgun_secret.$error" | ||||
|           v-model.trim="mailConfigData.mail_mailgun_secret" | ||||
|           :type="getInputType" | ||||
|           name="mailgun_secret" | ||||
|           @input="$v.mailConfigData.mail_mailgun_secret.$touch()" | ||||
|         > | ||||
|           <template v-slot:rightIcon> | ||||
|             <eye-off-icon | ||||
|               v-if="isShowPassword" | ||||
|               class="w-5 h-5 mr-1 text-gray-500 cursor-pointer" | ||||
|               @click="isShowPassword = !isShowPassword" | ||||
|             /> | ||||
|             <eye-icon | ||||
|               v-else | ||||
|               class="w-5 h-5 mr-1 text-gray-500 cursor-pointer" | ||||
|               @click="isShowPassword = !isShowPassword" | ||||
|             /> | ||||
|           </template> | ||||
|         </sw-input> | ||||
|       </sw-input-group> | ||||
|  | ||||
|       <sw-input-group | ||||
|         :label="$t('wizard.mail.mailgun_endpoint')" | ||||
|         :error="endpointError" | ||||
|         required | ||||
|       > | ||||
|         <sw-input | ||||
|           :invalid="$v.mailConfigData.mail_mailgun_endpoint.$error" | ||||
|           v-model.trim="mailConfigData.mail_mailgun_endpoint" | ||||
|           type="text" | ||||
|           name="mailgun_endpoint" | ||||
|           @input="$v.mailConfigData.mail_mailgun_endpoint.$touch()" | ||||
|         /> | ||||
|       </sw-input-group> | ||||
|     </div> | ||||
|     <div class="grid grid-cols-1 gap-4 mb-6 md:grid-cols-2"> | ||||
|       <sw-input-group | ||||
|         :label="$t('wizard.mail.from_mail')" | ||||
|         :error="fromMailError" | ||||
|         required | ||||
|       > | ||||
|         <sw-input | ||||
|           :invalid="$v.mailConfigData.from_mail.$error" | ||||
|           v-model.trim="mailConfigData.from_mail" | ||||
|           type="text" | ||||
|           name="from_mail" | ||||
|           @input="$v.mailConfigData.from_mail.$touch()" | ||||
|         /> | ||||
|       </sw-input-group> | ||||
|  | ||||
|       <sw-input-group | ||||
|         :label="$t('wizard.mail.from_name')" | ||||
|         :error="fromNameError" | ||||
|         required | ||||
|       > | ||||
|         <sw-input | ||||
|           :invalid="$v.mailConfigData.from_name.$error" | ||||
|           v-model.trim="mailConfigData.from_name" | ||||
|           type="text" | ||||
|           name="from_name" | ||||
|           @input="$v.mailConfigData.from_name.$touch()" | ||||
|         /> | ||||
|       </sw-input-group> | ||||
|     </div> | ||||
|     <sw-button | ||||
|       :loading="loading" | ||||
|       :disabled="loading" | ||||
|       variant="primary" | ||||
|       type="submit" | ||||
|       class="mt-4" | ||||
|     > | ||||
|       <save-icon v-if="!loading" class="mr-2" /> | ||||
|       {{ $t('general.save') }} | ||||
|     </sw-button> | ||||
|   </form> | ||||
| </template> | ||||
| <script> | ||||
| const { required, email } = require('vuelidate/lib/validators') | ||||
| import { EyeIcon, EyeOffIcon } from '@vue-hero-icons/outline' | ||||
|  | ||||
| export default { | ||||
|   props: { | ||||
|     configData: { | ||||
|       type: Object, | ||||
|       require: true, | ||||
|       default: Object, | ||||
|     }, | ||||
|     loading: { | ||||
|       type: Boolean, | ||||
|       require: true, | ||||
|       default: false, | ||||
|     }, | ||||
|     mailDrivers: { | ||||
|       type: Array, | ||||
|       require: true, | ||||
|       default: Array, | ||||
|     }, | ||||
|   }, | ||||
|   components: { | ||||
|     EyeIcon, | ||||
|     EyeOffIcon, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       isShowPassword: false, | ||||
|       mailConfigData: { | ||||
|         mail_driver: '', | ||||
|         mail_mailgun_domain: '', | ||||
|         mail_mailgun_secret: '', | ||||
|         mail_mailgun_endpoint: '', | ||||
|         from_mail: '', | ||||
|         from_name: '', | ||||
|       }, | ||||
|     } | ||||
|   }, | ||||
|   validations: { | ||||
|     mailConfigData: { | ||||
|       mail_driver: { | ||||
|         required, | ||||
|       }, | ||||
|       mail_mailgun_domain: { | ||||
|         required, | ||||
|       }, | ||||
|       mail_mailgun_endpoint: { | ||||
|         required, | ||||
|       }, | ||||
|       mail_mailgun_secret: { | ||||
|         required, | ||||
|       }, | ||||
|       from_mail: { | ||||
|         required, | ||||
|         email, | ||||
|       }, | ||||
|       from_name: { | ||||
|         required, | ||||
|       }, | ||||
|     }, | ||||
|   }, | ||||
|   computed: { | ||||
|     driverError() { | ||||
|       if (!this.$v.mailConfigData.mail_driver.$error) { | ||||
|         return '' | ||||
|       } | ||||
|       if (!this.$v.mailConfigData.mail_driver.required) { | ||||
|         return tthis.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|     domainError() { | ||||
|       if (!this.$v.mailConfigData.mail_mailgun_domain.$error) { | ||||
|         return '' | ||||
|       } | ||||
|       if (!this.$v.mailConfigData.mail_mailgun_domain.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|     secretError() { | ||||
|       if (!this.$v.mailConfigData.mail_mailgun_secret.$error) { | ||||
|         return '' | ||||
|       } | ||||
|       if (!this.$v.mailConfigData.mail_mailgun_secret.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|     endpointError() { | ||||
|       if (!this.$v.mailConfigData.mail_mailgun_endpoint.$error) { | ||||
|         return '' | ||||
|       } | ||||
|       if (!this.$v.mailConfigData.mail_mailgun_endpoint.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|     fromMailError() { | ||||
|       if (!this.$v.mailConfigData.from_mail.$error) { | ||||
|         return '' | ||||
|       } | ||||
|       if (!this.$v.mailConfigData.from_mail.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|       if (!this.$v.mailConfigData.from_mail.email) { | ||||
|         return this.$tc('validation.email_incorrect') | ||||
|       } | ||||
|     }, | ||||
|     fromNameError() { | ||||
|       if (!this.$v.mailConfigData.from_name.$error) { | ||||
|         return '' | ||||
|       } | ||||
|       if (!this.$v.mailConfigData.from_name.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|     getInputType() { | ||||
|       if (this.isShowPassword) { | ||||
|         return 'text' | ||||
|       } | ||||
|       return 'password' | ||||
|     }, | ||||
|   }, | ||||
|   mounted() { | ||||
|     for (const key in this.mailConfigData) { | ||||
|       if (this.configData.hasOwnProperty(key)) { | ||||
|         this.mailConfigData[key] = this.configData[key] | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     async saveEmailConfig() { | ||||
|       this.$v.mailConfigData.$touch() | ||||
|       if (!this.$v.mailConfigData.$invalid) { | ||||
|         this.$emit('submit-data', this.mailConfigData) | ||||
|       } | ||||
|  | ||||
|       return false | ||||
|     }, | ||||
|     onChangeDriver() { | ||||
|       this.$v.mailConfigData.mail_driver.$touch() | ||||
|       this.$emit('on-change-driver', this.mailConfigData.mail_driver) | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
							
								
								
									
										323
									
								
								resources/assets/js/views/wizard/mail-driver/SesMailDriver.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										323
									
								
								resources/assets/js/views/wizard/mail-driver/SesMailDriver.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,323 @@ | ||||
| <template> | ||||
|   <form @submit.prevent="saveEmailConfig"> | ||||
|     <div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 md:mb-6"> | ||||
|       <sw-input-group | ||||
|         :label="$t('wizard.mail.driver')" | ||||
|         :error="driverError" | ||||
|         required | ||||
|       > | ||||
|         <sw-select | ||||
|           v-model="mailConfigData.mail_driver" | ||||
|           :invalid="$v.mailConfigData.mail_driver.$error" | ||||
|           :options="mailDrivers" | ||||
|           :searchable="true" | ||||
|           :allow-empty="false" | ||||
|           :show-labels="false" | ||||
|           @input="onChangeDriver" | ||||
|         /> | ||||
|       </sw-input-group> | ||||
|  | ||||
|       <sw-input-group | ||||
|         :label="$t('wizard.mail.host')" | ||||
|         :error="hostError" | ||||
|         required | ||||
|       > | ||||
|         <sw-input | ||||
|           :invalid="$v.mailConfigData.mail_host.$error" | ||||
|           v-model.trim="mailConfigData.mail_host" | ||||
|           type="text" | ||||
|           name="mail_host" | ||||
|           @input="$v.mailConfigData.mail_host.$touch()" | ||||
|         /> | ||||
|       </sw-input-group> | ||||
|     </div> | ||||
|  | ||||
|     <div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 md:mb-6"> | ||||
|       <sw-input-group | ||||
|         :label="$t('wizard.mail.port')" | ||||
|         :error="portError" | ||||
|         required | ||||
|       > | ||||
|         <sw-input | ||||
|           :invalid="$v.mailConfigData.mail_port.$error" | ||||
|           v-model.trim="mailConfigData.mail_port" | ||||
|           type="text" | ||||
|           name="mail_port" | ||||
|           @input="$v.mailConfigData.mail_port.$touch()" | ||||
|         /> | ||||
|       </sw-input-group> | ||||
|  | ||||
|       <sw-input-group | ||||
|         :label="$t('wizard.mail.encryption')" | ||||
|         :error="encryptionError" | ||||
|         required | ||||
|       > | ||||
|         <sw-select | ||||
|           v-model.trim="mailConfigData.mail_encryption" | ||||
|           :invalid="$v.mailConfigData.mail_encryption.$error" | ||||
|           :options="encryptions" | ||||
|           :searchable="true" | ||||
|           :show-labels="false" | ||||
|           @input="$v.mailConfigData.mail_encryption.$touch()" | ||||
|         /> | ||||
|       </sw-input-group> | ||||
|     </div> | ||||
|  | ||||
|     <div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 md:mb-6"> | ||||
|       <sw-input-group | ||||
|         :label="$t('wizard.mail.from_mail')" | ||||
|         :error="fromEmailError" | ||||
|         required | ||||
|       > | ||||
|         <sw-input | ||||
|           :invalid="$v.mailConfigData.from_mail.$error" | ||||
|           v-model.trim="mailConfigData.from_mail" | ||||
|           type="text" | ||||
|           name="from_mail" | ||||
|           @input="$v.mailConfigData.from_mail.$touch()" | ||||
|         /> | ||||
|       </sw-input-group> | ||||
|  | ||||
|       <sw-input-group | ||||
|         :label="$t('wizard.mail.from_name')" | ||||
|         :error="fromNameError" | ||||
|         required | ||||
|       > | ||||
|         <sw-input | ||||
|           :invalid="$v.mailConfigData.from_name.$error" | ||||
|           v-model.trim="mailConfigData.from_name" | ||||
|           type="text" | ||||
|           name="name" | ||||
|           @input="$v.mailConfigData.from_name.$touch()" | ||||
|         /> | ||||
|       </sw-input-group> | ||||
|     </div> | ||||
|     <div class="grid grid-cols-1 gap-4 mb-6 md:grid-cols-2"> | ||||
|       <sw-input-group | ||||
|         :label="$t('wizard.mail.ses_key')" | ||||
|         :error="keyError" | ||||
|         required | ||||
|       > | ||||
|         <sw-input | ||||
|           :invalid="$v.mailConfigData.mail_ses_key.$error" | ||||
|           v-model.trim="mailConfigData.mail_ses_key" | ||||
|           type="text" | ||||
|           name="mail_ses_key" | ||||
|           @input="$v.mailConfigData.mail_ses_key.$touch()" | ||||
|         /> | ||||
|       </sw-input-group> | ||||
|  | ||||
|       <sw-input-group | ||||
|         :label="$t('wizard.mail.ses_secret')" | ||||
|         :error="secretError" | ||||
|         required | ||||
|       > | ||||
|         <sw-input | ||||
|           :invalid="$v.mailConfigData.mail_ses_secret.$error" | ||||
|           v-model.trim="mailConfigData.mail_ses_secret" | ||||
|           :type="getInputType" | ||||
|           name="mail_ses_secret" | ||||
|           @input="$v.mailConfigData.mail_ses_secret.$touch()" | ||||
|         > | ||||
|           <template v-slot:rightIcon> | ||||
|             <eye-off-icon | ||||
|               v-if="isShowPassword" | ||||
|               class="w-5 h-5 mr-1 text-gray-500 cursor-pointer" | ||||
|               @click="isShowPassword = !isShowPassword" | ||||
|             /> | ||||
|             <eye-icon | ||||
|               v-else | ||||
|               class="w-5 h-5 mr-1 text-gray-500 cursor-pointer" | ||||
|               @click="isShowPassword = !isShowPassword" | ||||
|             /> | ||||
|           </template> | ||||
|         </sw-input> | ||||
|       </sw-input-group> | ||||
|     </div> | ||||
|     <sw-button | ||||
|       :loading="loading" | ||||
|       :disabled="loading" | ||||
|       variant="primary" | ||||
|       type="submit" | ||||
|       class="mt-4" | ||||
|     > | ||||
|       <save-icon v-if="!loading" class="mr-2" /> | ||||
|       {{ $t('general.save') }} | ||||
|     </sw-button> | ||||
|   </form> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| const { required, email, numeric } = require('vuelidate/lib/validators') | ||||
| import { EyeIcon, EyeOffIcon } from '@vue-hero-icons/outline' | ||||
|  | ||||
| export default { | ||||
|   props: { | ||||
|     configData: { | ||||
|       type: Object, | ||||
|       require: true, | ||||
|       default: Object, | ||||
|     }, | ||||
|     loading: { | ||||
|       type: Boolean, | ||||
|       require: true, | ||||
|       default: false, | ||||
|     }, | ||||
|     mailDrivers: { | ||||
|       type: Array, | ||||
|       require: true, | ||||
|       default: Array, | ||||
|     }, | ||||
|   }, | ||||
|   components: { | ||||
|     EyeIcon, | ||||
|     EyeOffIcon, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       isShowPassword: false, | ||||
|       mailConfigData: { | ||||
|         mail_driver: '', | ||||
|         mail_host: '', | ||||
|         mail_port: null, | ||||
|         mail_ses_key: '', | ||||
|         mail_ses_secret: '', | ||||
|         mail_encryption: 'tls', | ||||
|         from_mail: '', | ||||
|         from_name: '', | ||||
|       }, | ||||
|       encryptions: ['tls', 'ssl', 'starttls'], | ||||
|     } | ||||
|   }, | ||||
|   validations: { | ||||
|     mailConfigData: { | ||||
|       mail_driver: { | ||||
|         required, | ||||
|       }, | ||||
|       mail_host: { | ||||
|         required, | ||||
|       }, | ||||
|       mail_port: { | ||||
|         required, | ||||
|         numeric, | ||||
|       }, | ||||
|       mail_ses_key: { | ||||
|         required, | ||||
|       }, | ||||
|       mail_ses_secret: { | ||||
|         required, | ||||
|       }, | ||||
|       mail_encryption: { | ||||
|         required, | ||||
|       }, | ||||
|       from_mail: { | ||||
|         required, | ||||
|         email, | ||||
|       }, | ||||
|       from_name: { | ||||
|         required, | ||||
|       }, | ||||
|     }, | ||||
|   }, | ||||
|   computed: { | ||||
|     driverError() { | ||||
|       if (!this.$v.mailConfigData.mail_driver.$error) { | ||||
|         return '' | ||||
|       } | ||||
|       if (!this.$v.mailConfigData.mail_driver.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|     hostError() { | ||||
|       if (!this.$v.mailConfigData.mail_host.$error) { | ||||
|         return '' | ||||
|       } | ||||
|       if (!this.$v.mailConfigData.mail_host.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|     portError() { | ||||
|       if (!this.$v.mailConfigData.mail_port.$error) { | ||||
|         return '' | ||||
|       } | ||||
|       if (!this.$v.mailConfigData.mail_port.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|       if (!this.$v.mailConfigData.mail_port.numeric) { | ||||
|         return this.$tc('validation.numbers_only') | ||||
|       } | ||||
|     }, | ||||
|     encryptionError() { | ||||
|       if (!this.$v.mailConfigData.mail_encryption.$error) { | ||||
|         return '' | ||||
|       } | ||||
|       if (!this.$v.mailConfigData.mail_encryption.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|     fromEmailError() { | ||||
|       if (!this.$v.mailConfigData.from_mail.$error) { | ||||
|         return '' | ||||
|       } | ||||
|       if (!this.$v.mailConfigData.from_mail.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.mailConfigData.from_mail.email) { | ||||
|         return this.$tc('validation.email_incorrect') | ||||
|       } | ||||
|     }, | ||||
|     fromNameError() { | ||||
|       if (!this.$v.mailConfigData.from_name.$error) { | ||||
|         return '' | ||||
|       } | ||||
|       if (!this.$v.mailConfigData.from_name.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|     keyError() { | ||||
|       if (!this.$v.mailConfigData.mail_ses_key.$error) { | ||||
|         return '' | ||||
|       } | ||||
|       if (!this.$v.mailConfigData.mail_ses_key.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|     secretError() { | ||||
|       if (!this.$v.mailConfigData.mail_ses_secret.$error) { | ||||
|         return '' | ||||
|       } | ||||
|       if (!this.$v.mailConfigData.mail_ses_secret.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|     getInputType() { | ||||
|       if (this.isShowPassword) { | ||||
|         return 'text' | ||||
|       } | ||||
|       return 'password' | ||||
|     }, | ||||
|   }, | ||||
|   mounted() { | ||||
|     for (const key in this.mailConfigData) { | ||||
|       if (this.configData.hasOwnProperty(key)) { | ||||
|         this.mailConfigData[key] = this.configData[key] | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     async saveEmailConfig() { | ||||
|       this.$v.mailConfigData.$touch() | ||||
|       if (!this.$v.mailConfigData.$invalid) { | ||||
|         this.$emit('submit-data', this.mailConfigData) | ||||
|       } | ||||
|  | ||||
|       return false | ||||
|     }, | ||||
|     onChangeDriver() { | ||||
|       this.$v.mailConfigData.mail_driver.$touch() | ||||
|       this.$emit('on-change-driver', this.mailConfigData.mail_driver) | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
							
								
								
									
										333
									
								
								resources/assets/js/views/wizard/mail-driver/SmtpMailDriver.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										333
									
								
								resources/assets/js/views/wizard/mail-driver/SmtpMailDriver.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,333 @@ | ||||
| <template> | ||||
|   <form @submit.prevent="saveEmailConfig()"> | ||||
|     <div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 md:mb-6"> | ||||
|       <sw-input-group | ||||
|         :label="$t('wizard.mail.driver')" | ||||
|         :error="driverError" | ||||
|         required | ||||
|       > | ||||
|         <sw-select | ||||
|           v-model="mailConfigData.mail_driver" | ||||
|           :invalid="$v.mailConfigData.mail_driver.$error" | ||||
|           :options="mailDrivers" | ||||
|           :searchable="true" | ||||
|           :allow-empty="false" | ||||
|           :show-labels="false" | ||||
|           @input="onChangeDriver" | ||||
|         /> | ||||
|       </sw-input-group> | ||||
|  | ||||
|       <sw-input-group | ||||
|         :label="$t('wizard.mail.host')" | ||||
|         :error="hostError" | ||||
|         required | ||||
|       > | ||||
|         <sw-input | ||||
|           :invalid="$v.mailConfigData.mail_host.$error" | ||||
|           v-model.trim="mailConfigData.mail_host" | ||||
|           type="text" | ||||
|           name="mail_host" | ||||
|           @input="$v.mailConfigData.mail_host.$touch()" | ||||
|         /> | ||||
|       </sw-input-group> | ||||
|     </div> | ||||
|  | ||||
|     <div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 md:mb-6"> | ||||
|       <sw-input-group | ||||
|         :label="$t('wizard.mail.username')" | ||||
|         :error="usernameError" | ||||
|         required | ||||
|       > | ||||
|         <sw-input | ||||
|           :invalid="$v.mailConfigData.mail_username.$error" | ||||
|           v-model.trim="mailConfigData.mail_username" | ||||
|           type="text" | ||||
|           name="db_name" | ||||
|           @input="$v.mailConfigData.mail_username.$touch()" | ||||
|         /> | ||||
|       </sw-input-group> | ||||
|  | ||||
|       <sw-input-group | ||||
|         :label="$t('wizard.mail.password')" | ||||
|         :error="passwordError" | ||||
|         required | ||||
|       > | ||||
|         <sw-input | ||||
|           :invalid="$v.mailConfigData.mail_password.$error" | ||||
|           v-model.trim="mailConfigData.mail_password" | ||||
|           :type="getInputType" | ||||
|           name="password" | ||||
|           @input="$v.mailConfigData.mail_password.$touch()" | ||||
|         > | ||||
|           <template v-slot:rightIcon> | ||||
|             <eye-off-icon | ||||
|               v-if="isShowPassword" | ||||
|               class="w-5 h-5 mr-1 text-gray-500 cursor-pointer" | ||||
|               @click="isShowPassword = !isShowPassword" | ||||
|             /> | ||||
|             <eye-icon | ||||
|               v-else | ||||
|               class="w-5 h-5 mr-1 text-gray-500 cursor-pointer" | ||||
|               @click="isShowPassword = !isShowPassword" | ||||
|             /> | ||||
|           </template> | ||||
|         </sw-input> | ||||
|       </sw-input-group> | ||||
|     </div> | ||||
|  | ||||
|     <div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 md:mb-6"> | ||||
|       <sw-input-group | ||||
|         :label="$t('wizard.mail.port')" | ||||
|         :error="portError" | ||||
|         required | ||||
|       > | ||||
|         <sw-input | ||||
|           :invalid="$v.mailConfigData.mail_port.$error" | ||||
|           v-model.trim="mailConfigData.mail_port" | ||||
|           type="text" | ||||
|           name="mail_port" | ||||
|           @input="$v.mailConfigData.mail_port.$touch()" | ||||
|         /> | ||||
|       </sw-input-group> | ||||
|  | ||||
|       <sw-input-group | ||||
|         :label="$t('wizard.mail.encryption')" | ||||
|         :error="encryptionError" | ||||
|         required | ||||
|       > | ||||
|         <sw-select | ||||
|           v-model.trim="mailConfigData.mail_encryption" | ||||
|           :invalid="$v.mailConfigData.mail_encryption.$error" | ||||
|           :options="encryptions" | ||||
|           :searchable="true" | ||||
|           :show-labels="false" | ||||
|           @input="$v.mailConfigData.mail_encryption.$touch()" | ||||
|         /> | ||||
|       </sw-input-group> | ||||
|     </div> | ||||
|  | ||||
|     <div class="grid grid-cols-1 gap-4 mb-6 md:grid-cols-2"> | ||||
|       <sw-input-group | ||||
|         :label="$t('wizard.mail.from_mail')" | ||||
|         :error="fromEmailError" | ||||
|         required | ||||
|       > | ||||
|         <sw-input | ||||
|           :invalid="$v.mailConfigData.from_mail.$error" | ||||
|           v-model.trim="mailConfigData.from_mail" | ||||
|           type="text" | ||||
|           name="from_mail" | ||||
|           @input="$v.mailConfigData.from_mail.$touch()" | ||||
|         /> | ||||
|       </sw-input-group> | ||||
|  | ||||
|       <sw-input-group | ||||
|         :label="$t('wizard.mail.from_name')" | ||||
|         :error="fromNameError" | ||||
|         required | ||||
|       > | ||||
|         <sw-input | ||||
|           :invalid="$v.mailConfigData.from_name.$error" | ||||
|           v-model.trim="mailConfigData.from_name" | ||||
|           type="text" | ||||
|           name="from_name" | ||||
|           @input="$v.mailConfigData.from_name.$touch()" | ||||
|         /> | ||||
|       </sw-input-group> | ||||
|     </div> | ||||
|  | ||||
|     <sw-button | ||||
|       :loading="loading" | ||||
|       :disabled="loading" | ||||
|       variant="primary" | ||||
|       type="submit" | ||||
|       class="mt-4" | ||||
|     > | ||||
|       <save-icon v-if="!loading" class="mr-2" /> | ||||
|       {{ $t('general.save') }} | ||||
|     </sw-button> | ||||
|   </form> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| const { required, email, numeric } = require('vuelidate/lib/validators') | ||||
| import { EyeIcon, EyeOffIcon } from '@vue-hero-icons/outline' | ||||
|  | ||||
| export default { | ||||
|   props: { | ||||
|     configData: { | ||||
|       type: Object, | ||||
|       require: true, | ||||
|       default: Object, | ||||
|     }, | ||||
|     loading: { | ||||
|       type: Boolean, | ||||
|       require: true, | ||||
|       default: false, | ||||
|     }, | ||||
|     mailDrivers: { | ||||
|       type: Array, | ||||
|       require: true, | ||||
|       default: Array, | ||||
|     }, | ||||
|   }, | ||||
|   components: { | ||||
|     EyeIcon, | ||||
|     EyeOffIcon, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       isShowPassword: false, | ||||
|       mailConfigData: { | ||||
|         mail_driver: '', | ||||
|         mail_host: '', | ||||
|         mail_port: null, | ||||
|         mail_username: '', | ||||
|         mail_password: '', | ||||
|         mail_encryption: 'tls', | ||||
|         from_mail: '', | ||||
|         from_name: '', | ||||
|       }, | ||||
|       encryptions: ['tls', 'ssl', 'starttls'], | ||||
|     } | ||||
|   }, | ||||
|   validations: { | ||||
|     mailConfigData: { | ||||
|       mail_driver: { | ||||
|         required, | ||||
|       }, | ||||
|       mail_host: { | ||||
|         required, | ||||
|       }, | ||||
|       mail_port: { | ||||
|         required, | ||||
|         numeric, | ||||
|       }, | ||||
|       mail_username: { | ||||
|         required, | ||||
|       }, | ||||
|       mail_password: { | ||||
|         required, | ||||
|       }, | ||||
|       mail_encryption: { | ||||
|         required, | ||||
|       }, | ||||
|       from_mail: { | ||||
|         required, | ||||
|         email, | ||||
|       }, | ||||
|       from_name: { | ||||
|         required, | ||||
|       }, | ||||
|     }, | ||||
|   }, | ||||
|   computed: { | ||||
|     driverError() { | ||||
|       if (!this.$v.mailConfigData.mail_driver.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.mailConfigData.mail_driver.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|     hostError() { | ||||
|       if (!this.$v.mailConfigData.mail_host.$error) { | ||||
|         return '' | ||||
|       } | ||||
|       if (!this.$v.mailConfigData.mail_host.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|     usernameError() { | ||||
|       if (!this.$v.mailConfigData.mail_username.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.mailConfigData.mail_username.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|     passwordError() { | ||||
|       if (!this.$v.mailConfigData.mail_password.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.mailConfigData.mail_password.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|     portError() { | ||||
|       if (!this.$v.mailConfigData.mail_port.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.mailConfigData.mail_port.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.mailConfigData.mail_port.numeric) { | ||||
|         return this.$tc('validation.numbers_only') | ||||
|       } | ||||
|     }, | ||||
|     encryptionError() { | ||||
|       if (!this.$v.mailConfigData.mail_encryption.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.mailConfigData.mail_encryption.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|     fromEmailError() { | ||||
|       if (!this.$v.mailConfigData.from_mail.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.mailConfigData.from_mail.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.mailConfigData.from_mail.email) { | ||||
|         return this.$tc('validation.email_incorrect') | ||||
|       } | ||||
|     }, | ||||
|     fromNameError() { | ||||
|       if (!this.$v.mailConfigData.from_name.$error) { | ||||
|         return '' | ||||
|       } | ||||
|  | ||||
|       if (!this.$v.mailConfigData.from_name.required) { | ||||
|         return this.$tc('validation.required') | ||||
|       } | ||||
|     }, | ||||
|     getInputType() { | ||||
|       if (this.isShowPassword) { | ||||
|         return 'text' | ||||
|       } | ||||
|       return 'password' | ||||
|     }, | ||||
|   }, | ||||
|   mounted() { | ||||
|     for (const key in this.mailConfigData) { | ||||
|       if (this.configData.hasOwnProperty(key)) { | ||||
|         this.mailConfigData[key] = this.configData[key] | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     async saveEmailConfig() { | ||||
|       this.$v.mailConfigData.$touch() | ||||
|       if (!this.$v.mailConfigData.$invalid) { | ||||
|         this.$emit('submit-data', this.mailConfigData) | ||||
|       } | ||||
|  | ||||
|       return false | ||||
|     }, | ||||
|     onChangeDriver() { | ||||
|       this.$v.mailConfigData.mail_driver.$touch() | ||||
|       this.$emit('on-change-driver', this.mailConfigData.mail_driver) | ||||
|     }, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
| @ -1,160 +0,0 @@ | ||||
| <template> | ||||
|   <form @submit.prevent="saveEmailConfig()"> | ||||
|     <div class="row"> | ||||
|       <div class="col-md-6 my-2"> | ||||
|         <label class="form-label">{{ $t('wizard.mail.driver') }}</label> | ||||
|         <span class="text-danger"> *</span> | ||||
|         <base-select | ||||
|           v-model="mailConfigData.mail_driver" | ||||
|           :invalid="$v.mailConfigData.mail_driver.$error" | ||||
|           :options="mailDrivers" | ||||
|           :allow-empty="false" | ||||
|           :searchable="true" | ||||
|           :show-labels="false" | ||||
|           @input="onChangeDriver" | ||||
|         /> | ||||
|         <div v-if="$v.mailConfigData.mail_driver.$error"> | ||||
|           <span v-if="!$v.mailConfigData.mail_driver.required" class="text-danger"> | ||||
|             {{ $tc('validation.required') }} | ||||
|           </span> | ||||
|         </div> | ||||
|       </div> | ||||
|       <!-- <div class="col-md-6 my-2"> | ||||
|         <label class="form-label">{{ $t('wizard.mail.host') }}</label> | ||||
|         <span class="text-danger"> *</span> | ||||
|         <base-input | ||||
|           :invalid="$v.mailConfigData.mail_host.$error" | ||||
|           v-model.trim="mailConfigData.mail_host" | ||||
|           type="text" | ||||
|           name="mail_host" | ||||
|           @input="$v.mailConfigData.mail_host.$touch()" | ||||
|         /> | ||||
|         <div v-if="$v.mailConfigData.mail_host.$error"> | ||||
|           <span v-if="!$v.mailConfigData.mail_host.required" class="text-danger"> | ||||
|             {{ $tc('validation.required') }} | ||||
|           </span> | ||||
|         </div> | ||||
|       </div> --> | ||||
|     </div> | ||||
|     <div class="row my-2"> | ||||
|       <div class="col-md-6 my-2"> | ||||
|         <label class="form-label">{{ $t('wizard.mail.from_mail') }}</label> | ||||
|         <span class="text-danger"> *</span> | ||||
|         <base-input | ||||
|           :invalid="$v.mailConfigData.from_mail.$error" | ||||
|           v-model.trim="mailConfigData.from_mail" | ||||
|           type="text" | ||||
|           name="from_mail" | ||||
|           @input="$v.mailConfigData.from_mail.$touch()" | ||||
|         /> | ||||
|         <div v-if="$v.mailConfigData.from_mail.$error"> | ||||
|           <span v-if="!$v.mailConfigData.from_mail.required" class="text-danger"> | ||||
|             {{ $tc('validation.required') }} | ||||
|           </span> | ||||
|           <span v-if="!$v.mailConfigData.from_mail.email" class="text-danger"> | ||||
|             {{ $tc('validation.email_incorrect') }} | ||||
|           </span> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="col-md-6 my-2"> | ||||
|         <label class="form-label">{{ $t('wizard.mail.from_name') }}</label> | ||||
|         <span class="text-danger"> *</span> | ||||
|         <base-input | ||||
|           :invalid="$v.mailConfigData.from_name.$error" | ||||
|           v-model.trim="mailConfigData.from_name" | ||||
|           type="text" | ||||
|           name="name" | ||||
|           @input="$v.mailConfigData.from_name.$touch()" | ||||
|         /> | ||||
|         <div v-if="$v.mailConfigData.from_name.$error"> | ||||
|           <span v-if="!$v.mailConfigData.from_name.required" class="text-danger"> | ||||
|             {{ $tc('validation.required') }} | ||||
|           </span> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <base-button | ||||
|       :loading="loading" | ||||
|       class="pull-right mt-4" | ||||
|       icon="save" | ||||
|       color="theme" | ||||
|       type="submit" | ||||
|     > | ||||
|       {{ $t('general.save') }} | ||||
|     </base-button> | ||||
|   </form> | ||||
| </template> | ||||
| <script> | ||||
| import MultiSelect from 'vue-multiselect' | ||||
| import { validationMixin } from 'vuelidate' | ||||
| const { required, email } = require('vuelidate/lib/validators') | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
|     MultiSelect | ||||
|   }, | ||||
|   mixins: [validationMixin], | ||||
|   props: { | ||||
|     configData: { | ||||
|       type: Object, | ||||
|       require: true, | ||||
|       default: Object | ||||
|     }, | ||||
|     loading: { | ||||
|       type: Boolean, | ||||
|       require: true, | ||||
|       default: false | ||||
|     }, | ||||
|     mailDrivers: { | ||||
|       type: Array, | ||||
|       require: true, | ||||
|       default: Array | ||||
|     } | ||||
|   }, | ||||
|   data () { | ||||
|     return { | ||||
|       mailConfigData: { | ||||
|         mail_driver: '', | ||||
|         mail_host: '', | ||||
|         from_mail: '', | ||||
|         from_name: '' | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   validations: { | ||||
|     mailConfigData: { | ||||
|       mail_driver: { | ||||
|         required | ||||
|       }, | ||||
|       from_mail: { | ||||
|         required, | ||||
|         email | ||||
|       }, | ||||
|       from_name: { | ||||
|         required | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   mounted () { | ||||
|     for (const key in this.mailConfigData) { | ||||
|       if (this.configData.hasOwnProperty(key)) { | ||||
|         this.mailConfigData[key] = this.configData[key] | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     async saveEmailConfig () { | ||||
|       this.$v.mailConfigData.$touch() | ||||
|       if (!this.$v.mailConfigData.$invalid) { | ||||
|         this.$emit('submit-data', this.mailConfigData) | ||||
|       } | ||||
|  | ||||
|       return false | ||||
|     }, | ||||
|     onChangeDriver () { | ||||
|       this.$v.mailConfigData.mail_driver.$touch() | ||||
|       this.$emit('on-change-driver', this.mailConfigData.mail_driver) | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
| @ -1,209 +0,0 @@ | ||||
| <template> | ||||
|   <form @submit.prevent="saveEmailConfig()"> | ||||
|     <div class="row"> | ||||
|       <div class="col-md-6 my-2"> | ||||
|         <label class="form-label">{{ $t('wizard.mail.driver') }}</label> | ||||
|         <span class="text-danger"> *</span> | ||||
|         <base-select | ||||
|           v-model="mailConfigData.mail_driver" | ||||
|           :invalid="$v.mailConfigData.mail_driver.$error" | ||||
|           :options="mailDrivers" | ||||
|           :searchable="true" | ||||
|           :allow-empty="false" | ||||
|           :show-labels="false" | ||||
|           @input="onChangeDriver" | ||||
|         /> | ||||
|         <div v-if="$v.mailConfigData.mail_driver.$error"> | ||||
|           <span v-if="!$v.mailConfigData.mail_driver.required" class="text-danger"> | ||||
|             {{ $tc('validation.required') }} | ||||
|           </span> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="col-md-6 my-2"> | ||||
|         <label class="form-label">{{ $t('wizard.mail.mailgun_domain') }}</label> | ||||
|         <span class="text-danger"> *</span> | ||||
|         <base-input | ||||
|           :invalid="$v.mailConfigData.mail_mailgun_domain.$error" | ||||
|           v-model.trim="mailConfigData.mail_mailgun_domain" | ||||
|           type="text" | ||||
|           name="mailgun_domain" | ||||
|           @input="$v.mailConfigData.mail_mailgun_domain.$touch()" | ||||
|         /> | ||||
|         <div v-if="$v.mailConfigData.mail_mailgun_domain.$error"> | ||||
|           <span v-if="!$v.mailConfigData.mail_mailgun_domain.required" class="text-danger"> | ||||
|             {{ $tc('validation.required') }} | ||||
|           </span> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <div class="row my-2"> | ||||
|       <div class="col-md-6 my-2"> | ||||
|         <label class="form-label">{{ $t('wizard.mail.mailgun_secret') }}</label> | ||||
|         <span class="text-danger"> *</span> | ||||
|         <base-input | ||||
|           :invalid="$v.mailConfigData.mail_mailgun_secret.$error" | ||||
|           v-model.trim="mailConfigData.mail_mailgun_secret" | ||||
|           type="password" | ||||
|           name="mailgun_secret" | ||||
|           show-password | ||||
|           @input="$v.mailConfigData.mail_mailgun_secret.$touch()" | ||||
|         /> | ||||
|         <div v-if="$v.mailConfigData.mail_mailgun_secret.$error"> | ||||
|           <span v-if="!$v.mailConfigData.mail_mailgun_secret.required" class="text-danger"> | ||||
|             {{ $tc('validation.required') }} | ||||
|           </span> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="col-md-6 my-2"> | ||||
|         <label class="form-label">{{ $t('wizard.mail.mailgun_endpoint') }}</label> | ||||
|         <span class="text-danger"> *</span> | ||||
|         <base-input | ||||
|           :invalid="$v.mailConfigData.mail_mailgun_endpoint.$error" | ||||
|           v-model.trim="mailConfigData.mail_mailgun_endpoint" | ||||
|           type="text" | ||||
|           name="mailgun_endpoint" | ||||
|           @input="$v.mailConfigData.mail_mailgun_endpoint.$touch()" | ||||
|         /> | ||||
|         <div v-if="$v.mailConfigData.mail_mailgun_endpoint.$error"> | ||||
|           <span v-if="!$v.mailConfigData.mail_mailgun_endpoint.required" class="text-danger"> | ||||
|             {{ $tc('validation.required') }} | ||||
|           </span> | ||||
|           <span v-if="!$v.mailConfigData.mail_mailgun_endpoint.numeric" class="text-danger"> | ||||
|             {{ $tc('validation.numbers_only') }} | ||||
|           </span> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <div class="row my-2"> | ||||
|       <div class="col-md-6 my-2"> | ||||
|         <label class="form-label">{{ $t('wizard.mail.from_mail') }}</label> | ||||
|         <span class="text-danger"> *</span> | ||||
|         <base-input | ||||
|           :invalid="$v.mailConfigData.from_mail.$error" | ||||
|           v-model.trim="mailConfigData.from_mail" | ||||
|           type="text" | ||||
|           name="from_mail" | ||||
|           @input="$v.mailConfigData.from_mail.$touch()" | ||||
|         /> | ||||
|         <div v-if="$v.mailConfigData.from_mail.$error"> | ||||
|           <span v-if="!$v.mailConfigData.from_mail.required" class="text-danger"> | ||||
|             {{ $tc('validation.required') }} | ||||
|           </span> | ||||
|           <span v-if="!$v.mailConfigData.from_mail.email" class="text-danger"> | ||||
|             {{ $tc('validation.email_incorrect') }} | ||||
|           </span> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="col-md-6 my-2"> | ||||
|         <label class="form-label">{{ $t('wizard.mail.from_name') }}</label> | ||||
|         <span class="text-danger"> *</span> | ||||
|         <base-input | ||||
|           :invalid="$v.mailConfigData.from_name.$error" | ||||
|           v-model.trim="mailConfigData.from_name" | ||||
|           type="text" | ||||
|           name="from_name" | ||||
|           @input="$v.mailConfigData.from_name.$touch()" | ||||
|         /> | ||||
|         <div v-if="$v.mailConfigData.from_name.$error"> | ||||
|           <span v-if="!$v.mailConfigData.from_name.required" class="text-danger"> | ||||
|             {{ $tc('validation.required') }} | ||||
|           </span> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <base-button | ||||
|       :loading="loading" | ||||
|       class="pull-right mt-4" | ||||
|       icon="save" | ||||
|       color="theme" | ||||
|       type="submit" | ||||
|     > | ||||
|       {{ $t('general.save') }} | ||||
|     </base-button> | ||||
|   </form> | ||||
| </template> | ||||
| <script> | ||||
| import MultiSelect from 'vue-multiselect' | ||||
| import { validationMixin } from 'vuelidate' | ||||
| const { required, email } = require('vuelidate/lib/validators') | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
|     MultiSelect | ||||
|   }, | ||||
|   mixins: [validationMixin], | ||||
|   props: { | ||||
|     configData: { | ||||
|       type: Object, | ||||
|       require: true, | ||||
|       default: Object | ||||
|     }, | ||||
|     loading: { | ||||
|       type: Boolean, | ||||
|       require: true, | ||||
|       default: false | ||||
|     }, | ||||
|     mailDrivers: { | ||||
|       type: Array, | ||||
|       require: true, | ||||
|       default: Array | ||||
|     } | ||||
|   }, | ||||
|   data () { | ||||
|     return { | ||||
|       mailConfigData: { | ||||
|         mail_driver: '', | ||||
|         mail_mailgun_domain: '', | ||||
|         mail_mailgun_secret: '', | ||||
|         mail_mailgun_endpoint: '', | ||||
|         from_mail: '', | ||||
|         from_name: '' | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   validations: { | ||||
|     mailConfigData: { | ||||
|       mail_driver: { | ||||
|         required | ||||
|       }, | ||||
|       mail_mailgun_domain: { | ||||
|         required | ||||
|       }, | ||||
|       mail_mailgun_endpoint: { | ||||
|         required | ||||
|       }, | ||||
|       mail_mailgun_secret: { | ||||
|         required | ||||
|       }, | ||||
|       from_mail: { | ||||
|         required, | ||||
|         email | ||||
|       }, | ||||
|       from_name: { | ||||
|         required | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   mounted () { | ||||
|     for (const key in this.mailConfigData) { | ||||
|       if (this.configData.hasOwnProperty(key)) { | ||||
|         this.mailConfigData[key] = this.configData[key] | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     async saveEmailConfig () { | ||||
|       this.$v.mailConfigData.$touch() | ||||
|       if (!this.$v.mailConfigData.$invalid) { | ||||
|         this.$emit('submit-data', this.mailConfigData) | ||||
|       } | ||||
|  | ||||
|       return false | ||||
|     }, | ||||
|     onChangeDriver () { | ||||
|       this.$v.mailConfigData.mail_driver.$touch() | ||||
|       this.$emit('on-change-driver', this.mailConfigData.mail_driver) | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
| @ -1,254 +0,0 @@ | ||||
| <template> | ||||
|   <form @submit.prevent="saveEmailConfig()"> | ||||
|     <div class="row"> | ||||
|       <div class="col-md-6 my-2"> | ||||
|         <label class="form-label">{{ $t('wizard.mail.driver') }}</label> | ||||
|         <span class="text-danger"> *</span> | ||||
|         <base-select | ||||
|           v-model="mailConfigData.mail_driver" | ||||
|           :invalid="$v.mailConfigData.mail_driver.$error" | ||||
|           :options="mailDrivers" | ||||
|           :searchable="true" | ||||
|           :allow-empty="false" | ||||
|           :show-labels="false" | ||||
|           @input="onChangeDriver" | ||||
|         /> | ||||
|         <div v-if="$v.mailConfigData.mail_driver.$error"> | ||||
|           <span v-if="!$v.mailConfigData.mail_driver.required" class="text-danger"> | ||||
|             {{ $tc('validation.required') }} | ||||
|           </span> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="col-md-6 my-2"> | ||||
|         <label class="form-label">{{ $t('wizard.mail.host') }}</label> | ||||
|         <span class="text-danger"> *</span> | ||||
|         <base-input | ||||
|           :invalid="$v.mailConfigData.mail_host.$error" | ||||
|           v-model.trim="mailConfigData.mail_host" | ||||
|           type="text" | ||||
|           name="mail_host" | ||||
|           @input="$v.mailConfigData.mail_host.$touch()" | ||||
|         /> | ||||
|         <div v-if="$v.mailConfigData.mail_host.$error"> | ||||
|           <span v-if="!$v.mailConfigData.mail_host.required" class="text-danger"> | ||||
|             {{ $tc('validation.required') }} | ||||
|           </span> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <div class="row my-2"> | ||||
|       <div class="col-md-6 my-2"> | ||||
|         <label class="form-label">{{ $t('wizard.mail.port') }}</label> | ||||
|         <span class="text-danger"> *</span> | ||||
|         <base-input | ||||
|           :invalid="$v.mailConfigData.mail_port.$error" | ||||
|           v-model.trim="mailConfigData.mail_port" | ||||
|           type="text" | ||||
|           name="mail_port" | ||||
|           @input="$v.mailConfigData.mail_port.$touch()" | ||||
|         /> | ||||
|         <div v-if="$v.mailConfigData.mail_port.$error"> | ||||
|           <span v-if="!$v.mailConfigData.mail_port.required" class="text-danger"> | ||||
|             {{ $tc('validation.required') }} | ||||
|           </span> | ||||
|           <span v-if="!$v.mailConfigData.mail_port.numeric" class="text-danger"> | ||||
|             {{ $tc('validation.numbers_only') }} | ||||
|           </span> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="col-md-6 my-2"> | ||||
|         <label class="form-label">{{ $t('wizard.mail.encryption') }}</label> | ||||
|         <span class="text-danger"> *</span> | ||||
|         <base-select | ||||
|           v-model.trim="mailConfigData.mail_encryption" | ||||
|           :invalid="$v.mailConfigData.mail_encryption.$error" | ||||
|           :options="encryptions" | ||||
|           :searchable="true" | ||||
|           :show-labels="false" | ||||
|           @input="$v.mailConfigData.mail_encryption.$touch()" | ||||
|         /> | ||||
|         <div v-if="$v.mailConfigData.mail_encryption.$error"> | ||||
|           <span v-if="!$v.mailConfigData.mail_encryption.required" class="text-danger"> | ||||
|             {{ $tc('validation.required') }} | ||||
|           </span> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <div class="row my-2"> | ||||
|       <div class="col-md-6 my-2"> | ||||
|         <label class="form-label">{{ $t('wizard.mail.from_mail') }}</label> | ||||
|         <span class="text-danger"> *</span> | ||||
|         <base-input | ||||
|           :invalid="$v.mailConfigData.from_mail.$error" | ||||
|           v-model.trim="mailConfigData.from_mail" | ||||
|           type="text" | ||||
|           name="from_mail" | ||||
|           @input="$v.mailConfigData.from_mail.$touch()" | ||||
|         /> | ||||
|         <div v-if="$v.mailConfigData.from_mail.$error"> | ||||
|           <span v-if="!$v.mailConfigData.from_mail.required" class="text-danger"> | ||||
|             {{ $tc('validation.required') }} | ||||
|           </span> | ||||
|           <span v-if="!$v.mailConfigData.from_mail.email" class="text-danger"> | ||||
|             {{ $tc('validation.email_incorrect') }} | ||||
|           </span> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="col-md-6 my-2"> | ||||
|         <label class="form-label">{{ $t('wizard.mail.from_name') }}</label> | ||||
|         <span class="text-danger"> *</span> | ||||
|         <base-input | ||||
|           :invalid="$v.mailConfigData.from_name.$error" | ||||
|           v-model.trim="mailConfigData.from_name" | ||||
|           type="text" | ||||
|           name="name" | ||||
|           @input="$v.mailConfigData.from_name.$touch()" | ||||
|         /> | ||||
|         <div v-if="$v.mailConfigData.from_name.$error"> | ||||
|           <span v-if="!$v.mailConfigData.from_name.required" class="text-danger"> | ||||
|             {{ $tc('validation.required') }} | ||||
|           </span> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <div class="row my-2"> | ||||
|       <div class="col-md-6 my-2"> | ||||
|         <label class="form-label">{{ $t('wizard.mail.ses_key') }}</label> | ||||
|         <span class="text-danger"> *</span> | ||||
|         <base-input | ||||
|           :invalid="$v.mailConfigData.mail_ses_key.$error" | ||||
|           v-model.trim="mailConfigData.mail_ses_key" | ||||
|           type="text" | ||||
|           name="mail_ses_key" | ||||
|           @input="$v.mailConfigData.mail_ses_key.$touch()" | ||||
|         /> | ||||
|         <div v-if="$v.mailConfigData.mail_ses_key.$error"> | ||||
|           <span v-if="!$v.mailConfigData.mail_ses_key.required" class="text-danger"> | ||||
|             {{ $tc('validation.required') }} | ||||
|           </span> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="col-md-6 my-2"> | ||||
|         <label class="form-label">{{ $t('wizard.mail.ses_secret') }}</label> | ||||
|         <span class="text-danger"> *</span> | ||||
|         <base-input | ||||
|           :invalid="$v.mailConfigData.mail_ses_secret.$error" | ||||
|           v-model.trim="mailConfigData.mail_ses_secret" | ||||
|           type="password" | ||||
|           name="mail_ses_secret" | ||||
|           show-password | ||||
|           @input="$v.mailConfigData.mail_ses_secret.$touch()" | ||||
|         /> | ||||
|         <div v-if="$v.mailConfigData.mail_ses_secret.$error"> | ||||
|           <span v-if="!$v.mailConfigData.mail_ses_secret.required" class="text-danger"> | ||||
|             {{ $tc('validation.required') }} | ||||
|           </span> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <base-button | ||||
|       :loading="loading" | ||||
|       class="pull-right mt-4" | ||||
|       icon="save" | ||||
|       color="theme" | ||||
|       type="submit" | ||||
|     > | ||||
|       {{ $t('general.save') }} | ||||
|     </base-button> | ||||
|   </form> | ||||
| </template> | ||||
| <script> | ||||
| import MultiSelect from 'vue-multiselect' | ||||
| import { validationMixin } from 'vuelidate' | ||||
| const { required, email, numeric } = require('vuelidate/lib/validators') | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
|     MultiSelect | ||||
|   }, | ||||
|   mixins: [validationMixin], | ||||
|   props: { | ||||
|     configData: { | ||||
|       type: Object, | ||||
|       require: true, | ||||
|       default: Object | ||||
|     }, | ||||
|     loading: { | ||||
|       type: Boolean, | ||||
|       require: true, | ||||
|       default: false | ||||
|     }, | ||||
|     mailDrivers: { | ||||
|       type: Array, | ||||
|       require: true, | ||||
|       default: Array | ||||
|     } | ||||
|   }, | ||||
|   data () { | ||||
|     return { | ||||
|       mailConfigData: { | ||||
|         mail_driver: '', | ||||
|         mail_host: '', | ||||
|         mail_port: null, | ||||
|         mail_ses_key: '', | ||||
|         mail_ses_secret: '', | ||||
|         mail_encryption: 'tls', | ||||
|         from_mail: '', | ||||
|         from_name: '' | ||||
|       }, | ||||
|       encryptions: ['tls', 'ssl', 'starttls'] | ||||
|     } | ||||
|   }, | ||||
|   validations: { | ||||
|     mailConfigData: { | ||||
|       mail_driver: { | ||||
|         required | ||||
|       }, | ||||
|       mail_host: { | ||||
|         required | ||||
|       }, | ||||
|       mail_port: { | ||||
|         required, | ||||
|         numeric | ||||
|       }, | ||||
|       mail_ses_key: { | ||||
|         required | ||||
|       }, | ||||
|       mail_ses_secret: { | ||||
|         required | ||||
|       }, | ||||
|       mail_encryption: { | ||||
|         required | ||||
|       }, | ||||
|       from_mail: { | ||||
|         required, | ||||
|         email | ||||
|       }, | ||||
|       from_name: { | ||||
|         required | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   mounted () { | ||||
|     for (const key in this.mailConfigData) { | ||||
|       if (this.configData.hasOwnProperty(key)) { | ||||
|         this.mailConfigData[key] = this.configData[key] | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     async saveEmailConfig () { | ||||
|       this.$v.mailConfigData.$touch() | ||||
|       if (!this.$v.mailConfigData.$invalid) { | ||||
|         this.$emit('submit-data', this.mailConfigData) | ||||
|       } | ||||
|  | ||||
|       return false | ||||
|     }, | ||||
|     onChangeDriver () { | ||||
|       this.$v.mailConfigData.mail_driver.$touch() | ||||
|       this.$emit('on-change-driver', this.mailConfigData.mail_driver) | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
| @ -1,254 +0,0 @@ | ||||
| <template> | ||||
|   <form @submit.prevent="saveEmailConfig()"> | ||||
|     <div class="row"> | ||||
|       <div class="col-md-6 my-2"> | ||||
|         <label class="form-label">{{ $t('wizard.mail.driver') }}</label> | ||||
|         <span class="text-danger"> *</span> | ||||
|         <base-select | ||||
|           v-model="mailConfigData.mail_driver" | ||||
|           :invalid="$v.mailConfigData.mail_driver.$error" | ||||
|           :options="mailDrivers" | ||||
|           :searchable="true" | ||||
|           :allow-empty="false" | ||||
|           :show-labels="false" | ||||
|           @input="onChangeDriver" | ||||
|         /> | ||||
|         <div v-if="$v.mailConfigData.mail_driver.$error"> | ||||
|           <span v-if="!$v.mailConfigData.mail_driver.required" class="text-danger"> | ||||
|             {{ $tc('validation.required') }} | ||||
|           </span> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="col-md-6 my-2"> | ||||
|         <label class="form-label">{{ $t('wizard.mail.host') }}</label> | ||||
|         <span class="text-danger"> *</span> | ||||
|         <base-input | ||||
|           :invalid="$v.mailConfigData.mail_host.$error" | ||||
|           v-model.trim="mailConfigData.mail_host" | ||||
|           type="text" | ||||
|           name="mail_host" | ||||
|           @input="$v.mailConfigData.mail_host.$touch()" | ||||
|         /> | ||||
|         <div v-if="$v.mailConfigData.mail_host.$error"> | ||||
|           <span v-if="!$v.mailConfigData.mail_host.required" class="text-danger"> | ||||
|             {{ $tc('validation.required') }} | ||||
|           </span> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <div class="row my-2"> | ||||
|       <div class="col-md-6 my-2"> | ||||
|         <label class="form-label">{{ $t('wizard.mail.username') }}</label> | ||||
|         <span class="text-danger"> *</span> | ||||
|         <base-input | ||||
|           :invalid="$v.mailConfigData.mail_username.$error" | ||||
|           v-model.trim="mailConfigData.mail_username" | ||||
|           type="text" | ||||
|           name="db_name" | ||||
|           @input="$v.mailConfigData.mail_username.$touch()" | ||||
|         /> | ||||
|         <div v-if="$v.mailConfigData.mail_username.$error"> | ||||
|           <span v-if="!$v.mailConfigData.mail_username.required" class="text-danger"> | ||||
|             {{ $tc('validation.required') }} | ||||
|           </span> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="col-md-6 my-2"> | ||||
|         <label class="form-label">{{ $t('wizard.mail.password') }}</label> | ||||
|         <span class="text-danger"> *</span> | ||||
|         <base-input | ||||
|           :invalid="$v.mailConfigData.mail_password.$error" | ||||
|           v-model.trim="mailConfigData.mail_password" | ||||
|           type="password" | ||||
|           name="name" | ||||
|           show-password | ||||
|           @input="$v.mailConfigData.mail_password.$touch()" | ||||
|         /> | ||||
|         <div v-if="$v.mailConfigData.mail_password.$error"> | ||||
|           <span v-if="!$v.mailConfigData.mail_password.required" class="text-danger"> | ||||
|             {{ $tc('validation.required') }} | ||||
|           </span> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <div class="row my-2"> | ||||
|       <div class="col-md-6 my-2"> | ||||
|         <label class="form-label">{{ $t('wizard.mail.port') }}</label> | ||||
|         <span class="text-danger"> *</span> | ||||
|         <base-input | ||||
|           :invalid="$v.mailConfigData.mail_port.$error" | ||||
|           v-model.trim="mailConfigData.mail_port" | ||||
|           type="text" | ||||
|           name="mail_port" | ||||
|           @input="$v.mailConfigData.mail_port.$touch()" | ||||
|         /> | ||||
|         <div v-if="$v.mailConfigData.mail_port.$error"> | ||||
|           <span v-if="!$v.mailConfigData.mail_port.required" class="text-danger"> | ||||
|             {{ $tc('validation.required') }} | ||||
|           </span> | ||||
|           <span v-if="!$v.mailConfigData.mail_port.numeric" class="text-danger"> | ||||
|             {{ $tc('validation.numbers_only') }} | ||||
|           </span> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="col-md-6 my-2"> | ||||
|         <label class="form-label">{{ $t('wizard.mail.encryption') }}</label> | ||||
|         <span class="text-danger"> *</span> | ||||
|         <base-select | ||||
|           v-model.trim="mailConfigData.mail_encryption" | ||||
|           :invalid="$v.mailConfigData.mail_encryption.$error" | ||||
|           :options="encryptions" | ||||
|           :searchable="true" | ||||
|           :show-labels="false" | ||||
|           @input="$v.mailConfigData.mail_encryption.$touch()" | ||||
|         /> | ||||
|         <div v-if="$v.mailConfigData.mail_encryption.$error"> | ||||
|           <span v-if="!$v.mailConfigData.mail_encryption.required" class="text-danger"> | ||||
|             {{ $tc('validation.required') }} | ||||
|           </span> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <div class="row my-2"> | ||||
|       <div class="col-md-6 my-2"> | ||||
|         <label class="form-label">{{ $t('wizard.mail.from_mail') }}</label> | ||||
|         <span class="text-danger"> *</span> | ||||
|         <base-input | ||||
|           :invalid="$v.mailConfigData.from_mail.$error" | ||||
|           v-model.trim="mailConfigData.from_mail" | ||||
|           type="text" | ||||
|           name="from_mail" | ||||
|           @input="$v.mailConfigData.from_mail.$touch()" | ||||
|         /> | ||||
|         <div v-if="$v.mailConfigData.from_mail.$error"> | ||||
|           <span v-if="!$v.mailConfigData.from_mail.required" class="text-danger"> | ||||
|             {{ $tc('validation.required') }} | ||||
|           </span> | ||||
|           <span v-if="!$v.mailConfigData.from_mail.email" class="text-danger"> | ||||
|             {{ $tc('validation.email_incorrect') }} | ||||
|           </span> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="col-md-6 my-2"> | ||||
|         <label class="form-label">{{ $t('wizard.mail.from_name') }}</label> | ||||
|         <span class="text-danger"> *</span> | ||||
|         <base-input | ||||
|           :invalid="$v.mailConfigData.from_name.$error" | ||||
|           v-model.trim="mailConfigData.from_name" | ||||
|           type="text" | ||||
|           name="from_name" | ||||
|           @input="$v.mailConfigData.from_name.$touch()" | ||||
|         /> | ||||
|         <div v-if="$v.mailConfigData.from_name.$error"> | ||||
|           <span v-if="!$v.mailConfigData.from_name.required" class="text-danger"> | ||||
|             {{ $tc('validation.required') }} | ||||
|           </span> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <base-button | ||||
|       :loading="loading" | ||||
|       class="pull-right mt-4" | ||||
|       icon="save" | ||||
|       color="theme" | ||||
|       type="submit" | ||||
|     > | ||||
|       {{ $t('general.save') }} | ||||
|     </base-button> | ||||
|   </form> | ||||
| </template> | ||||
| <script> | ||||
| import MultiSelect from 'vue-multiselect' | ||||
| import { validationMixin } from 'vuelidate' | ||||
| const { required, email, numeric } = require('vuelidate/lib/validators') | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
|     MultiSelect | ||||
|   }, | ||||
|   mixins: [validationMixin], | ||||
|   props: { | ||||
|     configData: { | ||||
|       type: Object, | ||||
|       require: true, | ||||
|       default: Object | ||||
|     }, | ||||
|     loading: { | ||||
|       type: Boolean, | ||||
|       require: true, | ||||
|       default: false | ||||
|     }, | ||||
|     mailDrivers: { | ||||
|       type: Array, | ||||
|       require: true, | ||||
|       default: Array | ||||
|     } | ||||
|   }, | ||||
|   data () { | ||||
|     return { | ||||
|       mailConfigData: { | ||||
|         mail_driver: '', | ||||
|         mail_host: '', | ||||
|         mail_port: null, | ||||
|         mail_username: '', | ||||
|         mail_password: '', | ||||
|         mail_encryption: 'tls', | ||||
|         from_mail: '', | ||||
|         from_name: '' | ||||
|       }, | ||||
|       encryptions: ['tls', 'ssl', 'starttls'] | ||||
|     } | ||||
|   }, | ||||
|   validations: { | ||||
|     mailConfigData: { | ||||
|       mail_driver: { | ||||
|         required | ||||
|       }, | ||||
|       mail_host: { | ||||
|         required | ||||
|       }, | ||||
|       mail_port: { | ||||
|         required, | ||||
|         numeric | ||||
|       }, | ||||
|       mail_username: { | ||||
|         required | ||||
|       }, | ||||
|       mail_password: { | ||||
|         required | ||||
|       }, | ||||
|       mail_encryption: { | ||||
|         required | ||||
|       }, | ||||
|       from_mail: { | ||||
|         required, | ||||
|         email | ||||
|       }, | ||||
|       from_name: { | ||||
|         required | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   mounted () { | ||||
|     for (const key in this.mailConfigData) { | ||||
|       if (this.configData.hasOwnProperty(key)) { | ||||
|         this.mailConfigData[key] = this.configData[key] | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     async saveEmailConfig () { | ||||
|       this.$v.mailConfigData.$touch() | ||||
|       if (!this.$v.mailConfigData.$invalid) { | ||||
|         this.$emit('submit-data', this.mailConfigData) | ||||
|       } | ||||
|  | ||||
|       return false | ||||
|     }, | ||||
|     onChangeDriver () { | ||||
|       this.$v.mailConfigData.mail_driver.$touch() | ||||
|       this.$emit('on-change-driver', this.mailConfigData.mail_driver) | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
		Reference in New Issue
	
	Block a user