Add plain text field to the Import view - Closes #288

This commit is contained in:
Bubka 2024-03-01 21:30:26 +01:00
parent 4ef3efd6ce
commit 4491852568
4 changed files with 128 additions and 0 deletions

View File

@ -0,0 +1,75 @@
<script setup>
import { useIdGenerator } from '@/composables/helpers'
defineOptions({
inheritAttrs: false
})
const { inputId } = useIdGenerator(props.inputType, props.fieldName)
const props = defineProps({
modelValue: [String, Number, Boolean],
label: {
type: String,
default: ''
},
fieldName: {
type: String,
default: '',
required: true
},
fieldError: [String],
placeholder: {
type: String,
default: ''
},
help: {
type: String,
default: ''
},
size: {
type: String,
default: ''
},
hasOffset: {
type: Boolean,
default: false
},
isDisabled: {
type: Boolean,
default: false
},
maxLength: {
type: Number,
default: null
},
isIndented: Boolean,
})
</script>
<template>
<div class="mb-3" :class="{ 'pt-3' : hasOffset, 'is-flex' : isIndented }">
<div v-if="isIndented" class="mx-2 pr-1" :style="{ 'opacity': isDisabled ? '0.5' : '1' }">
<FontAwesomeIcon class="has-text-grey" :icon="['fas', 'chevron-right']" transform="rotate-135"/>
</div>
<div class="field" :class="{ 'is-flex-grow-5' : isIndented }">
<label :for="inputId" class="label" v-html="$t(label)"></label>
<div class="control" :class="{ 'has-icons-left' : leftIcon, 'has-icons-right': rightIcon }">
<textarea
:disabled="isDisabled"
:id="inputId"
class="textarea"
:class="size"
:value="modelValue"
:placeholder="placeholder"
v-bind="$attrs"
v-on:input="$emit('update:modelValue', $event.target.value)"
v-on:change="$emit('change:modelValue', $event.target.value)"
:maxlength="maxLength"
/>
</div>
<FieldError v-if="fieldError != undefined" :error="fieldError" :field="fieldName" />
<p class="help" v-html="$t(help)" v-if="help"></p>
</div>
</div>
</template>

View File

@ -47,6 +47,7 @@ import {
faVideoSlash,
faChevronRight,
faSlash,
faAlignLeft,
} from '@fortawesome/free-solid-svg-icons'
import {
@ -109,6 +110,7 @@ library.add(
faOpenid,
faPaperPlane,
faSlash,
faAlignLeft
);
export default FontAwesomeIcon

View File

@ -1,5 +1,6 @@
<script setup>
import Form from '@/components/formElements/Form'
import FormTextarea from '@/components/formElements/FormTextarea.vue'
import twofaccountService from '@/services/twofaccountService'
import OtpDisplay from '@/components/OtpDisplay.vue'
import Spinner from '@/components/Spinner.vue'
@ -17,6 +18,8 @@
const otpDisplay = ref(null)
const fileInput = ref(null)
const qrcodeInput = ref(null)
const directInput = ref(null)
const directInputError = ref(null)
const form = reactive(new Form({
service: '',
account: '',
@ -86,6 +89,7 @@
exportedAccounts.value.push(data)
})
notifyValidAccountFound()
directInput.value = directInputError.value = null
})
.catch(error => {
notify.alert({ text: trans(error.response.data.message) })
@ -225,6 +229,18 @@
notify.success({ text: trans('twofaccounts.import.x_valid_accounts_found', { count: importableCount.value }) })
}
/**
* Submits the directInput form to the backend
*/
function submitDirectInput() {
directInputError.value = null
if (! directInput.value) {
directInputError.value = trans('validation.required', { attribute: 'Direct input' })
}
else migrate(directInput.value)
}
</script>
<template>
@ -295,6 +311,33 @@
</footer>
</div>
</div>
<div class="block">
<div class="card">
<div class="card-content">
<div class="media">
<div class="media-left">
<figure class="image is-32x32">
<UseColorMode v-slot="{ mode }">
<FontAwesomeIcon :icon="['fas', 'align-left']" size="2x" :class="mode == 'dark' ? 'has-text-grey-darker' : 'has-text-grey-lighter'" />
</UseColorMode>
</figure>
</div>
<div class="media-content">
<p class="title is-5 has-text-grey" v-html="$t('twofaccounts.import.direct_input')" />
<p class="subtitle is-6 is-size-7-mobile">{{ $t('twofaccounts.import.expected_format_for_direct_input') }}</p>
</div>
</div>
<div class="content">
<FormTextarea v-model="directInput" :fieldError="directInputError" fieldName="payload" rows="5" :size="'is-small'" />
</div>
</div>
<footer class="card-footer">
<a role="button" tabindex="0" class="card-footer-item is-relative" @click.stop="submitDirectInput">
{{ $t('commons.submit') }}
</a>
</footer>
</div>
</div>
</div>
</div>
<!-- Supported migration resources -->
@ -331,6 +374,12 @@
<td></td>
<td><FontAwesomeIcon :icon="['fas', 'circle-check']" /></td>
</tr>
<tr>
<th>FreeOTP+</th>
<td><FontAwesomeIcon :icon="['fas', 'circle-check']" /></td>
<td></td>
<td></td>
</tr>
<tr>
<th>2FAuth</th>
<td></td>

View File

@ -143,9 +143,11 @@ return [
'scan' => 'Scan',
'supported_formats_for_qrcode_upload' => 'Accepted: jpg, jpeg, png, bmp, gif, svg, or webp',
'supported_formats_for_file_upload' => 'Accepted: Plain text, json, 2fas',
'expected_format_for_direct_input' => 'Expected: A list of otpauth URI, one by line',
'supported_migration_formats' => 'Supported migration formats',
'qr_code' => 'QR Code',
'text_file' => 'Text file',
'direct_input' => 'Direct input',
'plain_text' => 'Plain text',
'parsing_data' => 'Parsing data...',
'issuer' => 'Issuer',