Set up the Start view

This commit is contained in:
Bubka 2023-10-09 13:00:56 +02:00
parent bde05233c5
commit c389378dc3
5 changed files with 172 additions and 14 deletions

View File

@ -210,12 +210,12 @@ class Form {
* @param {Object} config (axios config)
* @return {Promise}
*/
upload (url, formData, config = {}) {
upload (url, config = {}) {
this.startProcessing()
return new Promise((resolve, reject) => {
// (Form.axios || axios).request({ url: this.route(url), method, data, ...config })
this.axios.request({ url: this.route(url), method: 'post', data: formData, header: {'Content-Type' : 'multipart/form-data'}, ...config })
// https://www.npmjs.com/package/axios#-automatic-serialization-to-formdata
this.axios.post(this.route(url), this.data(), { headers: {'Content-Type' : 'multipart/form-data'}, ...config })
.then(response => {
this.finishProcessing()
@ -227,9 +227,9 @@ class Form {
if (error.response) {
this.errors.set(this.extractErrors(error.response))
}
if (error.response?.status != 422) {
// if (error.response?.status != 422) {
reject(error)
}
// }
})
})
}

View File

@ -2,12 +2,12 @@ import { createRouter, createWebHistory } from 'vue-router'
import middlewarePipeline from "@/router/middlewarePipeline";
import { useUserStore } from '@/stores/user'
// import Start from './views/Start.vue'
// import Capture from './views/Capture.vue'
import Start from '../views/Start.vue'
import Accounts from '../views/Accounts.vue'
// import CreateAccount from './views/twofaccounts/Create.vue'
import Capture from '../views/twofaccounts/Capture.vue'
import CreateAccount from '../views/twofaccounts/Create.vue'
// import EditAccount from './views/twofaccounts/Edit.vue'
// import ImportAccount from './views/twofaccounts/Import.vue'
import ImportAccount from '../views/twofaccounts/Import.vue'
// import QRcodeAccount from './views/twofaccounts/QRcode.vue'
// import Groups from './views/Groups.vue'
// import CreateGroup from './views/groups/Create.vue'
@ -33,12 +33,12 @@ import noEmptyError from './middlewares/noEmptyError'
const router = createRouter({
history: createWebHistory('/'),
routes: [
// { path: '/start', name: 'start', component: Start, meta: { middlewares: [authGuard] }, props: true },
// { path: '/capture', name: 'capture', component: Capture, meta: { middlewares: [authGuard] }, props: true },
{ path: '/start', name: 'start', component: Start, meta: { middlewares: [authGuard] } },
{ path: '/capture', name: 'capture', component: Capture, meta: { middlewares: [authGuard] } },
{ path: '/accounts', name: 'accounts', component: Accounts, meta: { middlewares: [authGuard] }, alias: '/', props: true },
// { path: '/account/create', name: 'createAccount', component: CreateAccount, meta: { middlewares: [authGuard] } },
// { path: '/account/import', name: 'importAccounts', component: ImportAccount, meta: { middlewares: [authGuard] } },
{ path: '/accounts', name: 'accounts', component: Accounts, meta: { middlewares: [authGuard] }, alias: '/' },
{ path: '/account/create', name: 'createAccount', component: CreateAccount, meta: { middlewares: [authGuard] } },
{ path: '/account/import', name: 'importAccounts', component: ImportAccount, meta: { middlewares: [authGuard] } },
// { path: '/account/:twofaccountId/edit', name: 'editAccount', component: EditAccount, meta: { middlewares: [authGuard] } },
// { path: '/account/:twofaccountId/qrcode', name: 'showQRcode', component: QRcodeAccount, meta: { middlewares: [authGuard] } },

19
resources/js_vue3/stores/bus.js vendored Normal file
View File

@ -0,0 +1,19 @@
import { defineStore } from 'pinia'
export const useBusStore = defineStore({
id: 'bus',
state: () => {
return {
migrationUri: null,
decodedUri: null,
goBackTo: null,
returnTo: null,
initialEditMode: null,
}
},
actions: {
},
})

16
resources/js_vue3/stores/data.js vendored Normal file
View File

@ -0,0 +1,16 @@
import { defineStore } from 'pinia'
export const useDataStore = defineStore({
id: 'data',
state: () => {
return {
twofaccounts: [],
groups: [],
}
},
actions: {
},
})

View File

@ -0,0 +1,123 @@
<script setup>
import Form from '@/components/formElements/Form'
import { useUserStore } from '@/stores/user'
import { useBusStore } from '@/stores/bus'
import { useDataStore } from '@/stores/data'
import { useNotifyStore } from '@/stores/notify'
import { UseColorMode } from '@vueuse/components'
const router = useRouter()
const user = useUserStore()
const bus = useBusStore()
const notify = useNotifyStore()
const data = useDataStore()
const { twofaccounts } = storeToRefs(data)
const qrcodeInput = ref(null)
const qrcodeInputLabel = ref(null)
const form = reactive(new Form({
qrcode: null,
inputFormat: 'fileUpload',
}))
/**
* Upload the submitted QR code file to the backend for decoding, then route the user
* to the Create or Import form with decoded URI to prefill the form
*/
function submitQrCode() {
form.qrcode = qrcodeInput.value.files[0]
form.upload('/api/v1/qrcode/decode', { returnError: true }).then(response => {
console.log(response.data)
if (response.data.data.slice(0, 33).toLowerCase() === "otpauth-migration://offline?data=") {
bus.migrationUri = response.data.data
router.push({ name: 'importAccounts' })
}
else {
bus.decodedUri = response.data.data
router.push({ name: 'createAccount' })
}
})
.catch(error => {
notify.alert({ text: trans(error.response.data.message) })
})
}
/**
* Push user to the dedicated capture view for live scan
*/
function capture() {
router.push({ name: 'capture' });
}
onMounted(() => {
if( user.preferences.useDirectCapture && user.preferences.defaultCaptureMode === 'upload' ) {
qrcodeInputLabel.value.click()
}
})
</script>
<template>
<!-- static landing UI -->
<div class="container has-text-centered">
<div class="columns quick-uploader">
<!-- trailer phrase that invite to add an account -->
<div class="column is-full quick-uploader-header" :class="{ 'is-invisible' : twofaccounts.length !== 0 }">
{{ $t('twofaccounts.no_account_here') }}<br>
{{ $t('twofaccounts.add_first_account') }}
</div>
<!-- Livescan button -->
<div class="column is-full quick-uploader-button" >
<div class="quick-uploader-centerer">
<!-- upload a qr code (with basic file field and backend decoding) -->
<label role="button" tabindex="0" v-if="user.preferences.useBasicQrcodeReader" class="button is-link is-medium is-rounded is-main" ref="qrcodeInputLabel" @keyup.enter="qrcodeInputLabel.click()">
<input aria-hidden="true" tabindex="-1" class="file-input" type="file" accept="image/*" v-on:change="submitQrCode" ref="qrcodeInput">
{{ $t('twofaccounts.forms.upload_qrcode') }}
</label>
<!-- scan button that launch camera stream -->
<button v-else class="button is-link is-medium is-rounded is-main" @click="capture()">
{{ $t('twofaccounts.forms.scan_qrcode') }}
</button>
<FieldError v-if="form.hasAny" :error="form.errors.get('qrcode')" :field="'qrcode'" />
</div>
</div>
<!-- alternative methods -->
<div class="column is-full">
<UseColorMode v-slot="{ mode }">
<div class="block" :class="mode == 'dark' ? 'has-text-light':'has-text-grey-dark'">{{ $t('twofaccounts.forms.alternative_methods') }}</div>
</UseColorMode>
<!-- upload a qr code -->
<div class="block has-text-link" v-if="!user.preferences.useBasicQrcodeReader">
<label role="button" tabindex="0" class="button is-link is-outlined is-rounded" ref="qrcodeInputLabel" @keyup.enter="qrcodeInputLabel.click()">
<input aria-hidden="true" tabindex="-1" class="file-input" type="file" accept="image/*" v-on:change="submitQrCode" ref="qrcodeInput">
{{ $t('twofaccounts.forms.upload_qrcode') }}
</label>
</div>
<!-- link to advanced form -->
<div class="block has-text-link">
<RouterLink class="button is-link is-outlined is-rounded" :to="{ name: 'createAccount' }" >
{{ $t('twofaccounts.forms.use_advanced_form') }}
</RouterLink>
</div>
<!-- link to import view -->
<div class="block has-text-link">
<RouterLink id="btnImport" class="button is-link is-outlined is-rounded" :to="{ name: 'importAccounts' }" >
{{ $t('twofaccounts.import.import') }}
</RouterLink>
</div>
</div>
</div>
<!-- Footer -->
<VueFooter :showButtons="true" >
<!-- back button -->
<p class="control" v-if="twofaccounts.length > 0">
<UseColorMode v-slot="{ mode }">
<RouterLink id="lnkBack" class="button is-rounded" :class="{'is-dark' : mode == 'dark'}" :to="{ name: 'accounts' }" >
{{ $t('commons.back') }}
</RouterLink>
</UseColorMode>
</p>
</VueFooter>
</div>
</template>